Giter Site home page Giter Site logo

pocket-ios-eth's Introduction

pocket-ios-eth

An Ethereum Plugin for the Pocket iOS SDK that conforms to the PocketPlugin interface. Uses web3.swift and Cryptoswift for core cryptography and Ethereum related functions. Conforms to the Pocket API guidelines.

Install

Need to install the following pod in your Podfile:

pod 'Pocket', :git => 'https://github.com/pokt-network/pocket-ios-sdk.git', :branch => 'master'

pod 'PocketEth', :git => 'https://github.com/pokt-network/pocket-ios-eth.git', :branch => 'master'

pod 'SwiftKeychainWrapper', :git => 'https://github.com/jrendel/SwiftKeychainWrapper.git', :branch => 'develop', :commit => '77f73c354d695d976bcf1437fc9fbcea981aa2b4'

Before hand

Pocket Network offers a node running in Rinkeby for testing. https://ethereum.pokt.network

To easily set it up:

1- In your appDelegate import Pocket and PocketEth 2- Add Configuration protocol to the class: class AppDelegate: UIResponder, UIApplicationDelegate, Configuration, {

3- Implement nodeURL with the node url: var nodeURL: URL { get { return URL.init(string: "https://ethereum.pokt.network")! } }

4- After we specified the URL, we need to set the configuration for Pocket in the Application function: Pocket.shared.setConfiguration(config: self)

Subnetwork

Currently the Pocket team is offering the https://ethereum.pokt.network endpoint, which supports both Mainnet and the Rinkeby testnet with the following subnetwork identifiers:

1 for Mainnet 4 for Rinkeby

Functionality

Creating and Importing a Wallet

The wallet creation primarily uses the web3 library and the SECP256k1.generatePrivateKey function and saves to the keystore on the device. Developers do not have to worry about encrypting, storing or retrieving the wallet from the device.

Follow the following example to create an Ethereum Wallet:

let newWallet = try PocketEth.createWallet(subnetwork: "4", data: nil)

And to import, you need to define:

1- Public Key

2- Private Key

3- Subnetwork

4- Data

let privateKey = "0x";
let address = "0x";
let subnetwork = "32";

let importWallet = try PocketEth.importWallet(privateKey: privateKey, subnetwork: "4", address: address, data: nil) 

Creating a Transaction

public static func createTransaction(wallet: Wallet, params: [AnyHashable : Any]) throws -> Transaction

To create an Ethereum transaction you need the following parameters:

1- nonce: A counter that increments by +1 each time a transaction is created on an account. You can retrieve the current transaction count using eth_getTransactionCount (Query)

2- gasPrice: The price of the transaction denominated in wei

3- gasLimit: Max amount of gas to be used for transaction denominated in wei

4- to: Public address receiving the transaction

5- value (optional): Amount of ETH being sent in the transaction

6- data (optional): Data such as ABI of the function being called on a smart contract can be sent through the data field

By passing these in through the params dictionary the Ethereum plugin abstracts all the difficulty of creating transactions for the developer by returning a simple Transaction object. An example transaction in creating a Quest in BANANO Quest:

Define contract function ABI

let functionABI = "{\"constant\":false,\"inputs\":[{\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"name\":\"_name\",\"type\":\"string\"},{\"name\":\"_hint\",\"type\":\"string\"},{\"name\":\"_maxWinners\",\"type\":\"uint256\"},{\"name\":\"_merkleRoot\",\"type\":\"bytes32\"},{\"name\":\"_merkleBody\",\"type\":\"string\"},{\"name\":\"_metadata\",\"type\":\"string\"}],\"name\":\"createQuest\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"}"

Define parameters

var functionParameters = [AnyObject]()
functionParameters.append(tokenAddress as AnyObject)
functionParameters.append(questName.description as AnyObject)
functionParameters.append(hint.description as AnyObject)
functionParameters.append(maxWinners as AnyObject)
functionParameters.append(merkleRoot as AnyObject)
functionParameters.append(merkleBody as AnyObject)
functionParameters.append(metadata as AnyObject)

let txParams = [
    "from": wallet.address,
    "nonce": BigUInt.init(transactionCount),
    "to": tavernAddress,
    "value": BigUInt.init(ethPrizeWei),
    "chainID": AppConfiguration.chainID,
    "gasLimit": BigUInt.init(2000000),
    "gasPrice": BigUInt.init(1000000000),
    "data": [
        "abi": functionABI,
        "params": functionParameters
    ] as [AnyHashable: Any]
] as [AnyHashable: Any]

Create transaction

guard let transaction = try? PocketEth.createTransaction(wallet: wallet, params: txParams) else {
self.error = PocketPluginError.transactionCreationError("Error creating transaction")
self.finish()
return
}

