Skip to content

Commit 9d06896

Browse files
chore: documentation update with detailed guides for function deploy
1 parent b4745fb commit 9d06896

File tree

2 files changed

+99
-16
lines changed

2 files changed

+99
-16
lines changed

Sources/web3swift/Contract/ContractProtocol.swift

Lines changed: 83 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,31 @@
99
import Foundation
1010
import BigInt
1111

12+
/// Standard representation of a smart contract.
1213
public protocol ContractProtocol {
14+
/// Address of the referenced smart contract. Can be set later, e.g. if the contract is deploying and address is not yet known.
1315
var address: EthereumAddress? {get set}
1416

1517
/// All ABI elements like: events, functions, constructors and errors.
1618
var abi: [ABI.Element] {get}
1719

18-
/// Functions filtered from `abi`.
19-
/// Contains methods mapped to function name, like `getData`,
20-
/// name with input parameters `getData(bytes32)` and 4 bytes signature `0xffffffff` (expected to be lowercased).
20+
/// Functions filtered from ``abi``.
21+
/// Functions are mapped to:
22+
/// - name, like `getData` that is defined in ``ABI/Element/Function/name``;
23+
/// - name with input parameters that is a combination of ``ABI/Element/Function/name`` and
24+
/// ``ABI/Element/Function/inputs``, e.g. `getData(bytes32)`;
25+
/// - and 4 bytes signature `0xffffffff` (expected to be lowercased).
2126
/// The mapping by name (e.g. `getData`) is the one most likely expected to return arrays with
2227
/// more than one entry due to the fact that solidity allows method overloading.
2328
var methods: [String:[ABI.Element.Function]] {get}
2429

25-
/// All entries from `methods`.
30+
/// All values from ``methods``.
2631
var allMethods: [ABI.Element.Function] {get}
2732

28-
/// Events filtered from `abi`.
33+
/// Events filtered from ``abi`` and mapped to their unchanged ``ABI/Element/Event/name``.
2934
var events: [String:ABI.Element.Event] {get}
3035

31-
/// All events from `events`.
36+
/// All values from ``events``.
3237
var allEvents: [ABI.Element.Event] {get}
3338

3439
/// Errors filtered from ``abi`` and mapped to their unchanged ``ABI/Element/EthError/name``.
@@ -49,7 +54,64 @@ public protocol ContractProtocol {
4954
/// new Solidity keywords, types etc. that are not yet supported, etc.
5055
init(_ abiString: String, at: EthereumAddress?) throws
5156

52-
/// Creates transaction to deploy a smart contract.
57+
/// Creates a smart contract deployment transaction.
58+
///
59+
/// ## How to
60+
/// To create a smart contract deployment transaction there is only one requirement - `bytecode`.
61+
/// That is the compiled smart contract that is ready to be executed by EVM, or eWASM if that is a Serenity.
62+
/// Creating a transaction is as simple as:
63+
///
64+
/// ```swift
65+
/// contractInstance.deploy(bytecode: smartContractBytecode)
66+
/// ```
67+
///
68+
/// One of the default implementations of `ContractProtocol` is ``EthereumContract``.
69+
/// ```swift
70+
/// let contract = EthereumContract(abi: [])
71+
/// contract.deploy(bytecode: smartContractBytecode)
72+
/// ```
73+
///
74+
/// ### Setting constructor arguments
75+
/// Some smart contracts expect input arguments for a constructor that is called on contract deployment.
76+
/// To set these input arguments you must provide `constructor` and `parameters`.
77+
/// Constructor can be statically created if you know upfront what are the input arguments and their exact order:
78+
///
79+
/// ```swift
80+
/// let inputArgsTypes: [ABI.Element.InOut] = [.init(name: "firstArgument", type: ABI.Element.ParameterType.string),
81+
/// .init(name: "secondArgument", type: ABI.Element.ParameterType.uint(bits: 256))]
82+
/// let constructor = ABI.Element.Constructor(inputs: inputArgsTypes, constant: false, payable: payable)
83+
/// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
84+
///
85+
/// contract.deploy(bytecode: smartContractBytecode,
86+
/// constructor: constructor,
87+
/// parameters: constructorArguments)
88+
/// ```
89+
///
90+
/// Alternatively, if you have ABI string that holds meta data about the constructor you can use it instead of creating constructor manually.
91+
/// But you must make sure the arguments for constructor call are of expected type in and correct order.
92+
/// Example of ABI string can be found in ``Web3/Utils/erc20ABI``.
93+
///
94+
/// ```swift
95+
/// let contract = EthereumContract(abiString)
96+
/// let constructorArguments = ["This is the array of constructor arguments", 10_000] as [AnyObject]
97+
///
98+
/// contract.deploy(bytecode: smartContractBytecode,
99+
/// constructor: contract.constructor,
100+
/// parameters: constructorArguments)
101+
/// ```
102+
///
103+
/// ⚠️ If you pass in only constructor or only parameters - it will have no effect on the final transaction object.
104+
/// Also, you have an option to set any extra bytes at the end of ``EthereumTransaction/data`` attribute.
105+
/// Alternatively you can encode constructor parameters outside of the deploy function and only set `extraData` to pass in these
106+
/// parameters:
107+
///
108+
/// ```swift
109+
/// // `encodeParameters` call returns `Data?`. Check it for nullability before calling `deploy`
110+
/// // function to create `EthereumTransaction`.
111+
/// let encodedConstructorArguments = someConstructor.encodeParameters(arrayOfInputArguments)
112+
/// constructor.deploy(bytecode: smartContractBytecode, extraData: encodedConstructorArguments)
113+
/// ```
114+
///
53115
/// - Parameters:
54116
/// - bytecode: bytecode to deploy.
55117
/// - constructor: constructor of the smart contract bytecode is related to. Used to encode `parameters`.
@@ -103,12 +165,19 @@ public protocol ContractProtocol {
103165
func decodeInputData(_ data: Data) -> [String: Any]?
104166

105167
/// Attempts to parse given event based on the data from `allEvents`, or in other words based on the given smart contract ABI.
106-
func parseEvent(_ eventLog: EventLog) -> (eventName:String?, eventData:[String: Any]?)
168+
func parseEvent(_ eventLog: EventLog) -> (eventName: String?, eventData: [String: Any]?)
107169

108-
func testBloomForEventPrecence(eventName: String, bloom: EthereumBloomFilter) -> Bool?
170+
/// Tests for probable presence of an event with `eventName` in a given bloom filter.
171+
/// - Parameters:
172+
/// - eventName: event name like `ValueReceived`.
173+
/// - bloom: bloom filter.
174+
/// - Returns: `true` if event is possibly present, `false` if definitely not present and `nil` if event with given name
175+
/// is not part of the ``EthereumContract/abi``.
109176
func testBloomForEventPresence(eventName: String, bloom: EthereumBloomFilter) -> Bool?
110177
}
111178

179+
// MARK: - Overloaded ContractProtocol's functions
180+
112181
extension ContractProtocol {
113182

114183
/// Overloading of ``ContractProtocol/deploy(bytecode:constructor:parameters:extraData:)`` to allow
@@ -119,10 +188,10 @@ extension ContractProtocol {
119188
constructor: ABI.Element.Constructor? = nil,
120189
parameters: [AnyObject]? = nil,
121190
extraData: Data? = nil) -> EthereumTransaction? {
122-
return deploy(bytecode: bytecode,
123-
constructor: constructor,
124-
parameters: parameters,
125-
extraData: extraData)
191+
deploy(bytecode: bytecode,
192+
constructor: constructor,
193+
parameters: parameters,
194+
extraData: extraData)
126195
}
127196

128197
/// Overloading of ``ContractProtocol/method(_:parameters:extraData:)`` to allow
@@ -132,7 +201,7 @@ extension ContractProtocol {
132201
func method(_ method: String = "fallback",
133202
parameters: [AnyObject]? = nil,
134203
extraData: Data? = nil) -> EthereumTransaction? {
135-
return self.method(method, parameters: parameters ?? [], extraData: extraData)
204+
self.method(method, parameters: parameters ?? [], extraData: extraData)
136205
}
137206

138207
func decodeInputData(_ data: Data) -> [String: Any]? {

Sources/web3swift/EthereumAddress/EthereumAddress.swift

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@ public struct EthereumAddress: Equatable {
3232
return lhs.addressData == rhs.addressData && lhs.type == rhs.type
3333
}
3434

35+
/// Raw representation of the address.
36+
/// If the ``type`` is ``EthereumAddress/AddressType/contractDeployment`` an empty `Data` object is returned.
3537
public var addressData: Data {
3638
get {
3739
switch self.type {
@@ -43,6 +45,9 @@ public struct EthereumAddress: Equatable {
4345
}
4446
}
4547
}
48+
49+
/// Checksummed address with `0x` HEX prefix.
50+
/// If the ``type`` is ``EthereumAddress/AddressType/contractDeployment`` only `0x` prefix is returned.
4651
public var address: String {
4752
switch self.type {
4853
case .normal:
@@ -52,6 +57,11 @@ public struct EthereumAddress: Equatable {
5257
}
5358
}
5459

60+
/// Validates and checksumms given `addr`.
61+
/// If given string is not an address, incomplete address or is invalid validation will fail and `nil` will be returned.
62+
/// - Parameter addr: address in string format, case insensitive, `0x` prefix is not required.
63+
/// - Returns: validates and checksumms the address. Returns `nil` if checksumm has failed or given string cannot be
64+
/// represented as `ASCII` data. Otherwise, checksummed address is returned with `0x` prefix.
5565
public static func toChecksumAddress(_ addr: String) -> String? {
5666
let address = addr.lowercased().stripHexPrefix()
5767
guard let hash = address.data(using: .ascii)?.sha3(.keccak256).toHexString().stripHexPrefix() else {return nil}
@@ -72,15 +82,19 @@ public struct EthereumAddress: Equatable {
7282
return ret
7383
}
7484

85+
/// Creates a special ``EthereumAddress`` that serves the purpose of the receiver, or `to` address of a transaction if it is a
86+
/// smart contract deployment.
87+
/// - Returns: special instance with type ``EthereumAddress/AddressType/contractDeployment`` and
88+
/// empty ``EthereumAddress/address``.
7589
public static func contractDeploymentAddress() -> EthereumAddress {
76-
return EthereumAddress("0x", type: .contractDeployment)!
90+
EthereumAddress("0x", type: .contractDeployment)!
7791
}
7892
}
7993

8094
/// In swift structs it's better to implement initializers in extension
8195
/// Since it's make available syntetized initializer then for free.
8296
extension EthereumAddress {
83-
public init?(_ addressString:String, type: AddressType = .normal, ignoreChecksum: Bool = false) {
97+
public init?(_ addressString: String, type: AddressType = .normal, ignoreChecksum: Bool = false) {
8498
switch type {
8599
case .normal:
86100
guard let data = Data.fromHex(addressString) else {return nil}

0 commit comments

Comments
 (0)