Skip to content

Commit

Permalink
Fetch balance + Cleanup
Browse files Browse the repository at this point in the history
  • Loading branch information
radeknovis committed Oct 20, 2023
1 parent e840b9c commit 7217d8d
Show file tree
Hide file tree
Showing 14 changed files with 255 additions and 258 deletions.
4 changes: 2 additions & 2 deletions Sample/Example.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\"";
DEVELOPMENT_TEAM = W5R8AG9K22;
ENABLE_HARDENED_RUNTIME = YES;
Expand Down Expand Up @@ -364,7 +364,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Example/Example.entitlements;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 2;
CURRENT_PROJECT_VERSION = 5;
DEVELOPMENT_ASSET_PATHS = "\"Example/Preview Content\"";
DEVELOPMENT_TEAM = W5R8AG9K22;
ENABLE_HARDENED_RUNTIME = YES;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"location" : "https://github.com/WalletConnect/WalletConnectSwiftV2",
"state" : {
"branch" : "remove-wcm",
"revision" : "0085250fd993f40a638f8d3e300f4af8cbf9e7a8"
"revision" : "04bcc547a61768598286cfa4cb0a06c0475c4d35"
}
}
],
Expand Down
91 changes: 88 additions & 3 deletions Sources/Web3Modal/Core/BlockchainAPIInteractor.swift
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import Foundation
import HTTPClient

import JSONRPC

final class BlockchainAPIInteractor: ObservableObject {

private let store: Store

init(store: Store = .shared) {
self.store = store
}

func getIdentity() async throws {

let account = store.session?.accounts.first
let address = account?.address
let chainId = account?.blockchainIdentifier
Expand All @@ -31,10 +31,95 @@ final class BlockchainAPIInteractor: ObservableObject {
self.store.identity = response
}
}

func getBalance() async throws {
enum GetBalanceError: Error {
case noAddress, invalidValue, noChain
}

guard let address = store.session?.accounts.first?.address else {
throw GetBalanceError.noAddress
}

guard let chain = store.selectedChain else {
throw GetBalanceError.noChain
}

let request = RPCRequest(
method: "eth_getBalance", params: [
address, "latest"
]
)

var urlRequest = URLRequest(url: URL(string: chain.rpcUrl)!)
urlRequest.httpMethod = "POST"
urlRequest.httpBody = try JSONEncoder().encode(request)
urlRequest.setValue("application/json", forHTTPHeaderField: "Content-Type")

let (data, _) = try await URLSession.shared.data(for: urlRequest)
let decodedResponse = try JSONDecoder().decode(RPCResponse.self, from: data)
let weiFactor = pow(10, chain.token.decimal)

guard let decimalValue = try decodedResponse.result?
.get(String.self)
.convertBalanceHexToBigDecimal()?
.toWei(weiFactor: weiFactor)
else {
throw GetBalanceError.invalidValue
}

let doubleValue = Double(truncating: decimalValue as NSNumber)

DispatchQueue.main.async {
self.store.balance = doubleValue
}
}
}


struct Identity: Codable {
let name: String?
let avatar: String?
}

struct BalanceRequest: Encodable {
init(address: String) {
self.address = address

self.id = RPCID()
self.params = [
address, "latest"
]
}

let address: String
let id: RPCID
let jsonrpc: String = "2.0"
let method: String = "eth_getBalance"
let params: [String]
}

struct BalanceRpcResponse: Codable {
let id: RPCID
let jsonrpc: String
let result: String?
let error: RpcError?

struct RpcError: Codable {
let code: Int
let message: String
}
}

private extension String {
func convertBalanceHexToBigDecimal() -> Decimal? {
let substring = dropFirst(2)
guard let longValue = UInt64(substring, radix: 16) else { return nil }
return Decimal(string: "\(longValue)")
}
}

extension Decimal {
func toWei(weiFactor: Decimal) -> Decimal {
return self / weiFactor
}
}
9 changes: 8 additions & 1 deletion Sources/Web3Modal/Core/SignInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ class SignInteractor: ObservableObject {
lazy var sessionResponsePublisher: AnyPublisher<Response, Never> = Web3Modal.instance.sessionResponsePublisher
lazy var sessionRejectionPublisher: AnyPublisher<(Session.Proposal, Reason), Never> = Web3Modal.instance.sessionRejectionPublisher
lazy var sessionDeletePublisher: AnyPublisher<(String, Reason), Never> = Web3Modal.instance.sessionDeletePublisher
lazy var sessionEventPublisher: AnyPublisher<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never> = Web3Modal.instance.sessionEventPublisher

init(store: Store = .shared) {
self.store = store
Expand All @@ -31,6 +32,12 @@ class SignInteractor: ObservableObject {
}
}

try await Web3Modal.instance.disconnect(topic: store.session?.topic ?? "")
do {
try await Web3Modal.instance.disconnect(topic: store.session?.topic ?? "")
} catch {
print(error.localizedDescription)
}
try await Web3Modal.instance.cleanup()
try await createPairingAndConnect()
}
}
38 changes: 37 additions & 1 deletion Sources/Web3Modal/Core/W3MAPIInteractor.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ final class W3MAPIInteractor: ObservableObject {
request.setValue("ios-3.0.0-alpha.0", forHTTPHeaderField: "x-sdk-version")

do {
let (data, _) = try await URLSession(configuration: .ephemeral).data(for: request)
let (data, _) = try await URLSession.shared.data(for: request)
return (wallet.imageId, UIImage(data: data))
} catch {
print(error.localizedDescription)
Expand All @@ -125,4 +125,40 @@ final class W3MAPIInteractor: ObservableObject {
}
}
}

