parent
50893a74c2
commit
0445e0e178
@ -0,0 +1,15 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
import AlphaWalletCore |
||||
typealias ReachabilityManager = AlphaWalletCore.ReachabilityManager |
||||
typealias Loadable = AlphaWalletCore.Loadable |
||||
typealias ReachabilityManagerProtocol = AlphaWalletCore.ReachabilityManagerProtocol |
||||
|
||||
import AlphaWalletTokenScript |
||||
typealias AssetAttributeValues = AlphaWalletTokenScript.AssetAttributeValues |
||||
typealias AssetAttribute = AlphaWalletTokenScript.AssetAttribute |
||||
typealias AssetInternalValue = AlphaWalletTokenScript.AssetInternalValue |
||||
typealias AttributeId = AlphaWalletTokenScript.AttributeId |
||||
typealias GeneralisedTime = AlphaWalletTokenScript.GeneralisedTime |
||||
typealias TokenScript = AlphaWalletTokenScript.TokenScript |
||||
typealias XMLHandler = AlphaWalletTokenScript.XMLHandler |
@ -0,0 +1,34 @@ |
||||
# |
||||
# Be sure to run `pod lib lint AlphaWalletABI.podspec' to ensure this is a |
||||
# valid spec before submitting. |
||||
# |
||||
# Any lines starting with a # are optional, but their use is encouraged |
||||
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html |
||||
# |
||||
|
||||
Pod::Spec.new do |s| |
||||
s.name = 'AlphaWalletABI' |
||||
s.version = '1.0.0' |
||||
s.summary = 'AlphaWallet ABI library' |
||||
s.description = <<-DESC |
||||
Lightweight library representing the AlphaWallet ABI functionality |
||||
DESC |
||||
s.homepage = "https://github.com/AlphaWallet/alpha-wallet-ios/tree/master/modules/AlphaWalletABI" |
||||
s.license = { :type => 'MIT', :file => 'LICENSE' } |
||||
s.author = { "Hwee-Boon Yar" => "hboon@motionobj.com" } |
||||
s.social_media_url = "https://twitter.com/hboon" |
||||
s.ios.deployment_target = '13.0' |
||||
s.swift_version = '5.0' |
||||
s.platform = :ios, "13.0" |
||||
s.source = { :git => 'git@github.com:AlphaWallet/alpha-wallet-ios.git', :tag => "#{s.version}" } |
||||
s.source_files = 'modules/AlphaWalletABI/AlphaWalletABI/**/*.{h,m,swift}' |
||||
s.pod_target_xcconfig = { 'SWIFT_OPTIMIZATION_LEVEL' => '-Owholemodule' } |
||||
|
||||
s.frameworks = 'Foundation' |
||||
|
||||
s.dependency 'AlphaWalletAddress' |
||||
s.dependency 'AlphaWalletWeb3' |
||||
s.dependency 'EthereumABI' |
||||
s.dependency 'TrustKeystore' |
||||
end |
||||
|
File diff suppressed because one or more lines are too long
@ -0,0 +1,39 @@ |
||||
# |
||||
# Be sure to run `pod lib lint AlphaWalletTokenScript.podspec' to ensure this is a |
||||
# valid spec before submitting. |
||||
# |
||||
# Any lines starting with a # are optional, but their use is encouraged |
||||
# To learn more about a Podspec see https://guides.cocoapods.org/syntax/podspec.html |
||||
# |
||||
|
||||
Pod::Spec.new do |s| |
||||
s.name = 'AlphaWalletTokenScript' |
||||
s.version = '1.0.0' |
||||
s.summary = 'AlphaWallet TokenScript library' |
||||
s.description = <<-DESC |
||||
Lightweight library representing the AlphaWallet TokenScript functionality |
||||
DESC |
||||
s.homepage = "https://github.com/AlphaWallet/alpha-wallet-ios/tree/master/modules/AlphaWalletTokenScript" |
||||
s.license = { :type => 'MIT', :file => 'LICENSE' } |
||||
s.author = { "Hwee-Boon Yar" => "hboon@motionobj.com" } |
||||
s.social_media_url = "https://twitter.com/hboon" |
||||
s.ios.deployment_target = '13.0' |
||||
s.swift_version = '5.0' |
||||
s.platform = :ios, "13.0" |
||||
s.source = { :git => 'git@github.com:AlphaWallet/alpha-wallet-ios.git', :tag => "#{s.version}" } |
||||
s.source_files = 'modules/AlphaWalletTokenScript/AlphaWalletTokenScript/**/*.{h,m,swift}' |
||||
s.pod_target_xcconfig = { 'SWIFT_OPTIMIZATION_LEVEL' => '-Owholemodule' } |
||||
|
||||
s.frameworks = 'Foundation' |
||||
|
||||
s.dependency 'APIKit' |
||||
s.dependency 'BigInt' |
||||
s.dependency 'Kanna' |
||||
s.dependency 'PromiseKit/CorePromise' |
||||
s.dependency 'AlphaWalletAddress' |
||||
s.dependency 'AlphaWalletABI' |
||||
s.dependency 'AlphaWalletCore' |
||||
s.dependency 'AlphaWalletLogger' |
||||
s.dependency 'AlphaWalletOpenSea' |
||||
s.dependency 'AlphaWalletWeb3' |
||||
end |
@ -1,4 +1,7 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
import AlphaWalletAddress |
||||
|
||||
extension AlphaWallet.Ethereum.ABI { |
||||
public static let erc1155String: String = { |
@ -1,4 +1,7 @@ |
||||
// Copyright © 2021 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
import AlphaWalletAddress |
||||
|
||||
extension AlphaWallet.Ethereum.ABI { |
||||
public static let erc20: Data = { |
@ -1,4 +1,7 @@ |
||||
// Copyright © 2021 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
import AlphaWalletAddress |
||||
|
||||
// swiftlint:disable line_length |
||||
extension AlphaWallet.Ethereum.ABI { |
@ -0,0 +1,13 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD.
|
||||
|
||||
#import <Foundation/Foundation.h> |
||||
|
||||
//! Project version number for AlphaWalletABI.
|
||||
FOUNDATION_EXPORT double AlphaWalletABIVersionNumber; |
||||
|
||||
//! Project version string for AlphaWalletABI.
|
||||
FOUNDATION_EXPORT const unsigned char AlphaWalletABIVersionString[]; |
||||
|
||||
// In this header, you should import all the public headers of your framework using statements like #import <AlphaWalletABI/PublicHeader.h>
|
||||
|
||||
|
@ -1,6 +1,7 @@ |
||||
// Copyright © 2020 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
import AlphaWalletAddress |
||||
import BigInt |
||||
|
||||
public struct FunctionCall { |
@ -0,0 +1,21 @@ |
||||
MIT License |
||||
|
||||
Copyright (c) 2023 AlphaWallet |
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
||||
of this software and associated documentation files (the "Software"), to deal |
||||
in the Software without restriction, including without limitation the rights |
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
||||
copies of the Software, and to permit persons to whom the Software is |
||||
furnished to do so, subject to the following conditions: |
||||
|
||||
The above copyright notice and this permission notice shall be included in all |
||||
copies or substantial portions of the Software. |
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
||||
SOFTWARE. |
@ -1,15 +0,0 @@ |
||||
// |
||||
// EthereumAddress_fromWeb3.swift |
||||
// AlphaWalletFoundation |
||||
// |
||||
// Created by Vladyslav Shepitko on 15.09.2022. |
||||
// |
||||
|
||||
import AlphaWalletWeb3 |
||||
|
||||
public typealias EthereumAddress_fromWeb3 = AlphaWalletWeb3.EthereumAddress |
||||
extension EthereumAddress_fromWeb3: CustomStringConvertible { |
||||
public var description: String { |
||||
return address |
||||
} |
||||
} |
@ -1,88 +0,0 @@ |
||||
// Copyright SIX DAY LLC. All rights reserved. |
||||
|
||||
import Foundation |
||||
|
||||
extension String { |
||||
internal var hex: String { |
||||
guard let data = self.data(using: .utf8) else { |
||||
return String() |
||||
} |
||||
|
||||
return data.map { |
||||
String(format: "%02x", $0) |
||||
}.joined() |
||||
} |
||||
|
||||
internal var hexEncoded: String { |
||||
guard let data = self.data(using: .utf8) else { |
||||
return String() |
||||
} |
||||
return data.hexEncoded |
||||
} |
||||
|
||||
internal var has0xPrefix: Bool { |
||||
return hasPrefix("0x") |
||||
} |
||||
|
||||
internal var isPrivateKey: Bool { |
||||
let value = self.drop0x.components(separatedBy: " ").joined() |
||||
return value.count == 64 |
||||
} |
||||
|
||||
public var drop0x: String { |
||||
if count > 2 && substring(with: 0..<2) == "0x" { |
||||
return String(dropFirst(2)) |
||||
} |
||||
return self |
||||
} |
||||
|
||||
internal var add0x: String { |
||||
if hasPrefix("0x") { |
||||
return self |
||||
} else { |
||||
return "0x" + self |
||||
} |
||||
} |
||||
|
||||
internal func index(from: Int) -> Index { |
||||
return index(startIndex, offsetBy: from) |
||||
} |
||||
|
||||
internal func substring(from: Int) -> String { |
||||
let fromIndex = index(from: from) |
||||
return String(self[fromIndex...]) |
||||
} |
||||
|
||||
internal func substring(to: Int) -> String { |
||||
let toIndex = index(from: to) |
||||
return String(self[..<toIndex]) |
||||
} |
||||
|
||||
internal func substring(with r: Range<Int>) -> String { |
||||
let startIndex = index(from: r.lowerBound) |
||||
let endIndex = index(from: r.upperBound) |
||||
return String(self[startIndex..<endIndex]) |
||||
} |
||||
} |
||||
|
||||
extension StringProtocol { |
||||
|
||||
internal func chunked(into size: Int) -> [SubSequence] { |
||||
var chunks: [SubSequence] = [] |
||||
|
||||
var i = startIndex |
||||
|
||||
while let nextIndex = index(i, offsetBy: size, limitedBy: endIndex) { |
||||
chunks.append(self[i ..< nextIndex]) |
||||
i = nextIndex |
||||
} |
||||
|
||||
let finalChunk = self[i ..< endIndex] |
||||
|
||||
if finalChunk.isEmpty == false { |
||||
chunks.append(finalChunk) |
||||
} |
||||
|
||||
return chunks |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
import Combine |
||||
import Foundation |
||||
import BigInt |
||||
|
||||
public func - <T: Equatable> (left: [T], right: [T]) -> [T] { |
||||
return left.filter { l in |
||||
!right.contains { $0 == l } |
||||
} |
||||
} |
@ -0,0 +1,12 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension Optional where Wrapped: Collection { |
||||
public var isEmpty: Bool { |
||||
switch self { |
||||
case .none: |
||||
return true |
||||
case .some(let value): |
||||
return value.isEmpty |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,59 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension Data { |
||||
public init(json: Any, options: JSONSerialization.WritingOptions = []) throws { |
||||
guard JSONSerialization.isValidJSONObject(json) else { |
||||
throw DecodeError.initFailure |
||||
} |
||||
self = try JSONSerialization.data(withJSONObject: json, options: options) |
||||
} |
||||
|
||||
//NOTE: as minimum chunck is as min time it will be executed, during testing we found that optimal chunck size is 100, but seems it could be optimized more, execution time (0.2 seconds), pretty good and doesn't block UI |
||||
public init(_hex value: String) { |
||||
let chunkSize: Int = 100 |
||||
if value.count > chunkSize { |
||||
self = value.chunked(into: chunkSize).reduce(NSMutableData()) { result, chunk -> NSMutableData in |
||||
let part = Data.data(from: String(chunk)) |
||||
result.append(part) |
||||
|
||||
return result |
||||
} as Data |
||||
} else { |
||||
self = Data.data(from: value) |
||||
} |
||||
} |
||||
|
||||
//NOTE: renamed to `_hex` because CryptoSwift has its own implementation of `.init(hex:)` that instantiates Data() object with additionaly byte at the end. That brokes `signing` in app. Not sure that this is good name. |
||||
private static func data(from hex: String) -> Data { |
||||
let len = hex.count / 2 |
||||
var data = Data(capacity: len) |
||||
for i in 0..<len { |
||||
let from = hex.index(hex.startIndex, offsetBy: i*2) |
||||
let to = hex.index(hex.startIndex, offsetBy: i*2 + 2) |
||||
let bytes = hex[from ..< to] |
||||
if var num = UInt8(bytes, radix: 16) { |
||||
data.append(&num, count: 1) |
||||
} |
||||
} |
||||
return data |
||||
} |
||||
|
||||
public struct HexEncodingOptions: OptionSet { |
||||
public static let upperCase = HexEncodingOptions(rawValue: 1 << 0) |
||||
|
||||
public let rawValue: Int |
||||
|
||||
public init(rawValue: Int) { |
||||
self.rawValue = rawValue |
||||
} |
||||
} |
||||
|
||||
public func hex(options: HexEncodingOptions = []) -> String { |
||||
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx" |
||||
return map { String(format: format, $0) }.joined() |
||||
} |
||||
|
||||
public var hexEncoded: String { |
||||
return "0x" + self.hex() |
||||
} |
||||
} |
@ -1,12 +1,16 @@ |
||||
// |
||||
// Date.swift |
||||
// Alpha-Wallet |
||||
// |
||||
// Created by Oguzhan Gungor on 2/24/18. |
||||
// Copyright © 2018 Alpha-Wallet. All rights reserved. |
||||
// |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
//TODO Some duplicate from AlphaWalletFoundation's Config |
||||
fileprivate struct Config { |
||||
fileprivate static func getLocale() -> String? { |
||||
let defaults = UserDefaults.standardOrForTests |
||||
return defaults.string(forKey: Keys.locale) |
||||
} |
||||
|
||||
struct Keys { |
||||
static let locale = "locale" |
||||
} |
||||
} |
||||
|
||||
public extension Date { |
||||
private static var formatsMap: AtomicDictionary<String, DateFormatter> = .init() |
@ -1,6 +1,4 @@ |
||||
// Copyright SIX DAY LLC. All rights reserved. |
||||
|
||||
import Foundation |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension Dictionary where Key: ExpressibleByStringLiteral, Value: Any { |
||||
public var jsonString: String? { |
@ -0,0 +1,54 @@ |
||||
// |
||||
// Publisher+Extensions.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 04.04.2022. |
||||
// |
||||
|
||||
import Foundation |
||||
import Combine |
||||
import PromiseKit |
||||
|
||||
public extension Publisher { |
||||
static func empty() -> AnyPublisher<Output, Failure> { |
||||
return Empty().eraseToAnyPublisher() |
||||
} |
||||
|
||||
static func just(_ output: Output) -> AnyPublisher<Output, Failure> { |
||||
return Just(output) |
||||
.setFailureType(to: Failure.self) |
||||
.eraseToAnyPublisher() |
||||
} |
||||
|
||||
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> { |
||||
return Fail(error: error).eraseToAnyPublisher() |
||||
} |
||||
|
||||
public func sinkAsync(receiveCompletion: @escaping (Subscribers.Completion<Failure>) -> Void = { _ in }, receiveValue: @escaping (Output) -> Void = { _ in }) { |
||||
var cancellable: AnyCancellable? |
||||
cancellable = self |
||||
.handleEvents(receiveCancel: { cancellable = nil }) |
||||
.sink { result in |
||||
receiveCompletion(result) |
||||
cancellable = nil |
||||
} receiveValue: { value in |
||||
receiveValue(value) |
||||
} |
||||
} |
||||
|
||||
public func promise() -> Promise<Output> { |
||||
var cancellable: AnyCancellable? |
||||
return Promise<Output> { seal in |
||||
cancellable = self |
||||
.receive(on: RunLoop.main) |
||||
.sink { result in |
||||
if case .failure(let error) = result { |
||||
seal.reject(error) |
||||
} |
||||
cancellable = nil |
||||
} receiveValue: { |
||||
seal.fulfill($0) |
||||
} |
||||
} |
||||
} |
||||
} |
@ -1,25 +0,0 @@ |
||||
// |
||||
// Publisher+Utils.swift |
||||
// AlphaWallet |
||||
// |
||||
// Created by Vladyslav Shepitko on 04.04.2022. |
||||
// |
||||
|
||||
import Foundation |
||||
import Combine |
||||
|
||||
public extension Publisher { |
||||
static func empty() -> AnyPublisher<Output, Failure> { |
||||
return Empty().eraseToAnyPublisher() |
||||
} |
||||
|
||||
static func just(_ output: Output) -> AnyPublisher<Output, Failure> { |
||||
return Just(output) |
||||
.setFailureType(to: Failure.self) |
||||
.eraseToAnyPublisher() |
||||
} |
||||
|
||||
static func fail(_ error: Failure) -> AnyPublisher<Output, Failure> { |
||||
return Fail(error: error).eraseToAnyPublisher() |
||||
} |
||||
} |
@ -0,0 +1,109 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension Optional where Wrapped == String { |
||||
public var nilIfEmpty: String? { |
||||
guard let strongSelf = self else { return nil } |
||||
if strongSelf.isEmpty { |
||||
return nil |
||||
} else { |
||||
return strongSelf |
||||
} |
||||
} |
||||
} |
||||
extension String { |
||||
public var nilIfEmpty: String? { |
||||
if isEmpty { |
||||
return nil |
||||
} else { |
||||
return self |
||||
} |
||||
} |
||||
} |
||||
|
||||
extension String { |
||||
public var hexToBytes: [UInt8] { |
||||
let hex: [Character] |
||||
if count % 2 == 0 { |
||||
hex = Array(self) |
||||
} else { |
||||
hex = Array(("0" + self)) |
||||
} |
||||
return stride(from: 0, to: count, by: 2).compactMap { |
||||
UInt8(String(hex[$0..<$0.advanced(by: 2)]), radix: 16) |
||||
} |
||||
} |
||||
|
||||
public func index(from: Int) -> Index { |
||||
return index(startIndex, offsetBy: from) |
||||
} |
||||
|
||||
public func substring(from: Int) -> String { |
||||
let fromIndex = index(from: from) |
||||
return String(self[fromIndex...]) |
||||
} |
||||
|
||||
public func substring(to: Int) -> String { |
||||
let toIndex = index(from: to) |
||||
return String(self[..<toIndex]) |
||||
} |
||||
|
||||
public func substring(with r: Range<Int>) -> String { |
||||
let startIndex = index(from: r.lowerBound) |
||||
let endIndex = index(from: r.upperBound) |
||||
return String(self[startIndex..<endIndex]) |
||||
} |
||||
|
||||
public func nextLetterInAlphabet(for index: Int) -> String? { |
||||
guard let uniCode = UnicodeScalar(self) else { |
||||
return nil |
||||
} |
||||
switch uniCode { |
||||
case "A"..<"Z": |
||||
return String(UnicodeScalar(uniCode.value.advanced(by: index))!) |
||||
default: |
||||
return nil |
||||
} |
||||
} |
||||
|
||||
public var trimmed: String { |
||||
return trimmingCharacters(in: CharacterSet.whitespacesAndNewlines) |
||||
} |
||||
|
||||
public var hex: String { |
||||
guard let data = self.data(using: .utf8) else { |
||||
return String() |
||||
} |
||||
|
||||
return data.map { String(format: "%02x", $0) }.joined() } |
||||
|
||||
internal var hexEncoded: String { |
||||
guard let data = self.data(using: .utf8) else { |
||||
return String() |
||||
} |
||||
return data.hexEncoded |
||||
} |
||||
|
||||
public var has0xPrefix: Bool { |
||||
return hasPrefix("0x") |
||||
} |
||||
|
||||
public var isPrivateKey: Bool { |
||||
let value = self.drop0x.components(separatedBy: " ").joined() |
||||
return value.count == 64 |
||||
} |
||||
|
||||
public var drop0x: String { |
||||
if count > 2 && substring(with: 0..<2) == "0x" { |
||||
return String(dropFirst(2)) |
||||
} |
||||
return self |
||||
} |
||||
|
||||
public var add0x: String { |
||||
if hasPrefix("0x") { |
||||
return self |
||||
} else { |
||||
return "0x" + self |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,22 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension StringProtocol { |
||||
public func chunked(into size: Int) -> [SubSequence] { |
||||
var chunks: [SubSequence] = [] |
||||
|
||||
var i = startIndex |
||||
|
||||
while let nextIndex = index(i, offsetBy: size, limitedBy: endIndex) { |
||||
chunks.append(self[i ..< nextIndex]) |
||||
i = nextIndex |
||||
} |
||||
|
||||
let finalChunk = self[i ..< endIndex] |
||||
|
||||
if finalChunk.isEmpty == false { |
||||
chunks.append(finalChunk) |
||||
} |
||||
|
||||
return chunks |
||||
} |
||||
} |
@ -0,0 +1,14 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
extension UserDefaults { |
||||
//NOTE: its quite important to use single instance of user defaults, otherwise the data will be written in different suites |
||||
private static let testSuiteDefaults = UserDefaults(suiteName: NSUUID().uuidString)! |
||||
|
||||
public static var standardOrForTests: UserDefaults { |
||||
if isRunningTests() { |
||||
return testSuiteDefaults |
||||
} else { |
||||
return .standard |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,6 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
public enum DecodeError: Error { |
||||
case typeMismatch |
||||
case initFailure |
||||
} |
@ -0,0 +1,185 @@ |
||||
// Copyright © 2023 Stormbird PTE. LTD. |
||||
|
||||
import Foundation |
||||
|
||||
public enum RPCServer: Hashable, CaseIterable { |
||||
public enum EtherscanCompatibleType: String, Codable { |
||||
case etherscan |
||||
case blockscout |
||||
case unknown |
||||
} |
||||
|
||||
case main |
||||
case classic |
||||
//As of 20210601, `.callisto` doesn't eth_blockNumber because their endpoint requires including `"params": []` in the payload even if it's empty and we don't. |
||||
//As of 20210601, `.callisto` doesn't support eth_call according to https://testnet-explorer.callisto.network/eth-rpc-api-docs |
||||
case callisto |
||||
case xDai |
||||
case goerli |
||||
case binance_smart_chain |
||||
case binance_smart_chain_testnet |
||||
case heco |
||||
case heco_testnet |
||||
case fantom |
||||
case fantom_testnet |
||||
case avalanche |
||||
case avalanche_testnet |
||||
case polygon |
||||
case mumbai_testnet |
||||
case optimistic |
||||
case cronosMainnet |
||||
case cronosTestnet |
||||
case custom(CustomRPC) |
||||
case arbitrum |
||||
case palm |
||||
case palmTestnet |
||||
case klaytnCypress |
||||
case klaytnBaobabTestnet |
||||
case ioTeX |
||||
case ioTeXTestnet |
||||
case optimismGoerli |
||||
case arbitrumGoerli |
||||
case okx |
||||
case sepolia |
||||
|
||||
public var chainID: Int { |
||||
switch self { |
||||
case .main: return 1 |
||||
case .classic: return 61 |
||||
case .callisto: return 104729 |
||||
case .xDai: return 100 |
||||
case .goerli: return 5 |
||||
case .binance_smart_chain: return 56 |
||||
case .binance_smart_chain_testnet: return 97 |
||||
case .heco: return 128 |
||||
case .heco_testnet: return 256 |
||||
case .custom(let custom): return custom.chainID |
||||
case .fantom: return 250 |
||||
case .fantom_testnet: return 0xfa2 |
||||
case .avalanche: return 0xa86a |
||||
case .avalanche_testnet: return 0xa869 |
||||
case .polygon: return 137 |
||||
case .mumbai_testnet: return 80001 |
||||
case .optimistic: return 10 |
||||
case .cronosTestnet: return 338 |
||||
case .cronosMainnet: return 25 |
||||
case .arbitrum: return 42161 |
||||
case .palm: return 11297108109 |
||||
case .palmTestnet: return 11297108099 |
||||
case .klaytnCypress: return 8217 |
||||
case .klaytnBaobabTestnet: return 1001 |
||||
case .ioTeX: return 4689 |
||||
case .ioTeXTestnet: return 4690 |
||||
case .optimismGoerli: return 420 |
||||
case .arbitrumGoerli: return 421613 |
||||
case .okx: return 66 |
||||
case .sepolia: return 11155111 |
||||
} |
||||
} |
||||
|
||||
//We'll have to manually new cases here |
||||
//Cannot be `let` as the chains can change dynamically without the app being restarted (i.e. killed). The UI can be restarted though (when switching changes) |
||||
public static var allCases: [RPCServer] { |
||||
return [ |
||||
.main, |
||||
.classic, |
||||
.xDai, |
||||
.goerli, |
||||
.binance_smart_chain_testnet, |
||||
.binance_smart_chain, |
||||
.heco, |
||||
//.heco_testnet, TODO: Enable if find another working rpc url |
||||
.fantom, |
||||
.fantom_testnet, |
||||
.avalanche, |
||||
.avalanche_testnet, |
||||
.polygon, |
||||
.callisto, |
||||
.mumbai_testnet, |
||||
.optimistic, |
||||
.cronosMainnet, |
||||
.cronosTestnet, |
||||
.arbitrum, |
||||
.klaytnCypress, |
||||
.klaytnBaobabTestnet, |
||||
.palm, |
||||
.palmTestnet, |
||||
//.ioTeX, //TODO: Disabled as non in Phase 1 anymore, need to take a look on transactions, native balances |
||||
//.ioTeXTestnet |
||||
.optimismGoerli, |
||||
.arbitrumGoerli, |
||||
.okx, |
||||
.sepolia, |
||||
] |
||||
} |
||||
|
||||
public private(set) static var customServers: [Self] = customRpcs.map { RPCServer.custom($0) } |
||||
|
||||
public static var customRpcs: [CustomRPC] = RPCServer.convertJsonToCustomRpcs(Config().customRpcServersJson) { |
||||
didSet { |
||||
if let data = try? JSONEncoder().encode(customRpcs), let json = String(data: data, encoding: .utf8) { |
||||
var c = Config() |
||||
c.customRpcServersJson = json |
||||
customServers = customRpcs.map { RPCServer.custom($0) } |
||||
} else { |
||||
//no-op |
||||
} |
||||
} |
||||
} |
||||
|
||||
public static var availableServers: [RPCServer] { |
||||
allCases + Self.customServers |
||||
} |
||||
|
||||
public init(chainID: Int) { |
||||
//TODO defaulting to .main is bad |
||||
self = Self.availableServers.first { $0.chainID == chainID } ?? .main |
||||
} |
||||
|
||||
private static func convertJsonToCustomRpcs(_ json: String?) -> [CustomRPC] { |
||||
if let json = json { |
||||
let data = json.data(using: .utf8) |
||||
if let servers = try? JSONDecoder().decode([CustomRPC].self, from: data!) { |
||||
return servers |
||||
} else { |
||||
return .init() |
||||
} |
||||
} else { |
||||
return .init() |
||||
} |
||||
} |
||||
} |
||||
|
||||
extension RPCServer: Codable { |
||||
private enum Keys: String, CodingKey { |
||||
case chainId |
||||
} |
||||
|
||||
public init(from decoder: Decoder) throws { |
||||
let container = try decoder.container(keyedBy: Keys.self) |
||||
let chainId = try container.decode(Int.self, forKey: .chainId) |
||||
self = .init(chainID: chainId) |
||||
} |
||||
|
||||
public func encode(to encoder: Encoder) throws { |
||||
var container = encoder.container(keyedBy: Keys.self) |
||||
try container.encode(chainID, forKey: .chainId) |
||||
} |
||||
} |
||||
|
||||
fileprivate class Config { |
||||
struct Keys { |
||||
static let customRpcServers = "customRpcServers" |
||||
} |
||||
|
||||
public var customRpcServersJson: String? { |
||||
get { |
||||
let defaults = UserDefaults.standardOrForTests |
||||
return defaults.string(forKey: Keys.customRpcServers) |
||||
} |
||||
set { |
||||
let defaults = UserDefaults.standardOrForTests |
||||
defaults.set(newValue, forKey: Keys.customRpcServers) |
||||
} |
||||
} |
||||
} |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue