mirror of
https://github.com/lil-org/tokenary.git
synced 2024-12-02 09:33:49 +03:00
Support arbitrum, polygon and optimism
This commit is contained in:
parent
ce010da765
commit
9798e03433
@ -36,6 +36,8 @@
|
||||
2C901C4A2689F01700D0926A /* Strings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C901C492689F01700D0926A /* Strings.swift */; };
|
||||
2C901C4D268A033100D0926A /* GasService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C901C4C268A033100D0926A /* GasService.swift */; };
|
||||
2C917429267D2A6E00049075 /* Keychain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C917428267D2A6E00049075 /* Keychain.swift */; };
|
||||
2C9F0B6526BDC9AF008FA3D6 /* EthereumNetwork.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */; };
|
||||
2C9F0B6826BDCB2E008FA3D6 /* EthereumChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */; };
|
||||
2CC0CDBE2692027E0072922A /* PriceService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC0CDBD2692027E0072922A /* PriceService.swift */; };
|
||||
2CC8946F269A2E8C00879245 /* SessionStorage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC8946E269A2E8C00879245 /* SessionStorage.swift */; };
|
||||
2CC89471269A334A00879245 /* UserDefaults.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2CC89470269A334A00879245 /* UserDefaults.swift */; };
|
||||
@ -80,6 +82,8 @@
|
||||
2C901C492689F01700D0926A /* Strings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Strings.swift; sourceTree = "<group>"; };
|
||||
2C901C4C268A033100D0926A /* GasService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GasService.swift; sourceTree = "<group>"; };
|
||||
2C917428267D2A6E00049075 /* Keychain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Keychain.swift; sourceTree = "<group>"; };
|
||||
2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumNetwork.swift; sourceTree = "<group>"; };
|
||||
2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EthereumChain.swift; sourceTree = "<group>"; };
|
||||
2CC0CDBD2692027E0072922A /* PriceService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PriceService.swift; sourceTree = "<group>"; };
|
||||
2CC8946E269A2E8C00879245 /* SessionStorage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SessionStorage.swift; sourceTree = "<group>"; };
|
||||
2CC89470269A334A00879245 /* UserDefaults.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserDefaults.swift; sourceTree = "<group>"; };
|
||||
@ -175,6 +179,8 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
2C1995552674D0F300A8E370 /* Ethereum.swift */,
|
||||
2C9F0B6426BDC9AF008FA3D6 /* EthereumNetwork.swift */,
|
||||
2C9F0B6726BDCB2E008FA3D6 /* EthereumChain.swift */,
|
||||
2CE3D014267F73E80032A62E /* LegacyAccountWithKey.swift */,
|
||||
2CE3D011267F73C00032A62E /* Transaction.swift */,
|
||||
);
|
||||
@ -382,10 +388,12 @@
|
||||
2CC0CDBE2692027E0072922A /* PriceService.swift in Sources */,
|
||||
2C8A09C6267513FC00993638 /* Agent.swift in Sources */,
|
||||
2C8A09D42675184700993638 /* Window.swift in Sources */,
|
||||
2C9F0B6526BDC9AF008FA3D6 /* EthereumNetwork.swift in Sources */,
|
||||
2C208A9F26813408005BA500 /* Secrets.swift in Sources */,
|
||||
2CC8946F269A2E8C00879245 /* SessionStorage.swift in Sources */,
|
||||
2CD0669126B5537B00728C20 /* InkWallet.swift in Sources */,
|
||||
2C8A09D726751A0C00993638 /* WalletConnect.swift in Sources */,
|
||||
2C9F0B6826BDCB2E008FA3D6 /* EthereumChain.swift in Sources */,
|
||||
2C03D1D2269B407900EF10EA /* NetworkMonitor.swift in Sources */,
|
||||
2C8A09E326757FC000993638 /* AccountCellView.swift in Sources */,
|
||||
2C6B964C26B9D92500D2C819 /* NSColor.swift in Sources */,
|
||||
|
@ -77,9 +77,9 @@ class Agent: NSObject {
|
||||
windowController.contentViewController = accountsList
|
||||
}
|
||||
|
||||
func showApprove(transaction: Transaction, peerMeta: WCPeerMeta?, completion: @escaping (Transaction?) -> Void) {
|
||||
func showApprove(transaction: Transaction, chain: EthereumChain, peerMeta: WCPeerMeta?, completion: @escaping (Transaction?) -> Void) {
|
||||
let windowController = Window.showNew()
|
||||
let approveViewController = ApproveTransactionViewController.with(transaction: transaction, peerMeta: peerMeta) { [weak self] transaction in
|
||||
let approveViewController = ApproveTransactionViewController.with(transaction: transaction, chain: chain, peerMeta: peerMeta) { [weak self] transaction in
|
||||
if transaction != nil {
|
||||
self?.askAuthentication(on: windowController.window, onStart: false, reason: Strings.sendTransaction) { success in
|
||||
completion(success ? transaction : nil)
|
||||
|
@ -19,10 +19,7 @@ struct Ethereum {
|
||||
|
||||
static let shared = Ethereum()
|
||||
|
||||
private let network: Network = AlchemyNetwork(
|
||||
chain: "mainnet",
|
||||
apiKey: Secrets.alchemy
|
||||
)
|
||||
private let networks = EthereumNetwork.allByChain
|
||||
|
||||
func sign(message: String, wallet: InkWallet) throws -> String {
|
||||
guard let privateKeyString = wallet.ethereumPrivateKeyString else { throw Error.keyNotFound }
|
||||
@ -58,8 +55,9 @@ struct Ethereum {
|
||||
return signed
|
||||
}
|
||||
|
||||
func send(transaction: Transaction, wallet: InkWallet) throws -> String {
|
||||
let bytes = try signedTransactionBytes(transaction: transaction, wallet: wallet)
|
||||
func send(transaction: Transaction, wallet: InkWallet, chain: EthereumChain) throws -> String {
|
||||
guard let network = networks[chain] else { throw Error.invalidInputData }
|
||||
let bytes = try signedTransactionBytes(transaction: transaction, wallet: wallet, chain: chain)
|
||||
let response = try SendRawTransactionProcedure(network: network, transactionBytes: bytes).call()
|
||||
guard let hash = response["result"].string else {
|
||||
throw Error.failedToSendTransaction
|
||||
@ -67,7 +65,8 @@ struct Ethereum {
|
||||
return hash
|
||||
}
|
||||
|
||||
private func signedTransactionBytes(transaction: Transaction, wallet: InkWallet) throws -> EthContractCallBytes {
|
||||
private func signedTransactionBytes(transaction: Transaction, wallet: InkWallet, chain: EthereumChain) throws -> EthContractCallBytes {
|
||||
guard let network = networks[chain] else { throw Error.invalidInputData }
|
||||
guard let privateKeyString = wallet.ethereumPrivateKeyString else { throw Error.keyNotFound }
|
||||
let senderKey = EthPrivateKey(hex: privateKeyString)
|
||||
let contractAddress = EthAddress(hex: transaction.to)
|
||||
@ -106,11 +105,11 @@ struct Ethereum {
|
||||
return bytes
|
||||
}
|
||||
|
||||
func prepareTransaction(_ transaction: Transaction, completion: @escaping (Transaction) -> Void) {
|
||||
func prepareTransaction(_ transaction: Transaction, chain: EthereumChain, completion: @escaping (Transaction) -> Void) {
|
||||
var transaction = transaction
|
||||
|
||||
if transaction.nonce == nil {
|
||||
getNonce(from: transaction.from) { nonce in
|
||||
getNonce(chain: chain, from: transaction.from) { nonce in
|
||||
transaction.nonce = nonce
|
||||
completion(transaction)
|
||||
}
|
||||
@ -118,7 +117,7 @@ struct Ethereum {
|
||||
|
||||
func getGasIfNeeded(gasPrice: String) {
|
||||
guard transaction.gas == nil else { return }
|
||||
getGas(from: transaction.from, to: transaction.to, gasPrice: gasPrice, weiAmount: transaction.weiAmount, data: transaction.data) { gas in
|
||||
getGas(chain: chain, from: transaction.from, to: transaction.to, gasPrice: gasPrice, weiAmount: transaction.weiAmount, data: transaction.data) { gas in
|
||||
transaction.gas = gas
|
||||
completion(transaction)
|
||||
}
|
||||
@ -127,7 +126,7 @@ struct Ethereum {
|
||||
if let gasPrice = transaction.gasPrice {
|
||||
getGasIfNeeded(gasPrice: gasPrice)
|
||||
} else {
|
||||
getGasPrice { gasPrice in
|
||||
getGasPrice(chain: chain) { gasPrice in
|
||||
transaction.gasPrice = gasPrice
|
||||
completion(transaction)
|
||||
if let gasPrice = gasPrice {
|
||||
@ -138,7 +137,8 @@ struct Ethereum {
|
||||
|
||||
}
|
||||
|
||||
private func getGas(from: String, to: String, gasPrice: String, weiAmount: EthNumber, data: String, completion: @escaping (String?) -> Void) {
|
||||
private func getGas(chain: EthereumChain, from: String, to: String, gasPrice: String, weiAmount: EthNumber, data: String, completion: @escaping (String?) -> Void) {
|
||||
guard let network = networks[chain] else { return }
|
||||
queue.async {
|
||||
let gas = try? EthGasEstimate(
|
||||
network: network,
|
||||
@ -162,7 +162,8 @@ struct Ethereum {
|
||||
}
|
||||
}
|
||||
|
||||
private func getGasPrice(completion: @escaping (String?) -> Void) {
|
||||
private func getGasPrice(chain: EthereumChain, completion: @escaping (String?) -> Void) {
|
||||
guard let network = networks[chain] else { return }
|
||||
queue.async {
|
||||
let gasPrice = try? EthGasPrice(network: network).value().toHexString()
|
||||
DispatchQueue.main.async {
|
||||
@ -171,7 +172,8 @@ struct Ethereum {
|
||||
}
|
||||
}
|
||||
|
||||
private func getNonce(from: String, completion: @escaping (String?) -> Void) {
|
||||
private func getNonce(chain: EthereumChain, from: String, completion: @escaping (String?) -> Void) {
|
||||
guard let network = networks[chain] else { return }
|
||||
queue.async {
|
||||
let nonce = try? EthTransactions(network: network, address: EthAddress(hex: from), blockChainState: PendingBlockChainState()).count().value().toHexString()
|
||||
DispatchQueue.main.async {
|
||||
|
15
Encrypted Ink/Ethereum/EthereumChain.swift
Normal file
15
Encrypted Ink/Ethereum/EthereumChain.swift
Normal file
@ -0,0 +1,15 @@
|
||||
// Copyright © 2021 Encrypted Ink. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
enum EthereumChain: Int {
|
||||
case main = 1
|
||||
case arbitrum = 42161
|
||||
case polygon = 137
|
||||
case optimism = 10
|
||||
|
||||
var id: Int {
|
||||
return rawValue
|
||||
}
|
||||
|
||||
}
|
29
Encrypted Ink/Ethereum/EthereumNetwork.swift
Normal file
29
Encrypted Ink/Ethereum/EthereumNetwork.swift
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright © 2021 Encrypted Ink. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
import Web3Swift
|
||||
|
||||
final class EthereumNetwork: Network {
|
||||
|
||||
static let allByChain: [EthereumChain: EthereumNetwork] = [
|
||||
.main: EthereumNetwork(url: "https://eth-mainnet.alchemyapi.io/v2/" + Secrets.alchemy),
|
||||
.polygon: EthereumNetwork(url: "https://polygon-mainnet.g.alchemy.com/v2/" + Secrets.alchemy),
|
||||
.arbitrum: EthereumNetwork(url: "https://arb-mainnet.g.alchemy.com/v2/" + Secrets.alchemy),
|
||||
.optimism: EthereumNetwork(url: "https://mainnet.optimism.io")
|
||||
]
|
||||
|
||||
private let origin: GethNetwork
|
||||
|
||||
init(url: String) {
|
||||
origin = GethNetwork(url: url)
|
||||
}
|
||||
|
||||
func id() throws -> IntegerScalar {
|
||||
return try origin.id()
|
||||
}
|
||||
|
||||
func call(method: String, params: [EthParameter]) throws -> Data {
|
||||
return try origin.call(method: method, params: params)
|
||||
}
|
||||
|
||||
}
|
@ -8,7 +8,7 @@ class AccountsListViewController: NSViewController {
|
||||
private let walletsManager = WalletsManager.shared
|
||||
private var cellModels = [CellModel]()
|
||||
|
||||
private let chainId = 1
|
||||
private var chain = EthereumChain.main
|
||||
var onSelectedWallet: ((Int, InkWallet) -> Void)?
|
||||
var newWalletId: String?
|
||||
|
||||
@ -259,7 +259,7 @@ extension AccountsListViewController: NSTableViewDelegate {
|
||||
case .wallet:
|
||||
let wallet = wallets[row]
|
||||
if let onSelectedWallet = onSelectedWallet {
|
||||
onSelectedWallet(chainId, wallet)
|
||||
onSelectedWallet(chain.id, wallet)
|
||||
} else {
|
||||
Timer.scheduledTimer(withTimeInterval: 0.01, repeats: false) { [weak self] _ in
|
||||
var point = NSEvent.mouseLocation
|
||||
|
@ -26,12 +26,14 @@ class ApproveTransactionViewController: NSViewController {
|
||||
private let priceService = PriceService.shared
|
||||
private var currentGasInfo: GasService.Info?
|
||||
private var transaction: Transaction!
|
||||
private var chain: EthereumChain!
|
||||
private var completion: ((Transaction?) -> Void)!
|
||||
private var didEnableSpeedConfiguration = false
|
||||
private var peerMeta: WCPeerMeta?
|
||||
|
||||
static func with(transaction: Transaction, peerMeta: WCPeerMeta?, completion: @escaping (Transaction?) -> Void) -> ApproveTransactionViewController {
|
||||
static func with(transaction: Transaction, chain: EthereumChain, peerMeta: WCPeerMeta?, completion: @escaping (Transaction?) -> Void) -> ApproveTransactionViewController {
|
||||
let new = instantiate(ApproveTransactionViewController.self)
|
||||
new.chain = chain
|
||||
new.transaction = transaction
|
||||
new.completion = completion
|
||||
new.peerMeta = peerMeta
|
||||
@ -58,7 +60,7 @@ class ApproveTransactionViewController: NSViewController {
|
||||
}
|
||||
|
||||
private func prepareTransaction() {
|
||||
ethereum.prepareTransaction(transaction) { [weak self] updated in
|
||||
ethereum.prepareTransaction(transaction, chain: chain) { [weak self] updated in
|
||||
self?.transaction = updated
|
||||
self?.updateInterface()
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ class WalletConnect {
|
||||
}
|
||||
|
||||
interactor.eth.onTransaction = { [weak self, weak interactor] (id, event, transaction) in
|
||||
self?.approveTransaction(id: id, wct: transaction, walletId: walletId, interactor: interactor)
|
||||
self?.approveTransaction(id: id, wct: transaction, walletId: walletId, chainId: chainId, interactor: interactor)
|
||||
self?.sessionStorage.didInteractWith(clientId: interactor?.clientId)
|
||||
}
|
||||
}
|
||||
@ -128,17 +128,17 @@ class WalletConnect {
|
||||
}
|
||||
}
|
||||
|
||||
private func approveTransaction(id: Int64, wct: WCEthereumTransaction, walletId: String, interactor: WCInteractor?) {
|
||||
guard let to = wct.to else {
|
||||
private func approveTransaction(id: Int64, wct: WCEthereumTransaction, walletId: String, chainId: Int, interactor: WCInteractor?) {
|
||||
guard let to = wct.to, let chain = EthereumChain(rawValue: chainId) else {
|
||||
rejectRequest(id: id, interactor: interactor, message: "Something went wrong.")
|
||||
return
|
||||
}
|
||||
|
||||
let peer = getPeerOfInteractor(interactor)
|
||||
let transaction = Transaction(from: wct.from, to: to, nonce: wct.nonce, gasPrice: wct.gasPrice, gas: wct.gas, value: wct.value, data: wct.data)
|
||||
Agent.shared.showApprove(transaction: transaction, peerMeta: peer) { [weak self, weak interactor] transaction in
|
||||
Agent.shared.showApprove(transaction: transaction, chain: chain, peerMeta: peer) { [weak self, weak interactor] transaction in
|
||||
if let transaction = transaction {
|
||||
self?.sendTransaction(transaction, walletId: walletId, requestId: id, interactor: interactor)
|
||||
self?.sendTransaction(transaction, walletId: walletId, chainId: chainId, requestId: id, interactor: interactor)
|
||||
} else {
|
||||
self?.rejectRequest(id: id, interactor: interactor, message: "Cancelled")
|
||||
}
|
||||
@ -176,12 +176,12 @@ class WalletConnect {
|
||||
interactor?.rejectRequest(id: id, message: message).cauterize()
|
||||
}
|
||||
|
||||
private func sendTransaction(_ transaction: Transaction, walletId: String, requestId: Int64, interactor: WCInteractor?) {
|
||||
guard let wallet = walletsManager.getWallet(id: walletId) else {
|
||||
private func sendTransaction(_ transaction: Transaction, walletId: String, chainId: Int, requestId: Int64, interactor: WCInteractor?) {
|
||||
guard let wallet = walletsManager.getWallet(id: walletId), let chain = EthereumChain(rawValue: chainId) else {
|
||||
rejectRequest(id: requestId, interactor: interactor, message: "Something went wrong.")
|
||||
return
|
||||
}
|
||||
guard let hash = try? ethereum.send(transaction: transaction, wallet: wallet) else {
|
||||
guard let hash = try? ethereum.send(transaction: transaction, wallet: wallet, chain: chain) else {
|
||||
rejectRequest(id: requestId, interactor: interactor, message: "Failed to send")
|
||||
return
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user