diff --git a/web3swift.xcodeproj/project.pbxproj b/web3swift.xcodeproj/project.pbxproj index 47c5bc527..1ad924e6c 100755 --- a/web3swift.xcodeproj/project.pbxproj +++ b/web3swift.xcodeproj/project.pbxproj @@ -222,6 +222,14 @@ E2DCA655218C879900F94FBA /* ENSResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B219DC162154F3EE0035BF94 /* ENSResolver.swift */; }; E2DCA656218C87A500F94FBA /* ENS.swift in Sources */ = {isa = PBXBuildFile; fileRef = B2E668CD214F8A7B00C3CC2D /* ENS.swift */; }; E2DCA657218C87A500F94FBA /* ENSResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = B219DC162154F3EE0035BF94 /* ENSResolver.swift */; }; + E2F8081F21CA90BA00B6BF15 /* Web3+ERC1410.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8081E21CA90BA00B6BF15 /* Web3+ERC1410.swift */; }; + E2F8082421CA9C3B00B6BF15 /* Web3+ERC1594.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8082321CA9C3B00B6BF15 /* Web3+ERC1594.swift */; }; + E2F8082721CA9F3100B6BF15 /* Web3+ERC1644.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8082621CA9F3100B6BF15 /* Web3+ERC1644.swift */; }; + E2F8082A21CAA07000B6BF15 /* Web3+ERC1643.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8082921CAA07000B6BF15 /* Web3+ERC1643.swift */; }; + E2F8082D21CB009A00B6BF15 /* Web3+ERC1633.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8082C21CB009A00B6BF15 /* Web3+ERC1633.swift */; }; + E2F8083021CB096D00B6BF15 /* Web3+ERC721x.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8082F21CB096D00B6BF15 /* Web3+ERC721x.swift */; }; + E2F8083321CB0EF300B6BF15 /* Web3+ERC1155.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8083221CB0EF300B6BF15 /* Web3+ERC1155.swift */; }; + E2F8083621CB142000B6BF15 /* Web3+ERC1376.swift in Sources */ = {isa = PBXBuildFile; fileRef = E2F8083521CB142000B6BF15 /* Web3+ERC1376.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -404,6 +412,14 @@ E279C9FD21C48A570081695F /* Web3+ERC888.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC888.swift"; sourceTree = ""; }; E2C590752152835400FF53D3 /* JSONRPCrequestDispatcher+ObjC.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "JSONRPCrequestDispatcher+ObjC.swift"; sourceTree = ""; }; E2E94C5F217788E0005F54A0 /* Web3+ERC721.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC721.swift"; sourceTree = ""; }; + E2F8081E21CA90BA00B6BF15 /* Web3+ERC1410.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1410.swift"; sourceTree = ""; }; + E2F8082321CA9C3B00B6BF15 /* Web3+ERC1594.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1594.swift"; sourceTree = ""; }; + E2F8082621CA9F3100B6BF15 /* Web3+ERC1644.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1644.swift"; sourceTree = ""; }; + E2F8082921CAA07000B6BF15 /* Web3+ERC1643.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1643.swift"; sourceTree = ""; }; + E2F8082C21CB009A00B6BF15 /* Web3+ERC1633.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1633.swift"; sourceTree = ""; }; + E2F8082F21CB096D00B6BF15 /* Web3+ERC721x.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC721x.swift"; sourceTree = ""; }; + E2F8083221CB0EF300B6BF15 /* Web3+ERC1155.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1155.swift"; sourceTree = ""; }; + E2F8083521CB142000B6BF15 /* Web3+ERC1376.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Web3+ERC1376.swift"; sourceTree = ""; }; 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 = ""; }; FC1E6C115639177F2629E42A /* Pods_web3swift_osx.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_web3swift_osx.framework; sourceTree = BUILT_PRODUCTS_DIR; }; /* End PBXFileReference section */ @@ -622,6 +638,14 @@ 8159C50921343EF900197B91 /* PrecompiledContracts */ = { isa = PBXGroup; children = ( + E2F8083421CB140E00B6BF15 /* ERC1376 */, + E2F8083121CB0ED400B6BF15 /* ERC1155 */, + E2F8082E21CB095A00B6BF15 /* ERC721x */, + E2F8082B21CB008800B6BF15 /* ERC1633 */, + E2F8082821CAA05C00B6BF15 /* ERC1643 */, + E2F8082521CA9F1400B6BF15 /* ERC1644 */, + E2F8082221CA9C1600B6BF15 /* ERC1594 */, + E2F8081D21CA8F5800B6BF15 /* ERC1410 */, E279C9FC21C48A430081695F /* ERC888 */, E279C9F921C484400081695F /* ERC1400 */, E279C9F621C47CC10081695F /* ERC820 */, @@ -1010,6 +1034,70 @@ path = ERC721; sourceTree = ""; }; + E2F8081D21CA8F5800B6BF15 /* ERC1410 */ = { + isa = PBXGroup; + children = ( + E2F8081E21CA90BA00B6BF15 /* Web3+ERC1410.swift */, + ); + path = ERC1410; + sourceTree = ""; + }; + E2F8082221CA9C1600B6BF15 /* ERC1594 */ = { + isa = PBXGroup; + children = ( + E2F8082321CA9C3B00B6BF15 /* Web3+ERC1594.swift */, + ); + path = ERC1594; + sourceTree = ""; + }; + E2F8082521CA9F1400B6BF15 /* ERC1644 */ = { + isa = PBXGroup; + children = ( + E2F8082621CA9F3100B6BF15 /* Web3+ERC1644.swift */, + ); + path = ERC1644; + sourceTree = ""; + }; + E2F8082821CAA05C00B6BF15 /* ERC1643 */ = { + isa = PBXGroup; + children = ( + E2F8082921CAA07000B6BF15 /* Web3+ERC1643.swift */, + ); + path = ERC1643; + sourceTree = ""; + }; + E2F8082B21CB008800B6BF15 /* ERC1633 */ = { + isa = PBXGroup; + children = ( + E2F8082C21CB009A00B6BF15 /* Web3+ERC1633.swift */, + ); + path = ERC1633; + sourceTree = ""; + }; + E2F8082E21CB095A00B6BF15 /* ERC721x */ = { + isa = PBXGroup; + children = ( + E2F8082F21CB096D00B6BF15 /* Web3+ERC721x.swift */, + ); + path = ERC721x; + sourceTree = ""; + }; + E2F8083121CB0ED400B6BF15 /* ERC1155 */ = { + isa = PBXGroup; + children = ( + E2F8083221CB0EF300B6BF15 /* Web3+ERC1155.swift */, + ); + path = ERC1155; + sourceTree = ""; + }; + E2F8083421CB140E00B6BF15 /* ERC1376 */ = { + isa = PBXGroup; + children = ( + E2F8083521CB142000B6BF15 /* Web3+ERC1376.swift */, + ); + path = ERC1376; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -1270,6 +1358,7 @@ files = ( E2DCA654218C879900F94FBA /* ENS.swift in Sources */, E2DCA655218C879900F94FBA /* ENSResolver.swift in Sources */, + E2F8082421CA9C3B00B6BF15 /* Web3+ERC1594.swift in Sources */, 81C146F71FF274B200AA943E /* Web3+Structures.swift in Sources */, 8104E2281FE82BDC00F952CB /* Web3+Utils.swift in Sources */, E228BE3E21A4492A0085268C /* Web3Legacy+Options.swift in Sources */, @@ -1288,6 +1377,7 @@ 81EB1E4B208173D7003BD47F /* Web3+Personal.swift in Sources */, E228BE7821A4492B0085268C /* Web3Legacy+BrowserFunctions.swift in Sources */, 81909D1821862D5A007D2AE5 /* Web3+Eventloop.swift in Sources */, + E2F8082721CA9F3100B6BF15 /* Web3+ERC1644.swift in Sources */, 81A1824B20D7DF1B0016741F /* Promise+Web3+Personal+UnlockAccount.swift in Sources */, 81A1823A20D79AD40016741F /* Promise+Web3+Eth+SendRawTransaction.swift in Sources */, E228BE0021A4492A0085268C /* TransactionSignerLegacy.swift in Sources */, @@ -1305,6 +1395,7 @@ 81FB21FE207BB297007F9A83 /* EIP67Code.swift in Sources */, 81A1821A20D5A6F70016741F /* Promise+HttpProvider.swift in Sources */, E228BECD21A4C89F0085268C /* Web3Legacy+Contract.swift in Sources */, + E2F8083621CB142000B6BF15 /* Web3+ERC1376.swift in Sources */, E279C9F821C47CD00081695F /* Web3+ERC820.swift in Sources */, 81A1823720D6E2BB0016741F /* Promise+Web3+Eth+GetBlockByHash.swift in Sources */, 81909D51218DAEC0007D2AE5 /* Promise+Web3+Personal+CreateAccount.swift in Sources */, @@ -1313,6 +1404,7 @@ E279C9EF21C46A140081695F /* Web3+ERC165.swift in Sources */, 81C5DA282072E18200424CD6 /* NativeTypesEncoding+Extensions.swift in Sources */, 8123E1C7200CBAC200B6D3AB /* Dictionary+Extension.swift in Sources */, + E2F8083321CB0EF300B6BF15 /* Web3+ERC1155.swift in Sources */, E228BE7421A4492B0085268C /* Promise+Web3Legacy+Eth+Call.swift in Sources */, 985BFD4E216E2E0A00B28C14 /* Promise+Web3+TxPool.swift in Sources */, 985BFD4A216CE8B100B28C14 /* Web3+TxPool.swift in Sources */, @@ -1324,6 +1416,7 @@ 81ED4EA82190D922003E932E /* NonceMiddleware.swift in Sources */, 81A1822520D678590016741F /* Promise+Web3+Eth+GetGasPrice.swift in Sources */, 8113DE7C1FD8514400CD8DF1 /* NSRegularExpressionExtension.swift in Sources */, + E2F8082A21CAA07000B6BF15 /* Web3+ERC1643.swift in Sources */, 81C5DA2E2074EBF500424CD6 /* EthereumContract.swift in Sources */, 810B0F9E1FEC5B9C00CF0DA2 /* Web3+Eth.swift in Sources */, 81531AA01FE7C07A002192CC /* EthereumKeystoreV3.swift in Sources */, @@ -1336,8 +1429,10 @@ 81DDECCF1FDF004E0063684A /* Web3.swift in Sources */, 81A1823420D6E1FD0016741F /* Promise+Web3+Eth+GetBlockByNumber.swift in Sources */, 81A1822820D678BF0016741F /* Promise+Web3+Eth+GetAccounts.swift in Sources */, + E2F8081F21CA90BA00B6BF15 /* Web3+ERC1410.swift in Sources */, E228BE3621A4492A0085268C /* Web3Legacy+TransactionIntermediate.swift in Sources */, 81A7B2512143C3A8004CD2C7 /* NameHash.swift in Sources */, + E2F8083021CB096D00B6BF15 /* Web3+ERC721x.swift in Sources */, 81C5DA312074EC1E00424CD6 /* ContractProtocol.swift in Sources */, E228BED121A4C89F0085268C /* Web3Legacy+Instance.swift in Sources */, 815630002007B48800A0EC2F /* BIP32KeystoreJSONStructure.swift in Sources */, @@ -1345,6 +1440,7 @@ E228BECF21A4C89F0085268C /* Web3Legacy+Eth.swift in Sources */, E228BE6221A4492B0085268C /* Promise+Web3Legacy+Eth+EstimateGas.swift in Sources */, E228BE0221A4492A0085268C /* EthereumTransactionLegacy.swift in Sources */, + E2F8082D21CB009A00B6BF15 /* Web3+ERC1633.swift in Sources */, 813FFF8D1FD82EEB006379A2 /* String+Extension.swift in Sources */, E228BE4421A4492A0085268C /* ENSLegacy.swift in Sources */, 81A1823120D68A110016741F /* Promise+Batching.swift in Sources */, diff --git a/web3swift/PrecompiledContracts/ERC1155/Web3+ERC1155.swift b/web3swift/PrecompiledContracts/ERC1155/Web3+ERC1155.swift new file mode 100644 index 000000000..387a6aab3 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1155/Web3+ERC1155.swift @@ -0,0 +1,150 @@ +// +// Web3+ERC1155.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 20/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import PromiseKit +import EthereumAddress + +//Multi Token Standard +protocol IERC1155: IERC165 { + + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, id: BigUInt, value: BigUInt, data: [UInt8]) throws -> WriteTransaction + + func safeBatchTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, ids: [BigUInt], values: [BigUInt], data: [UInt8]) throws -> WriteTransaction + + func balanceOf(account: EthereumAddress, id: BigUInt) throws -> BigUInt + + func setApprovalForAll(from: EthereumAddress, operator user: EthereumAddress, approved: Bool, scope: Data) throws -> WriteTransaction + + func isApprovedForAll(owner: EthereumAddress, operator user: EthereumAddress, scope: Data) throws -> Bool +} + +protocol IERC1155Metadata { + func uri(id: BigUInt) throws -> String + func name(id: BigUInt) throws -> String +} + +public class ERC1155: IERC1155 { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _tokenId: BigUInt? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1155ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + self.transactionOptions = mergedOptions + } + + public var tokenId: BigUInt { + self.readProperties() + if self._tokenId != nil { + return self._tokenId! + } + return 0 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + guard contract.contract.address != nil else {return} + var transactionOptions = TransactionOptions.defaultOptions + transactionOptions.callOnBlock = .latest + + guard let tokenIdPromise = contract.read("id", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [tokenIdPromise] + let queue = self.web3.requestDispatcher.queue + when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in + guard case .fulfilled(let tokenIdResult) = resolvedPromises[0] else {return} + guard let tokenId = tokenIdResult["0"] as? BigUInt else {return} + self._tokenId = tokenId + + self._hasReadProperties = true + }.wait() + } + + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, id: BigUInt, value: BigUInt, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("safeTransferFrom", parameters: [originalOwner, to, id, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func safeBatchTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, ids: [BigUInt], values: [BigUInt], data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("safeBatchTransferFrom", parameters: [originalOwner, to, ids, values, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func balanceOf(account: EthereumAddress, id: BigUInt) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account, id] as [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 + } + + func setApprovalForAll(from: EthereumAddress, operator user: EthereumAddress, approved: Bool, scope: Data) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setApprovalForAll", parameters: [user, approved, scope] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func isApprovedForAll(owner: EthereumAddress, operator user: EthereumAddress, scope: Data) throws -> Bool { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.callOnBlock = .latest + let result = try contract.read("isApprovedForAll", parameters: [owner, user, scope] 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 + } + + func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } +} diff --git a/web3swift/PrecompiledContracts/ERC1376/Web3+ERC1376.swift b/web3swift/PrecompiledContracts/ERC1376/Web3+ERC1376.swift new file mode 100644 index 000000000..d259a3909 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1376/Web3+ERC1376.swift @@ -0,0 +1,505 @@ +// +// Web3+ERC1376.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 20/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +public enum IERC1376DelegateMode: UInt { + case PublicMsgSender = 0 + case PublicTxOrigin = 1 + case PrivateMsgSender = 2 + case PrivateTxOrigin = 3 +} + +public struct DirectDebitInfo { + let amount: BigUInt + let startTime: BigUInt + let interval: BigUInt +} + +public struct DirectDebit { + let info: DirectDebitInfo + let epoch: BigUInt +} + +extension DirectDebit: Hashable { +} + +extension DirectDebitInfo: Hashable { +} + +//Service-Friendly Token Standard +protocol IERC1376: IERC20 { + func approve(from: EthereumAddress, spender: EthereumAddress, expectedValue: String, newValue: String) throws -> WriteTransaction + func increaseAllowance(from: EthereumAddress, spender: EthereumAddress, value: String) throws -> WriteTransaction + func decreaseAllowance(from: EthereumAddress, spender: EthereumAddress, value: String, strict: Bool) throws -> WriteTransaction + func setERC20ApproveChecking(from: EthereumAddress, approveChecking: Bool) throws -> WriteTransaction + + func spendableAllowance(owner: EthereumAddress, spender: EthereumAddress) throws -> BigUInt + func transfer(from: EthereumAddress, data: String) throws -> WriteTransaction + func transferAndCall(from: EthereumAddress, to: EthereumAddress, value: String, data: [UInt8]) throws -> WriteTransaction + + func nonceOf(owner: EthereumAddress) throws -> BigUInt + func increaseNonce(from: EthereumAddress) throws -> WriteTransaction + func delegateTransferAndCall(from: EthereumAddress, + nonce: BigUInt, + fee: BigUInt, + gasAmount: BigUInt, + to: EthereumAddress, + value: String, + data: [UInt8], + mode: IERC1376DelegateMode, + v: UInt8, + r: Data, + s: Data) throws -> WriteTransaction + + func directDebit(debtor: EthereumAddress, receiver: EthereumAddress) throws -> DirectDebit + func setupDirectDebit(from: EthereumAddress, receiver: EthereumAddress, info: DirectDebitInfo) throws -> WriteTransaction + func terminateDirectDebit(from: EthereumAddress, receiver: EthereumAddress) throws -> WriteTransaction + func withdrawDirectDebit(from: EthereumAddress, debtor: EthereumAddress) throws -> WriteTransaction + func withdrawDirectDebit(from: EthereumAddress, debtors: [EthereumAddress], strict: Bool) throws -> WriteTransaction +} + +public class ERC1376: IERC1376 { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1376ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 + } + + func approve(from: EthereumAddress, spender: EthereumAddress, expectedValue: String, newValue: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let eValue = Web3.Utils.parseToBigUInt(expectedValue, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + guard let nValue = Web3.Utils.parseToBigUInt(newValue, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, eValue, nValue] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func increaseAllowance(from: EthereumAddress, spender: EthereumAddress, value: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("increaseAllowance", parameters: [spender, amount] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func decreaseAllowance(from: EthereumAddress, spender: EthereumAddress, value: String, strict: Bool) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("decreaseAllowance", parameters: [spender, amount, strict] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func setERC20ApproveChecking(from: EthereumAddress, approveChecking: Bool) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setERC20ApproveChecking", parameters: [approveChecking] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func spendableAllowance(owner: EthereumAddress, spender: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("spendableAllowance", parameters: [owner, spender] as [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 + } + + func transfer(from: EthereumAddress, data: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(data, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func transferAndCall(from: EthereumAddress, to: EthereumAddress, value: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transferAndCall", parameters: [to, amount, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func nonceOf(owner: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("nonceOf", parameters: [owner] as [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 + } + + func increaseNonce(from: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + let tx = contract.write("increaseNonce", parameters: [] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func delegateTransferAndCall(from: EthereumAddress, nonce: BigUInt, fee: BigUInt, gasAmount: BigUInt, to: EthereumAddress, value: String, data: [UInt8], mode: IERC1376DelegateMode, v: UInt8, r: Data, s: Data) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let amount = Web3.Utils.parseToBigUInt(value, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let modeValue = mode.rawValue + + let tx = contract.write("delegateTransferAndCall", parameters: [nonce, fee, gasAmount, to, amount, data, modeValue, v, r, s] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func directDebit(debtor: EthereumAddress, receiver: EthereumAddress) throws -> DirectDebit { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("directDebit", parameters: [debtor, receiver] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? DirectDebit else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + func setupDirectDebit(from: EthereumAddress, receiver: EthereumAddress, info: DirectDebitInfo) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setupDirectDebit", parameters: [receiver, info] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func terminateDirectDebit(from: EthereumAddress, receiver: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("terminateDirectDebit", parameters: [receiver] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func withdrawDirectDebit(from: EthereumAddress, debtor: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("withdrawDirectDebit", parameters: [debtor] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func withdrawDirectDebit(from: EthereumAddress, debtors: [EthereumAddress], strict: Bool) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("withdrawDirectDebit", parameters: [debtors, strict] as [AnyObject], transactionOptions: basicOptions)! + return tx + } +} diff --git a/web3swift/PrecompiledContracts/ERC1400/Web3+ERC1400.swift b/web3swift/PrecompiledContracts/ERC1400/Web3+ERC1400.swift index 299100fc0..faa97ea04 100644 --- a/web3swift/PrecompiledContracts/ERC1400/Web3+ERC1400.swift +++ b/web3swift/PrecompiledContracts/ERC1400/Web3+ERC1400.swift @@ -10,8 +10,8 @@ import BigInt import EthereumAddress import PromiseKit -// ERC1400 = ERC20 + IERC1400 -protocol IERC1400 { +//Security Token Standard +protocol IERC1400: IERC20 { // Document Management func getDocument(name: Data) throws -> (String, Data) @@ -64,7 +64,7 @@ protocol IERC1400 { // This namespace contains functions to work with ERC1400 tokens. // variables are lazyly evaluated or global token information (name, ticker, total supply) // can be imperatively read and saved -public class ERC1400: IERC20, IERC1400 { +public class ERC1400: IERC1400 { @available(*, deprecated, renamed: "transactionOptions") public var options: Web3Options = .init() @@ -72,26 +72,27 @@ public class ERC1400: IERC20, IERC1400 { private var _name: String? = nil private var _symbol: String? = nil private var _decimals: UInt8? = nil - private var _totalSupply: BigUInt? = nil private var _hasReadProperties: Bool = false public var transactionOptions: TransactionOptions public var web3: web3 public var provider: Web3Provider public var address: EthereumAddress + public var abi: String lazy var contract: web3.web3contract = { - let contract = self.web3.contract(Web3.Utils.erc1400ABI, at: self.address, abiVersion: 2) + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) precondition(contract != nil) return contract! }() - public init(web3: web3, provider: Web3Provider, address: EthereumAddress) { + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1400ABI) { self.web3 = web3 self.provider = provider self.address = address var mergedOptions = web3.transactionOptions mergedOptions.to = address + self.abi = abi self.transactionOptions = mergedOptions } @@ -119,14 +120,6 @@ public class ERC1400: IERC20, IERC1400 { return 255 } - public var totalSupply: BigUInt { - self.readProperties() - if self._totalSupply != nil { - return self._totalSupply! - } - return 0 - } - public func readProperties() { if self._hasReadProperties { return @@ -141,9 +134,7 @@ public class ERC1400: IERC20, IERC1400 { guard let decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - guard let totalSupplyPromise = contract.read("totalSupply", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - - let allPromises = [namePromise, symbolPromise, decimalPromise, totalSupplyPromise] + let allPromises = [namePromise, symbolPromise, decimalPromise] let queue = self.web3.requestDispatcher.queue when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in guard case .fulfilled(let nameResult) = resolvedPromises[0] else {return} @@ -158,10 +149,6 @@ public class ERC1400: IERC20, IERC1400 { guard let decimals = decimalsResult["0"] as? BigUInt else {return} self._decimals = UInt8(decimals) - guard case .fulfilled(let totalSupplyResult) = resolvedPromises[3] else {return} - guard let totalSupply = totalSupplyResult["0"] as? BigUInt else {return} - self._totalSupply = totalSupply - self._hasReadProperties = true }.wait() } @@ -252,6 +239,15 @@ public class ERC1400: IERC20, IERC1400 { return tx } + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { let contract = self.contract var basicOptions = TransactionOptions() @@ -274,6 +270,7 @@ public class ERC1400: IERC20, IERC1400 { return tx } + //ERC1400 methods public func getDocument(name: Data) throws -> (String, Data) { let contract = self.contract var transactionOptions = TransactionOptions() @@ -287,6 +284,7 @@ public class ERC1400: IERC20, IERC1400 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("setDocument", parameters: [name, uri, documentHash] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -728,3 +726,209 @@ public class ERC1400: IERC20, IERC1400 { return res } } + +extension ERC1400: IERC777 { + public func canImplementInterfaceForAddress(interfaceHash: Data, addr: EthereumAddress) throws -> Data { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("canImplementInterfaceForAddress", parameters: [interfaceHash, addr] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? Data else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func getInterfaceImplementer(addr: EthereumAddress, interfaceHash: Data) throws -> EthereumAddress { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("getInterfaceImplementer", parameters: [addr, interfaceHash] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func setInterfaceImplementer(from: EthereumAddress, addr: EthereumAddress, interfaceHash: Data, implementer: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setInterfaceImplementer", parameters: [addr, interfaceHash, implementer] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setManager(from: EthereumAddress, addr: EthereumAddress, newManager: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setManager", parameters: [addr, newManager] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func interfaceHash(interfaceName: String) throws -> Data { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("interfaceHash", parameters: [interfaceName] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? Data else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func updateERC165Cache(from: EthereumAddress, contract: EthereumAddress, interfaceId: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("updateERC165Cache", parameters: [contract, interfaceId] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } + + public func getGranularity() throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("granularity", parameters: [] as [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 getDefaultOperators() throws -> [EthereumAddress] { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("defaultOperators", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? [EthereumAddress] else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func authorize(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + let tx = contract.write("authorizeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func revoke(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + let tx = contract.write("revokeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func isOperatorFor(operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isOperatorFor", parameters: [user, tokenHolder] 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 + } + + public func send(from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("send", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorSend(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("operatorSend", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func burn(from: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("burn", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorBurn(from: EthereumAddress, amount: String, originalOwner: EthereumAddress, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } +} diff --git a/web3swift/PrecompiledContracts/ERC1410/Web3+ERC1410.swift b/web3swift/PrecompiledContracts/ERC1410/Web3+ERC1410.swift new file mode 100644 index 000000000..82c7ba8d8 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1410/Web3+ERC1410.swift @@ -0,0 +1,667 @@ +// +// Web3+ERC1410.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 19/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +//Partially Fungible Token Standard +protocol IERC1410: IERC20 { + + // Token Information + func getBalance(account: EthereumAddress) throws -> BigUInt + func balanceOfByPartition(partition: Data, tokenHolder: EthereumAddress) throws -> BigUInt + func partitionsOf(tokenHolder: EthereumAddress) throws -> [Data] + func totalSupply() throws -> BigUInt + + // Token Transfers + func transferByPartition(partition: Data, from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + func operatorTransferByPartition(partition: Data, from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction + func canTransferByPartition(originalOwner: EthereumAddress, to: EthereumAddress, partition: Data, amount: String, data: [UInt8]) throws -> ([UInt8], Data, Data) + + // Operator Information + func isOperator(operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool + func isOperatorForPartition(partition: Data, operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool + + // Operator Management + func authorizeOperator(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction + func revokeOperator(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction + func authorizeOperatorByPartition(from: EthereumAddress, partition: Data, operator user: EthereumAddress) throws -> WriteTransaction + func revokeOperatorByPartition(from: EthereumAddress, partition: Data, operator user: EthereumAddress) throws -> WriteTransaction + + // Issuance / Redemption + func issueByPartition(from: EthereumAddress, partition: Data, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + func redeemByPartition(from: EthereumAddress, partition: Data, amount: String, data: [UInt8]) throws -> WriteTransaction + func operatorRedeemByPartition(from: EthereumAddress, partition: Data, tokenHolder: EthereumAddress, amount: String, operatorData: [UInt8]) throws -> WriteTransaction + +} + +public class ERC1410: IERC1410 { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _totalSupply: BigUInt? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1410ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + //ERC1410 methods + public func balanceOfByPartition(partition: Data, tokenHolder: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOfByPartition", parameters: [partition, tokenHolder] as [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 partitionsOf(tokenHolder: EthereumAddress) throws -> [Data] { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("partitionsOf", parameters: [tokenHolder] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? [Data] else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func transferByPartition(partition: Data, from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferByPartition", parameters: [partition, to, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorTransferByPartition(partition: Data, from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("operatorTransferByPartition", parameters: [partition, originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func canTransferByPartition(originalOwner: EthereumAddress, to: EthereumAddress, partition: Data, amount: String, data: [UInt8]) throws -> ([UInt8], Data, Data) { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: transactionOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let result = try contract.read("canTransfer", parameters: [originalOwner, to, partition, value, data] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? ([UInt8], Data, Data) else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func isOperator(operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isOperator", parameters: [user, tokenHolder] 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 + } + + public func isOperatorForPartition(partition: Data, operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isOperatorForPartition", parameters: [partition, user, tokenHolder] 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 + } + + public func authorizeOperator(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("authorizeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func revokeOperator(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("revokeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func authorizeOperatorByPartition(from: EthereumAddress, partition: Data, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("authorizeOperatorByPartition", parameters: [partition, user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func revokeOperatorByPartition(from: EthereumAddress, partition: Data, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("revokeOperatorByPartition", parameters: [partition, user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func issueByPartition(from: EthereumAddress, partition: Data, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("issueByPartition", parameters: [partition, tokenHolder, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func redeemByPartition(from: EthereumAddress, partition: Data, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("redeemByPartition", parameters: [partition, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorRedeemByPartition(from: EthereumAddress, partition: Data, tokenHolder: EthereumAddress, amount: String, operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("operatorRedeemByPartition", parameters: [partition, tokenHolder, value, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } +} + +extension ERC1410: IERC777 { + public func canImplementInterfaceForAddress(interfaceHash: Data, addr: EthereumAddress) throws -> Data { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("canImplementInterfaceForAddress", parameters: [interfaceHash, addr] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? Data else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func getInterfaceImplementer(addr: EthereumAddress, interfaceHash: Data) throws -> EthereumAddress { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("getInterfaceImplementer", parameters: [addr, interfaceHash] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func setInterfaceImplementer(from: EthereumAddress, addr: EthereumAddress, interfaceHash: Data, implementer: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + + let tx = contract.write("setInterfaceImplementer", parameters: [addr, interfaceHash, implementer] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setManager(from: EthereumAddress, addr: EthereumAddress, newManager: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + + let tx = contract.write("setManager", parameters: [addr, newManager] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func interfaceHash(interfaceName: String) throws -> Data { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("interfaceHash", parameters: [interfaceName] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? Data else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func updateERC165Cache(from: EthereumAddress, contract: EthereumAddress, interfaceId: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + + let tx = contract.write("updateERC165Cache", parameters: [contract, interfaceId] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } + + public func authorize(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.callOnBlock = .latest + + let tx = contract.write("authorizeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func revoke(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.callOnBlock = .latest + + let tx = contract.write("revokeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func isOperatorFor(operator user: EthereumAddress, tokenHolder: EthereumAddress) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isOperatorFor", parameters: [user, tokenHolder] 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 + } + + public func send(from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("send", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorSend(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("operatorSend", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func burn(from: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("burn", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func operatorBurn(from: EthereumAddress, amount: String, originalOwner: EthereumAddress, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func getGranularity() throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("granularity", parameters: [] as [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 getDefaultOperators() throws -> [EthereumAddress] { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("defaultOperators", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? [EthereumAddress] else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } +} diff --git a/web3swift/PrecompiledContracts/ERC1594/Web3+ERC1594.swift b/web3swift/PrecompiledContracts/ERC1594/Web3+ERC1594.swift new file mode 100644 index 000000000..cb32899fa --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1594/Web3+ERC1594.swift @@ -0,0 +1,412 @@ +// +// Web3+ERC1594.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 19/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +//Core Security Token Standard +protocol IERC1594: IERC20 { + + // Transfers + func transferWithData(from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + func transferFromWithData(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + + // Token Issuance + func isIssuable() throws -> Bool + func issue(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + + // Token Redemption + func redeem(from: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + func redeemFrom(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction + + // Transfer Validity + func canTransfer(to: EthereumAddress, amount: String, data: [UInt8]) throws -> ([UInt8], Data) + func canTransferFrom(originalOwner: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> ([UInt8], Data) + +} + +public class ERC1594: IERC1594 { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1594ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + //ERC1594 + public func transferWithData(from: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferWithData", parameters: [to, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFromWithData(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFromWithData", parameters: [originalOwner, to, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func isIssuable() throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isIssuable", parameters: [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 + } + + public func issue(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("issue", parameters: [tokenHolder, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func redeem(from: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("redeem", parameters: [value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func redeemFrom(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("redeemFrom", parameters: [tokenHolder, value, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func canTransfer(to: EthereumAddress, amount: String, data: [UInt8]) throws -> ([UInt8], Data) { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: transactionOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let result = try contract.read("canTransfer", parameters: [to, value, data] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? ([UInt8], Data) else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func canTransferFrom(originalOwner: EthereumAddress, to: EthereumAddress, amount: String, data: [UInt8]) throws -> ([UInt8], Data) { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: transactionOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let result = try contract.read("canTransfer", parameters: [originalOwner, to, value, data] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? ([UInt8], Data) else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } +} + + diff --git a/web3swift/PrecompiledContracts/ERC1633/Web3+ERC1633.swift b/web3swift/PrecompiledContracts/ERC1633/Web3+ERC1633.swift new file mode 100644 index 000000000..b4c9ba061 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1633/Web3+ERC1633.swift @@ -0,0 +1,257 @@ +// +// Web3+ERC1634.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 20/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +///Re-Fungible Token Standard (RFT) +protocol IERC1633: IERC20, IERC165 { + + func parentToken() throws -> EthereumAddress + func parentTokenId() throws -> BigUInt + +} + +public class ERC1633: IERC1633 { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1633ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func parentToken() throws -> EthereumAddress { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("parentToken", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + func parentTokenId() throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("parentTokenId", parameters: [] as [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 supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } + +} diff --git a/web3swift/PrecompiledContracts/ERC1643/Web3+ERC1643.swift b/web3swift/PrecompiledContracts/ERC1643/Web3+ERC1643.swift new file mode 100644 index 000000000..6ba4c056e --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1643/Web3+ERC1643.swift @@ -0,0 +1,269 @@ +// +// Web3+ERC1643.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 19/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +//Document Management Standard +protocol IERC1643: IERC20 { + + // Document Management + func getDocument(name: Data) throws -> (String, Data) + func setDocument(from: EthereumAddress, name: Data, uri: String, documentHash: Data) throws -> WriteTransaction + func removeDocument(from: EthereumAddress, name: Data) throws -> WriteTransaction + func getAllDocuments() throws -> [Data] + +} + +public class ERC1643: IERC1643 { + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1643ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + //ERC1643 methods + public func getDocument(name: Data) throws -> (String, Data) { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("getDocument", parameters: [name] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? (String, Data) else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func setDocument(from: EthereumAddress, name: Data, uri: String, documentHash: Data) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("setDocument", parameters: [name, uri, documentHash] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func removeDocument(from: EthereumAddress, name: Data) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("removeDocument", parameters: [name] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func getAllDocuments() throws -> [Data] { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("getAllDocuments", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? [Data] else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } +} diff --git a/web3swift/PrecompiledContracts/ERC1644/Web3+ERC1644.swift b/web3swift/PrecompiledContracts/ERC1644/Web3+ERC1644.swift new file mode 100644 index 000000000..819ff3a64 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC1644/Web3+ERC1644.swift @@ -0,0 +1,285 @@ +// +// Web3+ERC1644.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 19/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import EthereumAddress +import PromiseKit + +//Controller Token Operation Standard +protocol IERC1644: IERC20 { + + // Controller Operation + func isControllable() throws -> Bool + func controllerTransfer(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction + func controllerRedeem(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction + +} + +public class ERC1644: IERC1644 { + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _name: String? = nil + private var _symbol: String? = nil + private var _decimals: UInt8? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc1644ABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + 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 decimals: UInt8 { + self.readProperties() + if self._decimals != nil { + return self._decimals! + } + return 255 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + 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 decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [namePromise, symbolPromise, decimalPromise] + 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 decimalsResult) = resolvedPromises[2] else {return} + guard let decimals = decimalsResult["0"] as? BigUInt else {return} + self._decimals = UInt8(decimals) + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("allowance", parameters: [originalOwner, delegate] as [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 transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + let tx = contract.write("transfer", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("transferFrom", parameters: [originalOwner, to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(newAmount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("setAllowance", parameters: [to, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + 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 approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("approve", parameters: [spender, value] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + //ERC1644 + public func isControllable() throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("isControllable", parameters: [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 + } + + public func controllerTransfer(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("controllerTransfer", parameters: [originalOwner, to, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + public func controllerRedeem(from: EthereumAddress, tokenHolder: EthereumAddress, amount: String, data: [UInt8], operatorData: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + basicOptions.callOnBlock = .latest + + // get the decimals manually + let callResult = try contract.read("decimals", transactionOptions: basicOptions)!.call() + var decimals = BigUInt(0) + guard let dec = callResult["0"], let decTyped = dec as? BigUInt else { + throw Web3Error.inputError(desc: "Contract may be not ERC20 compatible, can not get decimals")} + decimals = decTyped + + let intDecimals = Int(decimals) + guard let value = Web3.Utils.parseToBigUInt(amount, decimals: intDecimals) else { + throw Web3Error.inputError(desc: "Can not parse inputted amount") + } + + let tx = contract.write("controllerRedeem", parameters: [tokenHolder, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! + return tx + } +} diff --git a/web3swift/PrecompiledContracts/ERC165/Web3+ERC165.swift b/web3swift/PrecompiledContracts/ERC165/Web3+ERC165.swift index 1875c0bef..6687e9c4e 100644 --- a/web3swift/PrecompiledContracts/ERC165/Web3+ERC165.swift +++ b/web3swift/PrecompiledContracts/ERC165/Web3+ERC165.swift @@ -8,6 +8,7 @@ import Foundation +//Standard Interface Detection protocol IERC165 { func supportsInterface(interfaceID: [UInt8]) throws -> Bool diff --git a/web3swift/PrecompiledContracts/ERC20/Web3+ERC20.swift b/web3swift/PrecompiledContracts/ERC20/Web3+ERC20.swift index 31e0d05a0..c6bd0b6b4 100644 --- a/web3swift/PrecompiledContracts/ERC20/Web3+ERC20.swift +++ b/web3swift/PrecompiledContracts/ERC20/Web3+ERC20.swift @@ -9,6 +9,7 @@ import BigInt import EthereumAddress import PromiseKit +//Token Standard protocol IERC20 { func getBalance(account: EthereumAddress) throws -> BigUInt func getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt @@ -16,6 +17,7 @@ protocol IERC20 { func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, amount: String) throws -> WriteTransaction func setAllowance(from: EthereumAddress, to: EthereumAddress, newAmount: String) throws -> WriteTransaction func approve(from: EthereumAddress, spender: EthereumAddress, amount: String) throws -> WriteTransaction + func totalSupply() throws -> BigUInt } // This namespace contains functions to work with ERC20 tokens. @@ -29,7 +31,6 @@ public class ERC20: IERC20 { private var _name: String? = nil private var _symbol: String? = nil private var _decimals: UInt8? = nil - private var _totalSupply: BigUInt? = nil private var _hasReadProperties: Bool = false public var transactionOptions: TransactionOptions @@ -76,14 +77,6 @@ public class ERC20: IERC20 { return 255 } - public var totalSupply: BigUInt { - self.readProperties() - if self._totalSupply != nil { - return self._totalSupply! - } - return 0 - } - public func readProperties() { if self._hasReadProperties { return @@ -97,10 +90,8 @@ public class ERC20: IERC20 { guard let symbolPromise = contract.read("symbol", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} guard let decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - - guard let totalSupplyPromise = contract.read("totalSupply", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - let allPromises = [namePromise, symbolPromise, decimalPromise, totalSupplyPromise] + let allPromises = [namePromise, symbolPromise, decimalPromise] let queue = self.web3.requestDispatcher.queue when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in guard case .fulfilled(let nameResult) = resolvedPromises[0] else {return} @@ -115,10 +106,6 @@ public class ERC20: IERC20 { guard let decimals = decimalsResult["0"] as? BigUInt else {return} self._decimals = UInt8(decimals) - guard case .fulfilled(let totalSupplyResult) = resolvedPromises[3] else {return} - guard let totalSupply = totalSupplyResult["0"] as? BigUInt else {return} - self._totalSupply = totalSupply - self._hasReadProperties = true }.wait() } @@ -213,6 +200,7 @@ public class ERC20: IERC20 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest // get the decimals manually @@ -231,4 +219,13 @@ public class ERC20: IERC20 { return tx } + 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 + } + } diff --git a/web3swift/PrecompiledContracts/ERC721/Web3+ERC721.swift b/web3swift/PrecompiledContracts/ERC721/Web3+ERC721.swift index 61ce34636..58c159c63 100644 --- a/web3swift/PrecompiledContracts/ERC721/Web3+ERC721.swift +++ b/web3swift/PrecompiledContracts/ERC721/Web3+ERC721.swift @@ -9,7 +9,8 @@ import BigInt import PromiseKit import EthereumAddress -protocol IERC721 { +//Non-Fungible Token Standard +protocol IERC721: IERC165 { func getBalance(account: EthereumAddress) throws -> BigUInt @@ -158,6 +159,7 @@ public class ERC721: IERC721 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("approve", parameters: [approved, tokenId] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -167,6 +169,7 @@ public class ERC721: IERC721 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("setApprovalForAll", parameters: [user, approved] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -181,6 +184,16 @@ public class ERC721: IERC721 { return res } + public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 { @@ -244,17 +257,3 @@ extension ERC721: IERC721Metadata { } } - -extension ERC721: IERC165 { - - public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { - let contract = self.contract - var transactionOptions = TransactionOptions() - transactionOptions.callOnBlock = .latest - transactionOptions.gasLimit = .manual(30000) - let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 - } - -} diff --git a/web3swift/PrecompiledContracts/ERC721x/Web3+ERC721x.swift b/web3swift/PrecompiledContracts/ERC721x/Web3+ERC721x.swift new file mode 100644 index 000000000..e014148d3 --- /dev/null +++ b/web3swift/PrecompiledContracts/ERC721x/Web3+ERC721x.swift @@ -0,0 +1,315 @@ +// +// Web3+ERC721x.swift +// web3swift-iOS +// +// Created by Anton Grigorev on 20/12/2018. +// Copyright © 2018 The Matter Inc. All rights reserved. +// + +import Foundation +import BigInt +import PromiseKit +import EthereumAddress + +///A Smarter Token for the Future of Crypto Collectibles +///ERC721x is an extension of ERC721 that adds support for multi-fungible tokens and batch transfers, while being fully backward-compatible. + +protocol IERC721x: IERC721, IERC721Metadata, IERC721Enumerable { + func implementsERC721X() throws -> Bool + func getOwner(tokenId: BigUInt) throws -> EthereumAddress + func getBalance(account: EthereumAddress) throws -> BigUInt + func getBalance(account: EthereumAddress, tokenId: BigUInt) throws -> BigUInt + + func tokensOwned(account: EthereumAddress) throws -> ([BigUInt], [BigUInt]) + + func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt, quantity: BigUInt) throws -> WriteTransaction + func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, quantity: BigUInt) throws -> WriteTransaction + + // Fungible Safe Transfer From + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, amount: BigUInt) throws -> WriteTransaction + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, amount: BigUInt, data: [UInt8]) throws -> WriteTransaction + + // Batch Safe Transfer From + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenIds: [BigUInt], amounts: [BigUInt], data: [UInt8]) throws -> WriteTransaction + + func name() throws -> String + func symbol() throws -> String +} + +public class ERC721x: IERC721x { + + @available(*, deprecated, renamed: "transactionOptions") + public var options: Web3Options = .init() + + private var _tokenId: BigUInt? = nil + private var _hasReadProperties: Bool = false + + public var transactionOptions: TransactionOptions + public var web3: web3 + public var provider: Web3Provider + public var address: EthereumAddress + public var abi: String + + lazy var contract: web3.web3contract = { + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) + precondition(contract != nil) + return contract! + }() + + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc721xABI) { + self.web3 = web3 + self.provider = provider + self.address = address + var mergedOptions = web3.transactionOptions + mergedOptions.to = address + self.abi = abi + self.transactionOptions = mergedOptions + } + + public var tokenId: BigUInt { + self.readProperties() + if self._tokenId != nil { + return self._tokenId! + } + return 0 + } + + public func readProperties() { + if self._hasReadProperties { + return + } + let contract = self.contract + guard contract.contract.address != nil else {return} + var transactionOptions = TransactionOptions.defaultOptions + transactionOptions.callOnBlock = .latest + + guard let tokenIdPromise = contract.read("tokenId", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} + + let allPromises = [tokenIdPromise] + let queue = self.web3.requestDispatcher.queue + when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in + guard case .fulfilled(let tokenIdResult) = resolvedPromises[0] else {return} + guard let tokenId = tokenIdResult["0"] as? BigUInt else {return} + self._tokenId = tokenId + + self._hasReadProperties = true + }.wait() + } + + public func getBalance(account: EthereumAddress) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account] as [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 getOwner(tokenId: BigUInt) throws -> EthereumAddress { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("ownerOf", parameters: [tokenId] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + public func getApproved(tokenId: BigUInt) throws -> EthereumAddress { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("getApproved", parameters: [tokenId] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? EthereumAddress else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + 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 + basicOptions.to = self.address + + 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 + basicOptions.to = self.address + + 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 + } + + public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } + + 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() + transactionOptions.callOnBlock = .latest + let result = try contract.read("tokenByIndex", parameters: [index] as [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 tokenOfOwnerByIndex(owner: EthereumAddress, index: BigUInt) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("tokenOfOwnerByIndex", parameters: [owner, index] as [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 name() throws -> String { + let contract = self.contract + 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 symbol() throws -> String { + let contract = self.contract + 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 + } + + func implementsERC721X() throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("implementsERC721X", parameters: [] 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 + } + + func getBalance(account: EthereumAddress, tokenId: BigUInt) throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("balanceOf", parameters: [account, tokenId] as [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 + } + + func tokensOwned(account: EthereumAddress) throws -> ([BigUInt], [BigUInt]) { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("tokensOwned", parameters: [account] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? ([BigUInt], [BigUInt]) else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + + func transfer(from: EthereumAddress, to: EthereumAddress, tokenId: BigUInt, quantity: 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, quantity] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func transferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, quantity: 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, quantity] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, amount: BigUInt) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("safeTransferFrom", parameters: [originalOwner, to, tokenId, amount] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenId: BigUInt, amount: BigUInt, data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("safeTransferFrom", parameters: [originalOwner, to, tokenId, amount, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } + + func safeTransferFrom(from: EthereumAddress, to: EthereumAddress, originalOwner: EthereumAddress, tokenIds: [BigUInt], amounts: [BigUInt], data: [UInt8]) throws -> WriteTransaction { + let contract = self.contract + var basicOptions = TransactionOptions() + basicOptions.from = from + basicOptions.to = self.address + + let tx = contract.write("safeTransferFrom", parameters: [originalOwner, to, tokenIds, amounts, data] as [AnyObject], transactionOptions: basicOptions)! + return tx + } +} diff --git a/web3swift/PrecompiledContracts/ERC777/Web3+ERC777.swift b/web3swift/PrecompiledContracts/ERC777/Web3+ERC777.swift index 239c81574..8127bf0fe 100644 --- a/web3swift/PrecompiledContracts/ERC777/Web3+ERC777.swift +++ b/web3swift/PrecompiledContracts/ERC777/Web3+ERC777.swift @@ -10,7 +10,10 @@ import BigInt import PromiseKit import EthereumAddress -protocol IERC777 { +//A New Advanced Token Standard +protocol IERC777: IERC20, IERC820 { + func getDefaultOperators() throws -> [EthereumAddress] + func getGranularity() throws -> BigUInt func getBalance(account: EthereumAddress) throws -> BigUInt func getAllowance(originalOwner: EthereumAddress, delegate: EthereumAddress) throws -> BigUInt func transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction @@ -27,14 +30,11 @@ protocol IERC777 { // This namespace contains functions to work with ERC777 tokens. // can be imperatively read and saved -public class ERC777: IERC20, IERC777 { +public class ERC777: IERC777 { private var _name: String? = nil private var _symbol: String? = nil private var _decimals: UInt8? = nil - private var _totalSupply: BigUInt? = nil - private var _granularity: BigUInt? = nil - private var _defaultOperators: [EthereumAddress]? = nil private var _hasReadProperties: Bool = false @@ -42,20 +42,21 @@ public class ERC777: IERC20, IERC777 { public var web3: web3 public var provider: Web3Provider public var address: EthereumAddress + public var abi: String lazy var contract: web3.web3contract = { - // TODO: - need erc777abi - let contract = self.web3.contract(Web3.Utils.erc777ABI, at: self.address, abiVersion: 2) + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) precondition(contract != nil) return contract! }() - public init(web3: web3, provider: Web3Provider, address: EthereumAddress) { + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc777ABI) { self.web3 = web3 self.provider = provider self.address = address var mergedOptions = web3.transactionOptions mergedOptions.to = address + self.abi = abi self.transactionOptions = mergedOptions } @@ -84,30 +85,6 @@ public class ERC777: IERC20, IERC777 { return 18 } - public var totalSupply: BigUInt { - self.readProperties() - if self._totalSupply != nil { - return self._totalSupply! - } - return 0 - } - - public var granularity: BigUInt { - self.readProperties() - if self._granularity != nil { - return self._granularity! - } - return 1 - } - - public var defaultOperators: [EthereumAddress] { - self.readProperties() - if self._defaultOperators != nil { - return self._defaultOperators! - } - return [] - } - public func readProperties() { if self._hasReadProperties { return @@ -122,13 +99,7 @@ public class ERC777: IERC20, IERC777 { guard let decimalPromise = contract.read("decimals", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - guard let totalSupplyPromise = contract.read("totalSupply", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - - guard let granularityPromise = contract.read("granularity", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - - guard let defaultOperatorsPromise = contract.read("defaultOperators", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: transactionOptions)?.callPromise() else {return} - - let allPromises = [namePromise, symbolPromise, decimalPromise, totalSupplyPromise, granularityPromise, defaultOperatorsPromise] + let allPromises = [namePromise, symbolPromise, decimalPromise] let queue = self.web3.requestDispatcher.queue when(resolved: allPromises).map(on: queue) { (resolvedPromises) -> Void in guard case .fulfilled(let nameResult) = resolvedPromises[0] else {return} @@ -143,22 +114,28 @@ public class ERC777: IERC20, IERC777 { guard let decimals = decimalsResult["0"] as? BigUInt else {return} self._decimals = UInt8(decimals) - guard case .fulfilled(let totalSupplyResult) = resolvedPromises[3] else {return} - guard let totalSupply = totalSupplyResult["0"] as? BigUInt else {return} - self._totalSupply = totalSupply - - guard case .fulfilled(let granularityResult) = resolvedPromises[4] else {return} - guard let granularity = granularityResult["0"] as? BigUInt else {return} - self._granularity = granularity - - guard case .fulfilled(let defaultOperatorsResult) = resolvedPromises[5] else {return} - guard let defaultOperators = defaultOperatorsResult["0"] as? [EthereumAddress] else {return} - self._defaultOperators = defaultOperators - self._hasReadProperties = true }.wait() } + public func getGranularity() throws -> BigUInt { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("granularity", parameters: [] as [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 getDefaultOperators() throws -> [EthereumAddress] { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + let result = try contract.read("defaultOperators", parameters: [] as [AnyObject], extraData: Data(), transactionOptions: self.transactionOptions)!.call(transactionOptions: transactionOptions) + guard let res = result["0"] as? [EthereumAddress] else {throw Web3Error.processingError(desc: "Failed to get result of expected type from the Ethereum node")} + return res + } + public func getBalance(account: EthereumAddress) throws -> BigUInt { let contract = self.contract var transactionOptions = TransactionOptions() @@ -245,11 +222,21 @@ public class ERC777: IERC20, IERC777 { return tx } + 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 + } + /// ERC777 methods public func authorize(from: EthereumAddress, operator user: EthereumAddress) throws -> WriteTransaction { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest let tx = contract.write("authorizeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! @@ -260,6 +247,7 @@ public class ERC777: IERC20, IERC777 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest let tx = contract.write("revokeOperator", parameters: [user] as [AnyObject], transactionOptions: basicOptions)! @@ -323,6 +311,7 @@ public class ERC777: IERC20, IERC777 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest // get the decimals manually @@ -344,6 +333,7 @@ public class ERC777: IERC20, IERC777 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest // get the decimals manually @@ -360,21 +350,7 @@ public class ERC777: IERC20, IERC777 { let tx = contract.write("burn", parameters: [originalOwner, value, data, operatorData] as [AnyObject], transactionOptions: basicOptions)! return tx } -} - -extension ERC777: IERC165 { - public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { - let contract = self.contract - var transactionOptions = TransactionOptions() - transactionOptions.callOnBlock = .latest - transactionOptions.gasLimit = .manual(30000) - let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 ERC777: IERC820 { + public func canImplementInterfaceForAddress(interfaceHash: Data, addr: EthereumAddress) throws -> Data { let contract = self.contract var transactionOptions = TransactionOptions() @@ -397,6 +373,7 @@ extension ERC777: IERC820 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("setInterfaceImplementer", parameters: [addr, interfaceHash, implementer] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -406,6 +383,7 @@ extension ERC777: IERC820 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("setManager", parameters: [addr, newManager] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -424,6 +402,7 @@ extension ERC777: IERC820 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address let tx = contract.write("updateERC165Cache", parameters: [contract, interfaceId] as [AnyObject], transactionOptions: basicOptions)! return tx @@ -433,6 +412,7 @@ extension ERC777: IERC820 { let contract = self.contract var basicOptions = TransactionOptions() basicOptions.from = from + basicOptions.to = self.address basicOptions.callOnBlock = .latest // get the decimals manually @@ -451,4 +431,15 @@ extension ERC777: IERC820 { return tx } + public func supportsInterface(interfaceID: [UInt8]) throws -> Bool { + let contract = self.contract + var transactionOptions = TransactionOptions() + transactionOptions.callOnBlock = .latest + transactionOptions.gasLimit = .manual(30000) + let result = try contract.read("supportsInterface", parameters: [interfaceID] 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 + } + } + diff --git a/web3swift/PrecompiledContracts/ERC820/Web3+ERC820.swift b/web3swift/PrecompiledContracts/ERC820/Web3+ERC820.swift index 1b0d51c57..4ae4e3cdb 100644 --- a/web3swift/PrecompiledContracts/ERC820/Web3+ERC820.swift +++ b/web3swift/PrecompiledContracts/ERC820/Web3+ERC820.swift @@ -9,7 +9,8 @@ import Foundation import EthereumAddress -protocol IERC820 { +//Pseudo-introspection using a registry contract +protocol IERC820: IERC165 { func canImplementInterfaceForAddress(interfaceHash: Data, addr: EthereumAddress) throws -> Data func getInterfaceImplementer(addr: EthereumAddress, interfaceHash: Data) throws -> EthereumAddress func setInterfaceImplementer(from: EthereumAddress, addr: EthereumAddress, interfaceHash: Data, implementer: EthereumAddress) throws -> WriteTransaction diff --git a/web3swift/PrecompiledContracts/ERC888/Web3+ERC888.swift b/web3swift/PrecompiledContracts/ERC888/Web3+ERC888.swift index 48f5fcee7..4da36bbf8 100644 --- a/web3swift/PrecompiledContracts/ERC888/Web3+ERC888.swift +++ b/web3swift/PrecompiledContracts/ERC888/Web3+ERC888.swift @@ -11,14 +11,12 @@ import BigInt import EthereumAddress import PromiseKit +//MultiDimensional Token Standard protocol IERC888 { func getBalance(account: EthereumAddress) throws -> BigUInt func transfer(from: EthereumAddress, to: EthereumAddress, amount: String) throws -> WriteTransaction } -// This namespace contains functions to work with ERC888 tokens. -// variables are lazyly evaluated or global token information (name, ticker, total supply) -// can be imperatively read and saved public class ERC888: IERC888 { @available(*, deprecated, renamed: "transactionOptions") @@ -33,19 +31,21 @@ public class ERC888: IERC888 { public var web3: web3 public var provider: Web3Provider public var address: EthereumAddress + public var abi: String lazy var contract: web3.web3contract = { - let contract = self.web3.contract(Web3.Utils.erc888ABI, at: self.address, abiVersion: 2) + let contract = self.web3.contract(self.abi, at: self.address, abiVersion: 2) precondition(contract != nil) return contract! }() - public init(web3: web3, provider: Web3Provider, address: EthereumAddress) { + public init(web3: web3, provider: Web3Provider, address: EthereumAddress, abi: String = Web3.Utils.erc888ABI) { self.web3 = web3 self.provider = provider self.address = address var mergedOptions = web3.transactionOptions mergedOptions.to = address + self.abi = abi self.transactionOptions = mergedOptions } diff --git a/web3swift/Web3/Classes/Web3+Utils.swift b/web3swift/Web3/Classes/Web3+Utils.swift index 46e1d59c7..46bdde704 100755 --- a/web3swift/Web3/Classes/Web3+Utils.swift +++ b/web3swift/Web3/Classes/Web3+Utils.swift @@ -73,10 +73,20 @@ extension Web3.Utils { /// Precoded ERC888 contracts ABI. Output parameters are named for ease of use. public static var erc888ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + /// TODO: - need to fix. + public static var erc1376ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + /// Precoded ERC20 contracts ABI. Output parameters are named for ease of use. public static var erc20ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" public static var erc721ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_approved\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_operator\",\"type\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_operator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"}]" + + // TODO: - Need to fix + public static var erc721xABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_approved\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_operator\",\"type\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_operator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"}]" + + // TODO: - Need to fix + public static var erc1155ABI = "[{\"constant\":true,\"inputs\":[{\"name\":\"interfaceID\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"_name\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"getApproved\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_approved\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenOfOwnerByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_index\",\"type\":\"uint256\"}],\"name\":\"tokenByIndex\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"ownerOf\",\"outputs\":[{\"name\":\"\",\"type\":\"address\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"_symbol\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_operator\",\"type\":\"address\"},{\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"setApprovalForAll\",\"outputs\":[],\"payable\":false,\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_tokenId\",\"type\":\"uint256\"},{\"name\":\"data\",\"type\":\"bytes\"}],\"name\":\"safeTransferFrom\",\"outputs\":[],\"payable\":true,\"stateMutability\":\"payable\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"tokenURI\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_operator\",\"type\":\"address\"}],\"name\":\"isApprovedForAll\",\"outputs\":[{\"name\":\"\",\"type\":\"bool\"}],\"payable\":false,\"stateMutability\":\"view\",\"type\":\"function\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_approved\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_tokenId\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_operator\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_approved\",\"type\":\"bool\"}],\"name\":\"ApprovalForAll\",\"type\":\"event\"}]" + /// Precoded ERC777 contracts ABI. Output parameters are named for ease of use. public static var erc777ABI = """ [ @@ -1806,6 +1816,1737 @@ extension Web3.Utils { "type": "constructor" } ] +""" + /// TODO: - Make it right + /// Precoded ERC1633 contracts ABI. Output parameters are named for ease of use. + public static var erc1633ABI = """ +[ + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "spender", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + }, + { + "name": "spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "defaultOperators", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "granularity", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_operatorData", + "type": "bytes" + } + ], + "name": "operatorSend", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_tokenHolder", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_operator", + "type": "address" + } + ], + "name": "authorizeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + } + ], + "name": "send", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_operator", + "type": "address" + }, + { + "name": "_tokenHolder", + "type": "address" + } + ], + "name": "isOperatorFor", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_operator", + "type": "address" + } + ], + "name": "revokeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_tokenHolder", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_operatorData", + "type": "bytes" + } + ], + "name": "operatorBurn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_granularity", + "type": "uint256" + }, + { + "name": "_defaultOperators", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Sent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "AuthorizedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "RevokedOperator", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "defaultOperators", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_spender", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "approve", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "transferFrom", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "decimals", + "outputs": [ + { + "name": "", + "type": "uint8" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "granularity", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_from", + "type": "address" + }, + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_operatorData", + "type": "bytes" + } + ], + "name": "operatorSend", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_tokenHolder", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_operator", + "type": "address" + } + ], + "name": "authorizeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + } + ], + "name": "send", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_to", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + } + ], + "name": "transfer", + "outputs": [ + { + "name": "success", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_operator", + "type": "address" + }, + { + "name": "_tokenHolder", + "type": "address" + } + ], + "name": "isOperatorFor", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "_owner", + "type": "address" + }, + { + "name": "_spender", + "type": "address" + } + ], + "name": "allowance", + "outputs": [ + { + "name": "remaining", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_operator", + "type": "address" + } + ], + "name": "revokeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_tokenHolder", + "type": "address" + }, + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + }, + { + "name": "_operatorData", + "type": "bytes" + } + ], + "name": "operatorBurn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "_amount", + "type": "uint256" + }, + { + "name": "_data", + "type": "bytes" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "name": "_name", + "type": "string" + }, + { + "name": "_symbol", + "type": "string" + }, + { + "name": "_granularity", + "type": "uint256" + }, + { + "name": "_defaultOperators", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Sent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "AuthorizedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "RevokedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Transfer", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "owner", + "type": "address" + }, + { + "indexed": true, + "name": "spender", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + } + ], + "name": "Approval", + "type": "event" + }, + { + "constant": true, + "inputs": [], + "name": "defaultOperators", + "outputs": [ + { + "name": "", + "type": "address[]" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "name", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "totalSupply", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "granularity", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operatorData", + "type": "bytes" + } + ], + "name": "operatorSend", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "owner", + "type": "address" + } + ], + "name": "balanceOf", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "operator", + "type": "address" + } + ], + "name": "authorizeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "symbol", + "outputs": [ + { + "name": "", + "type": "string" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "send", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "operator", + "type": "address" + }, + { + "name": "tokenHolder", + "type": "address" + } + ], + "name": "isOperatorFor", + "outputs": [ + { + "name": "", + "type": "bool" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "operator", + "type": "address" + } + ], + "name": "revokeOperator", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "from", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operatorData", + "type": "bytes" + } + ], + "name": "operatorBurn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + } + ], + "name": "burn", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Sent", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "to", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Minted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "from", + "type": "address" + }, + { + "indexed": false, + "name": "amount", + "type": "uint256" + }, + { + "indexed": false, + "name": "data", + "type": "bytes" + }, + { + "indexed": false, + "name": "operatorData", + "type": "bytes" + } + ], + "name": "Burned", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "AuthorizedOperator", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "name": "operator", + "type": "address" + }, + { + "indexed": true, + "name": "tokenHolder", + "type": "address" + } + ], + "name": "RevokedOperator", + "type": "event" + }, + { + "constant": false, + "inputs": [ + { + "name": "operator", + "type": "address" + }, + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "data", + "type": "bytes" + }, + { + "name": "operatorData", + "type": "bytes" + } + ], + "name": "tokensReceived", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "operator", + "type": "address" + }, + { + "name": "from", + "type": "address" + }, + { + "name": "to", + "type": "address" + }, + { + "name": "amount", + "type": "uint256" + }, + { + "name": "userData", + "type": "bytes" + }, + { + "name": "operatorData", + "type": "bytes" + } + ], + "name": "tokensToSend", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "addr", + "type": "address" + }, + { + "name": "iHash", + "type": "bytes32" + }, + { + "name": "implementer", + "type": "address" + } + ], + "name": "setInterfaceImplementer", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "addr", + "type": "address" + } + ], + "name": "getManager", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "addr", + "type": "address" + }, + { + "name": "newManager", + "type": "address" + } + ], + "name": "setManager", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [ + { + "name": "addr", + "type": "address" + }, + { + "name": "iHash", + "type": "bytes32" + } + ], + "name": "getInterfaceImplementer", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "new_address", + "type": "address" + } + ], + "name": "upgrade", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "last_completed_migration", + "outputs": [ + { + "name": "", + "type": "uint256" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": true, + "inputs": [], + "name": "owner", + "outputs": [ + { + "name": "", + "type": "address" + } + ], + "payable": false, + "stateMutability": "view", + "type": "function" + }, + { + "constant": false, + "inputs": [ + { + "name": "completed", + "type": "uint256" + } + ], + "name": "setCompleted", + "outputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "payable": false, + "stateMutability": "nonpayable", + "type": "constructor" + } +] """ public static var ensRegistryABI = """ [{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"label","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"type":"function"},{"constant":true,"inputs":[{"name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"name":"","type":"uint64"}],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"type":"function"},{"constant":false,"inputs":[{"name":"node","type":"bytes32"},{"name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"type":"function"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":true,"name":"label","type":"bytes32"},{"indexed":false,"name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"node","type":"bytes32"},{"indexed":false,"name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"}] @@ -1813,6 +3554,22 @@ extension Web3.Utils { /// TODO: - Need to add correct ABI for ERC1400 /// Precoded ERC1400 contracts ABI. Output parameters are named for ease of use. public static var erc1400ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + + /// TODO: - Need to add correct ABI for ERC1410 + /// Precoded ERC1410 contracts ABI. Output parameters are named for ease of use. + public static var erc1410ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + + /// TODO: - Need to add correct ABI for ERC1594 + /// Precoded ERC1594 contracts ABI. Output parameters are named for ease of use. + public static var erc1594ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + + /// TODO: - Need to add correct ABI for ERC1644 + /// Precoded ERC1644 contracts ABI. Output parameters are named for ease of use. + public static var erc1644ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" + + /// TODO: - Need to add correct ABI for ERC1644 + /// Precoded ERC1643 contracts ABI. Output parameters are named for ease of use. + public static var erc1643ABI = "[{\"constant\":true,\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"name\":\"\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_from\",\"type\":\"address\"},{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"name\":\"\",\"type\":\"uint8\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"name\":\"balance\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"name\":\"\",\"type\":\"string\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_to\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":false,\"inputs\":[{\"name\":\"_spender\",\"type\":\"address\"},{\"name\":\"_value\",\"type\":\"uint256\"},{\"name\":\"_extraData\",\"type\":\"bytes\"}],\"name\":\"approveAndCall\",\"outputs\":[{\"name\":\"success\",\"type\":\"bool\"}],\"payable\":false,\"type\":\"function\"},{\"constant\":true,\"inputs\":[{\"name\":\"_owner\",\"type\":\"address\"},{\"name\":\"_spender\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"name\":\"remaining\",\"type\":\"uint256\"}],\"payable\":false,\"type\":\"function\"},{\"inputs\":[{\"name\":\"_initialAmount\",\"type\":\"uint256\"},{\"name\":\"_tokenName\",\"type\":\"string\"},{\"name\":\"_decimalUnits\",\"type\":\"uint8\"},{\"name\":\"_tokenSymbol\",\"type\":\"string\"}],\"type\":\"constructor\"},{\"payable\":false,\"type\":\"fallback\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_from\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_to\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"name\":\"_owner\",\"type\":\"address\"},{\"indexed\":true,\"name\":\"_spender\",\"type\":\"address\"},{\"indexed\":false,\"name\":\"_value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},]" //function setAddr(bytes32 node, address addr) public static var resolverABI = """