Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

recent changes #104

Merged
merged 32 commits into from
Nov 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
85c36b0
Merge pull request #59 from matterinc/develop
shamatar Oct 4, 2018
6480bca
Merge pull request #68 from matterinc/develop
shamatar Oct 18, 2018
21b448e
Merge pull request #70 from matterinc/develop
shamatar Oct 22, 2018
3e90f67
- Remove "Result"
shamatar Oct 29, 2018
fa38a7a
- Add extra check to not transact to the non-mutating function
shamatar Oct 29, 2018
23d47bb
- Start fixing tests one by one
shamatar Oct 29, 2018
df91e11
more tests passing
shamatar Oct 29, 2018
56e5b50
- cleanup
shamatar Oct 30, 2018
3adf09b
- allow EIP681 for now
shamatar Oct 30, 2018
7a2178d
- Import cleanups
shamatar Oct 30, 2018
7f83ea2
- Remove "Result" everywhere
shamatar Oct 30, 2018
cbca306
- Implement event loop. Should be started manually
shamatar Oct 30, 2018
b988fa5
updated pods to fix building
TonioMacaronio Nov 2, 2018
0a6e5b0
fixed ens and ens resolver for 2.0, tests dont pass - need to fix
TonioMacaronio Nov 2, 2018
b7e6f55
fixed tests for ens
TonioMacaronio Nov 2, 2018
23a1315
Merge pull request #83 from matterinc/ENSfix
shamatar Nov 3, 2018
0e03dbb
first commit after the Devcon. Add more options into the event loop
shamatar Nov 3, 2018
43256b1
restore parsing of ENS names in EIP681
shamatar Nov 3, 2018
b256f11
- add "create account" call for remote node
shamatar Nov 3, 2018
38f8caa
- Add extra hook function
shamatar Nov 5, 2018
d596ea4
Merge pull request #84 from matterinc/2.0
shamatar Nov 6, 2018
233d2a0
- initial web3webview support with example
shamatar Nov 8, 2018
99c75af
fix zero value on gas estimation
shamatar Nov 20, 2018
5708ea4
Merge pull request #93 from matterinc/2.0
shamatar Nov 20, 2018
0f01a17
Merge pull request #94 from matterinc/master
shamatar Nov 20, 2018
68ed43c
test fix
TonioMacaronio Nov 20, 2018
6c8c862
migration fixes
TonioMacaronio Nov 21, 2018
d065773
Update web3swift 2.0 Migration Guide.md
TonioMacaronio Nov 21, 2018
9e3aec9
fixed errors in tests
TonioMacaronio Nov 21, 2018
cba657c
Update web3swift 2.0 Migration Guide.md
TonioMacaronio Nov 21, 2018
97aa273
Update web3swift 2.0 Migration Guide.md
TonioMacaronio Nov 21, 2018
1d46759
Merge pull request #96 from matterinc/moduleFix0
TonioMacaronio Nov 26, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,4 @@ fastlane/screenshots
fastlane/test_output
API_keys.plist
web3swiftTests/key.json
web3swiftTests/Resources/key.json
306 changes: 306 additions & 0 deletions Documentation/web3swift 2.0 Migration Guide.md
Original file line number Diff line number Diff line change
@@ -1 +1,307 @@

# web3swift 2.0 Migration Guide

web3swift 2.0 is the latest major release of web3swift by Matter, Swift implementation of web3.js functionality for iOS and macOS. Following Semantic Versioning conventions, 2.0 introduces major release API-breaking changes.

This guide is provided in order to ease the transition of existing applications using web3swift 1.x to the latest APIs, as well as explain the design and structure of new and updated functionality.

