Skip to content

Commit 57fb16b

Browse files
Merge pull request #677 from janndriessen/task/erc20-read-properties
ERC20 read properties issue
2 parents e2b248d + 2f1b5e3 commit 57fb16b

File tree

16 files changed

+149
-195
lines changed

16 files changed

+149
-195
lines changed

Sources/web3swift/Tokens/ERC1376/Web3+ERC1376.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -67,23 +67,14 @@ protocol IERC1376: IERC20 {
6767

6868
// FIXME: Rewrite this to CodableTransaction
6969
public class ERC1376: IERC1376, ERC20BaseProperties {
70-
71-
internal var _name: String?
72-
internal var _symbol: String?
73-
internal var _decimals: UInt8?
74-
internal var _hasReadProperties: Bool = false
75-
70+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
7671
public var transaction: CodableTransaction
7772
public var web3: Web3
7873
public var provider: Web3Provider
7974
public var address: EthereumAddress
8075
public var abi: String
8176

82-
lazy var contract: Web3.Contract = {
83-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
84-
precondition(contract != nil)
85-
return contract!
86-
}()
77+
public let contract: Web3.Contract
8778

8879
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1376ABI, transaction: CodableTransaction = .emptyTransaction) {
8980
self.web3 = web3
@@ -92,6 +83,9 @@ public class ERC1376: IERC1376, ERC20BaseProperties {
9283
self.transaction = transaction
9384
self.transaction.to = address
9485
self.abi = abi
86+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
87+
contract = web3.contract(abi, at: address)!
88+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
9589
}
9690

9791
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1400/Web3+ERC1400.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -64,23 +64,14 @@ protocol IERC1400: IERC20 {
6464
// can be imperatively read and saved
6565
// FIXME: Rewrite this to CodableTransaction
6666
public class ERC1400: IERC1400, ERC20BaseProperties {
67-
68-
internal var _name: String?
69-
internal var _symbol: String?
70-
internal var _decimals: UInt8?
71-
internal var _hasReadProperties: Bool = false
72-
67+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
7368
public var transaction: CodableTransaction
7469
public var web3: Web3
7570
public var provider: Web3Provider
7671
public var address: EthereumAddress
7772
public var abi: String
7873

79-
lazy var contract: Web3.Contract = {
80-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
81-
precondition(contract != nil)
82-
return contract!
83-
}()
74+
public let contract: Web3.Contract
8475

8576
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1400ABI, transaction: CodableTransaction = .emptyTransaction) {
8677
self.web3 = web3
@@ -89,6 +80,9 @@ public class ERC1400: IERC1400, ERC20BaseProperties {
8980
self.transaction = transaction
9081
self.transaction.to = address
9182
self.abi = abi
83+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
84+
contract = web3.contract(abi, at: address)!
85+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
9286
}
9387

9488
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1410/Web3+ERC1410.swift

Lines changed: 5 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -42,24 +42,14 @@ protocol IERC1410: IERC20 {
4242

4343
// FIXME: Rewrite this to CodableTransaction
4444
public class ERC1410: IERC1410, ERC20BaseProperties {
45-
46-
internal var _name: String?
47-
internal var _symbol: String?
48-
internal var _decimals: UInt8?
49-
private var _totalSupply: BigUInt?
50-
internal var _hasReadProperties: Bool = false
51-
45+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
5246
public var transaction: CodableTransaction
5347
public var web3: Web3
5448
public var provider: Web3Provider
5549
public var address: EthereumAddress
5650
public var abi: String
5751

58-
lazy var contract: Web3.Contract = {
59-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
60-
precondition(contract != nil)
61-
return contract!
62-
}()
52+
public let contract: Web3.Contract
6353

6454
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1410ABI, transaction: CodableTransaction = .emptyTransaction) {
6555
self.web3 = web3
@@ -68,6 +58,9 @@ public class ERC1410: IERC1410, ERC20BaseProperties {
6858
self.abi = abi
6959
self.transaction = transaction
7060
self.transaction.to = address
61+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
62+
contract = web3.contract(abi, at: address)!
63+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
7164
}
7265

7366
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1594/Web3+ERC1594.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -32,23 +32,14 @@ protocol IERC1594: IERC20 {
3232

3333
// FIXME: Rewrite this to CodableTransaction
3434
public class ERC1594: IERC1594, ERC20BaseProperties {
35-
36-
internal var _name: String?
37-
internal var _symbol: String?
38-
internal var _decimals: UInt8?
39-
internal var _hasReadProperties: Bool = false
40-
35+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
4136
public var transaction: CodableTransaction
4237
public var web3: Web3
4338
public var provider: Web3Provider
4439
public var address: EthereumAddress
4540
public var abi: String
4641

47-
lazy var contract: Web3.Contract = {
48-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
49-
precondition(contract != nil)
50-
return contract!
51-
}()
42+
public let contract: Web3.Contract
5243

5344
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1594ABI, transaction: CodableTransaction = .emptyTransaction) {
5445
self.web3 = web3
@@ -57,6 +48,9 @@ public class ERC1594: IERC1594, ERC20BaseProperties {
5748
self.transaction = transaction
5849
self.transaction.to = address
5950
self.abi = abi
51+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
52+
contract = web3.contract(abi, at: address)!
53+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
6054
}
6155

6256
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1633/Web3+ERC1633.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,23 +19,14 @@ protocol IERC1633: IERC20, IERC165 {
1919
}
2020

2121
public class ERC1633: IERC1633, ERC20BaseProperties {
22-
23-
internal var _name: String?
24-
internal var _symbol: String?
25-
internal var _decimals: UInt8?
26-
internal var _hasReadProperties: Bool = false
27-
22+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
2823
public var transaction: CodableTransaction
2924
public var web3: Web3
3025
public var provider: Web3Provider
3126
public var address: EthereumAddress
3227
public var abi: String
3328

34-
lazy var contract: Web3.Contract = {
35-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
36-
precondition(contract != nil)
37-
return contract!
38-
}()
29+
public let contract: Web3.Contract
3930

4031
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1633ABI, transaction: CodableTransaction = .emptyTransaction) {
4132
self.web3 = web3
@@ -44,6 +35,9 @@ public class ERC1633: IERC1633, ERC20BaseProperties {
4435
self.transaction = transaction
4536
self.transaction.to = address
4637
self.abi = abi
38+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
39+
contract = web3.contract(abi, at: address)!
40+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
4741
}
4842

4943
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1643/Web3+ERC1643.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,23 +22,14 @@ protocol IERC1643: IERC20 {
2222

2323
// FIXME: Rewrite this to CodableTransaction
2424
public class ERC1643: IERC1643, ERC20BaseProperties {
25-
26-
internal var _name: String?
27-
internal var _symbol: String?
28-
internal var _decimals: UInt8?
29-
internal var _hasReadProperties: Bool = false
30-
25+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
3126
public var transaction: CodableTransaction
3227
public var web3: Web3
3328
public var provider: Web3Provider
3429
public var address: EthereumAddress
3530
public var abi: String
3631

37-
lazy var contract: Web3.Contract = {
38-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
39-
precondition(contract != nil)
40-
return contract!
41-
}()
32+
public let contract: Web3.Contract
4233

4334
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1643ABI, transaction: CodableTransaction = .emptyTransaction) {
4435
self.web3 = web3
@@ -47,6 +38,9 @@ public class ERC1643: IERC1643, ERC20BaseProperties {
4738
self.transaction = transaction
4839
self.transaction.to = address
4940
self.abi = abi
41+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
42+
contract = web3.contract(abi, at: address)!
43+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
5044
}
5145

5246
public func getBalance(account: EthereumAddress) async throws -> BigUInt {

Sources/web3swift/Tokens/ERC1644/Web3+ERC1644.swift

Lines changed: 5 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,14 @@ protocol IERC1644: IERC20 {
2121

2222
// FIXME: Rewrite this to CodableTransaction
2323
public class ERC1644: IERC1644, ERC20BaseProperties {
24-
25-
internal var _name: String?
26-
internal var _symbol: String?
27-
internal var _decimals: UInt8?
28-
internal var _hasReadProperties: Bool = false
29-
24+
public private(set) var basePropertiesProvider: ERC20BasePropertiesProvider
3025
public var transaction: CodableTransaction
3126
public var web3: Web3
3227
public var provider: Web3Provider
3328
public var address: EthereumAddress
3429
public var abi: String
3530

36-
lazy var contract: Web3.Contract = {
37-
let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2)
38-
precondition(contract != nil)
39-
return contract!
40-
}()
31+
public let contract: Web3.Contract
4132

4233
public init(web3: Web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1644ABI, transaction: CodableTransaction = .emptyTransaction) {
4334
self.web3 = web3
@@ -46,6 +37,9 @@ public class ERC1644: IERC1644, ERC20BaseProperties {
4637
self.transaction = transaction
4738
self.transaction.to = address
4839
self.abi = abi
40+
// TODO: Make `init` and `web3.contract.init` throwing. Forced because this should fail if ABI is wrongly configured
41+
contract = web3.contract(abi, at: address)!
42+
basePropertiesProvider = ERC20BasePropertiesProvider(contract: contract)
4943
}
5044

5145
public func getBalance(account: EthereumAddress) async throws -> BigUInt {
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
//
2+
// ERC20BaseProperties.swift
3+
//
4+
//
5+
// Created by Jann Driessen on 21.11.22.
6+
//
7+
8+
import Foundation
9+
10+
/// Declares common properties of an [ERC-20](https://eips.ethereum.org/EIPS/eip-20) complient smart contract.
11+
/// Default implementation of access to these properties is declared in the extension of this protocol.
12+
public protocol ERC20BaseProperties: AnyObject {
13+
var basePropertiesProvider: ERC20BasePropertiesProvider { get }
14+
var contract: Web3.Contract { get }
15+
var name: String? { get }
16+
var symbol: String? { get }
17+
var decimals: UInt8? { get }
18+
}
19+
20+
public extension ERC20BaseProperties {
21+
var name: String? {
22+
basePropertiesProvider.name
23+
}
24+
25+
var symbol: String? {
26+
basePropertiesProvider.symbol
27+
}
28+
29+
var decimals: UInt8? {
30+
basePropertiesProvider.decimals
31+
}
32+
33+
var hasReadProperties: Bool {
34+
basePropertiesProvider.hasReadProperties
35+
}
36+
37+
func readProperties() async throws {
38+
if basePropertiesProvider.hasReadProperties { return }
39+
try await basePropertiesProvider.readProperties()
40+
}
41+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
//
2+
// ERC20BasePropertiesProvider.swift
3+
//
4+
//
5+
// Created by Jann Driessen on 21.11.22.
6+
//
7+
8+
import BigInt
9+
import Foundation
10+
11+
/// The default implementation of access of common [ERC-20](https://eips.ethereum.org/EIPS/eip-20#methods) properties `name`, `symbol` and `decimals`.
12+
public final class ERC20BasePropertiesProvider {
13+
var name: String?
14+
var symbol: String?
15+
var decimals: UInt8?
16+
17+
private let contract: Web3.Contract
18+
private (set) var hasReadProperties: Bool = false
19+
init(contract: Web3.Contract) {
20+
self.contract = contract
21+
}
22+
23+
public func readProperties() async throws {
24+
guard !hasReadProperties else { return }
25+
guard contract.contract.address != nil else {return}
26+
name = try await contract
27+
.createReadOperation("name")?
28+
.callContractMethod()["0"] as? String
29+
30+
symbol = try await contract
31+
.createReadOperation("symbol")?
32+
.callContractMethod()["0"] as? String
33+
34+
let decimals = try await contract
35+
.createReadOperation("decimals")?
36+
.callContractMethod()["0"] as? BigUInt
37+
self.decimals = decimals != nil ? UInt8(decimals!) : nil
38+
hasReadProperties = true
39+
}
40+
}

0 commit comments

Comments
 (0)