Skip to content

Commit d6a710c

Browse files
started erc721
1 parent 47021be commit d6a710c

File tree

2 files changed

+216
-0
lines changed

2 files changed

+216
-0
lines changed

web3swift.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,7 @@
209209
E23B5AE320EA69B900DC7F32 /* web3swift_numberFormattingUtil_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5AE220EA69B900DC7F32 /* web3swift_numberFormattingUtil_Tests.swift */; };
210210
E23B5AE520EA6A0A00DC7F32 /* web3swift_contractV2_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E23B5AE420EA6A0A00DC7F32 /* web3swift_contractV2_Tests.swift */; };
211211
E2C590762152835400FF53D3 /* JSONRPCrequestDispatcher+ObjC.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2C590752152835400FF53D3 /* JSONRPCrequestDispatcher+ObjC.swift */; };
212+
E2E94C60217788E0005F54A0 /* Web3+ERC721.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2E94C5F217788E0005F54A0 /* Web3+ERC721.swift */; };
212213
/* End PBXBuildFile section */
213214

214215
/* Begin PBXContainerItemProxy section */
@@ -376,6 +377,7 @@
376377
E23B5AE220EA69B900DC7F32 /* web3swift_numberFormattingUtil_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_numberFormattingUtil_Tests.swift; sourceTree = "<group>"; };
377378
E23B5AE420EA6A0A00DC7F32 /* web3swift_contractV2_Tests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = web3swift_contractV2_Tests.swift; sourceTree = "<group>"; };
378379
E2C590752152835400FF53D3 /* JSONRPCrequestDispatcher+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONRPCrequestDispatcher+ObjC.swift"; sourceTree = "<group>"; };
380+
E2E94C5F217788E0005F54A0 /* Web3+ERC721.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC721.swift"; sourceTree = "<group>"; };
379381
FB43EC035C593F9E5A3644B6 /* Pods-web3swift-macOS.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-web3swift-macOS.debug.xcconfig"; path = "Pods/Target Support Files/Pods-web3swift-macOS/Pods-web3swift-macOS.debug.xcconfig"; sourceTree = "<group>"; };
380382
FC1E6C115639177F2629E42A /* Pods_web3swift_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_web3swift_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; };
381383
/* End PBXFileReference section */
@@ -615,6 +617,7 @@
615617
8159C50921343EF900197B91 /* PrecompiledContracts */ = {
616618
isa = PBXGroup;
617619
children = (
620+
E2E94C5E2177886C005F54A0 /* ERC721 */,
618621
8159C50621343ED300197B91 /* ERC20 */,
619622
);
620623
path = PrecompiledContracts;
@@ -815,6 +818,14 @@
815818
name = Pods;
816819
sourceTree = "<group>";
817820
};
821+
E2E94C5E2177886C005F54A0 /* ERC721 */ = {
822+
isa = PBXGroup;
823+
children = (
824+
E2E94C5F217788E0005F54A0 /* Web3+ERC721.swift */,
825+
);
826+
path = ERC721;
827+
sourceTree = "<group>";
828+
};
818829
/* End PBXGroup section */
819830

