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

Fixed erc721 precompiled contract #3

Merged
merged 7 commits into from
Dec 14, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
189 changes: 127 additions & 62 deletions web3swift/PrecompiledContracts/ERC721/Web3+ERC721.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,52 @@ import BigInt
import PromiseKit
import EthereumAddress

protocol IERC721 {

func getBalance(account: EthereumAddress) throws -> BigUInt

func getOwner(tokenId: BigUInt) throws -> EthereumAddress

func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction

func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction

func approve(from: EthereumAddress, approved: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction

func setApprovalForAll(from: EthereumAddress, operator user: EthereumAddress, approved: Bool) throws -> WriteTransaction

func getApproved(tokenId: BigUInt) throws -> EthereumAddress

func isApprovedForAll(owner: EthereumAddress, operator user: EthereumAddress) throws -> Bool
}

protocol IERC721Metadata {

func name() throws -> String

func symbol() throws -> String

func tokenURI(tokenId: BigUInt) throws -> String

}

protocol IERC721Enumerable {

func totalSupply() throws -> BigUInt

func tokenByIndex(index: BigUInt) throws -> BigUInt

func tokenOfOwnerByIndex(owner: EthereumAddress, index: BigUInt) throws -> BigUInt
}

// This namespace contains functions to work with ERC721 tokens.
// can be imperatively read and saved
public class ERC721 {
public class ERC721: IERC721 {

@available(*, deprecated, renamed: "transactionOptions")
public var options: Web3Options = .init()

private var _name: String? = nil
private var _symbol: String? = nil
private var _tokenId: BigUInt? = nil
private var _tokenURI: String? = nil
private var _hasReadProperties: Bool = false

public var transactionOptions: TransactionOptions
Expand All @@ -42,22 +77,6 @@ public class ERC721 {
self.transactionOptions = mergedOptions
}

public var name: String {
self.readProperties()
if self._name != nil {
return self._name!
}
return ""
}

public var symbol: String {
self.readProperties()
if self._symbol != nil {
return self._symbol!
}
return ""
}

public var tokenId: BigUInt {
self.readProperties()
if self._tokenId != nil {
Expand All @@ -66,14 +85,6 @@ public class ERC721 {
return 0
}

public var tokenURI: String {
self.readProperties()
if self._tokenURI != nil {
return self._tokenURI!
}
return ""
}

public func readProperties() {
if self._hasReadProperties {
return
Expand All @@ -82,33 +93,16 @@ public class ERC721 {
guard contract.contract.address != nil else {return}
var transactionOptions = TransactionOptions.defaultOptions
transactionOptions.callOnBlock = .latest
guard let namePromise = contract.read("name", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return}

guard let symbolPromise = contract.read("symbol", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return}

guard let tokenIdPromise = contract.read("tokenId", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return}

guard let tokenURIpromise = contract.read("tokenURI", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return}

let allPromises = [namePromise, symbolPromise, tokenIdPromise, tokenURIpromise]
let allPromises = [tokenIdPromise]
let queue = self.web3.requestDispatcher.queue
when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in
guard case .fulfilled(let nameResult) = resolvedPromises[0] else {return}
guard let name = nameResult["0"] as? String else {return}
self._name = name

guard case .fulfilled(let symbolResult) = resolvedPromises[1] else {return}
guard let symbol = symbolResult["0"] as? String else {return}
self._symbol = symbol

guard case .fulfilled(let tokenIdResult) = resolvedPromises[2] else {return}
guard case .fulfilled(let tokenIdResult) = resolvedPromises[0] else {return}
guard let tokenId = tokenIdResult["0"] as? BigUInt else {return}
self._tokenId = tokenId

guard case .fulfilled(let tokenURIresult) = resolvedPromises[3] else {return}
guard let uri = tokenURIresult["0"] as? String else {return}
self._tokenURI = uri

self._hasReadProperties = true
}.wait()
}
Expand All @@ -122,7 +116,7 @@ public class ERC721 {
return res
}

public func getOwner(tokenId: BigUInt) throws -> EthereumAddress{
public func getOwner(tokenId: BigUInt) throws -> EthereumAddress {
let contract = self.contract
var transactionOptions = TransactionOptions()
transactionOptions.callOnBlock = .latest
Expand All @@ -140,6 +134,66 @@ public class ERC721 {
return res
}

public func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from
basicOptions.to = self.address

let tx = contract.write("transfer", parameters: [to, tokenId] as [AnyObject], transactionOptions: basicOptions)!
return tx
}

public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from
basicOptions.to = self.address

let tx = contract.write("transferFrom", parameters: [originalOwner, to, tokenId] as [AnyObject], transactionOptions: basicOptions)!
return tx
}

public func approve(from: EthereumAddress, approved: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from

let tx = contract.write("approve", parameters: [approved, tokenId] as [AnyObject], transactionOptions: basicOptions)!
return tx
}

public func setApprovalForAll(from: EthereumAddress, operator user: EthereumAddress, approved: Bool) throws -> WriteTransaction {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from

let tx = contract.write("setApprovalForAll", parameters: [user, approved] as [AnyObject], transactionOptions: basicOptions)!
return tx
}

public func isApprovedForAll(owner: EthereumAddress, operator user: EthereumAddress) throws -> Bool {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.callOnBlock = .latest
let result = try contract.read("isApprovedForAll", parameters: [owner, user] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions)
guard let res = result["0"] as? Bool else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")}
return res
}

}

extension ERC721: IERC721Enumerable {

public func totalSupply() throws -> BigUInt {
let contract = self.contract
var transactionOptions = TransactionOptions()
transactionOptions.callOnBlock = .latest
let result = try contract.read("totalSupply", parameters: [AnyObject](), extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions)
guard let res = result["0"] as? BigUInt else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")}
return res
}

public func tokenByIndex(index: BigUInt) throws -> BigUInt {
let contract = self.contract
var transactionOptions = TransactionOptions()
Expand All @@ -158,24 +212,35 @@ public class ERC721 {
return res
}

public func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction {
}

extension ERC721: IERC721Metadata {

public func name() throws -> String {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from
basicOptions.to = self.address

let tx = contract.write("transfer", parameters: [to, tokenId] as [AnyObject], transactionOptions: basicOptions)!
return tx
var transactionOptions = TransactionOptions()
transactionOptions.callOnBlock = .latest
let result = try contract.read("name", parameters: [AnyObject](), extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions)
guard let res = result["0"] as? String else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")}
return res
}

public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt) throws -> WriteTransaction {
public func symbol() throws -> String {
let contract = self.contract
var basicOptions = TransactionOptions()
basicOptions.from = from
basicOptions.to = self.address

let tx = contract.write("transferFrom", parameters: [originalOwner, to, tokenId] as [AnyObject], transactionOptions: basicOptions)!
return tx
var transactionOptions = TransactionOptions()
transactionOptions.callOnBlock = .latest
let result = try contract.read("symbol", parameters: [AnyObject](), extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions)
guard let res = result["0"] as? String else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")}
return res
}

public func tokenURI(tokenId: BigUInt) throws -> String {
let contract = self.contract
var transactionOptions = TransactionOptions()
transactionOptions.callOnBlock = .latest
let result = try contract.read("tokenId", parameters: [tokenId] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions)
guard let res = result["0"] as? String else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")}
return res
}

}