Send Transaction

Pocket.shared.sendTransaction(transaction: transaction) { (transactionResponse, error) in
if error != nil {
self.error = error
self.finish()
return
}

Parse transaction hash response

guard let txHash = transactionResponse?.hash else {
self.error = UploadQuestOperationError.invalidTxHash
self.finish()
return
}

self.txHash = txHash
self.finish()

Creating a Query

public static func createQuery(subnetwork: String, params: [AnyHashable: Any], decoder: [AnyHashable: Any]?) throws -> Query

To create a Pocket Query for Ethereum you'll need the subnetwork and params for the specific JSON RPC call you are wishing to make. There are two types of params to create a Query:

  • rpcMethod: Name of the smart contract method you are calling
  • rpcParams: Inputs of the smart contract method you are calling

The decoder dictionary allows the developer to specify the return types from the read request.

An example in creating a getBalance Query and getting the balance of an account using Pocket:

let params = [
"rpcMethod": "eth_getBalance",
"rpcParams": [address, "latest"]
] as [AnyHashable: Any]

guard let query = try? PocketEth.createQuery(params: params, decoder: nil) else {
self.error = PocketPluginError.queryCreationError("Error creating query")
self.finish()
return
}

Pocket.shared.executeQuery(query: query) { (queryResponse, error) in
if error != nil {
self.error = error
self.finish()
return
}

Creating a Query for a smart contract constant is a little bit more involved, as you need to provide the ABI interface for the method you are calling, the functionParameters and the decoder. An example in getting a list of Quests from BANANO Quest:

Create transaction

var tx = [AnyHashable: Any]()

Create ABI

let functionABI = "{\"constant\":true,\"inputs\":[{\"name\":\"_tokenAddress\",\"type\":\"address\"},{\"name\":\"_questIndex\",\"type\":\"uint256\"}],\"name\":\"getQuest\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bytes32\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"string\"},{\"name\":\"\",\"type\":\"bool\"},{\"name\":\"\",\"type\":\"uint256\"},{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"}"

Pass in address and index

let functionParameters = [tokenAddress, questIndex] as [AnyObject]

Encode the ABI and parameters

guard let data = try? PocketEth.encodeFunction(functionABI: functionABI, parameters: functionParameters).toHexString() else {
self.error = PocketPluginError.queryCreationError("Error creating query")
self.finish()
return
}

Add parameters for an Ethereum transaction

tx["to"] = tavernAddress
tx["data"] = "0x" + data
tx["from"] = self.playerAddress

Create the parameters for the final Ethereum Query

let params = [
"rpcMethod": "eth_call",
"rpcParams": [tx, "latest"]
] as [AnyHashable: Any]

Create the decoder

let decoder = [
"returnTypes": ["address", "uint256", "string", "string", "bytes32", "string", "uint256", "string", "bool", "uint256", "uint256"]
] as [AnyHashable : Any]

Create Query object

guard let query = try? PocketEth.createQuery(params: params, decoder: decoder) else {
self.error = PocketPluginError.queryCreationError("Error creating query")
self.finish()
return
}

Execute the Query

Pocket.shared.executeQuery(query: query) { (queryResponse, error) in
if error != nil {
self.error = error
self.finish()
return
}

Get and parse response

guard let questArr = queryResponse?.result?.value() as? [JSON] else {
    self.error = DownloadQuestOperationError.questParsing
    self.finish()
    return
}

    let creator = questArr[0].value() as? String ?? ""
    let index = questArr[1].value() as? String ?? "0"
    let name = questArr[2].value() as? String ?? ""
    let hint = questArr[3].value() as? String ?? ""
    let merkleRoot = questArr[4].value() as? String ?? ""
    let merkleBody = questArr[5].value() as? String ?? ""
    let maxWinners = questArr[6].value() as? String ?? "0"
    let metadata = questArr[7].value() as? String ?? ""
    let valid = questArr[8].value() as? Bool ?? false
    let winnersAmount = questArr[9].value() as? String ?? "0"
    let claimersAmount = questArr[10].value() as? String ?? "0"

self.questDict = [
    "creator": creator,
    "index": index,
    "name": name,
    "hint": hint,
    "merkleRoot": merkleRoot,
    "merkleBody": merkleBody,
    "maxWinners": maxWinners,
    "metadata": metadata,
    "valid": valid,
    "winnersAmount": winnersAmount,
    "claimersAmount": claimersAmount
] as [AnyHashable: Any]
    self.finish()

pocket-ios-eth's People

Contributors

luyzdeleon avatar pabelnl avatar jeremybeal11 avatar

Watchers

James Cloos 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.