From 7221776fd919dbbd7ca19a8efccddf26df827cd0 Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 17:02:51 +0800 Subject: [PATCH 1/6] fix: url query dictionary decoding. --- Sources/Core/Utilities/QueryDecoding.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Core/Utilities/QueryDecoding.swift b/Sources/Core/Utilities/QueryDecoding.swift index 8dce45f..53db284 100644 --- a/Sources/Core/Utilities/QueryDecoding.swift +++ b/Sources/Core/Utilities/QueryDecoding.swift @@ -100,8 +100,8 @@ public enum QueryDecoding { param: [String: String], target: String ) throws -> [String: Any] { - let leftBrackets = QueryEscape.escape("[") - let rightBrackets = QueryEscape.escape("]") + let leftBrackets = "[" + let rightBrackets = "]" let targets: [String: String] = param.reduce([:]) { var copied = $0 copied[$1.key] = ($1.key.contains(target) ? $1.value : nil) From 3e594378604c25c6c57dcd4cc7c314c5898e81cb Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 17:10:21 +0800 Subject: [PATCH 2/6] fix: url query array decoding. --- Sources/Core/Utilities/QueryDecoding.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Sources/Core/Utilities/QueryDecoding.swift b/Sources/Core/Utilities/QueryDecoding.swift index 53db284..2d45603 100644 --- a/Sources/Core/Utilities/QueryDecoding.swift +++ b/Sources/Core/Utilities/QueryDecoding.swift @@ -83,8 +83,8 @@ public enum QueryDecoding { param: [String: String], target: String ) throws -> [String] { - let leftBrackets = QueryEscape.escape("[") - let rightBrackets = QueryEscape.escape("]") + let leftBrackets = "[" + let rightBrackets = "]" let array: [String] = param.reduce([]) { if $1.key == (target + leftBrackets + rightBrackets) { var copied = $0 From 04c9cc045509f7a471545778cf327fd66c483ada Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 18:01:30 +0800 Subject: [PATCH 3/6] fix: escaping. --- Sources/Core/Utilities/QueryDecoding.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Sources/Core/Utilities/QueryDecoding.swift b/Sources/Core/Utilities/QueryDecoding.swift index 2d45603..bf5235a 100644 --- a/Sources/Core/Utilities/QueryDecoding.swift +++ b/Sources/Core/Utilities/QueryDecoding.swift @@ -107,7 +107,7 @@ public enum QueryDecoding { copied[$1.key] = ($1.key.contains(target) ? $1.value : nil) return copied } - let regex = try NSRegularExpression(pattern: "(?<=\(leftBrackets))(.*?)(?=\(rightBrackets))") + let regex = try NSRegularExpression(pattern: #"(?<=\\#(leftBrackets))(.*?)(?=\\#(rightBrackets))"#) let value = targets.reduce([:]) { result, target -> [String: String] in var finalResult = result if let result: NSTextCheckingResult = regex.firstMatch( From f23d3d3ce55b79b8900443e2a86003e3996c4ac9 Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 21:16:47 +0800 Subject: [PATCH 4/6] feat: filter for other then 200 status code. --- Sources/Flow/Extensions/URLSessionExtension.swift | 12 +++++++++++- Sources/Solana/BloctoSolanaSDK.swift | 12 +++++++++++- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/Sources/Flow/Extensions/URLSessionExtension.swift b/Sources/Flow/Extensions/URLSessionExtension.swift index e389646..5567ec3 100644 --- a/Sources/Flow/Extensions/URLSessionExtension.swift +++ b/Sources/Flow/Extensions/URLSessionExtension.swift @@ -18,7 +18,17 @@ extension URLSession { private func data(for request: URLRequest) async throws -> Data { try await withCheckedThrowingContinuation { continuation in - dataTask(with: request) { data, _, error in + dataTask(with: request) { data, response, error in + guard let response = response as? HTTPURLResponse, + (200 ..< 300) ~= response.statusCode else { + log(enable: BloctoSDK.shared.logging, message: "error: \(error.debugDescription)") + if let data = data, + let text = String(data: data, encoding: .utf8) { + log(enable: BloctoSDK.shared.logging, message: "response: \(text)") + } + continuation.resume(with: .failure(BloctoSDKError.responseUnexpected)) + return + } if let error = error { continuation.resume(with: .failure(error)) } else if let data = data { diff --git a/Sources/Solana/BloctoSolanaSDK.swift b/Sources/Solana/BloctoSolanaSDK.swift index 532f4ec..9b9581e 100644 --- a/Sources/Solana/BloctoSolanaSDK.swift +++ b/Sources/Solana/BloctoSolanaSDK.swift @@ -178,11 +178,21 @@ public class BloctoSolanaSDK { ] ) session - .dataTask(with: request) { [weak self] data, _, error in + .dataTask(with: request) { [weak self] data, response, error in do { guard let self = self else { throw BloctoSDKError.callbackSelfNotfound } + guard let response = response as? HTTPURLResponse, + (200 ..< 300) ~= response.statusCode else { + log(enable: self.base.logging, message: "error: \(error.debugDescription)") + if let data = data, + let text = String(data: data, encoding: .utf8) { + log(enable: self.base.logging, message: "response: \(text)") + } + completion(.failure(BloctoSDKError.responseUnexpected)) + return + } if let error = error { completion(.failure(error)) return From d0c4642b94867d0379ac9cbb119636c3b010c222 Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 21:17:06 +0800 Subject: [PATCH 5/6] fix: UI thread operation. --- .../SolanaDemoViewController.swift | 86 ++++++++++--------- 1 file changed, 46 insertions(+), 40 deletions(-) diff --git a/Example/BloctoSDK/ViewControllers/SolanaDemoViewController.swift b/Example/BloctoSDK/ViewControllers/SolanaDemoViewController.swift index 542c183..4a2b6f5 100644 --- a/Example/BloctoSDK/ViewControllers/SolanaDemoViewController.swift +++ b/Example/BloctoSDK/ViewControllers/SolanaDemoViewController.swift @@ -640,13 +640,15 @@ final class SolanaDemoViewController: UIViewController { transaction: transaction ) { [weak self] result in guard let self = self else { return } - self.resetSetValueStatus() - switch result { - case let .success(txHsh): - self.setValueResultLabel.text = txHsh - self.setValueExplorerButton.isHidden = false - case let .failure(error): - self.handleSetValueError(error) + DispatchQueue.main.async { + self.resetSetValueStatus() + switch result { + case let .success(txHsh): + self.setValueResultLabel.text = txHsh + self.setValueExplorerButton.isHidden = false + case let .failure(error): + self.handleSetValueError(error) + } } } } @@ -660,17 +662,19 @@ final class SolanaDemoViewController: UIViewController { connetion.getAccountInfo( publicKey: dappPublicKey) { [weak self] (result: Result?, Connection.Error>) in guard let self = self else { return } - self.resetGetValueStatus() - switch result { - case let .success(valueAccount): - guard let data = valueAccount?.data else { - self.handleGetValueError(Error.message("data not found.")) - return - } - self.getValueResultLabel.text = "\(data.value)" - case let .failure(error): - debugPrint(error) - self.handleGetValueError(error) + DispatchQueue.main.async { + self.resetGetValueStatus() + switch result { + case let .success(valueAccount): + guard let data = valueAccount?.data else { + self.handleGetValueError(Error.message("data not found.")) + return + } + self.getValueResultLabel.text = "\(data.value)" + case let .failure(error): + debugPrint(error) + self.handleGetValueError(error) + } } } } @@ -729,31 +733,33 @@ final class SolanaDemoViewController: UIViewController { solanaAddress: userWalletAddress ) { [weak self] result in guard let self = self else { return } - switch result { - case let .success(transaction): - do { - var newTransaction = transaction - try newTransaction.partialSign(signers: [newAccount]) - - self.bloctoSolanaSDK.signAndSendTransaction( - from: userWalletAddress, - transaction: newTransaction - ) { [weak self] result in - guard let self = self else { return } - self.resetPartialSignTxStatus() - switch result { - case let .success(txHash): - self.partialSignTxResultLabel.text = txHash - self.partialSignTxExplorerButton.isHidden = false - case let .failure(error): - self.handlePartialSignTxError(error) + DispatchQueue.main.async { + switch result { + case let .success(transaction): + do { + var newTransaction = transaction + try newTransaction.partialSign(signers: [newAccount]) + + self.bloctoSolanaSDK.signAndSendTransaction( + from: userWalletAddress, + transaction: newTransaction + ) { [weak self] result in + guard let self = self else { return } + self.resetPartialSignTxStatus() + switch result { + case let .success(txHash): + self.partialSignTxResultLabel.text = txHash + self.partialSignTxExplorerButton.isHidden = false + case let .failure(error): + self.handlePartialSignTxError(error) + } } + } catch { + self.handlePartialSignTxError(error) } - } catch { + case let .failure(error): self.handlePartialSignTxError(error) - } - case let .failure(error): - self.handlePartialSignTxError(error) + } } } } catch { From 28ccd421a4c7b7515b6eecba4b01a0ad7c6c9650 Mon Sep 17 00:00:00 2001 From: andrew54068 Date: Fri, 25 Nov 2022 21:50:05 +0800 Subject: [PATCH 6/6] fix: remove key escaping. --- Example/Tests/Methods/URLSessionMock.swift | 10 ++++++++-- .../QueryItemCoding/QueryItemEncodingTests.swift | 12 ++++++------ Sources/Core/Utilities/URLEncoding.swift | 10 +++++----- 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/Example/Tests/Methods/URLSessionMock.swift b/Example/Tests/Methods/URLSessionMock.swift index 31e5b53..07499ca 100644 --- a/Example/Tests/Methods/URLSessionMock.swift +++ b/Example/Tests/Methods/URLSessionMock.swift @@ -18,14 +18,20 @@ class URLSessionMock: URLSessionProtocol { with request: URLRequest, completionHandler: @escaping (Data?, URLResponse?, Error?) -> Void ) -> URLSessionDataTask { + guard let url = request.url else { + return URLSessionDataTaskMock { + completionHandler(nil, nil, nil) + } + } let error = error + let response = HTTPURLResponse(url: url, statusCode: 200, httpVersion: nil, headerFields: nil) if let dataString = responseJsonString { return URLSessionDataTaskMock { - completionHandler(Data(dataString.utf8), nil, error) + completionHandler(Data(dataString.utf8), response, error) } } return URLSessionDataTaskMock { - completionHandler(nil, nil, error) + completionHandler(nil, response, error) } } diff --git a/Example/Tests/QueryItemCoding/QueryItemEncodingTests.swift b/Example/Tests/QueryItemCoding/QueryItemEncodingTests.swift index bd8707e..8547fca 100644 --- a/Example/Tests/QueryItemCoding/QueryItemEncodingTests.swift +++ b/Example/Tests/QueryItemCoding/QueryItemEncodingTests.swift @@ -35,8 +35,8 @@ func testDictionaryDecoding() throws { // Given: let param = [ - QueryName.publicKeySignaturePairs.rawValue + "%5Btest1%5D": "1", - QueryName.publicKeySignaturePairs.rawValue + "%5Btest2%5D": "2" + QueryName.publicKeySignaturePairs.rawValue + "[test1]": "1", + QueryName.publicKeySignaturePairs.rawValue + "[test2]": "2" ] let expect: [String: String] = [ @@ -64,8 +64,8 @@ "test2": data2 ]) let expect: [URLQueryItem] = [ - URLQueryItem(name: QueryName.appendTx.rawValue + "%5Btest1%5D", value: "0x1234"), - URLQueryItem(name: QueryName.appendTx.rawValue + "%5Btest2%5D", value: "0x2345") + URLQueryItem(name: QueryName.appendTx.rawValue + "[test1]", value: "0x1234"), + URLQueryItem(name: QueryName.appendTx.rawValue + "[test2]", value: "0x2345") ] // When: @@ -78,8 +78,8 @@ func testDictionaryDataDecoding() throws { // Given: let param = [ - QueryName.appendTx.rawValue + "%5Btest1%5D": "1234", - QueryName.appendTx.rawValue + "%5Btest2%5D": "2345" + QueryName.appendTx.rawValue + "[test1]": "1234", + QueryName.appendTx.rawValue + "[test2]": "2345" ] let expect: [String: Data] = [ diff --git a/Sources/Core/Utilities/URLEncoding.swift b/Sources/Core/Utilities/URLEncoding.swift index 53884ea..10bb9e2 100644 --- a/Sources/Core/Utilities/URLEncoding.swift +++ b/Sources/Core/Utilities/URLEncoding.swift @@ -43,13 +43,13 @@ public enum URLEncoding { let boolEncoding = BoolEncoding() components.append( .init( - name: escape(key), + name: key, value: escape(boolEncoding.encode(value: number.boolValue)) )) } else { components.append( .init( - name: escape(key), + name: key, value: escape("\(number)") )) } @@ -57,13 +57,13 @@ public enum URLEncoding { let boolEncoding = BoolEncoding() components.append( .init( - name: escape(key), + name: key, value: escape(boolEncoding.encode(value: bool)) )) case let data as Data: components.append( .init( - name: escape(key), + name: key, value: data.bloctoSDK.hexStringWith0xPrefix )) case let string as String: @@ -75,7 +75,7 @@ public enum URLEncoding { default: components.append( .init( - name: escape(key), + name: key, value: "\(value)" )) }