Skip to content

Commit

Permalink
improve iso8601 date parsing from anchor responses
Browse files Browse the repository at this point in the history
  • Loading branch information
christian-rogobete committed Jan 14, 2025
1 parent 4c52755 commit da3b2f8
Show file tree
Hide file tree
Showing 10 changed files with 200 additions and 28 deletions.
6 changes: 6 additions & 0 deletions stellarsdk/stellarsdk.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -768,6 +768,8 @@
83379C2C2280BE2A00BD5F8E /* CreatePassiveSellOfferOperationResponse.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83379C262280B64500BD5F8E /* CreatePassiveSellOfferOperationResponse.swift */; };
83379C2E2280CF9C00BD5F8E /* CreatePassiveSellOfferOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83379C2D2280CF9C00BD5F8E /* CreatePassiveSellOfferOperation.swift */; };
83379C2F2280CF9C00BD5F8E /* CreatePassiveSellOfferOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = 83379C2D2280CF9C00BD5F8E /* CreatePassiveSellOfferOperation.swift */; };
8339DA5B2D36A55200232C8B /* ISO8601DateFormatter+Full.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8339DA5A2D36A55200232C8B /* ISO8601DateFormatter+Full.swift */; };
8339DA5C2D36A55300232C8B /* ISO8601DateFormatter+Full.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8339DA5A2D36A55200232C8B /* ISO8601DateFormatter+Full.swift */; };
833C67282B84C85000E034C6 /* QuoteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 833C67272B84C85000E034C6 /* QuoteService.swift */; };
833C67292B84C85000E034C6 /* QuoteService.swift in Sources */ = {isa = PBXBuildFile; fileRef = 833C67272B84C85000E034C6 /* QuoteService.swift */; };
833C672C2B84C97000E034C6 /* Sep38Responses.swift in Sources */ = {isa = PBXBuildFile; fileRef = 833C672B2B84C97000E034C6 /* Sep38Responses.swift */; };
Expand Down Expand Up @@ -1686,6 +1688,7 @@
83379C242280AE9C00BD5F8E /* ManageBuyOfferOperationResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ManageBuyOfferOperationResponse.swift; sourceTree = "<group>"; };
83379C262280B64500BD5F8E /* CreatePassiveSellOfferOperationResponse.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePassiveSellOfferOperationResponse.swift; sourceTree = "<group>"; };
83379C2D2280CF9C00BD5F8E /* CreatePassiveSellOfferOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreatePassiveSellOfferOperation.swift; sourceTree = "<group>"; };
8339DA5A2D36A55200232C8B /* ISO8601DateFormatter+Full.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ISO8601DateFormatter+Full.swift"; sourceTree = "<group>"; };
833C67272B84C85000E034C6 /* QuoteService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuoteService.swift; sourceTree = "<group>"; };
833C672B2B84C97000E034C6 /* Sep38Responses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sep38Responses.swift; sourceTree = "<group>"; };
833C672F2B84CF2F00E034C6 /* Sep38PostQuoteRequest.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sep38PostQuoteRequest.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2374,6 +2377,7 @@
74A504ED2192CC0000A608A0 /* String+KeyUtils.swift */,
74A504F02192D5D600A608A0 /* Data+KeyUtils.swift */,
83DD714F281DE65C00530C64 /* Data+B16.swift */,
8339DA5A2D36A55200232C8B /* ISO8601DateFormatter+Full.swift */,
);
path = extensions;
sourceTree = "<group>";
Expand Down Expand Up @@ -4495,6 +4499,7 @@
745DF4E92052FF9C000D3660 /* Blowfish.swift in Sources */,
745DF4EA2052FF9C000D3660 /* DigestType.swift in Sources */,
745DF4EB2052FF9C000D3660 /* Utils.swift in Sources */,
8339DA5C2D36A55300232C8B /* ISO8601DateFormatter+Full.swift in Sources */,
830E7DBC2529E24B0059A4B4 /* TrustlineSponsorshipUpdatedEffectResponse.swift in Sources */,
8320A9F1251E6ED6002FE6FA /* CreateClaimableBalanceResultXDR.swift in Sources */,
83B827822B306E1F0064D7CB /* SimulateTransactionRequest.swift in Sources */,
Expand Down Expand Up @@ -5186,6 +5191,7 @@
744C4DBF202A29E400B46CDE /* AccountCreatedOperationResponse.swift in Sources */,
EC34A0D020503CAB000FB042 /* RIPEMD160.swift in Sources */,
EC34A11A20503CC5000FB042 /* HKDF.swift in Sources */,
8339DA5B2D36A55200232C8B /* ISO8601DateFormatter+Full.swift in Sources */,
830E7DBB2529E24B0059A4B4 /* TrustlineSponsorshipUpdatedEffectResponse.swift in Sources */,
8320A9F0251E6ED6002FE6FA /* CreateClaimableBalanceResultXDR.swift in Sources */,
83B827812B306E1F0064D7CB /* SimulateTransactionRequest.swift in Sources */,
Expand Down
17 changes: 17 additions & 0 deletions stellarsdk/stellarsdk/extensions/ISO8601DateFormatter+Full.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// ISO8601DateFormatter+Full.swift
// stellarsdk
//
// Created by Christian Rogobete on 14.01.25.
// Copyright © 2025 Soneso. All rights reserved.
//