820831
/* Begin PBXHeadersBuildPhase section */
@@ -1095,6 +1106,7 @@
10951106
817EBB122004FE2F00E02EAA /* BIP32HDNode.swift in Sources */,
10961107
8113D2C41FD7E1590074282C /* CryptoExtensions.swift in Sources */,
10971108
81A1822220D678060016741F /* Promise+Web3+Eth+GetBlockNumber.swift in Sources */,
1109+
E2E94C60217788E0005F54A0 /* Web3+ERC721.swift in Sources */,
10981110
81C5DA252072E14E00424CD6 /* ABIv2Encoding.swift in Sources */,
10991111
81A1824220D7AA750016741F /* Promise+Web3+Eth+SendTransaction.swift in Sources */,
11001112
817EBB2920075D2E00E02EAA /* BIP39.swift in Sources */,
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
//
2+
// Web3+ERC721.swift
3+
// web3swift-iOS
4+
//
5+
// Created by Anton Grigorev on 17.10.2018.
6+
// Copyright © 2018 The Matter Inc. All rights reserved.
7+
//
8+
9+
import Foundation
10+
import BigInt
11+
import Result
12+
13+
// This namespace contains functions to work with ERC721 tokens.
14+
// variables are lazyly evaluated or global token information (name, ticker, total supply)
15+
// can be imperatively read and saved
16+
class ERC721 {
17+
private var _name: String? = nil
18+
private var _symbol: String? = nil
19+
private var _tokenId: BigUInt? = nil
20+
private var _tokenURI: String? = nil
21+
private var _owner: EthereumAddress? = nil
22+
private var _hasReadProperties: Bool = false
23+
24+
public var options: Web3Options
25+
public var web3: web3
26+
public var provider: Web3Provider
27+
public var address: EthereumAddress
28+
29+
lazy var contract: web3.web3contract = {
30+
let contract = self.web3.contract(Web3.Utils.erc721ABI, at: self.address, abiVersion: 2)
31+
precondition(contract != nil)
32+
return contract!
33+
}()
34+
35+
public init(web3: web3, provider: Web3Provider, address: EthereumAddress) {
36+
self.web3 = web3
37+
self.provider = provider
38+
self.address = address
39+
var mergedOptions = web3.options
40+
mergedOptions.to = address
41+
self.options = mergedOptions
42+
}
43+
44+
public var name: String {
45+
self.readProperties()
46+
if self._name != nil {
47+
return self._name!
48+
}
49+
return ""
50+
}
51+
52+
public var symbol: String {
53+
self.readProperties()
54+
if self._symbol != nil {
55+
return self._symbol!
56+
}
57+
return ""
58+
}
59+
60+
public var tokenId: BigUInt {
61+
self.readProperties()
62+
if self._tokenId != nil {
63+
return self._tokenId!
64+
}
65+
return 0
66+
}
67+
68+
public var tokenURI: String {
69+
self.readProperties()
70+
if self._tokenURI != nil {
71+
return self._tokenURI!
72+
}
73+
return ""
74+
}
75+
76+
public func readProperties() {
77+
if self._hasReadProperties {
78+
return
79+
}
80+
defer { self._hasReadProperties = true }
81+
let contract = self.contract
82+
guard contract.contract.address != nil else {return}
83+
guard let nameResult = contract.method("name", parameters: [] as [AnyObject], extraData: Data(), options: self.options)?.call(options: nil, onBlock: "latest") else {return}
84+
switch nameResult {
85+
case .success(let returned):
86+
guard let res = returned["0"] as? String else {break}
87+
self._name = res
88+
default:
89+
self._name = ""
90+
}
91+
92+
guard let symbol = contract.method("symbol", parameters: [] as [AnyObject], extraData: Data(), options: self.options)?.call(options: nil, onBlock: "latest") else {return}
93+
switch symbol {
94+
case .success(let returned):
95+
guard let res = returned["0"] as? String else {break}
96+
self._symbol = res
97+
default:
98+
self._symbol = ""
99+
}
100+
101+
guard let tokenId = contract.method("tokenId", parameters: [] as [AnyObject], extraData: Data(), options: self.options)?.call(options: nil, onBlock: "latest") else {return}
102+
switch tokenId {
103+
case .success(let returned):
104+
guard let res = returned["0"] as? BigUInt else {break}
105+
self._tokenId = res
106+
default:
107+
self._tokenId = 0
108+
}
109+
110+
guard let tokenURI = contract.method("tokenURI", parameters: [_tokenId] as [AnyObject], extraData: Data(), options: self.options)?.call(options: nil, onBlock: "latest") else {return}
111+
switch tokenURI {
112+
case .success(let returned):
113+
guard let res = returned["0"] as? String else {return}
114+
self._tokenURI = res
115+
default:
116+
self._tokenURI = ""
117+
}
118+
}
119+
120+
func getBalance(account: EthereumAddress) -> Result<BigUInt, Web3Error> {
121+
let contract = self.contract
122+
let result = contract.method("balanceOf", parameters: [account] as [AnyObject], extraData: Data(), options: self.options)!.call(options: nil, onBlock: "latest")
123+
switch result {
124+
case .success(let returned):
125+
guard let res = returned["0"] as? BigUInt else {return Result.failure(Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node"))}
126+
return Result(res)
127+
case .failure(let error):
128+
return Result.failure(error)
129+
}
130+
}
131+
132+
func getOwner(tokenId: BigUInt) -> Result<EthereumAddress, Web3Error> {
133+
let contract = self.contract
134+
let result = contract.method("ownerOf", parameters: [account] as [tokenId], extraData: Data(), options: self.options)!.call(options: nil, onBlock: "latest")
135+
switch result {
136+
case .success(let returned):
137+
guard let res = returned["0"] as? EthereumAddress else {return Result.failure(Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node"))}
138+
return Result(res)
139+
case .failure(let error):
140+
return Result.failure(error)
141+
}
142+
}
143+
144+
// func getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) -> Result<BigUInt, Web3Error> {
145+
// let contract = self.contract
146+
// let result = contract.method("allowance", parameters: [originalOwner, delegate] as [AnyObject], extraData: Data(), options: self.options)!.call(options: nil, onBlock: "latest")
147+
// switch result {
148+
// case .success(let returned):
149+
// guard let res = returned["0"] as? BigUInt else {return Result.failure(Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node"))}
150+
// return Result(res)
151+
// case .failure(let error):
152+
// return Result.failure(error)
153+
// }
154+
// }
155+
156+
func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt) -> Result<TransactionIntermediate, Web3Error> {
157+
let contract = self.contract
158+
var basicOptions = Web3Options()
159+
basicOptions.from = from
160+
basicOptions.to = self.address
161+
162+
let intermediateToSend = contract.method("transfer", parameters: [to, tokenId] as [AnyObject], options: basicOptions)!
163+
return Result(intermediateToSend)
164+
}
165+
166+
func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt) -> Result<TransactionIntermediate, Web3Error> {
167+
let contract = self.contract
168+
var basicOptions = Web3Options()
169+
basicOptions.from = from
170+
basicOptions.to = self.address
171+
172+
let intermediateToSend = contract.method("transferFrom", parameters: [originalOwner, to, tokenId] as [AnyObject], options: basicOptions)!
173+
return Result(intermediateToSend)
174+
}
175+
176+
// func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) -> Result<TransactionIntermediate, Web3Error> {
177+
// let contract = self.contract
178+
// var basicOptions = Web3Options()
179+
// basicOptions.from = from
180+
// basicOptions.to = self.address
181+
//
182+
// // get the decimals manually
183+
// let intermediate = contract.method("setAllowance", options: basicOptions)!
184+
// let callResult = intermediate.call(options: basicOptions, onBlock: "latest")
185+
// var decimals = BigUInt(0)
186+
// switch callResult {
187+
// case .success(let response):
188+
// guard let dec = response["0"], let decTyped = dec as? BigUInt else {
189+
// return Result.failure(Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals"))}
190+
// decimals = decTyped
191+
// break
192+
// case .failure(let error):
193+
// return Result.failure(error)
194+
// }
195+
// let intDecimals = Int(decimals)
196+
// guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else {
197+
// return Result.failure(Web3Error.inputError(desc: "Can not parse inputted amount"))
198+
// }
199+
// let intermediateToSend = contract.method("setAllowance", parameters: [to, value] as [AnyObject], options: basicOptions)!
200+
// return Result(intermediateToSend)
201+
// }
202+
203+
204+
}

0 commit comments

Comments
 (0)