- [Requirements](#requirements)
- [Benefits of Upgrading](#benefits-of-upgrading)
- [Follow naming convention](#follow-naming-convention)
- [New pods](#new-pods)
- [Breaking API Changes](#breaking-api-changes)
- [Setting Transaction Options](#setting-transaction-options)
- [Preparing transaction](#preparing-transaction)
- [For sending Ether](#for-sending-ether)
- [For sending ERC20](#for-sending-erc20)
- [For sending to contract](#for-sending-to-contract)
- [Send transaction](#send-transaction)
- [For sending ether or tokens to wallets and contracts](#for-sending-ether-or-tokens-to-wallets-and-contracts)
- [For calling contract methods](#for-calling-contract-methods)
- [Get balance](#get-balance)
- [Get Ether balance](#get-ether-balance)
- [Get ERC20 balance](#get-erc20-balance)
- [Chain state](#chain-state)
- [Get Block number](#get-block-number)

## Requirements

- iOS 9.0+, macOS 10.11.0+
- Xcode 10.0+
- Swift 4.0+

## Benefits of Upgrading

- **Complete Swift 4 Compatibility:** includes the full adoption of the new [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/).
- **Separate libraries: EthereumAddress, EthereumABI:** Since there are several Matter products uses this classes, we've decided make them separate and turn in Pods.
- **New class: TransactionOptions:** "Web3Options" is no longer used, instead new class introduced: "TransactionOptions" used to specify gas price, limit, nonce policy, value.
- **New classes: Write Transaction & Read Transaction:** "TransactionIntermediate" is no longer used, instead two new classes introduced: "ReadTransaction" and "WriteTransaction", that have a variable "transactionOptions" used to specify gas price, limit, nonce policy, value
- **WKWebView with injected "web3" provider:** create a simple DApps' browser with "web3" provider onboard.
- **Add or remove "middleware":** that intercepts, modifies and even cancel transaction workflow on stages "before assembly" (before obtaining nonce, gas price, etc), "after assembly" (when nonce and gas price is set for transaction) and "before submission" (right before transaction is either signed locally and is sent as raw, or just send to remote node).
- **Hooks and event loops functionality:** easy monitor properties in web3.
- **New errors handling:** more 'try-catch' less optionals for errors handling.
- **Removed "Result" framework:** usage of "Result" framework was removed due to large amount if name conflicts, now functions throw instead of returning "Result" wrapper.

---

## Follow naming convention

Now you have to do "import Web3swift" (capitalization!) instead of "import web3swift" to follow naming convention.

## New pods

Now EthereumAddress and Ethereum ABI are separate projects. Use "import EthereumAddress" and "import Ethereum ABI" everywhere you use them.

## Breaking API Changes

web3swift 2.0 has fully adopted all the new Swift 4 changes and conventions, including the new [API Design Guidelines](https://swift.org/documentation/api-design-guidelines/). Because of this, almost every API in web3swift has been modified in some way. We can't possibly document every single change, so we're going to attempt to identify the most important API changes to help you through those sometimes less than helpful compiler errors.

### Setting Transaction Options

Since setting transaction options is the most important operation for building transaction in web3swift, here are some examples of web3swift 1.x building transaction options compared to their new equivalents in web3swift 2.0.

```swift
// web3swift 1.0
var options = Web3Options()
options.gasLimit = BigUInt(0)
options.gasPrice = BigUInt(0)
options.value = BigUInt(0)
options.to = EthereumAddress("<Reciever address>")!
options.from = EthereumAddress("<Sender address>")!

// web3swift 2.0
var options = TransactionOptions()
options.callOnBlock = .pending // or .latest / or .exactBlockNumber(BigUInt)
options.nonce = .pending // or .latest / or .manual(BigUInt)
options.gasLimit = .automatic // or .manual(BigUInt) / or .limited(BigUInt) / or .withMargin(Double)
options.gasPrice = .automatic // or .manual(BigUInt) / or .withMargin(Double)
options.to = EthereumAddress("<Reciever address>")!
options.from = EthereumAddress("<Sender address>")!
```

### Preparing transaction

In web3swift 1.0 you specified transactions for Ether, ERC20 and to contract in different, inconvenient and unobvious ways. From 2.0 on it became more convenient and obvious.

#### For sending Ether

```swift
// web3swift 1.0
guard let destinationEthAddress = EthereumAddress(destinationAddressString) else {return}
guard let amount = Web3.Utils.parseToBigUInt(amountString, units: .eth) else {return}
guard let selectedKey = KeysService().selectedWallet()?.address else {return}
let web3 = web3swift.web3(provider: InfuraProvider(Networks.Mainnet)!) //or any other network
web3.addKeystoreManager(KeysService().keystoreManager())
let ethAddressFrom = EthereumAddress(selectedKey)
var options = Web3Options.defaultOptions()
options.from = ethAddressFrom
options.value = BigUInt(amount)
guard let contract = web3.contract(Web3.Utils.coldWalletABI, at: destinationEthAddress) else {return}
guard let estimatedGas = contract.method(options: options)?.estimateGas(options: nil).value else {return}
options.gasLimit = estimatedGas
guard let gasPrice = web3.eth.getGasPrice().value else {return}
options.gasPrice = gasPrice
guard let transaction = contract.method(options: options) else {return}
return transaction

// web3swift 2.0
guard let destinationEthAddress = EthereumAddress(destinationAddressString) else {return}
guard let amount = Web3.Utils.parseToBigUInt(amountString, units: .eth) else {return}
guard let selectedKey = KeysService().selectedWallet()?.address else {return}
let web3 = Web3.InfuraMainnetWeb3() //or any other network
web3.addKeystoreManager(KeysService().keystoreManager())
guard let ethAddressFrom = EthereumAddress(selectedKey) else {return}
guard let contract = web3.contract(Web3.Utils.coldWalletABI, at: destinationEthAddress, abiVersion: 2) else {return}
guard let writeTX = contract.write("fallback") else {return}
writeTX.transactionOptions.from = ethAddressFrom
writeTX.transactionOptions.value = value
return writeTX
```

#### For sending ERC20

```swift
// web3swift 1.0
guard let destinationEthAddress = EthereumAddress(destinationAddressString) else {return}
guard let amount = Web3.Utils.parseToBigUInt(amountString, units: .eth) else {return}
let web3 = web3swift.web3(provider: InfuraProvider(Networks.Mainnet)!) //or any other network
web3.addKeystoreManager(KeysService().keystoreManager())
let contract = self.contract(for: token, web3: web3)
var options = Web3Options.defaultOptions()
guard let tokenAddress = EthereumAddress(token),
let fromAddress = Web3SwiftService.currentAddress,
let intermediate = web3.eth.sendERC20tokensWithNaturalUnits(tokenAddress: tokenAddress,
from: fromAddress,
to: destinationEthAddress,
amount: amountString) else {return}
//MARK: - Just to check that everything is all right
guard let _ = contract?.method(options: options)?.estimateGas(options: options).value else {return}
guard let gasPrice = web3.eth.getGasPrice().value else {return}
options.from = Web3SwiftService.currentAddress
options.gasPrice = gasPrice
options.value = 0
options.to = EthereumAddress(token)
let parameters = [destinationEthAddress, amount] as [Any]
guard let transaction = contract?.method("transfer",
parameters: parameters as [AnyObject],
options: options) else {return}
return transaction

// web3swift 2.0
guard let contractAddress = EthereumAddress(contractAddressString) else {return}
guard let amount = Web3.Utils.parseToBigUInt(amountString, units: .eth) else {return}
guard let selectedKey = KeysService().selectedWallet()?.address else {return}
let web3 = Web3.InfuraMainnetWeb3() //or any other network
web3.addKeystoreManager(KeysService().keystoreManager())
guard let ethAddressFrom = EthereumAddress(selectedKey) else {return}
guard let contract = web3.contract(Web3.Utils.erc20ABI, at: contractAddress, abiVersion: 2) else {return}
guard let writeTX = contract.write("transfer") else {return}
writeTX.transactionOptions.from = ethAddressFrom
writeTX.transactionOptions.value = value
return writeTX
```

#### For sending to contract

```swift
// web3swift 1.0
let wallet = TransactionsService.keyservice.selectedWallet()
guard let address = wallet?.address else {return}
guard let ethAddressFrom = EthereumAddress(address) else {return}
guard let ethContractAddress = EthereumAddress(contractAddress) else {return}
let web3 = Web3.InfuraMainnetWeb3() //or any other web
web3.addKeystoreManager(TransactionsService.keyservice.keystoreManager())
var options = predefinedOptions ?? Web3Options.defaultOptions()
options.from = ethAddressFrom
options.to = ethContractAddress
options.value = options.value ?? 0
guard let contract = web3.contract(contractAbi,
at: ethContractAddress,
abiVersion: 2) else {return}
guard let gasPrice = web3.eth.getGasPrice().value else {return}
options.gasPrice = predefinedOptions?.gasPrice ?? gasPrice
guard let transaction = contract.method(method,
parameters: data,
options: options) else {return}
guard case .success(let estimate) = transaction.estimateGas(options: options) else {return}
print("estimated cost: \(estimate)")
return transaction

// web3swift 2.0
guard let contractAddress = EthereumAddress(contractAddressString) else {return}
guard let amount = Web3.Utils.parseToBigUInt(amountString, units: .eth) else {return}
guard let selectedKey = KeysService().selectedWallet()?.address else {return}
let web3 = Web3.InfuraMainnetWeb3() //or any other network
web3.addKeystoreManager(KeysService().keystoreManager())
guard let ethAddressFrom = EthereumAddress(selectedKey) else {return}
guard let contract = web3.contract(contractAbi, at: contractAddress, abiVersion: 2) else {return}
guard let writeTX = contract.write(method,
parameters: parameters,
extraData: data,
transactionOptions: predefinedOptions) else {return}
writeTX.transactionOptions.from = ethAddressFrom
writeTX.transactionOptions.value = value
return writeTX
```

### Send transaction

In web3swift 1.0 you specified sending operations with only value and to contract in different, inconvenient and unobvious ways. From 2.0 on you can use two methods: Send to send ether or tokens and Call for calling contract methods.

#### For sending ether or tokens to wallets and contracts

```swift
// web3swift 1.0
let result = transaction.send(password: <your password>,
options: options)
if let error = result.error {return}
guard let value = result.value else {return}
return value

// web3swift 2.0
let options = options ?? transaction.transactionOptions
guard let result = password == nil ?
try? transaction.send() :
try? transaction.send(password: <your password>, transactionOptions: options) else {return}
return result
```

#### For calling contract methods

```swift
// web3swift 1.0
let result = transaction.send(password: <your password>,
options: transaction.options)
if let error = result.error {return}
guard let value = result.value else {return}
return value

// web3swift 2.0
let options = options ?? transaction.transactionOptions
guard let result = try? transaction.call(transactionOptions: options) else {return}
return result
```

### Get balance

### Get Ether balance

```swift
// web3swift 1.0
let address = EthereumAddress("<Address>")!
let web3Main = Web3.InfuraMainnetWeb3()
let balanceResult = web3Main.eth.getBalance(address)
guard case .success(let balance) = balanceResult else {return}
let balanceString = Web3.Utils.formatToEthereumUnits(balance, toUnits: .eth, decimals: 3)

// web3swift 2.0
let address = EthereumAddress("<Address>")!
let web3Main = Web3.InfuraMainnetWeb3()
let balance = try web3.eth.getBalance(address: address)
let balanceString = Web3.Utils.formatToEthereumUnits(balance, toUnits: .eth, decimals: 3)
```

### Get ERC20 balance

```swift
// web3swift 1.0
let contractAddress = EthereumAddress("<Contract ddress>")! // w3s token on Ethereum mainnet
let contract = web3.contract(Web3.Utils.erc20ABI, at: contractAddress, abiVersion: 2)! // utilize precompiled ERC20 ABI for your concenience
guard let w3sBalanceResult = contract.method("balanceOf",
parameters: [coldWalletAddress] as [AnyObject],
options: options)?.call(options: nil) else {return} // encode parameters for transaction
guard case .success(let w3sBalance) = w3sBalanceResult, let bal = w3sBalance["0"] as? BigUInt else {return} // w3sBalance is [String: Any], and parameters are enumerated as "0", "1", etc in order of being returned. If returned parameter has a name in ABI, it is also duplicated

// web3swift 2.0
let contractAddress = EthereumAddress("<Contract address>")! // w3s token on Ethereum mainnet
let contract = web3.contract(Web3.Utils.erc20ABI, at: contractAddress, abiVersion: 2) // utilize precompiled ERC20 ABI for your concenience
let userAddress = EthereumAddress("<address>")!
guard let readTX = contract?.read("balanceOf", parameters: [addressOfUser] as [AnyObject]) else {return}
readTX.transactionOptions.from = EthereumAddress("<address>")!
let tokenBalance = try readTX.callPromise().wait()
guard let balance = tokenBalance["0"] as? BigUInt else {return}
```

### Chain state

### Get Block number

```swift
// web3swift 1.0
let web3 = WalletWeb3Factory.web3()
let res = web3.eth.getBlockNumber()
switch res {
case .failure(let error):
return error
case .success(let number):
return number
}

// web3swift 2.0
do {
let number = try web3.eth.getBlockNumber()
return number
} catch let error {
return error
}
```
7 changes: 7 additions & 0 deletions Example/web3swiftBrowser/Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
platform :ios, '12.0'

target 'web3swiftBrowser' do
use_frameworks!
pod 'web3swift', :path => '../../'
pod "WKBridge"
end
73 changes: 73 additions & 0 deletions Example/web3swiftBrowser/Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
PODS:
- BigInt (3.1.0):
- SipHash (~> 1.2)
- CryptoSwift (0.13.0)
- EthereumABI (1.1.1):
- BigInt (~> 3.1)
- CryptoSwift (~> 0.13)
- EthereumAddress (~> 1.0.0)
- EthereumAddress (1.0.0):
- CryptoSwift (~> 0.13)
- PromiseKit (6.5.2):
- PromiseKit/CorePromise (= 6.5.2)
- PromiseKit/Foundation (= 6.5.2)
- PromiseKit/UIKit (= 6.5.2)
- PromiseKit/CorePromise (6.5.2)
- PromiseKit/Foundation (6.5.2):
- PromiseKit/CorePromise
- PromiseKit/UIKit (6.5.2):
- PromiseKit/CorePromise
- scrypt (2.0):
- CryptoSwift (~> 0.11)
- secp256k1_swift (1.0.3)
- SipHash (1.2.2)
- SwiftRLP (1.2):
- BigInt (~> 3.1)
- web3swift (2.0.1):
- BigInt (~> 3.1)
- CryptoSwift (~> 0.13)
- EthereumABI (~> 1.1.1)
- EthereumAddress (~> 1.0.0)
- PromiseKit (~> 6.3)
- scrypt (~> 2.0)
- secp256k1_swift (~> 1.0.3)
- SwiftRLP (~> 1.1)
- WKBridge (0.2.4)

DEPENDENCIES:
- web3swift (from `../../`)
- WKBridge

SPEC REPOS:
https://github.com/cocoapods/specs.git:
- BigInt
- CryptoSwift
- EthereumABI
- EthereumAddress
- PromiseKit
- scrypt
- secp256k1_swift
- SipHash
- SwiftRLP
- WKBridge

EXTERNAL SOURCES:
web3swift:
:path: "../../"

SPEC CHECKSUMS:
BigInt: 76b5dfdfa3e2e478d4ffdf161aeede5502e2742f
CryptoSwift: 16e78bebf567bad1c87b2d58f6547f25b74c31aa
EthereumABI: f040f5429e5a4366d028c88b88d9441e137593af
EthereumAddress: f476e1320dca3a0024431e713ede7a09c7eb7796
PromiseKit: 27c1601bfb73405871b805bcb8cf7e55c4dad3db
scrypt: 3fe5b1a3b0976f97cd87488673a8f7c65708cc84
secp256k1_swift: 4fc5c4b2d2c6d21ee8ccb868cdc92da12f38bed9
SipHash: fad90a4683e420c52ef28063063dbbce248ea6d4
SwiftRLP: 98a02b2210128353ca02e4c2f4d83e2a9796db4f
web3swift: aadc7a9b0c3b0384227eff181e39ba24ebfcd76c
WKBridge: 677fc36b9a9e4a80b6f9c4e915480d8fd91f5ad5

PODFILE CHECKSUM: ed17f63e9fc4feec3b3d9d88971f86da22d55a1f

COCOAPODS: 1.6.0.beta.2
Loading