Skip to content

Commit e766fa3

Browse files
committed
Add flow encode and bump version
1 parent 50b6082 commit e766fa3

7 files changed

Lines changed: 315 additions & 5 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ https://outblock.github.io/flow-swift/
2929
This is a Swift Package, and can be installed via Xcode with the URL of this repository:
3030

3131
```swift
32-
.package(name: "Flow", url: "https://github.com/outblock/flow-swift.git", from: "0.3.6")
32+
.package(name: "Flow", url: "https://github.com/outblock/flow-swift.git", from: "0.4.0")
3333
```
3434

3535
## Config

Sources/Decode/FlowArgument+Decode.swift renamed to Sources/Codeable/FlowArgument+Decode.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,15 +19,15 @@
1919
import BigInt
2020
import Foundation
2121

22-
protocol FlowCodable {
22+
protocol FlowDecodable {
2323
func decode() -> Any?
2424

2525
func decode<T: Decodable>(_ decodable: T.Type) throws -> T
2626

2727
func decode<T: Decodable>() throws -> T
2828
}
2929

30-
extension Flow.Argument: FlowCodable {
30+
extension Flow.Argument: FlowDecodable {
3131
public func decode<T: Decodable>() throws -> T {
3232
guard let value = decode() else {
3333
throw Flow.FError.decodeFailure
Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
//
2+
// CadenceTypeTest
3+
//
4+
// Copyright 2022 Outblock Pty Ltd
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
import BigInt
20+
import Foundation
21+
22+
public protocol FlowEncodable {
23+
func toFlowArgument() -> Flow.Argument?
24+
}
25+
26+
extension Int: FlowEncodable {
27+
public func toFlowArgument() -> Flow.Argument? {
28+
return .init(type: .int, value: .int(self))
29+
}
30+
}
31+
32+
extension String: FlowEncodable {
33+
public func toFlowArgument() -> Flow.Argument? {
34+
return .init(type: .string, value: .string(self))
35+
}
36+
}
37+
38+
extension Bool: FlowEncodable {
39+
public func toFlowArgument() -> Flow.Argument? {
40+
return .init(type: .bool, value: .bool(self))
41+
}
42+
}
43+
44+
extension Double: FlowEncodable {
45+
public func toFlowArgument() -> Flow.Argument? {
46+
return .init(type: .ufix64, value: .ufix64(Decimal(self)))
47+
}
48+
}
49+
50+
extension Decimal: FlowEncodable {
51+
public func toFlowArgument() -> Flow.Argument? {
52+
return .init(type: .ufix64, value: .ufix64(self))
53+
}
54+
}
55+
56+
extension Int8: FlowEncodable {
57+
public func toFlowArgument() -> Flow.Argument? {
58+
return .init(type: .int8, value: .int8(self))
59+
}
60+
}
61+
62+
extension UInt8: FlowEncodable {
63+
public func toFlowArgument() -> Flow.Argument? {
64+
return .init(type: .uint8, value: .uint8(self))
65+
}
66+
}
67+
68+
extension Int16: FlowEncodable {
69+
public func toFlowArgument() -> Flow.Argument? {
70+
return .init(type: .int16, value: .int16(self))
71+
}
72+
}
73+
74+
extension UInt16: FlowEncodable {
75+
public func toFlowArgument() -> Flow.Argument? {
76+
return .init(type: .uint16, value: .uint16(self))
77+
}
78+
}
79+
80+
extension Int32: FlowEncodable {
81+
public func toFlowArgument() -> Flow.Argument? {
82+
return .init(type: .int32, value: .int32(self))
83+
}
84+
}
85+
86+
extension UInt32: FlowEncodable {
87+
public func toFlowArgument() -> Flow.Argument? {
88+
return .init(type: .uint32, value: .uint32(self))
89+
}
90+
}
91+
92+
extension Int64: FlowEncodable {
93+
public func toFlowArgument() -> Flow.Argument? {
94+
return .init(type: .int64, value: .int64(self))
95+
}
96+
}
97+
98+
extension UInt64: FlowEncodable {
99+
public func toFlowArgument() -> Flow.Argument? {
100+
return .init(type: .uint64, value: .uint64(self))
101+
}
102+
}
103+
104+
extension BigInt: FlowEncodable {
105+
public func toFlowArgument() -> Flow.Argument? {
106+
return .init(type: .int128, value: .int128(self))
107+
}
108+
}
109+
110+
extension BigUInt: FlowEncodable {
111+
public func toFlowArgument() -> Flow.Argument? {
112+
return .init(type: .uint128, value: .uint128(self))
113+
}
114+
}
115+
116+
extension Array: FlowEncodable where Element: FlowEncodable {
117+
public func toFlowArgument() -> Flow.Argument? {
118+
let arguments = compactMap { $0.toFlowArgument() }
119+
return .init(type: .array, value: .array(arguments.toValue()))
120+
}
121+
}
122+
123+
extension Optional: FlowEncodable where Wrapped: FlowEncodable {
124+
public func toFlowArgument() -> Flow.Argument? {
125+
switch self {
126+
case .none:
127+
return .init(type: .optional, value: .optional(nil))
128+
case .some(let value):
129+
return .init(type: .optional, value: .optional(value.toFlowArgument()?.value))
130+
}
131+
}
132+
}
133+
134+
extension Dictionary: FlowEncodable where Key: FlowEncodable, Value: FlowEncodable {
135+
public func toFlowArgument() -> Flow.Argument? {
136+
let entries = compactMap { key, value -> Flow.Argument.Dictionary? in
137+
guard let keyArg = key.toFlowArgument(),
138+
let valueArg = value.toFlowArgument() else {
139+
return nil
140+
}
141+
return Flow.Argument.Dictionary(key: keyArg.value, value: valueArg.value)
142+
}
143+
return .init(type: .dictionary, value: .dictionary(entries))
144+
}
145+
}

Sources/Models/FlowArgument.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,14 @@ public extension Flow {
6161
self.value = value
6262
}
6363

64+
public init?(_ value: FlowEncodable) {
65+
guard let flowArgument = value.toFlowArgument() else {
66+
return nil
67+
}
68+
self.type = flowArgument.type
69+
self.value = flowArgument.value
70+
}
71+
6472
public init?(jsonData: Data) {
6573
do {
6674
let result = try JSONDecoder().decode(Flow.Argument.self, from: jsonData)

Sources/Models/FlowEvent.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ extension Flow.Snapshot: CustomStringConvertible {
111111
public var description: String { data.hexValue }
112112
}
113113

114-
extension Flow.Event.Payload: FlowCodable {
114+
extension Flow.Event.Payload: FlowDecodable {
115115
public func decode() -> Any? {
116116
return fields?.decode()
117117
}

Sources/Models/FlowScript.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ public extension Flow {
6161
}
6262
}
6363

64-
extension Flow.ScriptResponse: FlowCodable {
64+
extension Flow.ScriptResponse: FlowDecodable {
6565
public func decode() -> Any? {
6666
return fields?.decode()
6767
}

Tests/ArgumentEncodeTests.swift

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
//
2+
// ArgumentEncodeTests.swift
3+
//
4+
// Copyright 2022 Outblock Pty Ltd
5+
//
6+
// Licensed under the Apache License, Version 2.0 (the "License");
7+
// you may not use this file except in compliance with the License.
8+
// You may obtain a copy of the License at
9+
//
10+
// http://www.apache.org/licenses/LICENSE-2.0
11+
//
12+
// Unless required by applicable law or agreed to in writing, software
13+
// distributed under the License is distributed on an "AS IS" BASIS,
14+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
// See the License for the specific language governing permissions and
16+
// limitations under the License.
17+
//
18+
19+
@testable import BigInt
20+
@testable import Flow
21+
import XCTest
22+
23+
final class ArgumentEncodeTests: XCTestCase {
24+
25+
func testEncodeIntType() throws {
26+
let value: [Int] = [1, 2, 3]
27+
let argument = Flow.Argument(value)!
28+
let expectedJson = """
29+
{
30+
"type": "Array",
31+
"value": [
32+
{"type": "Int", "value": "1"},
33+
{"type": "Int", "value": "2"},
34+
{"type": "Int", "value": "3"}
35+
]
36+
}
37+
"""
38+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
39+
}
40+
41+
func testEncodeUIntType() throws {
42+
let value: [UInt8] = [1, 2, 3]
43+
let argument = Flow.Argument(value)!
44+
let expectedJson = """
45+
{
46+
"type": "Array",
47+
"value": [
48+
{"type": "UInt8", "value": "1"},
49+
{"type": "UInt8", "value": "2"},
50+
{"type": "UInt8", "value": "3"}
51+
]
52+
}
53+
"""
54+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
55+
}
56+
57+
func testEncodeStringType() throws {
58+
let value = "absolutely"
59+
let argument = Flow.Argument(value)!
60+
let expectedJson = """
61+
{
62+
"type": "String",
63+
"value": "absolutely"
64+
}
65+
"""
66+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
67+
}
68+
69+
func testEncodeBoolType() throws {
70+
let value = true
71+
let argument = Flow.Argument(value)!
72+
let expectedJson = """
73+
{
74+
"type": "Bool",
75+
"value": true
76+
}
77+
"""
78+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
79+
}
80+
81+
func testEncodeOptionalType() throws {
82+
let value: String? = "test"
83+
let argument = Flow.Argument(value)!
84+
let expectedJson = """
85+
{
86+
"type": "Optional",
87+
"value": {
88+
"type": "String",
89+
"value": "test"
90+
}
91+
}
92+
"""
93+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
94+
}
95+
96+
func testEncodeNilOptionalType() throws {
97+
let value: String? = nil
98+
let argument = Flow.Argument(value)!
99+
let expectedJson = """
100+
{
101+
"type": "Optional",
102+
"value": null
103+
}
104+
"""
105+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
106+
}
107+
108+
func testEncodeDictionaryType() throws {
109+
let value: [Int: String] = [1: "one"]
110+
let argument = Flow.Argument(value)!
111+
let expectedJson = """
112+
{
113+
"type": "Dictionary",
114+
"value": [
115+
{
116+
"key": {"type": "Int", "value": "1"},
117+
"value": {"type": "String", "value": "one"}
118+
}
119+
]
120+
}
121+
"""
122+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
123+
}
124+
125+
func testEncodeArrayType() throws {
126+
let value = ["test1", "test2"]
127+
let argument = Flow.Argument(value)!
128+
let expectedJson = """
129+
{
130+
"type": "Array",
131+
"value": [
132+
{
133+
"type": "String",
134+
"value": "test1"
135+
},
136+
{
137+
"type": "String",
138+
"value": "test2"
139+
}
140+
]
141+
}
142+
"""
143+
XCTAssertEqual(argument.jsonString, formatJsonString(jsonString: expectedJson))
144+
}
145+
146+
// MARK: - Util Method
147+
148+
func formatJsonString(jsonString: String) -> String? {
149+
guard let jsonData = jsonString.data(using: .utf8),
150+
let object = try? JSONSerialization.jsonObject(with: jsonData),
151+
let formattedData = try? JSONSerialization.data(withJSONObject: object, options: []),
152+
let formattedString = String(data: formattedData, encoding: .utf8) else {
153+
return nil
154+
}
155+
return formattedString
156+
}
157+
}

0 commit comments

Comments
 (0)