Giter VIP home page Giter VIP logo

horizontalsystems / evmkit.swift Goto Github PK

View Code? Open in Web Editor NEW
15.0 3.0 19.0 10.24 MB

EVM toolkit for iOS. This is a core package, that implements the main features of an Ethereum client like interactions with Ethereum RPC node, account and transactions synchronization and others.

License: MIT License

Swift 100.00%
arbitrum avalanche avalanche-c-chain bep20 binance-smart-chain eip1159 erc-20 erc20 ethereum ethereum-library ethereum-sdk ethereum-wallet evm matic nft optimism polygon solana web3

evmkit.swift's Introduction

EvmKit.Swift

EvmKit.Swift is a native(Swift) toolkit for EVM compatible networks. It's implemented and used by Unstoppable Wallet, a multi-currency crypto wallet. Together with other libraries Eip20Kit.Swift, NftKit.Swift, UniswapKit.Swift, OneInchKit.swift it implements a lot of features of the DeFi world natively (no need for WalletConnect) out-of-the-box.

Core Features

  • Restore with mnemonic phrase, BIP39 Seed, EVM private key, or simply an Ethereum address
  • Local storage of account data (ETH balance and transactions)
  • Synchronization over HTTP/WebSocket
  • Watch accounts. Restore with any address
  • Ethereum Name Service (ENS) support
  • EIP-1559 Gas Prices with live updates
  • Reactive-functional API by RxSwift
  • Implementation of Ethereum's JSON-RPC API
  • Support for Infura and Etherscan
  • Can be extended to natively support any smart contract

Blockchains supported

Any EVM blockchain that supports the Ethereum's RPC API and has an Etherscan-like block explorer can be easily integrated to your wallet using EvmKit.Swift. The following blockchains are currently integrated to Unstoppable Wallet:

  • Ethereum
  • Binance Smart Chain
  • Polygon
  • ArbitrumOne
  • Optimism
  • Avalanche C-Chain

Usage

Initialization

First you need to initialize an EvmKit.Kit instance

import EvmKit

let address = try Address(hex: "0x...")

let evmKit = try Kit.instance(
        address: address,
        chain: .ethereum,
        rpcSource: .ethereumInfuraWebsocket(projectId: "...", projectSecret: "..."),
        transactionSource: .ethereumEtherscan(apiKey: "..."),
        walletId: "unique_wallet_id",
        minLogLevel: .error
)

Starting and Stopping

EvmKit.Kit instance requires to be started with start command. This start the process of synchronization with the blockchain state.

evmKit.start()
evmKit.stop()

Get wallet data

You can get account state, last block height, sync state, transactions sync state and some others synchronously:

guard let state = evmKit.accountState else {
    return
}

state.balance    // 2937096768
state.nonce      // 10

evmKit.lastBlockHeight  // 10000000

You also can subscribe to Rx observables of those and more:

evmKit.accountStateObservable.subscribe(onNext: { state in print("balance: \(state.balance); nonce: \(state.nonce)") })
evmKit.lastBlockHeightObservable.subscribe(onNext: { height in print(height) })
evmKit.syncStateObservable.subscribe(onNext: { state in print(state) })

// Subscribe to ETH transactions synced by the kit
evmKit.transactionsObservable(tagQueries: [TransactionTagQuery(protocol: .native)]).subscribe(onNext: { transactions in print(transactions.count) })

// Subscribe to all EVM transactions
evmKit.allTransactionsObservable.subscribe(onNext: { transactions, initialSync in print(transactions.count) })

Send Transaction

To send a transaction you need a Signer object. Here's how you can create it using Mnemonic seed phrase:

let words = ["mnemonic", "words", ...]

guard let seed = Mnemonic.seed(mnemonic: words) else {
    return
}

let signer = try Signer.instance(seed: seed, chain: .ethereum)

Now you can use it to sign an Ethereum transaction:

// This must be retained until the transaction send is completed
let disposeBag = DisposeBag()

let to = try EvmKit.Address(hex: "0x..recipient..address..here")
let amount = BigUInt("100000000000000000")                         // 0.1 ETH in WEIs
let gasPrice = GasPrice.legacy(gasPrice: 50_000_000_000)

// Construct TransactionData which is the key payload of any EVM transaction
let transactionData = evmKit.transferTransactionData(to: to, value: amount)

// Estimate gas for the transaction
let estimateGasSingle = evmKit.estimateGas(transactionData: transactionData, gasPrice: gasPrice)

// Generate a raw transaction which is ready to be signed. This step also synchronizes the nonce
let rawTransactionSingle = estimateGasSingle.flatMap { estimatedGasLimit in
    evmKit.rawTransaction(transactionData: transactionData, gasPrice: gasPrice, gasLimit: estimatedGasLimit)
}

let sendSingle = rawTransactionSingle.flatMap { rawTransaction in
    // Sign the transaction
    let signature = try signer.signature(rawTransaction: rawTransaction)
    
    // Send the transaction to RPC node
    return evmKit.sendSingle(rawTransaction: rawTransaction, signature: signature)
}

// This step is needed for Rx reactive code to run
sendSingle
    .subscribe(
        onSuccess: { fullTransaction in
            // sendSingle returns FullTransaction object that contains transaction and a transaction decoration
            let transaction = fullTransaction.transaction
            print("Transaction sent: \(transaction.hash.hs.hexString)")
            print("To: \(transaction.to!.eip55)")
            print("Amount: \(transaction.value!.description)")
        }, onError: { error in
            print("Send failed: \(error)")
        }
    )
    .disposed(by: disposeBag)

Get ETH transactions

The following code retrieves the transactions that have ETH coin incoming or outgoing, including the transactions where ETH is received in internal transactions.

evmKit.transactionsSingle(tagQueries: [TransactionTagQuery(protocol: .native)])
    .subscribe(
        onSuccess: { fullTransactions in
            for fullTransaction in fullTransactions {
                let transaction = fullTransaction.transaction
                print("Transaction hash: \(transaction.hash.hs.hexString)")

                switch fullTransaction.decoration {
                case let decoration as IncomingDecoration:
                    print("From: \(decoration.from.eip55)")
                    print("Amount: \(decoration.value.description)")

                case let decoration as OutgoingDecoration:
                    print("To: \(decoration.to.eip55)")
                    print("Amount: \(decoration.value.description)")

                ...

                }
            }
        }, onError: { error in
            print("Couldn't get transactions: \(error)")
        }
    )
    .disposed(by: disposeBag)
}

Extending

Smart contract call

In order to send an EVM smart contract call transaction, you need to create an instance of TransactionData object. Then you can sign and send it as seen above. Please look in Eip20Kit.Swift and UniswapKit.Swift for an examples.

Installation

Swift Package Manager

Swift Package Manager is a dependency manager for Swift projects. You can install it with the following command:

dependencies: [
    .package(url: "https://github.com/horizontalsystems/EvmKit.Swift.git", .upToNextMajor(from: "1.0.0"))
]

Prerequisites

  • Xcode 10.0+
  • Swift 5.5+
  • iOS 13+

Example Project

All features of the library are used in example project located in iOS Example folder. It can be referred as a starting point for usage of the library.

License

The EvmKit.Swift toolkit is open source and available under the terms of the MIT License.

evmkit.swift's People

Contributors

ant013 avatar ealymbaev avatar esen avatar esengulov avatar mnizhurin avatar rex4539 avatar rusik avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.