mirror of
https://github.com/lil-org/wallet.git
synced 2024-12-28 23:14:11 +03:00
commit
fc78b1125f
@ -21,8 +21,8 @@ extension SafariRequest {
|
||||
|
||||
let method: Method
|
||||
let address: String
|
||||
let chain: EthereumNetwork?
|
||||
let switchToChain: EthereumNetwork?
|
||||
let currentChainId: Int?
|
||||
let switchToChainId: Int?
|
||||
let parameters: [String: Any]?
|
||||
|
||||
init?(name: String, json: [String: Any]) {
|
||||
@ -32,21 +32,19 @@ extension SafariRequest {
|
||||
self.address = address
|
||||
self.method = method
|
||||
|
||||
if let network = json["networkId"] as? String, let networkId = Int(network) {
|
||||
self.chain = EthereumNetwork(rawValue: networkId)
|
||||
if let currentChainId = json["chainId"] as? String, let chainId = Int(hexString: currentChainId) {
|
||||
self.currentChainId = chainId
|
||||
} else {
|
||||
self.chain = nil
|
||||
self.currentChainId = nil
|
||||
}
|
||||
|
||||
let parameters = json["object"] as? [String: Any]
|
||||
self.parameters = parameters
|
||||
|
||||
if let chainId = parameters?["chainId"] as? String,
|
||||
let networkId = Int(hexString: chainId),
|
||||
let chain = EthereumNetwork(rawValue: networkId) {
|
||||
self.switchToChain = chain
|
||||
if let toChainId = parameters?["chainId"] as? String, let chainId = Int(hexString: toChainId) {
|
||||
self.switchToChainId = chainId
|
||||
} else {
|
||||
self.switchToChain = nil
|
||||
self.switchToChainId = nil
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -14,7 +14,7 @@ extension SafariRequest {
|
||||
struct ProviderConfiguration {
|
||||
let provider: InpageProvider
|
||||
let address: String
|
||||
let network: EthereumNetwork?
|
||||
let chainId: String?
|
||||
}
|
||||
|
||||
let method: Method
|
||||
@ -37,7 +37,7 @@ extension SafariRequest {
|
||||
case .ethereum:
|
||||
guard let response = try? jsonDecoder.decode(ResponseToExtension.Ethereum.self, from: data),
|
||||
let address = response.results?.first else { continue }
|
||||
configurations.append(ProviderConfiguration(provider: provider, address: address, network: EthereumNetwork.withChainId(response.chainId)))
|
||||
configurations.append(ProviderConfiguration(provider: provider, address: address, chainId: response.chainId))
|
||||
case .unknown, .multiple:
|
||||
continue
|
||||
}
|
||||
|
File diff suppressed because one or more lines are too long
@ -39,8 +39,9 @@ class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
|
||||
self.context = context
|
||||
if case let .ethereum(ethereumRequest) = request.body,
|
||||
ethereumRequest.method == .switchEthereumChain || ethereumRequest.method == .addEthereumChain {
|
||||
if let chain = ethereumRequest.switchToChain {
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [ethereumRequest.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString)
|
||||
if let switchToChainId = ethereumRequest.switchToChainId, let rpcURL = Nodes.getNode(chainId: switchToChainId) {
|
||||
let chainId = String.hex(switchToChainId, withPrefix: true)
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [ethereumRequest.address], chainId: chainId, rpcURL: rpcURL)
|
||||
let response = ResponseToExtension(for: request, body: .ethereum(responseBody))
|
||||
respond(with: response.json)
|
||||
} else {
|
||||
|
@ -22,7 +22,7 @@ class TokenaryEthereum extends EventEmitter {
|
||||
|
||||
constructor() {
|
||||
super();
|
||||
const config = {address: "", chainId: "0x1", rpcUrl: "https://mainnet.infura.io/v3/3f99b6096fda424bbb26e17866dcddfc"};
|
||||
const config = {address: "", chainId: "0x1", rpcUrl: "https://eth.llamarpc.com"};
|
||||
this.setConfig(config);
|
||||
this.idMapping = new IdMapping();
|
||||
this.callbacks = new Map();
|
||||
@ -381,7 +381,7 @@ class TokenaryEthereum extends EventEmitter {
|
||||
let object = {
|
||||
object: data,
|
||||
address: this.address,
|
||||
networkId: this.net_version()
|
||||
chainId: this.chainId
|
||||
};
|
||||
window.tokenary.postMessage(handler, id, object, "ethereum");
|
||||
} else {
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"name": "__MSG_extension_name__",
|
||||
"description": "__MSG_extension_description__",
|
||||
"version": "2.0.19",
|
||||
"version": "2.0.20",
|
||||
|
||||
"icons": {
|
||||
"48": "images/icon-48.png",
|
||||
@ -40,6 +40,7 @@
|
||||
"nativeMessaging",
|
||||
"browserAction",
|
||||
"storage",
|
||||
"https://*.llamarpc.com/",
|
||||
"https://*.infura.io/",
|
||||
"https://*.infura.io/*",
|
||||
"https://*.infura.io/*/*",
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
"name": "__MSG_extension_name__",
|
||||
"description": "__MSG_extension_description__",
|
||||
"version": "2.0.19",
|
||||
"version": "2.0.20",
|
||||
|
||||
"icons": {
|
||||
"48": "images/icon-48.png",
|
||||
@ -38,6 +38,7 @@
|
||||
"permissions": [
|
||||
"nativeMessaging",
|
||||
"storage",
|
||||
"https://*.llamarpc.com/",
|
||||
"https://*.infura.io/",
|
||||
"https://*.infura.io/*",
|
||||
"https://*.infura.io/*/*",
|
||||
|
@ -96,7 +96,7 @@ struct Ethereum {
|
||||
let gasPriceHex = transaction.gasPrice?.cleanEvenHex,
|
||||
let gasHex = transaction.gas?.cleanEvenHex,
|
||||
let valueHex = transaction.value?.cleanEvenHex,
|
||||
let chainID = Data(hexString: network.hexStringId.cleanEvenHex),
|
||||
let chainID = Data(hexString: network.chainIdHexString.cleanEvenHex),
|
||||
let nonce = Data(hexString: nonceHex),
|
||||
let gasPrice = Data(hexString: gasPriceHex),
|
||||
let gasLimit = Data(hexString: gasHex),
|
||||
|
@ -2,154 +2,19 @@
|
||||
|
||||
import Foundation
|
||||
|
||||
enum EthereumNetwork: Int {
|
||||
case ethereum = 1
|
||||
case arbitrum = 42161
|
||||
case polygon = 137
|
||||
case optimism = 10
|
||||
case binance = 56
|
||||
case avalanche = 43114
|
||||
case gnosisChain = 100
|
||||
case fantomOpera = 250
|
||||
case celo = 42220
|
||||
case aurora = 1313161554
|
||||
case neon = 245022934
|
||||
case base = 8453
|
||||
case zora = 7777777
|
||||
case klaytn = 8217
|
||||
case scroll = 534352
|
||||
struct EthereumNetwork: Codable, Equatable {
|
||||
|
||||
// Testnets
|
||||
case arbitrumRinkeby = 421611
|
||||
case arbitrumKovan = 144545313136048
|
||||
case optimisticKovan = 69
|
||||
case ethereumGoerli = 5
|
||||
case polygonMumbai = 80001
|
||||
case binanceTestnet = 97
|
||||
case avalancheFuji = 43113
|
||||
case fantomTestnet = 4002
|
||||
case fantomSonicOpen = 64240
|
||||
case neonDevnet = 245022926
|
||||
case scrollSepolia = 534351
|
||||
let chainId: Int
|
||||
let name: String
|
||||
let symbol: String
|
||||
let nodeURLString: String
|
||||
let isTestnet: Bool
|
||||
let mightShowPrice: Bool
|
||||
|
||||
var id: Int {
|
||||
return rawValue
|
||||
}
|
||||
var symbolIsETH: Bool { return symbol == "ETH" }
|
||||
var chainIdHexString: String { String.hex(chainId, withPrefix: true) }
|
||||
var isEthMainnet: Bool { return chainId == EthereumNetwork.ethMainnetChainId }
|
||||
|
||||
var hexStringId: String {
|
||||
return String.hex(id, withPrefix: true)
|
||||
}
|
||||
|
||||
static func withChainId(_ chainId: String?) -> EthereumNetwork? {
|
||||
guard let chainId = chainId else { return nil }
|
||||
if let rawValue = Int(hexString: chainId) {
|
||||
return EthereumNetwork(rawValue: rawValue)
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
static let allMainnets: [EthereumNetwork] = [.ethereum, .zora, .base, .klaytn, .polygon, .optimism, .binance, .arbitrum, .avalanche, .gnosisChain, .fantomOpera, .celo, .aurora, .neon, .scroll]
|
||||
static let allTestnets: [EthereumNetwork] = [.ethereumGoerli, .optimisticKovan, .arbitrumKovan, .arbitrumRinkeby, .polygonMumbai, .binanceTestnet, .avalancheFuji, .fantomTestnet, .neonDevnet, .fantomSonicOpen, .scrollSepolia]
|
||||
|
||||
var name: String {
|
||||
switch self {
|
||||
case .ethereum: return "Ethereum"
|
||||
case .zora: return "Zora"
|
||||
case .klaytn: return "Klaytn"
|
||||
case .base: return "Base"
|
||||
case .arbitrum: return "Arbitrum"
|
||||
case .optimism: return "Optimism"
|
||||
case .polygon: return "Polygon"
|
||||
case .binance: return "BNB Smart Chain"
|
||||
case .avalanche: return "Avalanche"
|
||||
case .gnosisChain: return "Gnosis Chain"
|
||||
case .fantomOpera: return "Fantom Opera"
|
||||
case .celo: return "Celo"
|
||||
case .aurora: return "Aurora"
|
||||
case .neon: return "Neon"
|
||||
case .scroll: return "Scroll"
|
||||
|
||||
case .arbitrumRinkeby: return "Arbitrum Rinkeby"
|
||||
case .optimisticKovan: return "Optimistic Kovan"
|
||||
case .ethereumGoerli: return "Ethereum Görli"
|
||||
case .polygonMumbai: return "Polygon Mumbai"
|
||||
case .arbitrumKovan: return "Arbitrum Kovan"
|
||||
case .binanceTestnet: return "BNB Testnet"
|
||||
case .avalancheFuji: return "Avalanche FUJI"
|
||||
case .fantomTestnet: return "Fantom Testnet"
|
||||
case .neonDevnet: return "Neon Devnet"
|
||||
case .fantomSonicOpen: return "Fantom Sonic Open"
|
||||
case .scrollSepolia: return "Scroll Sepolia"
|
||||
}
|
||||
}
|
||||
|
||||
var symbol: String {
|
||||
switch self {
|
||||
case .binance, .binanceTestnet:
|
||||
return "BNB"
|
||||
case .polygon, .polygonMumbai:
|
||||
return "MATIC"
|
||||
case .arbitrum, .arbitrumKovan, .arbitrumRinkeby, .ethereum, .ethereumGoerli, .optimism, .optimisticKovan, .aurora, .zora, .base, .scroll, .scrollSepolia:
|
||||
return "ETH"
|
||||
case .avalanche, .avalancheFuji:
|
||||
return "AVAX"
|
||||
case .gnosisChain:
|
||||
return "xDai"
|
||||
case .fantomOpera, .fantomTestnet, .fantomSonicOpen:
|
||||
return "FTM"
|
||||
case .celo:
|
||||
return "CELO"
|
||||
case .neonDevnet, .neon:
|
||||
return "NEON"
|
||||
case .klaytn:
|
||||
return "KLAY"
|
||||
}
|
||||
}
|
||||
|
||||
var symbolIsETH: Bool {
|
||||
return symbol == "ETH"
|
||||
}
|
||||
|
||||
var hasUSDPrice: Bool {
|
||||
switch self {
|
||||
case .ethereum, .arbitrum, .klaytn, .polygon, .optimism, .binance, .avalanche, .gnosisChain, .fantomOpera, .celo, .aurora, .neon, .base, .zora, .scroll:
|
||||
return symbolIsETH
|
||||
case .fantomTestnet, .neonDevnet, .avalancheFuji, .binanceTestnet, .polygonMumbai, .ethereumGoerli, .optimisticKovan, .arbitrumKovan, .arbitrumRinkeby, .fantomSonicOpen, .scrollSepolia:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var nodeURLString: String {
|
||||
switch self {
|
||||
case .ethereum: return "https://mainnet.infura.io/v3/" + infuraKey
|
||||
case .arbitrum: return "https://arbitrum-mainnet.infura.io/v3/" + infuraKey
|
||||
case .optimism: return "https://optimism-mainnet.infura.io/v3/" + infuraKey
|
||||
case .polygon: return "https://polygon-mainnet.infura.io/v3/" + infuraKey
|
||||
case .binance: return "https://bsc-dataseed.binance.org/"
|
||||
case .avalanche: return "https://api.avax.network/ext/bc/C/rpc"
|
||||
case .gnosisChain: return "https://rpc.gnosischain.com/"
|
||||
case .fantomOpera: return "https://rpc.ftm.tools/"
|
||||
case .celo: return "https://rpc.ankr.com/celo"
|
||||
case .aurora: return "https://mainnet.aurora.dev"
|
||||
case .neon: return "https://neon-proxy-mainnet.solana.p2p.org/"
|
||||
case .zora: return "https://rpc.zora.energy"
|
||||
case .base: return "https://mainnet.base.org"
|
||||
case .klaytn: return "https://1rpc.io/klay"
|
||||
case .scroll: return "https://rpc.scroll.io"
|
||||
|
||||
case .arbitrumRinkeby: return "https://rinkeby.arbitrum.io/rpc"
|
||||
case .arbitrumKovan: return "https://kovan5.arbitrum.io/rpc"
|
||||
case .optimisticKovan: return "https://kovan.optimism.io"
|
||||
case .ethereumGoerli: return "https://rpc.ankr.com/eth_goerli"
|
||||
case .binanceTestnet: return "https://data-seed-prebsc-1-s1.binance.org:8545/"
|
||||
case .avalancheFuji: return "https://api.avax-test.network/ext/bc/C/rpc"
|
||||
case .polygonMumbai: return "https://rpc.ankr.com/polygon_mumbai"
|
||||
case .fantomTestnet: return "https://rpc.testnet.fantom.network/"
|
||||
case .neonDevnet: return "https://devnet.neonevm.org/"
|
||||
case .fantomSonicOpen: return "https://rpcapi.sonic.fantom.network/"
|
||||
case .scrollSepolia: return "https://sepolia-rpc.scroll.io"
|
||||
}
|
||||
}
|
||||
static let ethMainnetChainId = 1
|
||||
|
||||
}
|
||||
|
54
Shared/Ethereum/Networks.swift
Normal file
54
Shared/Ethereum/Networks.swift
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
struct Networks {
|
||||
|
||||
static var ethereum: EthereumNetwork {
|
||||
return withChainId(EthereumNetwork.ethMainnetChainId)!
|
||||
}
|
||||
|
||||
static func withChainId(_ chainId: Int?) -> EthereumNetwork? {
|
||||
guard let chainId = chainId else { return nil }
|
||||
return allBundledDict[chainId]
|
||||
}
|
||||
|
||||
static func withChainIdHex(_ chainIdHex: String?) -> EthereumNetwork? {
|
||||
guard let chainIdHex = chainIdHex, let id = Int(hexString: chainIdHex) else { return nil }
|
||||
return allBundledDict[id]
|
||||
}
|
||||
|
||||
static let allMainnets: [EthereumNetwork] = {
|
||||
return allBundled.filter { !$0.isTestnet }
|
||||
}()
|
||||
|
||||
static let allTestnets: [EthereumNetwork] = {
|
||||
return allBundled.filter { $0.isTestnet }
|
||||
}()
|
||||
|
||||
private static let allBundled: [EthereumNetwork] = {
|
||||
return Array(allBundledDict.values.sorted(by: { $0.name < $1.name }))
|
||||
}()
|
||||
|
||||
private static let allBundledDict: [Int: EthereumNetwork] = {
|
||||
if let url = Bundle.main.url(forResource: "bundled-networks", withExtension: "json"),
|
||||
let data = try? Data(contentsOf: url),
|
||||
let bundledNetworks = try? JSONDecoder().decode([Int: BundledNetwork].self, from: data) {
|
||||
let mapped = bundledNetworks.compactMap { (key, value) -> (Int, EthereumNetwork)? in
|
||||
guard let node = Nodes.getNode(chainId: key) else { return nil }
|
||||
let network = EthereumNetwork(chainId: key,
|
||||
name: value.name,
|
||||
symbol: value.symbol,
|
||||
nodeURLString: node,
|
||||
isTestnet: value.isTest,
|
||||
mightShowPrice: value.okToShowPriceForSymbol)
|
||||
return (key, network)
|
||||
}
|
||||
let dict = [Int: EthereumNetwork](uniqueKeysWithValues: mapped)
|
||||
return dict
|
||||
} else {
|
||||
return [:]
|
||||
}
|
||||
}()
|
||||
|
||||
}
|
20
Shared/Ethereum/Nodes.swift
Normal file
20
Shared/Ethereum/Nodes.swift
Normal file
@ -0,0 +1,20 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
struct Nodes {
|
||||
|
||||
static func getNode(chainId: Int) -> String? {
|
||||
if let domain = BundledNodes.dict[chainId] {
|
||||
let https = "https://" + domain
|
||||
if domain.hasSuffix(".infura.io/v3/") {
|
||||
return https + infuraKey
|
||||
} else {
|
||||
return https
|
||||
}
|
||||
} else {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,12 +21,12 @@ struct Transaction {
|
||||
return value.gweiUInt
|
||||
}
|
||||
|
||||
func description(chain: EthereumNetwork, ethPrice: Double?) -> String {
|
||||
func description(chain: EthereumNetwork, price: Double?) -> String {
|
||||
var result = ["🌐 " + chain.name]
|
||||
if let value = valueWithSymbol(chain: chain, ethPrice: ethPrice, withLabel: false) {
|
||||
if let value = valueWithSymbol(chain: chain, price: price, withLabel: false) {
|
||||
result.append(value)
|
||||
}
|
||||
result.append(feeWithSymbol(chain: chain, ethPrice: ethPrice))
|
||||
result.append(feeWithSymbol(chain: chain, price: price))
|
||||
result.append(dataWithLabel)
|
||||
|
||||
return result.joined(separator: "\n\n")
|
||||
@ -54,13 +54,13 @@ struct Transaction {
|
||||
return "Gas price: " + gwei
|
||||
}
|
||||
|
||||
func feeWithSymbol(chain: EthereumNetwork, ethPrice: Double?) -> String {
|
||||
func feeWithSymbol(chain: EthereumNetwork, price: Double?) -> String {
|
||||
let feeString: String
|
||||
if let gasPriceString = gasPrice, let gasString = gas,
|
||||
let gasPrice = BigInt(hexString: gasPriceString),
|
||||
let gas = BigInt(hexString: gasString) {
|
||||
let fee = gas * gasPrice
|
||||
let costString = chain.hasUSDPrice ? cost(value: fee, price: ethPrice) : ""
|
||||
let costString = chain.mightShowPrice ? cost(value: fee, price: price) : ""
|
||||
feeString = fee.eth.prefix(8) + " \(chain.symbol)" + costString
|
||||
} else {
|
||||
feeString = Strings.calculating
|
||||
@ -68,9 +68,9 @@ struct Transaction {
|
||||
return "Fee: " + feeString
|
||||
}
|
||||
|
||||
func valueWithSymbol(chain: EthereumNetwork, ethPrice: Double?, withLabel: Bool) -> String? {
|
||||
func valueWithSymbol(chain: EthereumNetwork, price: Double?, withLabel: Bool) -> String? {
|
||||
guard let value = value, let value = BigInt(hexString: value) else { return nil }
|
||||
let costString = chain.hasUSDPrice ? cost(value: value, price: ethPrice) : ""
|
||||
let costString = chain.mightShowPrice ? cost(value: value, price: price) : ""
|
||||
let valueString = "\(value.eth) \(chain.symbol)" + costString
|
||||
return withLabel ? "Value: " + valueString : valueString
|
||||
}
|
||||
|
@ -27,7 +27,8 @@ struct DappRequestProcessor {
|
||||
guard let coin = CoinType.correspondingToInpageProvider(configuration.provider) else { return nil }
|
||||
return walletsManager.getSpecificAccount(coin: coin, address: configuration.address)
|
||||
}
|
||||
let network = body.providerConfigurations.compactMap { $0.network }.first
|
||||
let chainId = body.providerConfigurations.compactMap { $0.chainId }.first
|
||||
let network = Networks.withChainIdHex(chainId)
|
||||
let initiallyConnectedProviders = Set(body.providerConfigurations.map { $0.provider })
|
||||
let action = SelectAccountAction(peer: request.peerMeta,
|
||||
coinType: nil,
|
||||
@ -41,7 +42,9 @@ struct DappRequestProcessor {
|
||||
let account = specificWalletAccount.account
|
||||
switch account.coin {
|
||||
case .ethereum:
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [account.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString)
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [account.address],
|
||||
chainId: chain.chainIdHexString,
|
||||
rpcURL: chain.nodeURLString)
|
||||
specificProviderBodies.append(.ethereum(responseBody))
|
||||
default:
|
||||
fatalError("Can't select that coin")
|
||||
@ -82,7 +85,7 @@ struct DappRequestProcessor {
|
||||
network: nil,
|
||||
source: .safariExtension) { chain, specificWalletAccounts in
|
||||
if let chain = chain, let specificWalletAccount = specificWalletAccounts?.first, specificWalletAccount.account.coin == .ethereum {
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [specificWalletAccount.account.address], chainId: chain.hexStringId, rpcURL: chain.nodeURLString)
|
||||
let responseBody = ResponseToExtension.Ethereum(results: [specificWalletAccount.account.address], chainId: chain.chainIdHexString, rpcURL: chain.nodeURLString)
|
||||
respond(to: request, body: .ethereum(responseBody), completion: completion)
|
||||
} else {
|
||||
respond(to: request, error: Strings.canceled, completion: completion)
|
||||
@ -137,7 +140,8 @@ struct DappRequestProcessor {
|
||||
}
|
||||
case .signTransaction:
|
||||
if let transaction = ethereumRequest.transaction,
|
||||
let chain = ethereumRequest.chain,
|
||||
let chainId = ethereumRequest.currentChainId,
|
||||
let chain = Networks.withChainId(chainId),
|
||||
let account = account,
|
||||
let privateKey = privateKey {
|
||||
let action = SendTransactionAction(provider: request.provider,
|
||||
|
@ -4,8 +4,22 @@ import Foundation
|
||||
|
||||
class PriceService {
|
||||
|
||||
private struct PriceResponse: Codable {
|
||||
let ethereum: Price
|
||||
private struct Prices: Codable {
|
||||
|
||||
let eth: Price?
|
||||
let bnb: Price?
|
||||
let matic: Price?
|
||||
let ftm: Price?
|
||||
let avax: Price?
|
||||
|
||||
enum CodingKeys: String, CodingKey, CaseIterable {
|
||||
case eth = "ethereum"
|
||||
case bnb = "binancecoin"
|
||||
case matic = "matic-network"
|
||||
case ftm = "fantom"
|
||||
case avax = "avalanche-2"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private struct Price: Codable {
|
||||
@ -15,10 +29,14 @@ class PriceService {
|
||||
static let shared = PriceService()
|
||||
private let jsonDecoder = JSONDecoder()
|
||||
private let urlSession = URLSession(configuration: .ephemeral)
|
||||
private let idsQuery: String = {
|
||||
let ids = Prices.CodingKeys.allCases.map { $0.rawValue }
|
||||
return ids.joined(separator: "%2C")
|
||||
}()
|
||||
|
||||
private init() {}
|
||||
|
||||
var currentPrice: Double?
|
||||
private var currentPrices: Prices?
|
||||
|
||||
func start() {
|
||||
getPrice(scheduleNextRequest: true)
|
||||
@ -28,13 +46,31 @@ class PriceService {
|
||||
getPrice(scheduleNextRequest: false)
|
||||
}
|
||||
|
||||
func forNetwork(_ network: EthereumNetwork) -> Double? {
|
||||
guard network.mightShowPrice else { return nil }
|
||||
switch network.symbol {
|
||||
case "ETH":
|
||||
return currentPrices?.eth?.usd
|
||||
case "BNB":
|
||||
return currentPrices?.bnb?.usd
|
||||
case "FTM":
|
||||
return currentPrices?.ftm?.usd
|
||||
case "MATIC":
|
||||
return currentPrices?.matic?.usd
|
||||
case "AVAX":
|
||||
return currentPrices?.avax?.usd
|
||||
default:
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
private func getPrice(scheduleNextRequest: Bool) {
|
||||
let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=ethereum&vs_currencies=usd")!
|
||||
let url = URL(string: "https://api.coingecko.com/api/v3/simple/price?ids=\(idsQuery)&vs_currencies=usd")!
|
||||
let dataTask = urlSession.dataTask(with: url) { [weak self] (data, _, _) in
|
||||
if let data = data,
|
||||
let priceResponse = try? self?.jsonDecoder.decode(PriceResponse.self, from: data) {
|
||||
let pricesResponse = try? self?.jsonDecoder.decode(Prices.self, from: data) {
|
||||
DispatchQueue.main.async {
|
||||
self?.currentPrice = priceResponse.ethereum.usd
|
||||
self?.currentPrices = pricesResponse
|
||||
}
|
||||
}
|
||||
if scheduleNextRequest {
|
||||
|
96
Shared/Views/NetworksListView.swift
Normal file
96
Shared/Views/NetworksListView.swift
Normal file
@ -0,0 +1,96 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct NetworksListView: View {
|
||||
@State private var searchText: String = ""
|
||||
let items: [String] = Networks.all().map { $0.name }
|
||||
|
||||
@Environment(\.presentationMode) var presentationMode
|
||||
|
||||
var filteredItems: [String] {
|
||||
items.filter { $0.contains(searchText) || searchText.isEmpty }
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
SearchBar(text: $searchText)
|
||||
List(filteredItems, id: \.self) { item in
|
||||
Text(item)
|
||||
}
|
||||
|
||||
Divider() // Separate the list from the buttons
|
||||
|
||||
HStack {
|
||||
Spacer()
|
||||
Button("Cancel") {
|
||||
self.presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
.padding()
|
||||
|
||||
Button("OK") {
|
||||
self.presentationMode.wrappedValue.dismiss()
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SearchBar: View {
|
||||
@Binding var text: String
|
||||
|
||||
var body: some View {
|
||||
HStack {
|
||||
TextField("Search ...", text: $text)
|
||||
.textFieldStyle(RoundedBorderTextFieldStyle())
|
||||
}.padding()
|
||||
}
|
||||
}
|
||||
|
||||
#if os(iOS)
|
||||
import UIKit
|
||||
|
||||
extension UIViewController {
|
||||
func showPopup() {
|
||||
let contentView = NetworksListView()
|
||||
let hostingController = UIHostingController(rootView: contentView)
|
||||
hostingController.modalPresentationStyle = .fullScreen
|
||||
self.present(hostingController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
#elseif os(macOS)
|
||||
import Cocoa
|
||||
|
||||
var popupWindow: NSWindow? // keep a reference within a NSViewController
|
||||
|
||||
extension NSViewController {
|
||||
|
||||
func showPopup() {
|
||||
let contentView = NetworksListView()
|
||||
|
||||
popupWindow = NSWindow(
|
||||
contentRect: NSRect(x: 0, y: 0, width: 300, height: 400),
|
||||
styleMask: [.closable, .fullSizeContentView, .titled],
|
||||
backing: .buffered, defer: false)
|
||||
popupWindow?.center()
|
||||
popupWindow?.titleVisibility = .hidden
|
||||
popupWindow?.titlebarAppearsTransparent = true
|
||||
popupWindow?.isMovableByWindowBackground = true
|
||||
popupWindow?.backgroundColor = NSColor.windowBackgroundColor
|
||||
popupWindow?.isOpaque = false
|
||||
popupWindow?.hasShadow = true
|
||||
|
||||
popupWindow?.contentView?.wantsLayer = true
|
||||
popupWindow?.contentView?.layer?.cornerRadius = 10
|
||||
popupWindow?.contentView?.layer?.masksToBounds = true
|
||||
|
||||
popupWindow?.isReleasedWhenClosed = false
|
||||
popupWindow?.contentView = NSHostingView(rootView: contentView)
|
||||
popupWindow?.makeKeyAndOrderFront(nil)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
@ -27,7 +27,7 @@ class AccountsListViewController: UIViewController, DataStateContainer {
|
||||
private var sections = [Section]()
|
||||
private let walletsManager = WalletsManager.shared
|
||||
|
||||
private var network = EthereumNetwork.ethereum
|
||||
private var network = Networks.ethereum
|
||||
var selectAccountAction: SelectAccountAction?
|
||||
|
||||
private var wallets: [TokenaryWallet] {
|
||||
@ -302,7 +302,7 @@ class AccountsListViewController: UIViewController, DataStateContainer {
|
||||
|
||||
let actionSheet = UIAlertController(title: Strings.selectNetwork, message: nil, preferredStyle: .actionSheet)
|
||||
actionSheet.popoverPresentationController?.sourceView = networkButton
|
||||
for network in EthereumNetwork.allMainnets {
|
||||
for network in Networks.allMainnets {
|
||||
let prefix = network == self.network ? "✅ " : ""
|
||||
let action = UIAlertAction(title: prefix + network.name, style: .default) { [weak self] _ in
|
||||
self?.selectNetwork(network)
|
||||
@ -321,7 +321,7 @@ class AccountsListViewController: UIViewController, DataStateContainer {
|
||||
private func showTestnets() {
|
||||
let actionSheet = UIAlertController(title: Strings.selectTestnet, message: nil, preferredStyle: .actionSheet)
|
||||
actionSheet.popoverPresentationController?.sourceView = networkButton
|
||||
for network in EthereumNetwork.allTestnets {
|
||||
for network in Networks.allTestnets {
|
||||
let prefix = network == self.network ? "✅ " : ""
|
||||
let action = UIAlertAction(title: prefix + network.name, style: .default) { [weak self] _ in
|
||||
self?.selectNetwork(network)
|
||||
|
@ -59,7 +59,7 @@ class ApproveTransactionViewController: UIViewController {
|
||||
navigationItem.largeTitleDisplayMode = .always
|
||||
isModalInPresentation = true
|
||||
|
||||
if chain == .ethereum {
|
||||
if chain.isEthMainnet {
|
||||
sectionModels = [[], [.gasPriceSlider]]
|
||||
} else {
|
||||
sectionModels = [[]]
|
||||
@ -85,10 +85,11 @@ class ApproveTransactionViewController: UIViewController {
|
||||
.textWithImage(text: chain.name, imageURL: nil, image: Images.network)
|
||||
]
|
||||
|
||||
if let value = transaction.valueWithSymbol(chain: chain, ethPrice: priceService.currentPrice, withLabel: true) {
|
||||
let price = priceService.forNetwork(chain)
|
||||
if let value = transaction.valueWithSymbol(chain: chain, price: price, withLabel: true) {
|
||||
cellModels.append(.text(text: value, oneLine: false))
|
||||
}
|
||||
cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, ethPrice: priceService.currentPrice), oneLine: false))
|
||||
cellModels.append(.text(text: transaction.feeWithSymbol(chain: chain, price: price), oneLine: false))
|
||||
cellModels.append(.text(text: transaction.gasPriceWithLabel(chain: chain), oneLine: false))
|
||||
if let data = transaction.nonEmptyDataWithLabel {
|
||||
cellModels.append(.text(text: data, oneLine: true))
|
||||
|
@ -127,7 +127,7 @@ class AccountsListViewController: NSViewController {
|
||||
private func callCompletion(specificWalletAccounts: [SpecificWalletAccount]?) {
|
||||
if !didCallCompletion {
|
||||
didCallCompletion = true
|
||||
let network = selectAccountAction?.network ?? .ethereum
|
||||
let network = selectAccountAction?.network ?? Networks.ethereum
|
||||
selectAccountAction?.completion(network, specificWalletAccounts)
|
||||
}
|
||||
}
|
||||
@ -147,18 +147,18 @@ class AccountsListViewController: NSViewController {
|
||||
networkButton.isHidden = true
|
||||
} else if networkButton.menu == nil {
|
||||
let menu = NSMenu()
|
||||
for mainnet in EthereumNetwork.allMainnets {
|
||||
for mainnet in Networks.allMainnets {
|
||||
let item = NSMenuItem(title: mainnet.name, action: #selector(didSelectChain(_:)), keyEquivalent: "")
|
||||
item.tag = mainnet.id
|
||||
item.tag = mainnet.chainId
|
||||
menu.addItem(item)
|
||||
}
|
||||
|
||||
let submenuItem = NSMenuItem()
|
||||
submenuItem.title = Strings.testnets
|
||||
let submenu = NSMenu()
|
||||
for testnet in EthereumNetwork.allTestnets {
|
||||
for testnet in Networks.allTestnets {
|
||||
let item = NSMenuItem(title: testnet.name, action: #selector(didSelectChain(_:)), keyEquivalent: "")
|
||||
item.tag = testnet.id
|
||||
item.tag = testnet.chainId
|
||||
submenu.addItem(item)
|
||||
}
|
||||
|
||||
@ -171,7 +171,7 @@ class AccountsListViewController: NSViewController {
|
||||
let titleItem = NSMenuItem(title: Strings.selectNetworkOptionally, action: nil, keyEquivalent: "")
|
||||
menu.addItem(titleItem)
|
||||
|
||||
if let network = selectAccountAction.network, network != .ethereum {
|
||||
if let network = selectAccountAction.network, !network.isEthMainnet {
|
||||
selectNetwork(network)
|
||||
}
|
||||
}
|
||||
@ -259,7 +259,7 @@ class AccountsListViewController: NSViewController {
|
||||
|
||||
@objc private func didSelectChain(_ sender: AnyObject) {
|
||||
guard let menuItem = sender as? NSMenuItem,
|
||||
let selectedNetwork = EthereumNetwork(rawValue: menuItem.tag) else { return }
|
||||
let selectedNetwork = Networks.withChainId(menuItem.tag) else { return }
|
||||
selectNetwork(selectedNetwork)
|
||||
}
|
||||
|
||||
|
@ -85,7 +85,7 @@ class ApproveTransactionViewController: NSViewController {
|
||||
}
|
||||
|
||||
private func updateInterface() {
|
||||
if chain != .ethereum {
|
||||
if !chain.isEthMainnet {
|
||||
speedContainerStackView.isHidden = true
|
||||
gweiLabel.isHidden = true
|
||||
infoTextViewBottomConstraint.constant = 30
|
||||
@ -94,7 +94,7 @@ class ApproveTransactionViewController: NSViewController {
|
||||
okButton.isEnabled = transaction.hasFee
|
||||
|
||||
enableSpeedConfigurationIfNeeded()
|
||||
let meta = transaction.description(chain: chain, ethPrice: priceService.currentPrice)
|
||||
let meta = transaction.description(chain: chain, price: priceService.forNetwork(chain))
|
||||
if metaTextView.string != meta {
|
||||
metaTextView.string = meta
|
||||
}
|
||||
|
@ -140,6 +140,9 @@
|
||||
2C96D3A62763CCA000687301 /* Images.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A52763CCA000687301 /* Images.swift */; };
|
||||
2C96D3A92763D13400687301 /* DataStateView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C96D3A72763D13400687301 /* DataStateView.swift */; };
|
||||
2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 2C96D3A82763D13400687301 /* DataStateView.xib */; };
|
||||
2C9B55D12AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; };
|
||||
2C9B55D22AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; };
|
||||
2C9B55D32AF2AE4B008BE899 /* BundledNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */; };
|
||||
2C9F0B6826BDCB2E008FA3D6 /* EthereumNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */; };
|
||||
2CAA412526C7CD93009F3535 /* ReviewRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CAA412426C7CD93009F3535 /* ReviewRequester.swift */; };
|
||||
2CB3845A27654EA900A189B9 /* _locales in Resources */ = {isa = PBXBuildFile; fileRef = 2CB3845827654E9700A189B9 /* _locales */; };
|
||||
@ -180,6 +183,21 @@
|
||||
2CE0594527640EF10042D844 /* ResponseToExtension.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C773F61274523DC007B04E7 /* ResponseToExtension.swift */; };
|
||||
2CE0594627640F470042D844 /* UserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC89470269A334A00879245 /* UserDefaults.swift */; };
|
||||
2CE3D012267F73C00032A62E /* Transaction.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CE3D011267F73C00032A62E /* Transaction.swift */; };
|
||||
2CED86A52AF00BC9006F9E26 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86A42AF00BC9006F9E26 /* main.swift */; };
|
||||
2CED86B02AF0167F006F9E26 /* EIP155ChainData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */; };
|
||||
2CED86B32AF01F99006F9E26 /* String.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C603D0126B6E13F00956955 /* String.swift */; };
|
||||
2CED86B62AF17D5A006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; };
|
||||
2CED86B72AF17D5A006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; };
|
||||
2CED86BA2AF1820E006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; };
|
||||
2CED86BB2AF1820E006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; };
|
||||
2CED86BF2AF25C32006F9E26 /* Networks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86BE2AF25C32006F9E26 /* Networks.swift */; };
|
||||
2CED86C02AF25C32006F9E26 /* Networks.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86BE2AF25C32006F9E26 /* Networks.swift */; };
|
||||
2CED86C12AF26114006F9E26 /* bundled-networks.json in Resources */ = {isa = PBXBuildFile; fileRef = 2CED86A92AF00F56006F9E26 /* bundled-networks.json */; };
|
||||
2CED86C22AF2611D006F9E26 /* bundled-networks.json in Resources */ = {isa = PBXBuildFile; fileRef = 2CED86A92AF00F56006F9E26 /* bundled-networks.json */; };
|
||||
2CED86C32AF262E6006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; };
|
||||
2CED86C42AF262E7006F9E26 /* Nodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B92AF1820E006F9E26 /* Nodes.swift */; };
|
||||
2CED86C52AF26327006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; };
|
||||
2CED86C62AF26328006F9E26 /* BundledNodes.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */; };
|
||||
2CEFEB16274D5DCA00CE23BD /* inpage.js in Resources */ = {isa = PBXBuildFile; fileRef = 2CEFEB15274D5DC900CE23BD /* inpage.js */; };
|
||||
2CF25597275A46D300AE54B9 /* Defaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C528A15267FA8EB00CA3ADD /* Defaults.swift */; };
|
||||
2CF25598275A46D600AE54B9 /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C901C492689F01700D0926A /* Strings.swift */; };
|
||||
@ -355,6 +373,9 @@
|
||||
2C96D3A52763CCA000687301 /* Images.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Images.swift; sourceTree = "<group>"; };
|
||||
2C96D3A72763D13400687301 /* DataStateView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DataStateView.swift; sourceTree = "<group>"; };
|
||||
2C96D3A82763D13400687301 /* DataStateView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DataStateView.xib; sourceTree = "<group>"; };
|
||||
2C9931DB2AEEC0E200577C8A /* NetworksListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NetworksListView.swift; sourceTree = "<group>"; };
|
||||
2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundledNetwork.swift; sourceTree = "<group>"; };
|
||||
2C9B55D42AF2B004008BE899 /* nodes-to-bundle.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "nodes-to-bundle.json"; sourceTree = "<group>"; };
|
||||
2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNetwork.swift; sourceTree = "<group>"; };
|
||||
2CAA412426C7CD93009F3535 /* ReviewRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReviewRequester.swift; sourceTree = "<group>"; };
|
||||
2CB3844327654BF600A189B9 /* error.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; name = error.js; path = "web3-provider/error.js"; sourceTree = "<group>"; };
|
||||
@ -389,6 +410,13 @@
|
||||
2CE059482764169E0042D844 /* Tokenary iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Tokenary iOS.entitlements"; sourceTree = "<group>"; };
|
||||
2CE0594B2764DF9A0042D844 /* Safari iOS.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "Safari iOS.entitlements"; sourceTree = "<group>"; };
|
||||
2CE3D011267F73C00032A62E /* Transaction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Transaction.swift; sourceTree = "<group>"; };
|
||||
2CED86A22AF00BC9006F9E26 /* tools */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = tools; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2CED86A42AF00BC9006F9E26 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = "<group>"; };
|
||||
2CED86A92AF00F56006F9E26 /* bundled-networks.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "bundled-networks.json"; sourceTree = "<group>"; };
|
||||
2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EIP155ChainData.swift; sourceTree = "<group>"; };
|
||||
2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BundledNodes.swift; sourceTree = "<group>"; };
|
||||
2CED86B92AF1820E006F9E26 /* Nodes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Nodes.swift; sourceTree = "<group>"; };
|
||||
2CED86BE2AF25C32006F9E26 /* Networks.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Networks.swift; sourceTree = "<group>"; };
|
||||
2CEFEB15274D5DC900CE23BD /* inpage.js */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.javascript; path = inpage.js; sourceTree = "<group>"; };
|
||||
2CF255B3275A744000AE54B9 /* PasswordViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PasswordViewController.swift; sourceTree = "<group>"; };
|
||||
2CF255B5275A746000AE54B9 /* AccountsListViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountsListViewController.swift; sourceTree = "<group>"; };
|
||||
@ -435,6 +463,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2CED869F2AF00BC9006F9E26 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
@ -483,6 +518,7 @@
|
||||
2CCEB7A227592A3800768473 /* Safari Shared */,
|
||||
2C09CBA0273979C1009AD39B /* Safari macOS */,
|
||||
2CCEB82E27594E2A00768473 /* Safari iOS */,
|
||||
2CED86A32AF00BC9006F9E26 /* tools */,
|
||||
2C19953D2674C4B900A8E370 /* Products */,
|
||||
FB5786212D81829B0FADBD25 /* Pods */,
|
||||
2A7484A18D772B4233D171DA /* Frameworks */,
|
||||
@ -496,6 +532,7 @@
|
||||
2C5FF96F26C84F7B00B32ACC /* Tokenary iOS.app */,
|
||||
2C09CB9F273979C1009AD39B /* Safari macOS.appex */,
|
||||
2CCEB82D27594E2A00768473 /* Safari iOS.appex */,
|
||||
2CED86A22AF00BC9006F9E26 /* tools */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@ -627,9 +664,11 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2C1995552674D0F300A8E370 /* Ethereum.swift */,
|
||||
2CE3D011267F73C00032A62E /* Transaction.swift */,
|
||||
2C8944CA2AEB0C10006A711F /* EthereumRPC.swift */,
|
||||
2C9F0B6726BDCB2E008FA3D6 /* EthereumNetwork.swift */,
|
||||
2CE3D011267F73C00032A62E /* Transaction.swift */,
|
||||
2CED86BE2AF25C32006F9E26 /* Networks.swift */,
|
||||
2CED86B92AF1820E006F9E26 /* Nodes.swift */,
|
||||
);
|
||||
path = Ethereum;
|
||||
sourceTree = "<group>";
|
||||
@ -705,6 +744,14 @@
|
||||
path = Library;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2C9B55D52AF2B8D5008BE899 /* helpers */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2C9B55D42AF2B004008BE899 /* nodes-to-bundle.json */,
|
||||
);
|
||||
path = helpers;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CB3844027654A0D00A189B9 /* Resources */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -755,6 +802,7 @@
|
||||
2CF255A4275A483600AE54B9 /* Services */,
|
||||
2CF2559F275A47B600AE54B9 /* Extension */,
|
||||
2CD0668826B213BB00728C20 /* Wallets */,
|
||||
2CED86B12AF01DFD006F9E26 /* Views */,
|
||||
2CF25596275A468B00AE54B9 /* Models */,
|
||||
2C8944D02AEC34F2006A711F /* Utilities */,
|
||||
2CF255AF275A490600AE54B9 /* Supporting Files */,
|
||||
@ -808,6 +856,43 @@
|
||||
path = Wallets;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CED86A32AF00BC9006F9E26 /* tools */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2CED86A42AF00BC9006F9E26 /* main.swift */,
|
||||
2CED86B42AF17BF0006F9E26 /* bundled */,
|
||||
2CED86BD2AF225A4006F9E26 /* models */,
|
||||
2C9B55D52AF2B8D5008BE899 /* helpers */,
|
||||
);
|
||||
path = tools;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CED86B12AF01DFD006F9E26 /* Views */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2C9931DB2AEEC0E200577C8A /* NetworksListView.swift */,
|
||||
);
|
||||
path = Views;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CED86B42AF17BF0006F9E26 /* bundled */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2CED86A92AF00F56006F9E26 /* bundled-networks.json */,
|
||||
2CED86B52AF17D5A006F9E26 /* BundledNodes.swift */,
|
||||
);
|
||||
path = bundled;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CED86BD2AF225A4006F9E26 /* models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2CED86AF2AF0167F006F9E26 /* EIP155ChainData.swift */,
|
||||
2C9B55D02AF2AE4B008BE899 /* BundledNetwork.swift */,
|
||||
);
|
||||
path = models;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
2CF25596275A468B00AE54B9 /* Models */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@ -962,13 +1047,29 @@
|
||||
productReference = 2CCEB82D27594E2A00768473 /* Safari iOS.appex */;
|
||||
productType = "com.apple.product-type.app-extension";
|
||||
};
|
||||
2CED86A12AF00BC9006F9E26 /* tools */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 2CED86A82AF00BC9006F9E26 /* Build configuration list for PBXNativeTarget "tools" */;
|
||||
buildPhases = (
|
||||
2CED869E2AF00BC9006F9E26 /* Sources */,
|
||||
2CED869F2AF00BC9006F9E26 /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = tools;
|
||||
productName = tools;
|
||||
productReference = 2CED86A22AF00BC9006F9E26 /* tools */;
|
||||
productType = "com.apple.product-type.tool";
|
||||
};
|
||||
/* End PBXNativeTarget section */
|
||||
|
||||
/* Begin PBXProject section */
|
||||
2C1995342674C4B900A8E370 /* Project object */ = {
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
LastSwiftUpdateCheck = 1310;
|
||||
LastSwiftUpdateCheck = 1500;
|
||||
LastUpgradeCheck = 1240;
|
||||
TargetAttributes = {
|
||||
2C09CB9E273979C1009AD39B = {
|
||||
@ -983,6 +1084,9 @@
|
||||
2CCEB82C27594E2A00768473 = {
|
||||
CreatedOnToolsVersion = 13.1;
|
||||
};
|
||||
2CED86A12AF00BC9006F9E26 = {
|
||||
CreatedOnToolsVersion = 15.0.1;
|
||||
};
|
||||
};
|
||||
};
|
||||
buildConfigurationList = 2C1995372674C4B900A8E370 /* Build configuration list for PBXProject "Tokenary" */;
|
||||
@ -1002,6 +1106,7 @@
|
||||
2C5FF96E26C84F7B00B32ACC /* Tokenary iOS */,
|
||||
2C09CB9E273979C1009AD39B /* Safari macOS */,
|
||||
2CCEB82C27594E2A00768473 /* Safari iOS */,
|
||||
2CED86A12AF00BC9006F9E26 /* tools */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@ -1025,6 +1130,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2CED86C12AF26114006F9E26 /* bundled-networks.json in Resources */,
|
||||
2C6B964F26B9D98C00D2C819 /* Colors.xcassets in Resources */,
|
||||
2C1995442674C4BA00A8E370 /* Assets.xcassets in Resources */,
|
||||
2C1995472674C4BA00A8E370 /* Main.storyboard in Resources */,
|
||||
@ -1036,6 +1142,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2CED86C22AF2611D006F9E26 /* bundled-networks.json in Resources */,
|
||||
2C96D3AA2763D13400687301 /* DataStateView.xib in Resources */,
|
||||
2C5FF97E26C84F7C00B32ACC /* LaunchScreen.storyboard in Resources */,
|
||||
2C40709527667A8600AB3D55 /* ImageWithLabelTableViewCell.xib in Resources */,
|
||||
@ -1202,11 +1309,13 @@
|
||||
2C2AA1D728AFB1AD00E35DBF /* MultipleResponseToExtension.swift in Sources */,
|
||||
2C773F5E27450B97007B04E7 /* ExtensionBridge.swift in Sources */,
|
||||
2C264BDE27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */,
|
||||
2CED86BA2AF1820E006F9E26 /* Nodes.swift in Sources */,
|
||||
2CC8C5AC276A7EF70083FB1B /* EthereumNetwork.swift in Sources */,
|
||||
2C264BC327B2F2C100234393 /* EthereumSafariRequest.swift in Sources */,
|
||||
2C264BBE27B2F25E00234393 /* SafariRequest.swift in Sources */,
|
||||
2C09CBA2273979C1009AD39B /* SafariWebExtensionHandler.swift in Sources */,
|
||||
2C773F63274523DC007B04E7 /* ResponseToExtension.swift in Sources */,
|
||||
2CED86B62AF17D5A006F9E26 /* BundledNodes.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1239,8 +1348,10 @@
|
||||
2C8A09E326757FC000993638 /* AccountCellView.swift in Sources */,
|
||||
2C6B964C26B9D92500D2C819 /* NSColor.swift in Sources */,
|
||||
2C603D0226B6E13F00956955 /* String.swift in Sources */,
|
||||
2CED86C32AF262E6006F9E26 /* Nodes.swift in Sources */,
|
||||
2C264BC127B2F2C100234393 /* EthereumSafariRequest.swift in Sources */,
|
||||
2C264BD027B2F30C00234393 /* UnknownSafariRequest.swift in Sources */,
|
||||
2CED86BF2AF25C32006F9E26 /* Networks.swift in Sources */,
|
||||
2C134BA627553EC500DAFBDB /* Browser.swift in Sources */,
|
||||
2CC89471269A334A00879245 /* UserDefaults.swift in Sources */,
|
||||
2C78F8282683BDCC00C10670 /* Alert.swift in Sources */,
|
||||
@ -1250,6 +1361,7 @@
|
||||
2C4768A9282598C5005E8D4D /* CoinDerivationCellView.swift in Sources */,
|
||||
2CB4031D281D745D00BAEBEE /* NSTableView.swift in Sources */,
|
||||
2CD0B3F726AC619900488D92 /* AddAccountOptionCellView.swift in Sources */,
|
||||
2CED86C52AF26327006F9E26 /* BundledNodes.swift in Sources */,
|
||||
2C8944C52AEAFF97006A711F /* FixedWidthInteger.swift in Sources */,
|
||||
0D059AD226C2796200EE3023 /* ApprovalSubject.swift in Sources */,
|
||||
2C1995422674C4B900A8E370 /* ImportViewController.swift in Sources */,
|
||||
@ -1280,6 +1392,7 @@
|
||||
2C8944CE2AEC34EB006A711F /* Blockies.swift in Sources */,
|
||||
2C8A09DF267579EA00993638 /* AccountsListViewController.swift in Sources */,
|
||||
2C917429267D2A6E00049075 /* Keychain.swift in Sources */,
|
||||
2C9B55D12AF2AE4B008BE899 /* BundledNetwork.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1298,6 +1411,7 @@
|
||||
2C40709027667A6600AB3D55 /* MultilineLabelTableViewCell.swift in Sources */,
|
||||
2CF255A6275A48BB00AE54B9 /* GasService.swift in Sources */,
|
||||
2C96D392276232A300687301 /* UITableView.swift in Sources */,
|
||||
2CED86C62AF26328006F9E26 /* BundledNodes.swift in Sources */,
|
||||
2CF255A5275A48BB00AE54B9 /* ReviewRequester.swift in Sources */,
|
||||
2CF255B6275A746000AE54B9 /* AccountsListViewController.swift in Sources */,
|
||||
2C96D3A42763C6A800687301 /* UIView.swift in Sources */,
|
||||
@ -1313,9 +1427,11 @@
|
||||
2CC6EF0D275E64810040CC62 /* UIViewController.swift in Sources */,
|
||||
2C264BDD27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */,
|
||||
2CF255A9275A48BB00AE54B9 /* Keychain.swift in Sources */,
|
||||
2CED86C42AF262E7006F9E26 /* Nodes.swift in Sources */,
|
||||
2CF255A7275A48BB00AE54B9 /* PriceService.swift in Sources */,
|
||||
2CF25598275A46D600AE54B9 /* Strings.swift in Sources */,
|
||||
2C4768B52826ED83005E8D4D /* CoinType.swift in Sources */,
|
||||
2CED86C02AF25C32006F9E26 /* Networks.swift in Sources */,
|
||||
2CF255AE275A48CF00AE54B9 /* Transaction.swift in Sources */,
|
||||
2C96D38F2762317300687301 /* AccountTableViewCell.swift in Sources */,
|
||||
2C264BEC27B6B50700234393 /* DappRequestProcessor.swift in Sources */,
|
||||
@ -1330,6 +1446,7 @@
|
||||
2C8ED8DD2AEADDC400818D74 /* BigInt.swift in Sources */,
|
||||
2C96D3A62763CCA000687301 /* Images.swift in Sources */,
|
||||
2C264BD127B2F30C00234393 /* UnknownSafariRequest.swift in Sources */,
|
||||
2C9B55D22AF2AE4B008BE899 /* BundledNetwork.swift in Sources */,
|
||||
2C96D39827623EC600687301 /* URL.swift in Sources */,
|
||||
2CF255AD275A48CF00AE54B9 /* EthereumNetwork.swift in Sources */,
|
||||
2CF2559C275A477F00AE54B9 /* ApprovalSubject.swift in Sources */,
|
||||
@ -1372,11 +1489,24 @@
|
||||
2C2AA1D828AFB1AD00E35DBF /* MultipleResponseToExtension.swift in Sources */,
|
||||
2CE0594327640EAB0042D844 /* ExtensionBridge.swift in Sources */,
|
||||
2C264BDF27B5AC5400234393 /* EthereumResponseToExtension.swift in Sources */,
|
||||
2CED86BB2AF1820E006F9E26 /* Nodes.swift in Sources */,
|
||||
2CC8C5AD276A7EF80083FB1B /* EthereumNetwork.swift in Sources */,
|
||||
2C264BC427B2F2C100234393 /* EthereumSafariRequest.swift in Sources */,
|
||||
2C264BBF27B2F25E00234393 /* SafariRequest.swift in Sources */,
|
||||
2CE0593F27640E300042D844 /* SafariWebExtensionHandler.swift in Sources */,
|
||||
2CE0594527640EF10042D844 /* ResponseToExtension.swift in Sources */,
|
||||
2CED86B72AF17D5A006F9E26 /* BundledNodes.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
2CED869E2AF00BC9006F9E26 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2C9B55D32AF2AE4B008BE899 /* BundledNetwork.swift in Sources */,
|
||||
2CED86B02AF0167F006F9E26 /* EIP155ChainData.swift in Sources */,
|
||||
2CED86A52AF00BC9006F9E26 /* main.swift in Sources */,
|
||||
2CED86B32AF01F99006F9E26 /* String.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -1430,7 +1560,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Safari macOS/Safari.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -1443,7 +1573,7 @@
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.4;
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SafariServices,
|
||||
@ -1464,7 +1594,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Safari macOS/Safari.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
@ -1477,7 +1607,7 @@
|
||||
"@executable_path/../../../../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.4;
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SafariServices,
|
||||
@ -1617,7 +1747,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Tokenary macOS/Supporting Files/Info.plist";
|
||||
@ -1626,7 +1756,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.4;
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@ -1645,7 +1775,7 @@
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
COMBINE_HIDPI_IMAGES = YES;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
INFOPLIST_FILE = "$(SRCROOT)/Tokenary macOS/Supporting Files/Info.plist";
|
||||
@ -1654,7 +1784,7 @@
|
||||
"@executable_path/../Frameworks",
|
||||
);
|
||||
MACOSX_DEPLOYMENT_TARGET = 11.4;
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
@ -1671,7 +1801,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "Tokenary iOS/Tokenary iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
INFOPLIST_FILE = "Tokenary iOS/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
@ -1679,7 +1809,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
@ -1700,7 +1830,7 @@
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CODE_SIGN_ENTITLEMENTS = "Tokenary iOS/Tokenary iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
INFOPLIST_FILE = "Tokenary iOS/Info.plist";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
@ -1708,7 +1838,7 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = mac.tokenary.io;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = iphoneos;
|
||||
@ -1727,7 +1857,7 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++17";
|
||||
CODE_SIGN_ENTITLEMENTS = "Safari iOS/Safari iOS.entitlements";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Safari iOS/Info.plist";
|
||||
@ -1739,7 +1869,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SafariServices,
|
||||
@ -1761,7 +1891,7 @@
|
||||
CODE_SIGN_ENTITLEMENTS = "Safari iOS/Safari iOS.entitlements";
|
||||
CODE_SIGN_IDENTITY = "Apple Development";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 63;
|
||||
CURRENT_PROJECT_VERSION = 64;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_FILE = "Safari iOS/Info.plist";
|
||||
@ -1773,7 +1903,7 @@
|
||||
"@executable_path/Frameworks",
|
||||
"@executable_path/../../Frameworks",
|
||||
);
|
||||
MARKETING_VERSION = 2.0.19;
|
||||
MARKETING_VERSION = 2.0.20;
|
||||
OTHER_LDFLAGS = (
|
||||
"-framework",
|
||||
SafariServices,
|
||||
@ -1790,6 +1920,41 @@
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
2CED86A62AF00BC9006F9E26 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
2CED86A72AF00BC9006F9E26 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
DEVELOPMENT_TEAM = XWNXDSM6BU;
|
||||
ENABLE_HARDENED_RUNTIME = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MACOSX_DEPLOYMENT_TARGET = 14.0;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
@ -1838,6 +2003,15 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
2CED86A82AF00BC9006F9E26 /* Build configuration list for PBXNativeTarget "tools" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
2CED86A62AF00BC9006F9E26 /* Debug */,
|
||||
2CED86A72AF00BC9006F9E26 /* Release */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
};
|
||||
rootObject = 2C1995342674C4B900A8E370 /* Project object */;
|
||||
|
79
Tokenary.xcodeproj/xcshareddata/xcschemes/tools.xcscheme
Normal file
79
Tokenary.xcodeproj/xcshareddata/xcschemes/tools.xcscheme
Normal file
@ -0,0 +1,79 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Scheme
|
||||
LastUpgradeVersion = "1500"
|
||||
version = "1.7">
|
||||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2CED86A12AF00BC9006F9E26"
|
||||
BuildableName = "tools"
|
||||
BlueprintName = "tools"
|
||||
ReferencedContainer = "container:Tokenary.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
shouldAutocreateTestPlan = "YES">
|
||||
</TestAction>
|
||||
<LaunchAction
|
||||
buildConfiguration = "Debug"
|
||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||
launchStyle = "0"
|
||||
useCustomWorkingDirectory = "YES"
|
||||
customWorkingDirectory = "$(SRCROOT)"
|
||||
ignoresPersistentStateOnLaunch = "NO"
|
||||
debugDocumentVersioning = "YES"
|
||||
debugServiceExtension = "internal"
|
||||
allowLocationSimulation = "YES"
|
||||
viewDebuggingEnabled = "No">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2CED86A12AF00BC9006F9E26"
|
||||
BuildableName = "tools"
|
||||
BlueprintName = "tools"
|
||||
ReferencedContainer = "container:Tokenary.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</LaunchAction>
|
||||
<ProfileAction
|
||||
buildConfiguration = "Release"
|
||||
shouldUseLaunchSchemeArgsEnv = "YES"
|
||||
savedToolIdentifier = ""
|
||||
useCustomWorkingDirectory = "NO"
|
||||
debugDocumentVersioning = "YES">
|
||||
<BuildableProductRunnable
|
||||
runnableDebuggingMode = "0">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "2CED86A12AF00BC9006F9E26"
|
||||
BuildableName = "tools"
|
||||
BlueprintName = "tools"
|
||||
ReferencedContainer = "container:Tokenary.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildableProductRunnable>
|
||||
</ProfileAction>
|
||||
<AnalyzeAction
|
||||
buildConfiguration = "Debug">
|
||||
</AnalyzeAction>
|
||||
<ArchiveAction
|
||||
buildConfiguration = "Release"
|
||||
revealArchiveInOrganizer = "YES">
|
||||
</ArchiveAction>
|
||||
</Scheme>
|
77
tools/bundled/BundledNodes.swift
Normal file
77
tools/bundled/BundledNodes.swift
Normal file
@ -0,0 +1,77 @@
|
||||
import Foundation
|
||||
|
||||
struct BundledNodes {
|
||||
|
||||
static let dict: [Int: String] = [
|
||||
1: "mainnet.infura.io/v3/",
|
||||
5: "goerli.infura.io/v3/",
|
||||
10: "optimism-mainnet.infura.io/v3/",
|
||||
25: "evm.cronos.org",
|
||||
56: "bsc-dataseed1.bnbchain.org",
|
||||
66: "exchainrpc.okex.org",
|
||||
69: "kovan.optimism.io/",
|
||||
77: "sokol.poa.network",
|
||||
97: "data-seed-prebsc-1-s1.bnbchain.org:8545",
|
||||
99: "core.poa.network",
|
||||
100: "rpc.gnosischain.com",
|
||||
122: "rpc.fuse.io",
|
||||
128: "http-mainnet.hecochain.com",
|
||||
137: "polygon-mainnet.infura.io/v3/",
|
||||
200: "arbitrum.xdaichain.com/",
|
||||
204: "opbnb-mainnet-rpc.bnbchain.org",
|
||||
250: "rpc.ftm.tools",
|
||||
280: "testnet.era.zksync.dev",
|
||||
288: "mainnet.boba.network",
|
||||
314: "api.node.glif.io/",
|
||||
324: "mainnet.era.zksync.io",
|
||||
338: "evm-t3.cronos.org",
|
||||
420: "goerli.optimism.io",
|
||||
424: "rpc.publicgoods.network",
|
||||
1001: "api.baobab.klaytn.net:8651",
|
||||
1088: "andromeda.metis.io/?owner=1088",
|
||||
1101: "zkevm-rpc.com",
|
||||
1284: "rpc.api.moonbeam.network",
|
||||
1285: "rpc.api.moonriver.moonbeam.network",
|
||||
1442: "rpc.public.zkevm-test.net",
|
||||
2221: "evm.testnet.kava.io",
|
||||
2222: "evm.kava.io",
|
||||
4002: "rpc.testnet.fantom.network",
|
||||
4337: "subnets.avax.network/beam/mainnet/rpc",
|
||||
5000: "rpc.mantle.xyz",
|
||||
5001: "rpc.testnet.mantle.xyz",
|
||||
5611: "opbnb-testnet-rpc.bnbchain.org",
|
||||
7700: "canto.slingshot.finance",
|
||||
8217: "1rpc.io/klay",
|
||||
8453: "mainnet.base.org/",
|
||||
10200: "rpc.chiadochain.net",
|
||||
42161: "arbitrum-mainnet.infura.io/v3/",
|
||||
42170: "nova.arbitrum.io/rpc",
|
||||
42220: "forno.celo.org",
|
||||
43113: "api.avax-test.network/ext/bc/C/rpc",
|
||||
43114: "api.avax.network/ext/bc/C/rpc",
|
||||
43288: "avax.boba.network",
|
||||
44787: "alfajores-forno.celo-testnet.org",
|
||||
58008: "sepolia.publicgoods.network",
|
||||
59140: "rpc.goerli.linea.build",
|
||||
59144: "rpc.linea.build",
|
||||
64240: "rpcapi.sonic.fantom.network/",
|
||||
80001: "rpc-mumbai.maticvigil.com",
|
||||
84531: "goerli.base.org",
|
||||
84532: "sepolia.base.org",
|
||||
421613: "goerli-rollup.arbitrum.io/rpc",
|
||||
421614: "sepolia-rollup.arbitrum.io/rpc",
|
||||
534351: "sepolia-rpc.scroll.io",
|
||||
534352: "rpc.scroll.io",
|
||||
7777777: "rpc.zora.energy/",
|
||||
11155111: "rpc.sepolia.org",
|
||||
245022926: "devnet.neonevm.org",
|
||||
245022934: "neon-proxy-mainnet.solana.p2p.org/",
|
||||
999999999: "sepolia.rpc.zora.energy",
|
||||
1313161554: "mainnet.aurora.dev",
|
||||
1313161555: "testnet.aurora.dev/",
|
||||
1666600000: "api.harmony.one",
|
||||
11297108099: "palm-testnet.infura.io/v3/",
|
||||
11297108109: "palm-mainnet.infura.io/v3/"
|
||||
]
|
||||
|
||||
}
|
326
tools/bundled/bundled-networks.json
Normal file
326
tools/bundled/bundled-networks.json
Normal file
@ -0,0 +1,326 @@
|
||||
{
|
||||
"1" : {
|
||||
"n" : "Ethereum",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"5" : {
|
||||
"n" : "Goerli",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"10" : {
|
||||
"n" : "Optimism",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"25" : {
|
||||
"n" : "Cronos",
|
||||
"s" : "CRO"
|
||||
},
|
||||
"56" : {
|
||||
"n" : "BNB Chain",
|
||||
"s" : "BNB",
|
||||
"o" : true
|
||||
},
|
||||
"66" : {
|
||||
"n" : "OKTC",
|
||||
"s" : "OKT"
|
||||
},
|
||||
"69" : {
|
||||
"n" : "Optimism Kovan",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"77" : {
|
||||
"n" : "POA Network Sokol",
|
||||
"s" : "SPOA",
|
||||
"t" : true
|
||||
},
|
||||
"97" : {
|
||||
"n" : "BNB Chain Testnet",
|
||||
"s" : "tBNB",
|
||||
"t" : true
|
||||
},
|
||||
"99" : {
|
||||
"n" : "POA Network",
|
||||
"s" : "POA"
|
||||
},
|
||||
"100" : {
|
||||
"n" : "Gnosis",
|
||||
"s" : "xDai"
|
||||
},
|
||||
"122" : {
|
||||
"n" : "Fuse",
|
||||
"s" : "FUSE"
|
||||
},
|
||||
"128" : {
|
||||
"n" : "Huobi ECO Chain",
|
||||
"s" : "HT"
|
||||
},
|
||||
"137" : {
|
||||
"n" : "Polygon",
|
||||
"s" : "MATIC",
|
||||
"o" : true
|
||||
},
|
||||
"200" : {
|
||||
"n" : "Arbitrum on xDai",
|
||||
"s" : "xDai"
|
||||
},
|
||||
"204" : {
|
||||
"n" : "opBNB",
|
||||
"s" : "BNB",
|
||||
"o" : true
|
||||
},
|
||||
"250" : {
|
||||
"n" : "Fantom Opera",
|
||||
"s" : "FTM",
|
||||
"o" : true
|
||||
},
|
||||
"280" : {
|
||||
"n" : "zkSync Era Testnet",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"288" : {
|
||||
"n" : "Boba",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"314" : {
|
||||
"n" : "Filecoin",
|
||||
"s" : "FIL"
|
||||
},
|
||||
"324" : {
|
||||
"n" : "zkSync Era",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"338" : {
|
||||
"n" : "Cronos Testnet",
|
||||
"s" : "TCRO",
|
||||
"t" : true
|
||||
},
|
||||
"420" : {
|
||||
"n" : "Optimism Goerli",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"424" : {
|
||||
"n" : "Public Goods Network",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"1001" : {
|
||||
"n" : "Klaytn Baobab",
|
||||
"s" : "KLAY",
|
||||
"t" : true
|
||||
},
|
||||
"1088" : {
|
||||
"n" : "Metis Andromeda",
|
||||
"s" : "METIS"
|
||||
},
|
||||
"1101" : {
|
||||
"n" : "Polygon zkEVM",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"1284" : {
|
||||
"n" : "Moonbeam",
|
||||
"s" : "GLMR"
|
||||
},
|
||||
"1285" : {
|
||||
"n" : "Moonriver",
|
||||
"s" : "MOVR"
|
||||
},
|
||||
"1442" : {
|
||||
"n" : "Polygon zkEVM Testnet",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"2221" : {
|
||||
"n" : "Kava Testnet",
|
||||
"s" : "TKAVA",
|
||||
"t" : true
|
||||
},
|
||||
"2222" : {
|
||||
"n" : "Kava",
|
||||
"s" : "KAVA"
|
||||
},
|
||||
"4002" : {
|
||||
"n" : "Fantom Testnet",
|
||||
"s" : "FTM",
|
||||
"t" : true
|
||||
},
|
||||
"4337" : {
|
||||
"n" : "Beam",
|
||||
"s" : "BEAM"
|
||||
},
|
||||
"5000" : {
|
||||
"n" : "Mantle",
|
||||
"s" : "MNT"
|
||||
},
|
||||
"5001" : {
|
||||
"n" : "Mantle Testnet",
|
||||
"s" : "MNT",
|
||||
"t" : true
|
||||
},
|
||||
"5611" : {
|
||||
"n" : "opBNB Testnet",
|
||||
"s" : "tBNB",
|
||||
"t" : true
|
||||
},
|
||||
"7700" : {
|
||||
"n" : "Canto",
|
||||
"s" : "CANTO"
|
||||
},
|
||||
"8217" : {
|
||||
"n" : "Klaytn",
|
||||
"s" : "KLAY"
|
||||
},
|
||||
"8453" : {
|
||||
"n" : "Base",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"10200" : {
|
||||
"n" : "Gnosis Chiado",
|
||||
"s" : "xDai",
|
||||
"t" : true
|
||||
},
|
||||
"42161" : {
|
||||
"n" : "Arbitrum One",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"42170" : {
|
||||
"n" : "Arbitrum Nova",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"42220" : {
|
||||
"n" : "Celo",
|
||||
"s" : "CELO"
|
||||
},
|
||||
"43113" : {
|
||||
"n" : "Avalanche Fuji",
|
||||
"s" : "AVAX",
|
||||
"t" : true
|
||||
},
|
||||
"43114" : {
|
||||
"n" : "Avalanche",
|
||||
"s" : "AVAX",
|
||||
"o" : true
|
||||
},
|
||||
"43288" : {
|
||||
"n" : "Boba Avax",
|
||||
"s" : "BOBA"
|
||||
},
|
||||
"44787" : {
|
||||
"n" : "Celo Alfajores Testnet",
|
||||
"s" : "CELO",
|
||||
"t" : true
|
||||
},
|
||||
"58008" : {
|
||||
"n" : "Public Goods Network Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"59140" : {
|
||||
"n" : "Linea Testnet",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"59144" : {
|
||||
"n" : "Linea",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"64240" : {
|
||||
"n" : "Fantom Sonic Open",
|
||||
"s" : "FTM",
|
||||
"t" : true
|
||||
},
|
||||
"80001" : {
|
||||
"n" : "Polygon Mumbai",
|
||||
"s" : "MATIC",
|
||||
"t" : true
|
||||
},
|
||||
"84531" : {
|
||||
"n" : "Base Goerli",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"84532" : {
|
||||
"n" : "Base Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"421613" : {
|
||||
"n" : "Arbitrum Goerli",
|
||||
"s" : "AGOR",
|
||||
"t" : true
|
||||
},
|
||||
"421614" : {
|
||||
"n" : "Arbitrum Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"534351" : {
|
||||
"n" : "Scroll Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"534352" : {
|
||||
"n" : "Scroll",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"7777777" : {
|
||||
"n" : "Zora",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"11155111" : {
|
||||
"n" : "Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"245022926" : {
|
||||
"n" : "Neon EVM DevNet",
|
||||
"s" : "NEON",
|
||||
"t" : true
|
||||
},
|
||||
"245022934" : {
|
||||
"n" : "Neon EVM",
|
||||
"s" : "NEON"
|
||||
},
|
||||
"999999999" : {
|
||||
"n" : "Zora Sepolia",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"1313161554" : {
|
||||
"n" : "Aurora",
|
||||
"s" : "ETH",
|
||||
"o" : true
|
||||
},
|
||||
"1313161555" : {
|
||||
"n" : "Aurora Testnet",
|
||||
"s" : "ETH",
|
||||
"t" : true
|
||||
},
|
||||
"1666600000" : {
|
||||
"n" : "Harmony",
|
||||
"s" : "ONE"
|
||||
},
|
||||
"11297108099" : {
|
||||
"n" : "Palm Testnet",
|
||||
"s" : "PALM",
|
||||
"t" : true
|
||||
},
|
||||
"11297108109" : {
|
||||
"n" : "Palm",
|
||||
"s" : "PALM"
|
||||
}
|
||||
}
|
71
tools/helpers/nodes-to-bundle.json
Normal file
71
tools/helpers/nodes-to-bundle.json
Normal file
@ -0,0 +1,71 @@
|
||||
{
|
||||
"1" : "mainnet.infura.io/v3/",
|
||||
"5" : "goerli.infura.io/v3/",
|
||||
"10" : "optimism-mainnet.infura.io/v3/",
|
||||
"25" : "evm.cronos.org",
|
||||
"56" : "bsc-dataseed1.bnbchain.org",
|
||||
"66" : "exchainrpc.okex.org",
|
||||
"69" : "kovan.optimism.io/",
|
||||
"77" : "sokol.poa.network",
|
||||
"97" : "data-seed-prebsc-1-s1.bnbchain.org:8545",
|
||||
"99" : "core.poa.network",
|
||||
"100" : "rpc.gnosischain.com",
|
||||
"122" : "rpc.fuse.io",
|
||||
"128" : "http-mainnet.hecochain.com",
|
||||
"137" : "polygon-mainnet.infura.io/v3/",
|
||||
"200" : "arbitrum.xdaichain.com/",
|
||||
"204" : "opbnb-mainnet-rpc.bnbchain.org",
|
||||
"250" : "rpc.ftm.tools",
|
||||
"280" : "testnet.era.zksync.dev",
|
||||
"288" : "mainnet.boba.network",
|
||||
"314" : "api.node.glif.io/",
|
||||
"324" : "mainnet.era.zksync.io",
|
||||
"338" : "evm-t3.cronos.org",
|
||||
"420" : "goerli.optimism.io",
|
||||
"424" : "rpc.publicgoods.network",
|
||||
"1001" : "api.baobab.klaytn.net:8651",
|
||||
"1088" : "andromeda.metis.io/?owner=1088",
|
||||
"1101" : "zkevm-rpc.com",
|
||||
"1284" : "rpc.api.moonbeam.network",
|
||||
"1285" : "rpc.api.moonriver.moonbeam.network",
|
||||
"1442" : "rpc.public.zkevm-test.net",
|
||||
"2221" : "evm.testnet.kava.io",
|
||||
"2222" : "evm.kava.io",
|
||||
"4002" : "rpc.testnet.fantom.network",
|
||||
"4337" : "subnets.avax.network/beam/mainnet/rpc",
|
||||
"5000" : "rpc.mantle.xyz",
|
||||
"5001" : "rpc.testnet.mantle.xyz",
|
||||
"5611" : "opbnb-testnet-rpc.bnbchain.org",
|
||||
"7700" : "canto.slingshot.finance",
|
||||
"8217" : "1rpc.io/klay",
|
||||
"8453" : "mainnet.base.org/",
|
||||
"10200" : "rpc.chiadochain.net",
|
||||
"42161" : "arbitrum-mainnet.infura.io/v3/",
|
||||
"42170" : "nova.arbitrum.io/rpc",
|
||||
"42220" : "forno.celo.org",
|
||||
"43113" : "api.avax-test.network/ext/bc/C/rpc",
|
||||
"43114" : "api.avax.network/ext/bc/C/rpc",
|
||||
"43288" : "avax.boba.network",
|
||||
"44787" : "alfajores-forno.celo-testnet.org",
|
||||
"58008" : "sepolia.publicgoods.network",
|
||||
"59140" : "rpc.goerli.linea.build",
|
||||
"59144" : "rpc.linea.build",
|
||||
"64240" : "rpcapi.sonic.fantom.network/",
|
||||
"80001" : "rpc-mumbai.maticvigil.com",
|
||||
"84531" : "goerli.base.org",
|
||||
"84532" : "sepolia.base.org",
|
||||
"421613" : "goerli-rollup.arbitrum.io/rpc",
|
||||
"421614" : "sepolia-rollup.arbitrum.io/rpc",
|
||||
"534351" : "sepolia-rpc.scroll.io",
|
||||
"534352" : "rpc.scroll.io",
|
||||
"7777777" : "rpc.zora.energy/",
|
||||
"11155111" : "rpc.sepolia.org",
|
||||
"245022926" : "devnet.neonevm.org",
|
||||
"245022934" : "neon-proxy-mainnet.solana.p2p.org/",
|
||||
"999999999" : "sepolia.rpc.zora.energy",
|
||||
"1313161554" : "mainnet.aurora.dev",
|
||||
"1313161555" : "testnet.aurora.dev/",
|
||||
"1666600000" : "api.harmony.one",
|
||||
"11297108099" : "palm-testnet.infura.io/v3/",
|
||||
"11297108109" : "palm-mainnet.infura.io/v3/"
|
||||
}
|
87
tools/main.swift
Normal file
87
tools/main.swift
Normal file
@ -0,0 +1,87 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
let semaphore = DispatchSemaphore(value: 0)
|
||||
|
||||
let projectDir = FileManager.default.currentDirectoryPath
|
||||
let base = "\(projectDir)/tools/"
|
||||
|
||||
let bundledNetworksFileURL = URL(fileURLWithPath: base + "bundled/bundled-networks.json")
|
||||
let bundledNodesFileURL = URL(fileURLWithPath: base + "bundled/BundledNodes.swift")
|
||||
let nodesToBundleFileURL = URL(fileURLWithPath: base + "helpers/nodes-to-bundle.json")
|
||||
|
||||
let https = "https://"
|
||||
|
||||
let encoder = JSONEncoder()
|
||||
encoder.outputFormatting = [.prettyPrinted, .withoutEscapingSlashes, .sortedKeys]
|
||||
|
||||
func fetchChains(completion: @escaping ([EIP155ChainData]) -> Void) {
|
||||
URLSession.shared.dataTask(with: URL(string: "https://chainid.network/chains.json")!) { (data, _, _) in
|
||||
completion(try! JSONDecoder().decode([EIP155ChainData].self, from: data!))
|
||||
}.resume()
|
||||
}
|
||||
|
||||
fetchChains { chains in
|
||||
let currentNetworksData = try! Data(contentsOf: bundledNetworksFileURL)
|
||||
let currentNodesData = try! Data(contentsOf: nodesToBundleFileURL)
|
||||
|
||||
let currentNetworks = try! JSONDecoder().decode([Int: BundledNetwork].self, from: currentNetworksData)
|
||||
let currentNodes = try! JSONDecoder().decode([String: String].self, from: currentNodesData)
|
||||
|
||||
let currentIds = Set(currentNetworks.keys)
|
||||
let newChainsIds = Set([1284, 1285, 288, 43288, 25, 338])
|
||||
|
||||
let newChains = chains.filter { chain in
|
||||
let isEIP3091 = chain.explorers?.contains(where: { $0.standard == "EIP3091" }) == true
|
||||
let allowNoEIP3091 = true
|
||||
if newChainsIds.contains(chain.chainId) &&
|
||||
!currentIds.contains(chain.chainId) &&
|
||||
chain.rpc.contains(where: { $0.hasPrefix(https) }) &&
|
||||
chain.redFlags == nil &&
|
||||
chain.status != "deprecated" &&
|
||||
chain.nativeCurrency.decimals == 18 &&
|
||||
(isEIP3091 || allowNoEIP3091) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
var updatedNetworks = currentNetworks
|
||||
var updatedNodes = currentNodes
|
||||
|
||||
newChains.forEach { chain in
|
||||
updatedNetworks[chain.chainId] = BundledNetwork(name: chain.name, symbol: chain.nativeCurrency.symbol, isTest: true)
|
||||
updatedNodes[String(chain.chainId)] = String(chain.rpc.first(where: { $0.hasPrefix(https) })!.dropFirst(https.count))
|
||||
}
|
||||
|
||||
let data = (try! encoder.encode(updatedNetworks)) + "\n".data(using: .utf8)!
|
||||
try! data.write(to: bundledNetworksFileURL)
|
||||
updateNodesFiles(nodes: updatedNodes)
|
||||
semaphore.signal()
|
||||
}
|
||||
|
||||
func updateNodesFiles(nodes: [String: String]) {
|
||||
let dictData = try! JSONSerialization.data(withJSONObject: nodes, options: [.prettyPrinted, .sortedKeys, .withoutEscapingSlashes]) + "\n".data(using: .utf8)!
|
||||
try! dictData.write(to: nodesToBundleFileURL)
|
||||
|
||||
let dictString = nodes.sorted(by: { Int($0.key)! < Int($1.key)! }).map { "\($0.key): \"\($0.value)\"" }.joined(separator: ",\n ")
|
||||
let contents = """
|
||||
import Foundation
|
||||
|
||||
struct BundledNodes {
|
||||
|
||||
static let dict: [Int: String] = [
|
||||
\(dictString)
|
||||
]
|
||||
|
||||
}
|
||||
|
||||
"""
|
||||
|
||||
try! contents.data(using: .utf8)?.write(to: bundledNodesFileURL)
|
||||
}
|
||||
|
||||
semaphore.wait()
|
||||
print("🟢 all done")
|
46
tools/models/BundledNetwork.swift
Normal file
46
tools/models/BundledNetwork.swift
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
struct BundledNetwork: Codable {
|
||||
|
||||
let name: String
|
||||
let symbol: String
|
||||
let isTest: Bool
|
||||
let okToShowPriceForSymbol: Bool
|
||||
|
||||
private enum CodingKeys: String, CodingKey {
|
||||
case name = "n"
|
||||
case symbol = "s"
|
||||
case isTest = "t"
|
||||
case okToShowPriceForSymbol = "o"
|
||||
}
|
||||
|
||||
init(name: String, symbol: String, isTest: Bool, okToShowPriceForSymbol: Bool) {
|
||||
self.name = name
|
||||
self.symbol = symbol
|
||||
self.isTest = isTest
|
||||
self.okToShowPriceForSymbol = okToShowPriceForSymbol
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
name = try container.decode(String.self, forKey: .name)
|
||||
symbol = try container.decode(String.self, forKey: .symbol)
|
||||
isTest = try container.decodeIfPresent(Bool.self, forKey: .isTest) ?? false
|
||||
if isTest {
|
||||
okToShowPriceForSymbol = false
|
||||
} else {
|
||||
okToShowPriceForSymbol = try container.decodeIfPresent(Bool.self, forKey: .okToShowPriceForSymbol) ?? false
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.container(keyedBy: CodingKeys.self)
|
||||
try container.encode(name, forKey: .name)
|
||||
try container.encode(symbol, forKey: .symbol)
|
||||
if isTest { try container.encode(isTest, forKey: .isTest) }
|
||||
if okToShowPriceForSymbol { try container.encode(okToShowPriceForSymbol, forKey: .okToShowPriceForSymbol) }
|
||||
}
|
||||
|
||||
}
|
63
tools/models/EIP155ChainData.swift
Normal file
63
tools/models/EIP155ChainData.swift
Normal file
@ -0,0 +1,63 @@
|
||||
// Copyright © 2023 Tokenary. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
// https://github.com/ethereum-lists/chains/blob/master/tools/schema/chainSchema.json
|
||||
|
||||
struct EIP155ChainData: Codable {
|
||||
|
||||
let name: String // Name of the Network
|
||||
let shortName: String
|
||||
let chain: String
|
||||
let chainId: Int
|
||||
let networkId: Int
|
||||
let rpc: [String]
|
||||
let faucets: [String]
|
||||
let infoURL: String
|
||||
let nativeCurrency: NativeCurrency
|
||||
|
||||
let title: String?
|
||||
let icon: String? // Icon type
|
||||
let features: [Feature]?
|
||||
let slip44: Int?
|
||||
let ens: ENS?
|
||||
let explorers: [Explorer]?
|
||||
let parent: Parent?
|
||||
let status: String? // Chain status
|
||||
let redFlags: [RedFlag]?
|
||||
|
||||
struct NativeCurrency: Codable {
|
||||
let name: String // Name of the Native Currency
|
||||
let symbol: String // Symbol of the Native Currency
|
||||
let decimals: Int // Decimal points supported
|
||||
}
|
||||
|
||||
struct Feature: Codable {
|
||||
let name: String // Feature name - e.g. EIP155
|
||||
}
|
||||
|
||||
struct ENS: Codable {
|
||||
let registry: String
|
||||
}
|
||||
|
||||
struct Explorer: Codable {
|
||||
let name: String
|
||||
let url: String
|
||||
let standard: String? // EIP3091 or none
|
||||
}
|
||||
|
||||
struct Parent: Codable {
|
||||
let type: String
|
||||
let chain: String
|
||||
let bridges: [Bridge]?
|
||||
|
||||
struct Bridge: Codable {
|
||||
let url: String
|
||||
}
|
||||
}
|
||||
|
||||
enum RedFlag: String, Codable {
|
||||
case reusedChainId = "reusedChainId"
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue
Block a user