From c7a27c0b86724ecbd6ff6872711e9c470c1031f3 Mon Sep 17 00:00:00 2001 From: Francisco Gindre Date: Mon, 27 Jun 2022 12:51:13 -0300 Subject: [PATCH] [#401] DecodingError when refreshing pending transactions (#402) Closes #401 This commit changes the way Codable in implemented for Zatoshi and PendingTransaction. SQLite attempts to decode Custom Types as JSONStrings inside a TEXT column whereas Zatoshi only needs to be an INTEGER that can be treated as an Int64 value `ConfirmedTransaction` entity is not affected because it is already deserialized in a custom fashion whereas `PendingTransaction` was relying on `Codable` and `CodingKey`. --- README.md | 6 +- .../DAO/PendingTransactionDao.swift | 79 ++++++++++++++++++- .../Extensions/Zatoshi+Codable.swift | 38 --------- .../Model/WalletTypes.swift | 11 +++ 4 files changed, 91 insertions(+), 43 deletions(-) delete mode 100644 Sources/ZcashLightClientKit/Extensions/Zatoshi+Codable.swift diff --git a/README.md b/README.md index d76bccc6..0bf350aa 100644 --- a/README.md +++ b/README.md @@ -20,15 +20,15 @@ This is an alpha build and is currently under active development. Please be advi ## Swift Package Manager -Add a package with the source "https://github.com/zcash/ZcashLightClientKit.git" and from version `0.13.0` onwards in either Xcode's GUI or in your `Package.swift` file. +Add a package with the source "https://github.com/zcash/ZcashLightClientKit.git" and from version `0.14.0-beta` onwards in either Xcode's GUI or in your `Package.swift` file. ### Beta version support for Xcode projects -If you want to include a beta version of `ZCashLightClientKit` in an Xcode project e.g `0.13.0-beta.2` you will need to specify it with the commit sha instead as it does not appear that Xcode supports 'meta data' from semantic version strings for swift packages (at the time of writing). +If you want to include a beta version of `ZCashLightClientKit` in an Xcode project e.g `0.14.0-beta` you will need to specify it with the commit sha instead as it does not appear that Xcode supports 'meta data' from semantic version strings for swift packages (at the time of writing). ## Cocoapods Support -Add `pod "ZcashLightClientKit", ~> "0.13.0-beta.2"` to the target you want to add the kit too. +Add `pod "ZcashLightClientKit", ~> "0.14.0-beta"` to the target you want to add the kit too. # Testing diff --git a/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift b/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift index 708f1826..ea323a3f 100644 --- a/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift +++ b/Sources/ZcashLightClientKit/DAO/PendingTransactionDao.swift @@ -7,8 +7,7 @@ import Foundation import SQLite -struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable { - +struct PendingTransaction: PendingTransactionEntity, Codable { enum CodingKeys: String, CodingKey { case toAddress = "to_address" case accountIndex = "account_index" @@ -63,6 +62,82 @@ struct PendingTransaction: PendingTransactionEntity, Decodable, Encodable { ) } + init( + toAddress: String, + accountIndex: Int, + minedHeight: BlockHeight, + expiryHeight: BlockHeight, + cancelled: Int, + encodeAttempts: Int, + submitAttempts: Int, + errorMessage: String?, + errorCode: Int?, + createTime: TimeInterval, + raw: Data?, + id: Int?, + value: Zatoshi, + memo: Data?, + rawTransactionId: Data? + ) { + self.toAddress = toAddress + self.accountIndex = accountIndex + self.minedHeight = minedHeight + self.expiryHeight = expiryHeight + self.cancelled = cancelled + self.encodeAttempts = encodeAttempts + self.submitAttempts = submitAttempts + self.errorMessage = errorMessage + self.errorCode = errorCode + self.createTime = createTime + self.raw = raw + self.id = id + self.value = value + self.memo = memo + self.rawTransactionId = rawTransactionId + } + + init(from decoder: Decoder) throws { + let container = try decoder.container(keyedBy: CodingKeys.self) + + self.toAddress = try container.decode(String.self, forKey: .toAddress) + self.accountIndex = try container.decode(Int.self, forKey: .accountIndex) + self.minedHeight = try container.decode(BlockHeight.self, forKey: .minedHeight) + self.expiryHeight = try container.decode(BlockHeight.self, forKey: .expiryHeight) + self.cancelled = try container.decode(Int.self, forKey: .cancelled) + self.encodeAttempts = try container.decode(Int.self, forKey: .encodeAttempts) + self.submitAttempts = try container.decode(Int.self, forKey: .submitAttempts) + self.errorMessage = try container.decodeIfPresent(String.self, forKey: .errorMessage) + self.errorCode = try container.decodeIfPresent(Int.self, forKey: .errorCode) + self.createTime = try container.decode(TimeInterval.self, forKey: .createTime) + self.raw = try container.decodeIfPresent(Data.self, forKey: .raw) + self.id = try container.decodeIfPresent(Int.self, forKey: .id) + + let zatoshiValue = try container.decode(Int64.self, forKey: .value) + self.value = Zatoshi(zatoshiValue) + self.memo = try container.decodeIfPresent(Data.self, forKey: .memo) + self.rawTransactionId = try container.decodeIfPresent(Data.self, forKey: .rawTransactionId) + } + + func encode(to encoder: Encoder) throws { + var container = encoder.container(keyedBy: CodingKeys.self) + + try container.encode(self.toAddress, forKey: .toAddress) + try container.encode(self.accountIndex, forKey: .accountIndex) + try container.encode(self.minedHeight, forKey: .minedHeight) + try container.encode(self.expiryHeight, forKey: .expiryHeight) + try container.encode(self.cancelled, forKey: .cancelled) + try container.encode(self.encodeAttempts, forKey: .encodeAttempts) + try container.encode(self.submitAttempts, forKey: .submitAttempts) + try container.encodeIfPresent(self.errorMessage, forKey: .errorMessage) + try container.encodeIfPresent(self.errorCode, forKey: .errorCode) + try container.encode(self.createTime, forKey: .createTime) + try container.encodeIfPresent(self.raw, forKey: .raw) + try container.encodeIfPresent(self.id, forKey: .id) + try container.encode(self.value.amount, forKey: .value) + try container.encodeIfPresent(self.memo, forKey: .memo) + try container.encodeIfPresent(self.rawTransactionId, forKey: .rawTransactionId) + } + func isSameTransactionId(other: T) -> Bool where T: RawIdentifiable { self.rawTransactionId == other.rawTransactionId } diff --git a/Sources/ZcashLightClientKit/Extensions/Zatoshi+Codable.swift b/Sources/ZcashLightClientKit/Extensions/Zatoshi+Codable.swift deleted file mode 100644 index 74e893ba..00000000 --- a/Sources/ZcashLightClientKit/Extensions/Zatoshi+Codable.swift +++ /dev/null @@ -1,38 +0,0 @@ -// -// Zatoshi+Codable.swift -// -// -// Created by Francisco Gindre on 6/20/22. -// - -import Foundation -/// This extension is needed to support SQLite Swift Codable Types -extension Zatoshi: Codable { - enum CodingError: Error { - case encodingError(String) - } - /// This codable implementation responds to limitaitons that SQLite Swift explains - /// on its documentation https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#codable-types - /// SQLite Sqift will encode custom types into a string and stores it in a single column. They do so by - /// leveraging the Codable interface so this has to abide by them and their choice. - public init(from decoder: Decoder) throws { - let container = try decoder.singleValueContainer() - let value = try container.decode(String.self) - - guard let amount = Int64(value) else { - throw CodingError.encodingError("Decoding Error") - } - - self.amount = amount - } - - /// This codable implementation responds to limitaitons that SQLite Swift explains - /// on its documentation https://github.com/stephencelis/SQLite.swift/blob/master/Documentation/Index.md#codable-types - /// SQLite Sqift will encode custom types into a string and stores it in a single column. They do so by - /// leveraging the Codable interface so this has to abide by them and their choice. - public func encode(to encoder: Encoder) throws { - var container = encoder.singleValueContainer() - - try container.encode(String(self.amount)) - } -} diff --git a/Sources/ZcashLightClientKit/Model/WalletTypes.swift b/Sources/ZcashLightClientKit/Model/WalletTypes.swift index 6be775d9..8532fb9e 100644 --- a/Sources/ZcashLightClientKit/Model/WalletTypes.swift +++ b/Sources/ZcashLightClientKit/Model/WalletTypes.swift @@ -105,4 +105,15 @@ public protocol UnifiedAddress { public struct WalletBalance { public var verified: Zatoshi public var total: Zatoshi + + public init(verified: Zatoshi, total: Zatoshi) { + self.verified = verified + self.total = total + } +} + +public extension WalletBalance { + static var zero: WalletBalance { + Self(verified: .zero, total: .zero) + } }