import Foundation

extension ISO8601DateFormatter {
public static let full: ISO8601DateFormatter = {
let formatter = ISO8601DateFormatter()
formatter.formatOptions = [.withFullDate, .withFullTime, .withTimeZone, .withFractionalSeconds]
return formatter
}()
}
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ public struct Sep24Transaction: Decodable {

/// Amount sent by anchor to user at end of transaction as a string with up to 7 decimals.
/// Excludes amount converted to XLM to fund account and any external fees.
public var amountOut:String
public var amountOut:String?

/// (optional) The asset delivered or to be delivered to the user. Must be present if the deposit/withdraw was made using non-equivalent assets.
/// The value must be in SEP-38 Asset Identification Format.
Expand All @@ -84,7 +84,7 @@ public struct Sep24Transaction: Decodable {
public var amountOutAsset:String?

/// Amount of fee charged by anchor
public var amountFee:String
public var amountFee:String?

/// (optional) The asset in which fees are calculated in. Must be present if the deposit/withdraw was made using non-equivalent assets.
/// The value must be in SEP-38 Asset Identification Format.
Expand Down Expand Up @@ -210,17 +210,42 @@ public struct Sep24Transaction: Decodable {
statusEta = try values.decodeIfPresent(Int.self, forKey: .statusEta)
kycVerified = try values.decodeIfPresent(Bool.self, forKey: .kycVerified)
moreInfoUrl = try values.decodeIfPresent(String.self, forKey: .moreInfoUrl)
amountIn = try values.decode(String.self, forKey: .amountIn)
amountIn = try values.decodeIfPresent(String.self, forKey: .amountIn)
amountInAsset = try values.decodeIfPresent(String.self, forKey: .amountInAsset)
amountOut = try values.decode(String.self, forKey: .amountOut)
amountOut = try values.decodeIfPresent(String.self, forKey: .amountOut)
amountOutAsset = try values.decodeIfPresent(String.self, forKey: .amountOutAsset)
amountFee = try values.decode(String.self, forKey: .amountFee)
amountFee = try values.decodeIfPresent(String.self, forKey: .amountFee)
amountFeeAsset = try values.decodeIfPresent(String.self, forKey: .amountFeeAsset)
quoteId = try values.decodeIfPresent(String.self, forKey: .quoteId)
startedAt = try values.decode(Date.self, forKey: .startedAt)
completedAt = try values.decodeIfPresent(Date.self, forKey: .completedAt)
updatedAt = try values.decodeIfPresent(Date.self, forKey: .updatedAt)
userActionRequiredBy = try values.decodeIfPresent(Date.self, forKey: .userActionRequiredBy)

let startedAtStr = try values.decode(String.self, forKey: .startedAt)
if let startedAtDate = ISO8601DateFormatter.full.date(from: startedAtStr) {
startedAt = startedAtDate
} else {
startedAt = try values.decode(Date.self, forKey: .startedAt)
}

if let completedAtStr = try values.decodeIfPresent(String.self, forKey: .completedAt),
let completedAtDate = ISO8601DateFormatter.full.date(from: completedAtStr) {
completedAt = completedAtDate
} else {
completedAt = try values.decodeIfPresent(Date.self, forKey: .completedAt)
}

if let updatedAtStr = try values.decodeIfPresent(String.self, forKey: .updatedAt),
let updatedAtDate = ISO8601DateFormatter.full.date(from: updatedAtStr) {
updatedAt = updatedAtDate
} else {
updatedAt = try values.decodeIfPresent(Date.self, forKey: .updatedAt)
}

if let userActionRequiredByStr = try values.decodeIfPresent(String.self, forKey: .userActionRequiredBy),
let userActionRequiredByDate = ISO8601DateFormatter.full.date(from: userActionRequiredByStr) {
userActionRequiredBy = userActionRequiredByDate
} else {
userActionRequiredBy = try values.decodeIfPresent(Date.self, forKey: .userActionRequiredBy)
}

stellarTransactionId = try values.decodeIfPresent(String.self, forKey: .stellarTransactionId)
externalTransactionId = try values.decodeIfPresent(String.self, forKey: .externalTransactionId)
message = try values.decodeIfPresent(String.self, forKey: .message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,12 @@ public struct CustomerFileResponse: Decodable {
fileId = try values.decode(String.self, forKey: .fileId)
contentType = try values.decode(String.self, forKey: .contentType)
size = try values.decode(Int.self, forKey: .size)
expiresAt = try values.decodeIfPresent(Date.self, forKey: .expiresAt)
if let expiresAtStr = try values.decodeIfPresent(String.self, forKey: .expiresAt),
let expiresAtDate = ISO8601DateFormatter.full.date(from: expiresAtStr) {
expiresAt = expiresAtDate
} else {
expiresAt = try values.decodeIfPresent(Date.self, forKey: .expiresAt)
}
customerId = try values.decodeIfPresent(String.self, forKey: .customerId)
}
}
7 changes: 6 additions & 1 deletion stellarsdk/stellarsdk/quote/responses/Sep38Responses.swift
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,12 @@ public struct Sep38QuoteResponse: Decodable {
public init(from decoder: Decoder) throws {
let values = try decoder.container(keyedBy: CodingKeys.self)
id = try values.decode(String.self, forKey: .id)
expiresAt = try values.decode(Date.self, forKey: .expiresAt)
let expiresAtStr = try values.decode(String.self, forKey: .expiresAt)
if let expiresAtDate = ISO8601DateFormatter.full.date(from: expiresAtStr) {
expiresAt = expiresAtDate
} else {
expiresAt = try values.decode(Date.self, forKey: .expiresAt)
}
totalPrice = try values.decode(String.self, forKey: .totalPrice)
price = try values.decode(String.self, forKey: .price)
sellAsset = try values.decode(String.self, forKey: .sellAsset)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -270,10 +270,35 @@ public struct AnchorTransaction: Decodable {
withdrawAnchorAccount = try values.decodeIfPresent(String.self, forKey: .withdrawAnchorAccount)
withdrawMemo = try values.decodeIfPresent(String.self, forKey: .withdrawMemo)
withdrawMemoType = try values.decodeIfPresent(String.self, forKey: .withdrawMemoType)
startedAt = try values.decodeIfPresent(Date.self, forKey: .startedAt)
updatedAt = try values.decodeIfPresent(Date.self, forKey: .updatedAt)
completedAt = try values.decodeIfPresent(Date.self, forKey: .completedAt)
userActionRequiredBy = try values.decodeIfPresent(Date.self, forKey: .userActionRequiredBy)

let startedAtStr = try values.decode(String.self, forKey: .startedAt)
if let startedAtDate = ISO8601DateFormatter.full.date(from: startedAtStr) {
startedAt = startedAtDate
} else {
startedAt = try values.decode(Date.self, forKey: .startedAt)
}

if let completedAtStr = try values.decodeIfPresent(String.self, forKey: .completedAt),
let completedAtDate = ISO8601DateFormatter.full.date(from: completedAtStr) {
completedAt = completedAtDate
} else {
completedAt = try values.decodeIfPresent(Date.self, forKey: .completedAt)
}

if let updatedAtStr = try values.decodeIfPresent(String.self, forKey: .updatedAt),
let updatedAtDate = ISO8601DateFormatter.full.date(from: updatedAtStr) {
updatedAt = updatedAtDate
} else {
updatedAt = try values.decodeIfPresent(Date.self, forKey: .updatedAt)
}

if let userActionRequiredByStr = try values.decodeIfPresent(String.self, forKey: .userActionRequiredBy),
let userActionRequiredByDate = ISO8601DateFormatter.full.date(from: userActionRequiredByStr) {
userActionRequiredBy = userActionRequiredByDate
} else {
userActionRequiredBy = try values.decodeIfPresent(Date.self, forKey: .userActionRequiredBy)
}

stellarTransactionId = try values.decodeIfPresent(String.self, forKey: .stellarTransactionId)
externalTransactionId = try values.decodeIfPresent(String.self, forKey: .externalTransactionId)
message = try values.decodeIfPresent(String.self, forKey: .message)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,9 +186,9 @@ class InteractiveServiceTestCase: XCTestCase {
XCTAssertEqual("510", tx.amountIn)
XCTAssertEqual("490", tx.amountOut)
XCTAssertEqual("5", tx.amountFee)
XCTAssertEqual("2017-03-20T17:00:02Z", tx.startedAt.ISO8601Format())
XCTAssertEqual("2017-03-20T17:09:58Z", tx.completedAt!.ISO8601Format())
XCTAssertEqual("2017-03-20T17:09:58Z", tx.updatedAt!.ISO8601Format())
XCTAssertEqual("2025-01-14T14:22:06Z", tx.startedAt.ISO8601Format())
XCTAssertEqual("2025-01-14T14:22:07Z", tx.updatedAt!.ISO8601Format())
XCTAssertEqual("2025-01-14T14:22:08Z", tx.completedAt!.ISO8601Format())
XCTAssertEqual("https://youranchor.com/tx/242523523", tx.moreInfoUrl)
XCTAssertNil(tx.claimableBalanceId)
XCTAssertNil(tx.refunded)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ class Sep24TransactionResponseMock: ResponsesMock {
"amount_in": "510",
"amount_out": "490",
"amount_fee": "5",
"started_at": "2017-03-20T17:00:02Z",
"completed_at": "2017-03-20T17:09:58Z",
"updated_at": "2017-03-20T17:09:58Z",
"started_at": "2025-01-14T14:22:06.391779Z",
"completed_at": "2025-01-14T14:22:08.491Z",
"updated_at": "2025-01-14T14:22:07Z",
"more_info_url": "https://youranchor.com/tx/242523523",
"stellar_transaction_id": "17a670bc424ff5ce3b386dbfaae9990b66a2a37b4fbe51547e8794962a3f9e6a",
"external_transaction_id": "1941491",
Expand Down
14 changes: 7 additions & 7 deletions stellarsdk/stellarsdkTests/soroban/SorobanAuthTest.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ import stellarsdk

class SorobanAuthTest: XCTestCase {

let sorobanServer = SorobanServer(endpoint: "https://rpc-futurenet.stellar.org") // SorobanServer(endpoint: "https://soroban-testnet.stellar.org")
let sdk = StellarSDK.futureNet() // StellarSDK.testNet()
let network = Network.futurenet // Network.testnet
let sorobanServer = SorobanServer(endpoint: "https://soroban-testnet.stellar.org") // SorobanServer(endpoint: "https://rpc-futurenet.stellar.org")
let sdk = StellarSDK.testNet() // StellarSDK.futureNet()
let network = Network.testnet // Network.futurenet
var invokerKeyPair = try! KeyPair.generateRandomKeyPair()
var senderKeyPair = try! KeyPair.generateRandomKeyPair()
var installTransactionId:String?
Expand All @@ -34,8 +34,8 @@ class SorobanAuthTest: XCTestCase {
let invokerId = invokerKeyPair.accountId
let senderId = senderKeyPair.accountId

//var responseEnum = await sdk.accounts.createTestAccount(accountId: invokerId)
var responseEnum = await sdk.accounts.createFutureNetTestAccount(accountId: invokerId)
var responseEnum = await sdk.accounts.createTestAccount(accountId: invokerId)
//var responseEnum = await sdk.accounts.createFutureNetTestAccount(accountId: invokerId)
switch responseEnum {
case .success(_):
break
Expand All @@ -44,8 +44,8 @@ class SorobanAuthTest: XCTestCase {
XCTFail("could not create invoker account: \(invokerId)")
}

responseEnum = await sdk.accounts.createFutureNetTestAccount(accountId: senderId)
// responseEnum = await sdk.accounts.createTestAccount(accountId: senderId)
//responseEnum = await sdk.accounts.createFutureNetTestAccount(accountId: senderId)
responseEnum = await sdk.accounts.createTestAccount(accountId: senderId)
switch responseEnum {
case .success(_):
break
Expand Down
Loading

0 comments on commit da3b2f8

Please sign in to comment.