Skip to content

Commit 295e137

Browse files
feat: encoding query parameters for EIP681 - except tuples, this is still a TODO
1 parent 1ae35e6 commit 295e137

File tree

1 file changed

+173
-0
lines changed

1 file changed

+173
-0
lines changed

Sources/web3swift/Utils/EIP/EIP681.swift

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,179 @@ extension Web3 {
5757
self.isPayRequest = isPayRequest
5858
self.targetAddress = targetAddress
5959
}
60+
<<<<<<< HEAD
61+
=======
62+
63+
public func makeEIP681Link() -> String? {
64+
let address: String
65+
switch targetAddress {
66+
case .ethereumAddress(let ethereumAddress):
67+
address = ethereumAddress.address
68+
case let .ensAddress(ensAdress):
69+
address = ensAdress
70+
}
71+
var link = "ethereum:\(address)\(chainID != nil ? "@\(chainID!.description)" : "")"
72+
if let functionName = functionName, !functionName.isEmpty {
73+
link = "\(link)/\(functionName)"
74+
}
75+
if !parameters.isEmpty {
76+
let queryParameters: [String] = parameters.compactMap { eip681Parameter in
77+
guard let queryValue = Web3
78+
.EIP681CodeEncoder
79+
.encodeFunctionArgument(eip681Parameter.type, eip681Parameter.value)
80+
else {
81+
return nil
82+
}
83+
return "\(eip681Parameter.type.abiRepresentation)=\(queryValue)"
84+
}
85+
86+
if queryParameters.count == parameters.count {
87+
link = "\(link)?\(queryParameters.joined(separator: "&"))"
88+
}
89+
}
90+
return link
91+
}
92+
}
93+
94+
public struct EIP681CodeEncoder {
95+
public static func encodeFunctionArgument(_ inputType: ABI.Element.ParameterType,
96+
_ rawValue: AnyObject) -> String? {
97+
switch inputType {
98+
case .address:
99+
if let ethAddress = rawValue as? EthereumAddress {
100+
return ethAddress.address
101+
}
102+
if let bytes = rawValue as? Data,
103+
let ethAddress = EthereumAddress(bytes) {
104+
return ethAddress.address
105+
}
106+
if let string = rawValue as? String {
107+
if let ethAddress = EthereumAddress(string) {
108+
return ethAddress.address
109+
}
110+
if let url = URL(string: string) {
111+
return string
112+
}
113+
}
114+
return nil
115+
case .uint(bits: _):
116+
let value: BigUInt?
117+
if let bigInt = rawValue as? BigInt {
118+
value = BigUInt(bigInt)
119+
} else if let bigUInt = rawValue as? BigUInt {
120+
value = bigUInt
121+
} else if let bytes = rawValue as? Data {
122+
value = BigUInt(bytes)
123+
} else if let string = rawValue as? String {
124+
value = BigUInt(string, radix: 10) ?? BigUInt(string.stripHexPrefix(), radix: 16)
125+
} else if let number = rawValue as? Int {
126+
value = BigUInt(exactly: number)
127+
} else if let number = rawValue as? Double {
128+
value = BigUInt(exactly: number)
129+
} else {
130+
value = nil
131+
}
132+
return value?.description
133+
case .int(bits: _):
134+
let value: BigInt?
135+
if let bigInt = rawValue as? BigInt {
136+
value = bigInt
137+
} else if let bigUInt = rawValue as? BigUInt {
138+
value = BigInt(bigUInt)
139+
} else if let bytes = rawValue as? Data {
140+
value = BigInt(bytes)
141+
} else if let string = rawValue as? String {
142+
value = BigInt(string, radix: 10) ?? BigInt(string.stripHexPrefix(), radix: 16)
143+
} else if let number = rawValue as? Int {
144+
value = BigInt(exactly: number)
145+
} else if let number = rawValue as? Double {
146+
value = BigInt(exactly: number)
147+
} else {
148+
value = nil
149+
}
150+
return value?.description
151+
case .string:
152+
if let bytes = rawValue as? Data,
153+
let string = String(data: bytes, encoding: .utf8) {
154+
return string
155+
} else if let string = rawValue as? String {
156+
return string
157+
}
158+
return nil
159+
case .dynamicBytes:
160+
if let bytes = rawValue as? Data {
161+
return bytes.toHexString().addHexPrefix()
162+
} else if let bytes = rawValue as? [UInt8] {
163+
return Data(bytes).toHexString().addHexPrefix()
164+
} else if let string = rawValue as? String {
165+
if let bytes = Data.fromHex(string) {
166+
return string.addHexPrefix()
167+
}
168+
return string.data(using: .utf8)?.toHexString().addHexPrefix()
169+
}
170+
return nil
171+
case let .bytes(length):
172+
var data: Data? = nil
173+
if let bytes = rawValue as? Data {
174+
data = bytes
175+
} else if let bytes = rawValue as? [UInt8] {
176+
data = Data(bytes)
177+
} else if let string = rawValue as? String {
178+
if let bytes = Data.fromHex(string) {
179+
data = bytes
180+
}
181+
data = string.data(using: .utf8)
182+
}
183+
184+
if let data = data,
185+
data.count == length {
186+
return data.toHexString().addHexPrefix()
187+
}
188+
return nil
189+
case .bool:
190+
if let bool = rawValue as? Bool {
191+
return bool ? "true" : "false"
192+
}
193+
if let number = rawValue as? Int,
194+
let int = BigInt(exactly: number) {
195+
return int == 0 ? "false" : "true"
196+
}
197+
if let number = rawValue as? Double,
198+
let int = BigInt(exactly: number) {
199+
return int == 0 ? "false" : "true"
200+
}
201+
if let string = rawValue as? String {
202+
switch string.lowercased() {
203+
case "true", "yes", "1":
204+
return "true"
205+
default:
206+
return "false"
207+
}
208+
}
209+
if let bytes = rawValue as? Data {
210+
return bytes.count == 0 || bytes.count == 1 && bytes.first == 0 ? "false" : "true"
211+
}
212+
return nil
213+
case let .array(type, length):
214+
if let array = rawValue as? [AnyObject] {
215+
let mappedArray = array.compactMap { object in
216+
encodeFunctionArgument(type, object)
217+
}
218+
219+
if length != 0 && UInt64(mappedArray.count) == length {
220+
return "[\(mappedArray.joined(separator: ","))]"
221+
} else if length == 0 && mappedArray.count == array.count {
222+
return "[\(mappedArray.joined(separator: ","))]"
223+
}
224+
}
225+
return nil
226+
case let .tuple(types):
227+
// TODO: implement!
228+
return nil
229+
default: return nil
230+
}
231+
}
232+
>>>>>>> 35c85fd7... feat: encoding query parameters for EIP681 - except tuples, this is still a TODO
60233
}
61234

62235
public struct EIP681CodeParser {

0 commit comments

Comments
 (0)