Skip to content
This repository has been archived by the owner on Sep 13, 2024. It is now read-only.

Wider range of parameter types as input to ABI encoder #59

Merged
merged 2 commits into from
Apr 16, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion web3swift.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "web3swift"
s.version = "0.5.1"
s.version = "0.5.2"
s.summary = "Web3 implementation in vanilla Swift for iOS ans macOS"

s.description = <<-DESC
Expand Down
201 changes: 129 additions & 72 deletions web3swift/ABIv2/Classes/ABIv2Encoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,121 @@ public struct ABIv2Encoder {
}

extension ABIv2Encoder {
public static func convertToBigUInt(_ value: AnyObject) -> BigUInt? {
switch value {
case let v as BigUInt:
return v
case let v as BigInt:
return v.magnitude
case let v as String:
let base10 = BigUInt(v, radix: 10)
if base10 != nil {
return base10!
}
let base16 = BigUInt(v.stripHexPrefix(), radix: 16)
if base16 != nil {
return base16!
}
break
case let v as UInt:
return BigUInt(v)
case let v as UInt8:
return BigUInt(v)
case let v as UInt16:
return BigUInt(v)
case let v as UInt32:
return BigUInt(v)
case let v as UInt64:
return BigUInt(v)
case let v as Int:
return BigUInt(v)
case let v as Int8:
return BigUInt(v)
case let v as Int16:
return BigUInt(v)
case let v as Int32:
return BigUInt(v)
case let v as Int64:
return BigUInt(v)
default:
return nil
}
return nil
}

public static func convertToBigInt(_ value: AnyObject) -> BigInt? {
switch value {
case let v as BigUInt:
return BigInt(v)
case let v as BigInt:
return v
case let v as String:
let base10 = BigInt(v, radix: 10)
if base10 != nil {
return base10
}
let base16 = BigInt(v.stripHexPrefix(), radix: 16)
if base16 != nil {
return base16
}
break
case let v as UInt:
return BigInt(v)
case let v as UInt8:
return BigInt(v)
case let v as UInt16:
return BigInt(v)
case let v as UInt32:
return BigInt(v)
case let v as UInt64:
return BigInt(v)
case let v as Int:
return BigInt(v)
case let v as Int8:
return BigInt(v)
case let v as Int16:
return BigInt(v)
case let v as Int32:
return BigInt(v)
case let v as Int64:
return BigInt(v)
default:
return nil
}
return nil
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@K0rka скажи, может это можно в Generics красиво обернуть?

}

public static func convertToData(_ value: AnyObject) -> Data? {
switch value {
case let d as Data:
return d
case let d as String:
let hex = Data.fromHex(d.stripHexPrefix())
if hex != nil {
return hex
}
let str = d.data(using: .utf8)
if str != nil {
return str
}
case let d as [UInt8]:
return Data(d)
case let d as EthereumAddress:
return d.addressData
case let d as [IntegerLiteralType]:
var bytesArray = [UInt8]()
for el in d {
guard el >= 0, el <= 255 else {return nil}
bytesArray.append(UInt8(el))
}
return Data(bytesArray)
default:
return nil
}
return nil
}


public static func encode(types: [ABIv2.Element.InOut], values: [AnyObject]) -> Data? {
guard types.count == values.count else {return nil}
let params = types.flatMap { (el) -> ABIv2.Element.ParameterType in
Expand Down Expand Up @@ -63,33 +178,17 @@ extension ABIv2Encoder {
public static func encodeSingleType(type: ABIv2.Element.ParameterType, value: AnyObject) -> Data? {
switch type {
case .uint(_):
if let biguint = value as? BigUInt {
if let biguint = convertToBigUInt(value) {
return biguint.abiEncode(bits: 256)
}
if let bigint = value as? BigInt {
if let bigint = convertToBigInt(value) {
return bigint.abiEncode(bits: 256)
}
if let num = value as? IntegerLiteralType {
let biguint = BigUInt(num)
return biguint.abiEncode(bits: 256)
}
if let numString = value as? String {
guard let biguint = BigUInt(numString, radix: 10) else {break}
return biguint.abiEncode(bits: 256)
}
case .int(_):
if let biguint = value as? BigUInt {
if let biguint = convertToBigUInt(value) {
return biguint.abiEncode(bits: 256)
}
if let bigint = value as? BigInt {
return bigint.abiEncode(bits: 256)
}
if let num = value as? IntegerLiteralType {
let bigint = BigInt(num)
return bigint.abiEncode(bits: 256)
}
if let numString = value as? String {
guard let bigint = BigInt(numString, radix: 10) else {break}
if let bigint = convertToBigInt(value) {
return bigint.abiEncode(bits: 256)
}
case .address:
Expand All @@ -114,27 +213,9 @@ extension ABIv2Encoder {
}
}
case .bytes(let length):
if let string = value as? String {
var dataGuess: Data?
if string.hasHexPrefix() {
dataGuess = Data.fromHex(string.lowercased().stripHexPrefix())
}
else {
dataGuess = string.data(using: .utf8)
}
guard let data = dataGuess else {break}
if data.count > length {break}
return data.setLengthRight(32)
} else if let addr = value as? EthereumAddress {
guard addr.isValid else {break}
let data = addr.addressData
return data.setLengthRight(32)
} else if let data = value as? Data {
return data.setLengthRight(32)
} else if let byteArray = value as? [UInt8] {
let data = Data(byteArray)
return data.setLengthRight(32)
}
guard let data = convertToData(value) else {break}
if data.count > length {break}
return data.setLengthRight(32)
case .string:
if let string = value as? String {
var dataGuess: Data?
Expand All @@ -153,37 +234,13 @@ extension ABIv2Encoder {
return total
}
case .dynamicBytes:
if let string = value as? String {
var dataGuess: Data?
if string.hasHexPrefix() {
dataGuess = Data.fromHex(string.lowercased().stripHexPrefix())
}
else {
dataGuess = string.data(using: .utf8)
}
guard let data = dataGuess else {break}
let minLength = ((data.count + 31) / 32)*32
guard let paddedData = data.setLengthRight(UInt64(minLength)) else {break}
let length = BigUInt(data.count)
guard let head = length.abiEncode(bits: 256) else {break}
let total = head+paddedData
return total
} else if let data = value as? Data {
let minLength = ((data.count + 31) / 32)*32
guard let paddedData = data.setLengthRight(UInt64(minLength)) else {break}
let length = BigUInt(data.count)
guard let head = length.abiEncode(bits: 256) else {break}
let total = head+paddedData
return total
} else if let byteArray = value as? [UInt8] {
let data = Data(byteArray)
let minLength = ((data.count + 31) / 32)*32
guard let paddedData = data.setLengthRight(UInt64(minLength)) else {break}
let length = BigUInt(data.count)
guard let head = length.abiEncode(bits: 256) else {break}
let total = head+paddedData
return total
}
guard let data = convertToData(value) else {break}
let minLength = ((data.count + 31) / 32)*32
guard let paddedData = data.setLengthRight(UInt64(minLength)) else {break}
let length = BigUInt(data.count)
guard let head = length.abiEncode(bits: 256) else {break}
let total = head+paddedData
return total
case .array(type: let subType, length: let length):
switch type.arraySize {
case .dynamicSize:
Expand Down