func prefetchChainImages() async throws {
var chainImages: [String: UIImage] = [:]

try await ChainsPresets.ethChains.concurrentMap { chain in

let url = URL(string: "https://api.web3modal.com/public/getAssetImage/\(chain.imageId)")!
var request = URLRequest(url: url)

request.setValue(Web3Modal.config.projectId, forHTTPHeaderField: "x-project-id")
request.setValue("w3m", forHTTPHeaderField: "x-sdk-type")
request.setValue("ios-3.0.0-alpha.0", forHTTPHeaderField: "x-sdk-version")

do {
let (data, _) = try await URLSession.shared.data(for: request)
return (chain.imageId, UIImage(data: data))
} catch {
print(error.localizedDescription)
}

return ("", UIImage?.none)
}
.forEach { key, value in
if value == nil {
return
}

chainImages[key] = value
}

DispatchQueue.main.async { [chainImages] in
self.store.chainImages.merge(chainImages) { _, new in
new
}
}
}
}
36 changes: 25 additions & 11 deletions Sources/Web3Modal/Core/Web3Modal.swift
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import SwiftUI
import WalletConnectSign
import WalletConnectVerify


#if canImport(UIKit)
import UIKit
#endif
Expand All @@ -29,10 +28,25 @@ public class Web3Modal {
guard let config = Web3Modal.config else {
fatalError("Error - you must call Web3Modal.configure(_:) before accessing the shared instance.")
}
return Web3ModalClient(

let client = Web3ModalClient(
signClient: Sign.instance,
pairingClient: Pair.instance as! (PairingClientProtocol & PairingInteracting & PairingRegisterer)
)

if let session = client.getSessions().first {
Store.shared.session = session

if let blockchain = session.accounts.first?.blockchain {
let matchingChain = ChainsPresets.ethChains.first(where: {
$0.chainNamespace == blockchain.namespace && $0.chainReference == blockchain.reference
})

Store.shared.selectedChain = matchingChain
}
}

return client
}()

struct Config {
Expand Down Expand Up @@ -68,7 +82,12 @@ public class Web3Modal {
includeWebWallets: includeWebWallets,
recommendedWalletIds: recommendedWalletIds,
excludedWalletIds: excludedWalletIds
)
)

Task {
try? await W3MAPIInteractor().fetchFeaturedWallets()
try? await W3MAPIInteractor().prefetchChainImages()
}
}

public static func set(sessionParams: SessionParams) {
Expand All @@ -79,7 +98,6 @@ public class Web3Modal {
#if canImport(UIKit)

extension Web3Modal {

public static func present(from presentingViewController: UIViewController? = nil) {
guard let vc = presentingViewController ?? topViewController() else {
assertionFailure("No controller found for presenting modal")
Expand All @@ -91,7 +109,6 @@ extension Web3Modal {
}

private static func topViewController(_ base: UIViewController? = nil) -> UIViewController? {

let base = base ?? UIApplication
.shared
.connectedScenes
Expand Down Expand Up @@ -121,10 +138,8 @@ extension Web3Modal {

import AppKit

extension Web3Modal {

public static func present(from presentingViewController: NSViewController? = nil) {

public extension Web3Modal {
static func present(from presentingViewController: NSViewController? = nil) {
let modal = Web3ModalSheetController()
presentingViewController!.presentAsModalWindow(modal)
}
Expand All @@ -137,7 +152,7 @@ public struct SessionParams {
public let optionalNamespaces: [String: ProposalNamespace]?
public let sessionProperties: [String: String]?

public init(requiredNamespaces: [String : ProposalNamespace], optionalNamespaces: [String : ProposalNamespace]? = nil, sessionProperties: [String : String]? = nil) {
public init(requiredNamespaces: [String: ProposalNamespace], optionalNamespaces: [String: ProposalNamespace]? = nil, sessionProperties: [String: String]? = nil) {
self.requiredNamespaces = requiredNamespaces
self.optionalNamespaces = optionalNamespaces
self.sessionProperties = sessionProperties
Expand All @@ -162,4 +177,3 @@ public struct SessionParams {
)
}()
}

7 changes: 7 additions & 0 deletions Sources/Web3Modal/Core/Web3ModalClient.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,13 @@ public class Web3ModalClient {
signClient.socketConnectionStatusPublisher.eraseToAnyPublisher()
}

/// Publisher that sends session event
///
/// Event will be emited on dApp client only
public var sessionEventPublisher: AnyPublisher<(event: Session.Event, sessionTopic: String, chainId: Blockchain?), Never> {
signClient.sessionEventPublisher.eraseToAnyPublisher()
}

// MARK: - Private Properties

private let signClient: SignClientProtocol
Expand Down
2 changes: 1 addition & 1 deletion Sources/Web3Modal/Models/Chain.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public struct Chain: Identifiable, Hashable {
"\(chainNamespace):\(chainReference)"
}

var chainName: String
public var chainName: String
var chainNamespace: String
var chainReference: String
var requiredMethods: [String]
Expand Down
1 change: 1 addition & 0 deletions Sources/Web3Modal/Networking/Web3ModalAPI.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ enum Web3ModalAPI: HTTPService {
"search": params.search ?? "",
"recommendedIds": params.recommendedIds.joined(separator: ","),
"excludedIds": params.excludedIds.joined(separator: ","),
"platform": "ios",
]
.compactMapValues { value in
value.isEmpty ? nil : value
Expand Down
Loading

0 comments on commit 7217d8d

Please sign in to comment.