Skip to content

Commit

Permalink
fix: handling rn sdk read-only calls (#187)
Browse files Browse the repository at this point in the history
* fix: handling rn sdk read-only calls

* update read only provider
  • Loading branch information
elefantel authored Sep 11, 2024
1 parent 1d440a2 commit 0399a53
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 17 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ Alternatively, you can add the URL directly in your project's package file:
dependencies: [
.package(
url: "https://github.com/MetaMask/metamask-ios-sdk",
from: "0.8.6"
from: "0.8.7"
)
]
```
Expand Down
31 changes: 22 additions & 9 deletions Sources/metamask-ios-sdk/Classes/API/InfuraProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ public class ReadOnlyRPCProvider {
let infuraAPIKey: String
private let network: any Networking

let rpcUrls: [String: String]
let readonlyRPCMap: [String: String]

public convenience init(infuraAPIKey: String? = nil, readonlyRPCMap: [String: String]? = nil) {
Expand All @@ -18,26 +19,31 @@ public class ReadOnlyRPCProvider {
init(infuraAPIKey: String? = nil, readonlyRPCMap: [String: String]?, network: any Networking) {
self.infuraAPIKey = infuraAPIKey ?? ""
self.network = network
self.readonlyRPCMap = readonlyRPCMap ?? [:]

if let providedRPCMap = readonlyRPCMap {
if let apiKey = infuraAPIKey {
// Merge infuraReadonlyRPCMap with readonlyRPCMap, overriding infura's keys if they are present in readonlyRPCMap
var mergedMap = ReadOnlyRPCProvider.infuraReadonlyRPCMap(apiKey)
providedRPCMap.forEach { mergedMap[$0.key] = $0.value }
self.readonlyRPCMap = mergedMap
self.rpcUrls = mergedMap
} else {
// Use only the provided readonlyRPCMap
self.readonlyRPCMap = providedRPCMap
self.rpcUrls = providedRPCMap
}
} else if let apiKey = infuraAPIKey {
// Use infuraReadonlyRPCMap as default
self.readonlyRPCMap = ReadOnlyRPCProvider.infuraReadonlyRPCMap(apiKey)
self.rpcUrls = ReadOnlyRPCProvider.infuraReadonlyRPCMap(apiKey)
} else {
// Default to an empty map if neither are provided
self.readonlyRPCMap = [:]
self.rpcUrls = [:]
}
}

func supportsChain(_ chainId: String) -> Bool {
return rpcUrls[chainId] != nil && (readonlyRPCMap[chainId] != nil || !infuraAPIKey.isEmpty)
}

static func infuraReadonlyRPCMap(_ infuraAPIKey: String) -> [String: String] {
[
// ###### Ethereum ######
Expand Down Expand Up @@ -96,17 +102,20 @@ public class ReadOnlyRPCProvider {
}

func endpoint(for chainId: String) -> String? {
readonlyRPCMap[chainId]
rpcUrls[chainId]
}

public func sendRequest(_ request: any RPCRequest, chainId: String, appMetadata: AppMetadata) async -> Any? {
public func sendRequest(_ request: any RPCRequest,
params: Any = "",
chainId: String,
appMetadata: AppMetadata) async -> Any? {
Logging.log("ReadOnlyRPCProvider:: Sending request \(request.method) on chain \(chainId) via Infura API")

let params: [String: Any] = [
"method": request.method,
"jsonrpc": "2.0",
"id": request.id,
"params": request.params
"params": params
]

guard let endpoint = endpoint(for: chainId) else {
Expand All @@ -132,10 +141,14 @@ public class ReadOnlyRPCProvider {
}

Logging.error("ReadOnlyRPCProvider:: could not get result from response \(json)")
if let error = json["error"] as? [String: Any] {
return RequestError(from: error)
}

return nil
} catch {
Logging.error("tracking error: \(error.localizedDescription)")
return nil
Logging.error("ReadOnlyRPCProvider:: error: \(error.localizedDescription)")
return RequestError(from: ["code": -1, "message": error.localizedDescription])
}
}
}
21 changes: 15 additions & 6 deletions Sources/metamask-ios-sdk/Classes/Ethereum/Ethereum.swift
Original file line number Diff line number Diff line change
Expand Up @@ -431,20 +431,29 @@ public class Ethereum {
submittedRequests.removeAll()
clearSession()
}

func useReadOnlyRPCProvider() -> Bool {
!readOnlyRPCProvider.infuraAPIKey.isEmpty || !readOnlyRPCProvider.readonlyRPCMap.isEmpty
}

// MARK: Request Sending

func sendRequest(_ request: any RPCRequest) {
if
EthereumMethod.isReadOnly(request.methodType),
useReadOnlyRPCProvider() {
readOnlyRPCProvider.supportsChain(chainId) {
Task {
let readOnlyRequest = EthereumRequest(
id: request.id,
method: request.method
)
var params: Any = request.params

if
let paramsData = request.params as? Data,
let json = try? JSONSerialization.jsonObject(with: paramsData, options: []) {
params = json
}

if let result = await readOnlyRPCProvider.sendRequest(
request,
readOnlyRequest,
params: params,
chainId: chainId,
appMetadata: commClient.appMetadata ?? AppMetadata(name: "", url: "")) {
sendResult(result, id: request.id)
Expand Down
2 changes: 1 addition & 1 deletion metamask-ios-sdk.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = 'metamask-ios-sdk'
s.version = '0.8.6'
s.version = '0.8.7'
s.summary = 'Enable users to easily connect with their MetaMask Mobile wallet.'
s.swift_version = '5.5'

Expand Down

0 comments on commit 0399a53

Please sign in to comment.