|
2 | 2 |
|
3 | 3 | ### Create Account
|
4 | 4 |
|
| 5 | +```swift |
| 6 | + // Create keystore and account with password. |
| 7 | + |
| 8 | + let keystore = try! EthereumKeystoreV3(password: "changeme"); // generates a private key internally if node "privateKey" parameter supplied |
| 9 | + let account = keystore!.addresses![0] |
| 10 | + print(account) |
| 11 | + |
| 12 | + let data = try! keystore!.serialize() // internally serializes to JSON |
| 13 | + print(try! JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions(rawValue:0))) |
| 14 | + let key = try! keystore!.UNSAFE_getPrivateKeyData(password: "changeme", account: account) // you should rarely use this and expose a key manually |
| 15 | +``` |
5 | 16 |
|
6 | 17 | ### Import Account
|
7 | 18 |
|
8 | 19 |
|
9 | 20 | ### Manage Keystore
|
10 | 21 |
|
| 22 | +#### Save keystore to the memory |
| 23 | + |
| 24 | +```swift |
| 25 | +//First you need a `KeystoreManager` instance: |
| 26 | +guard let userDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first, |
| 27 | + let keystoreManager = KeystoreManager.managerForPath(userDirectory + "/keystore") |
| 28 | +else { |
| 29 | + fatalError("Couldn't create a KeystoreManager.") |
| 30 | +} |
| 31 | + |
| 32 | +//Next you create a new Keystore: |
| 33 | + |
| 34 | +let newKeystore = try? EthereumKeystoreV3(password: "YOUR_PASSWORD") |
| 35 | + |
| 36 | +// Then you save the created keystore to the file system: |
| 37 | + |
| 38 | +let newKeystoreJSON = try? JSONEncoder().encode(newKeystore.keystoreParams) |
| 39 | +FileManager.default.createFile(atPath: "\(keystoreManager.path)/keystore.json", contents: newKeystoreJSON, attributes: nil) |
| 40 | + |
| 41 | +// Later you can retreive it: |
| 42 | + |
| 43 | +if let address = keystoreManager.addresses?.first, |
| 44 | +let retrievedKeystore = keystoreManager.walletForAddress(address) as? EthereumKeystoreV3 { |
| 45 | + return retrievedKeystore |
| 46 | +} |
| 47 | +``` |
11 | 48 |
|
12 | 49 | ### Ethereum Address
|
13 | 50 |
|
| 51 | +#### Initializing Ethereum Address |
| 52 | + |
| 53 | +```swift |
| 54 | +let coldWalletAddress = EthereumAddress("0x6394b37Cf80A7358b38068f0CA4760ad49983a1B") |
| 55 | +let constractAddress = EthereumAddress("0x45245bc59219eeaaf6cd3f382e078a461ff9de7b", ignoreChecksum: true) |
| 56 | +``` |
| 57 | +Ethereum addresses are checksum checked if they are not lowercased or uppercased and always length checked |
14 | 58 |
|
15 | 59 | ### Get Balance
|
16 | 60 |
|
| 61 | +#### Getting ETH balance |
| 62 | + |
| 63 | +```swift |
| 64 | +let address = EthereumAddress("0xE6877A4d8806e9A9F12eB2e8561EA6c1db19978d")! |
| 65 | +let web3Main = Web3.InfuraMainnetWeb3() |
| 66 | +let balanceResult = web3Main.eth.getBalance(address) |
| 67 | +guard case .success(let balance) = balanceResult else {return} |
| 68 | +``` |
| 69 | + |
| 70 | +#### Getting ERC20 token balance |
| 71 | +```swift |
| 72 | +let contractAddress = EthereumAddress("0x45245bc59219eeaaf6cd3f382e078a461ff9de7b")! // BKX token on Ethereum mainnet |
| 73 | +let contract = web3.contract(Web3.Utils.erc20ABI, at: contractAddress, abiVersion: 2)! // utilize precompiled ERC20 ABI for your concenience |
| 74 | +guard let bkxBalanceResult = contract.method("balanceOf", parameters: [coldWalletAddress] as [AnyObject], options: options)?.call(options: nil) else {return} // encode parameters for transaction |
| 75 | +guard case .success(let bkxBalance) = bkxBalanceResult, let bal = bkxBalance["0"] as? BigUInt else {return} // bkxBalance 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 |
| 76 | +print("BKX token balance = " + String(bal)) |
| 77 | +``` |
17 | 78 |
|
18 | 79 | ### Prepare Transaction
|
19 | 80 |
|
| 81 | +#### Setting Transaction Options |
| 82 | + |
| 83 | +```swift |
| 84 | +var options = Web3Options.defaultOptions() |
| 85 | + // public var to: EthereumAddress? = nil - to what address transaction is aimed |
| 86 | + // public var from: EthereumAddress? = nil - form what address it should be sent (either signed locally or on the node) |
| 87 | + // public var gasLimit: BigUInt? = BigUInt(90000) - default gas limit |
| 88 | + // public var gasPrice: BigUInt? = BigUInt(5000000000) - default gas price, quite small |
| 89 | + // public var value: BigUInt? = BigUInt(0) - amount of WEI sent along the transaction |
| 90 | +options.gasPrice = gasPrice |
| 91 | +options.gasLimit = gasLimit |
| 92 | +options.from = EthereumAddress("0xE6877A4d8806e9A9F12eB2e8561EA6c1db19978d") |
| 93 | +``` |
20 | 94 |
|
21 | 95 | ### Send Transaction
|
22 | 96 |
|
| 97 | +#### Sending ETH |
| 98 | + |
| 99 | +```swift |
| 100 | +let web3Rinkeby = Web3.InfuraRinkebyWeb3() |
| 101 | +web3Rinkeby.addKeystoreManager(bip32keystoreManager) // attach a keystore if you want to sign locally. Otherwise unsigned request will be sent to remote node |
| 102 | +options.from = bip32ks?.addresses?.first! // specify from what address you want to send it |
| 103 | +intermediateSend = web3Rinkeby.contract(Web3.Utils.coldWalletABI, at: coldWalletAddress, abiVersion: 2)!.method(options: options)! // an address with a private key attached in not different from any other address, just has very simple ABI |
| 104 | +let sendResultBip32 = intermediateSend.send(password: "changeme") |
| 105 | +``` |
| 106 | + |
| 107 | +#### Sending ERC20 |
| 108 | +```swift |
| 109 | +var convenienceTransferOptions = Web3Options.defaultOptions() |
| 110 | +convenienceTransferOptions.gasPrice = gasPriceRinkeby |
| 111 | +let convenienceTokenTransfer = web3Rinkeby.eth.sendERC20tokensWithNaturalUnits(tokenAddress: EthereumAddress("0xa407dd0cbc9f9d20cdbd557686625e586c85b20a")!, from: (ks?.addresses?.first!)!, to: EthereumAddress("0x6394b37Cf80A7358b38068f0CA4760ad49983a1B")!, amount: "0.0001", options: convenienceTransferOptions) // there are also convenience functions to send ETH and ERC20 under the .eth structure |
| 112 | +let gasEstimateResult = convenienceTokenTransfer!.estimateGas(options: nil) |
| 113 | +guard case .success(let gasEstimate) = gasEstimateResult else {return} |
| 114 | +convenienceTransferOptions.gasLimit = gasEstimate |
| 115 | +let convenienceTransferResult = convenienceTokenTransfer!.send(password: "changeme", options: convenienceTransferOptions) |
| 116 | +switch convenienceTransferResult { |
| 117 | + case .success(let res): |
| 118 | + print("Token transfer successful") |
| 119 | + print(res) |
| 120 | + case .failure(let error): |
| 121 | + print(error) |
| 122 | +} |
| 123 | +``` |
23 | 124 |
|
24 | 125 | ### Get gas price
|
25 | 126 |
|
| 127 | +```swift |
| 128 | +let web3Main = Web3.InfuraMainnetWeb3() |
| 129 | +let gasPriceResult = web3Main.eth.getGasPrice() |
| 130 | +guard case .success(let gasPrice) = gasPriceResult else {return} |
| 131 | +``` |
26 | 132 |
|
27 | 133 | ### Serialize & deserialize transactions
|
28 | 134 |
|
|
0 commit comments