react-native-candle 0.1.16 → 0.1.18

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (105) hide show
  1. package/ReactNativeCandle.podspec +1 -1
  2. package/ios/Sources/CandleLinkSheetWrapperView.swift +2 -167
  3. package/ios/Sources/RNCandle.swift +558 -47
  4. package/lib/commonjs/index.js +157 -1
  5. package/lib/commonjs/index.js.map +1 -1
  6. package/lib/module/index.js +157 -1
  7. package/lib/module/index.js.map +1 -1
  8. package/lib/typescript/commonjs/src/index.d.ts +79 -3
  9. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  10. package/lib/typescript/commonjs/src/specs/RNCandle.nitro.d.ts +197 -9
  11. package/lib/typescript/commonjs/src/specs/RNCandle.nitro.d.ts.map +1 -1
  12. package/lib/typescript/module/src/index.d.ts +79 -3
  13. package/lib/typescript/module/src/index.d.ts.map +1 -1
  14. package/lib/typescript/module/src/specs/RNCandle.nitro.d.ts +197 -9
  15. package/lib/typescript/module/src/specs/RNCandle.nitro.d.ts.map +1 -1
  16. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Bridge.cpp +36 -4
  17. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Bridge.hpp +528 -35
  18. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Umbrella.hpp +108 -6
  19. package/nitrogen/generated/ios/c++/HybridRNCandleSpecSwift.hpp +122 -12
  20. package/nitrogen/generated/ios/swift/ACHAccountKind.swift +38 -0
  21. package/nitrogen/generated/ios/swift/ACHDetails.swift +55 -0
  22. package/nitrogen/generated/ios/swift/{Details.swift → ActiveLinkedAccountDetails.swift} +55 -22
  23. package/nitrogen/generated/ios/swift/Address.swift +33 -0
  24. package/nitrogen/generated/ios/swift/AssetAccount.swift +55 -0
  25. package/nitrogen/generated/ios/swift/AssetAccountDetails.swift +83 -0
  26. package/nitrogen/generated/ios/swift/AssetAccountKind.swift +42 -0
  27. package/nitrogen/generated/ios/swift/AssetAccountQuery.swift +76 -0
  28. package/nitrogen/generated/ios/swift/Coordinates.swift +44 -0
  29. package/nitrogen/generated/ios/swift/Counterparty.swift +115 -0
  30. package/nitrogen/generated/ios/swift/FiatAccountDetails.swift +165 -0
  31. package/nitrogen/generated/ios/swift/FiatAsset.swift +123 -0
  32. package/nitrogen/generated/ios/swift/FiatAssetQuoteRequest.swift +119 -0
  33. package/nitrogen/generated/ios/swift/Func_void_Trade.swift +44 -0
  34. package/nitrogen/generated/ios/swift/Func_void_std__vector_AssetAccount_.swift +46 -0
  35. package/nitrogen/generated/ios/swift/Func_void_std__vector_TradeQuote_.swift +46 -0
  36. package/nitrogen/generated/ios/swift/Func_void_std__vector_Trade_.swift +45 -0
  37. package/nitrogen/generated/ios/swift/HybridRNCandleSpec.swift +4 -3
  38. package/nitrogen/generated/ios/swift/HybridRNCandleSpec_cxx.swift +79 -40
  39. package/nitrogen/generated/ios/swift/InactiveLinkedAccountDetails.swift +33 -0
  40. package/nitrogen/generated/ios/swift/LegalAccountKind.swift +46 -0
  41. package/nitrogen/generated/ios/swift/LinkedAccount.swift +16 -34
  42. package/nitrogen/generated/ios/swift/LinkedAccountDetails.swift +87 -0
  43. package/nitrogen/generated/ios/swift/MarketAccountDetails.swift +69 -0
  44. package/nitrogen/generated/ios/swift/MarketAssetQuoteRequest.swift +151 -0
  45. package/nitrogen/generated/ios/swift/MarketTradeAsset.swift +150 -0
  46. package/nitrogen/generated/ios/swift/MerchantCounterparty.swift +86 -0
  47. package/nitrogen/generated/ios/swift/MerchantLocation.swift +55 -0
  48. package/nitrogen/generated/ios/swift/NothingAsset.swift +33 -0
  49. package/nitrogen/generated/ios/swift/NothingAssetQuoteRequest.swift +33 -0
  50. package/nitrogen/generated/ios/swift/OtherAsset.swift +33 -0
  51. package/nitrogen/generated/ios/swift/ServiceCounterparty.swift +44 -0
  52. package/nitrogen/generated/ios/swift/Trade.swift +80 -0
  53. package/nitrogen/generated/ios/swift/TradeAsset.swift +175 -0
  54. package/nitrogen/generated/ios/swift/TradeAssetQuoteRequest.swift +148 -0
  55. package/nitrogen/generated/ios/swift/TradeQuery.swift +175 -0
  56. package/nitrogen/generated/ios/swift/TradeQuote.swift +44 -0
  57. package/nitrogen/generated/ios/swift/TradeQuoteRequest.swift +63 -0
  58. package/nitrogen/generated/ios/swift/TradeState.swift +42 -0
  59. package/nitrogen/generated/ios/swift/TransportAsset.swift +174 -0
  60. package/nitrogen/generated/ios/swift/TransportAssetQuoteRequest.swift +212 -0
  61. package/nitrogen/generated/ios/swift/UserCounterparty.swift +66 -0
  62. package/nitrogen/generated/ios/swift/WireDetails.swift +44 -0
  63. package/nitrogen/generated/shared/c++/{State.hpp → ACHAccountKind.hpp} +17 -17
  64. package/nitrogen/generated/shared/c++/ACHDetails.hpp +79 -0
  65. package/nitrogen/generated/shared/c++/{Details.hpp → ActiveLinkedAccountDetails.hpp} +25 -23
  66. package/nitrogen/generated/shared/c++/Address.hpp +69 -0
  67. package/nitrogen/generated/shared/c++/AssetAccount.hpp +82 -0
  68. package/nitrogen/generated/shared/c++/AssetAccountDetails.hpp +78 -0
  69. package/nitrogen/generated/shared/c++/AssetAccountKind.hpp +82 -0
  70. package/nitrogen/generated/shared/c++/AssetAccountQuery.hpp +76 -0
  71. package/nitrogen/generated/shared/c++/Coordinates.hpp +73 -0
  72. package/nitrogen/generated/shared/c++/Counterparty.hpp +85 -0
  73. package/nitrogen/generated/shared/c++/FiatAccountDetails.hpp +106 -0
  74. package/nitrogen/generated/shared/c++/FiatAsset.hpp +96 -0
  75. package/nitrogen/generated/shared/c++/FiatAssetQuoteRequest.hpp +82 -0
  76. package/nitrogen/generated/shared/c++/HybridRNCandleSpec.cpp +1 -0
  77. package/nitrogen/generated/shared/c++/HybridRNCandleSpec.hpp +22 -3
  78. package/nitrogen/generated/shared/c++/InactiveLinkedAccountDetails.hpp +69 -0
  79. package/nitrogen/generated/shared/c++/LegalAccountKind.hpp +86 -0
  80. package/nitrogen/generated/shared/c++/LinkedAccount.hpp +13 -14
  81. package/nitrogen/generated/shared/c++/LinkedAccountDetails.hpp +78 -0
  82. package/nitrogen/generated/shared/c++/MarketAccountDetails.hpp +83 -0
  83. package/nitrogen/generated/shared/c++/MarketAssetQuoteRequest.hpp +86 -0
  84. package/nitrogen/generated/shared/c++/MarketTradeAsset.hpp +111 -0
  85. package/nitrogen/generated/shared/c++/MerchantCounterparty.hpp +84 -0
  86. package/nitrogen/generated/shared/c++/MerchantLocation.hpp +77 -0
  87. package/nitrogen/generated/shared/c++/NothingAsset.hpp +69 -0
  88. package/nitrogen/generated/shared/c++/NothingAssetQuoteRequest.hpp +69 -0
  89. package/nitrogen/generated/shared/c++/OtherAsset.hpp +69 -0
  90. package/nitrogen/generated/shared/c++/ServiceCounterparty.hpp +75 -0
  91. package/nitrogen/generated/shared/c++/Trade.hpp +93 -0
  92. package/nitrogen/generated/shared/c++/TradeAsset.hpp +99 -0
  93. package/nitrogen/generated/shared/c++/TradeAssetQuoteRequest.hpp +92 -0
  94. package/nitrogen/generated/shared/c++/TradeQuery.hpp +86 -0
  95. package/nitrogen/generated/shared/c++/TradeQuote.hpp +74 -0
  96. package/nitrogen/generated/shared/c++/TradeQuoteRequest.hpp +76 -0
  97. package/nitrogen/generated/shared/c++/TradeState.hpp +82 -0
  98. package/nitrogen/generated/shared/c++/TransportAsset.hpp +125 -0
  99. package/nitrogen/generated/shared/c++/TransportAssetQuoteRequest.hpp +99 -0
  100. package/nitrogen/generated/shared/c++/UserCounterparty.hpp +81 -0
  101. package/nitrogen/generated/shared/c++/WireDetails.hpp +73 -0
  102. package/package.json +1 -1
  103. package/src/index.ts +259 -3
  104. package/src/specs/RNCandle.nitro.ts +237 -10
  105. package/nitrogen/generated/ios/swift/State.swift +0 -38
@@ -5,6 +5,11 @@ import NitroModules
5
5
  import SwiftUI
6
6
  import UIKit
7
7
 
8
+ public enum RNClientError: Error {
9
+ case badEncoding
10
+ case badInitialization(message: String)
11
+ }
12
+
8
13
  @available(iOS 17.0, *)
9
14
  final class HybridRNCandle: HybridRNCandleSpec {
10
15
 
@@ -55,15 +60,27 @@ final class HybridRNCandle: HybridRNCandleSpec {
55
60
  try viewModel.showDynamicLoading = showDynamicLoading
56
61
  try viewModel.presentationBackground = presentationBackground
57
62
  try viewModel.presentationStyle = presentationStyle
58
- try viewModel.showSheet = isPresented
63
+ // FIXME: there's a glitch the first time it's presented unless you do this
64
+ DispatchQueue.main.async { [weak self] in
65
+ guard let self else {
66
+ #if DEBUG
67
+ print("Self was deinitialized \(#function).")
68
+ #endif
69
+ return
70
+ }
71
+ do {
72
+ try self.viewModel.showSheet = isPresented
73
+ } catch {
74
+ #if DEBUG
75
+ print("Failed to present sheet \(#function).")
76
+ #endif
77
+ }
78
+ }
59
79
  try viewModel.$linkedAccount
60
80
  .removeDuplicates()
61
- .compactMap { $0 }
81
+ .compactMap(\.?.toLinkedAccount)
62
82
  .receive(on: RunLoop.main)
63
- .sink { [weak self] linkedAccount in
64
- guard let self else { return }
65
- onSuccess(self.toLinkedAccount(linkedAccount))
66
- }
83
+ .sink(receiveValue: onSuccess)
67
84
  .store(in: &cancellables)
68
85
  }
69
86
  }
@@ -71,39 +88,123 @@ final class HybridRNCandle: HybridRNCandleSpec {
71
88
  // MARK: - Public
72
89
 
73
90
  public func unlinkAccount(linkedAccountID: String) throws -> Promise<Void> {
74
- Promise.async {
91
+ .async {
75
92
  try await self.viewModel.candleClient.unlinkAccount(linkedAccountID: linkedAccountID)
76
93
  }
77
94
  }
78
95
 
79
96
  public func getLinkedAccounts() throws -> Promise<[LinkedAccount]> {
80
- Promise.async { [weak self] in
81
- guard let self else {
82
- throw RNClientError.badInitialization(message: "Self was deinitialized \(#function).")
83
- }
97
+ .async {
84
98
  let accounts = try await self.viewModel.candleClient.getLinkedAccounts()
85
- return accounts.map(self.toLinkedAccount)
99
+ return accounts.map(\.toLinkedAccount)
86
100
  }
87
101
  }
88
102
 
89
- public func getAssetAccounts() throws -> Promise<String> {
103
+ public func getAssetAccounts(query: AssetAccountQuery) throws -> Promise<[AssetAccount]> {
90
104
  .async {
91
- return ""
105
+ let accounts = try await self.viewModel.candleClient.getAssetAccounts(
106
+ query: .init(
107
+ linkedAccountIDs: query.linkedAccountIDs,
108
+ assetKind: query.assetKind?.asCandleModel
109
+ )
110
+ )
111
+ return accounts.map { model in
112
+ let legalAccountKind = model.legalAccountKind.toRNModel
113
+ switch model.details {
114
+ case .FiatAccountDetails(let fiatDetails):
115
+ let ach = fiatDetails.ach.map { details in
116
+ ACHDetails(
117
+ accountNumber: details.accountNumber,
118
+ routingNumber: details.routingNumber,
119
+ accountKind: details.accountKind.toRNModel
120
+ )
121
+ }
122
+
123
+ let wire = fiatDetails.wire.map { details in
124
+ WireDetails(
125
+ accountNumber: details.accountNumber,
126
+ routingNumber: details.routingNumber
127
+ )
128
+ }
129
+ return AssetAccount(
130
+ legalAccountKind: legalAccountKind,
131
+ nickname: model.nickname,
132
+ details: .init(
133
+ fiatAccountDetails: .init(
134
+ assetKind: fiatDetails.assetKind.rawValue,
135
+ serviceAccountID: fiatDetails.serviceAccountID,
136
+ currencyCode: fiatDetails.currencyCode,
137
+ balance: fiatDetails.balance,
138
+ ach: ach,
139
+ wire: wire,
140
+ linkedAccountID: fiatDetails.linkedAccountID,
141
+ service: fiatDetails.service.toService),
142
+ marketAccountDetails: nil
143
+ )
144
+ )
145
+ case .MarketAccountDetails(let marketDetails):
146
+ return AssetAccount(
147
+ legalAccountKind: legalAccountKind,
148
+ nickname: model.nickname,
149
+ details: .init(
150
+ fiatAccountDetails: nil,
151
+ marketAccountDetails: .init(
152
+ assetKind: marketDetails.assetKind.rawValue,
153
+ serviceAccountID: marketDetails.serviceAccountID,
154
+ linkedAccountID: marketDetails.linkedAccountID,
155
+ service: marketDetails.service.toService
156
+ )
157
+ )
158
+ )
159
+ }
160
+ }
92
161
  }
93
162
  }
94
163
 
95
- public func getTrades(span: String?) throws -> Promise<String> {
164
+ public func getTrades(query: TradeQuery) throws -> Promise<[Trade]> {
96
165
  .async {
97
- return ""
166
+ let trades = try await self.viewModel.candleClient.getTrades(
167
+ query: .init(
168
+ linkedAccountIDs: query.linkedAccountIDs,
169
+ dateTimeSpan: query.dateTimeSpan,
170
+ gainedAssetKind: .init(rawValue: query.gainedAssetKind ?? ""),
171
+ lostAssetKind: .init(rawValue: query.lostAssetKind ?? ""),
172
+ counterpartyKind: .init(rawValue: query.counterpartyKind ?? "")
173
+ ))
174
+ return trades.map { trade in
175
+ return Trade(
176
+ dateTime: trade.dateTime,
177
+ state: TradeState(fromString: trade.state.rawValue)!,
178
+ counterparty: trade.toCounterparty,
179
+ lost: trade.lost.toAsset,
180
+ gained: trade.gained.toAsset
181
+ )
182
+ }
98
183
  }
99
184
  }
100
185
 
101
- func getTradeQuotes(span: String?) throws -> Promise<String> {
186
+ public func getTradeQuotes(request: TradeQuoteRequest) throws -> Promise<[TradeQuote]> {
102
187
  .async {
103
- return ""
188
+ let accounts = try await self.viewModel.candleClient.getTradeQuotes(
189
+ request:
190
+ .init(
191
+ linkedAccountIDs: request.linkedAccountIDs,
192
+ gained: try request.toGained
193
+ )
194
+ )
195
+ return accounts.map { account in
196
+ TradeQuote(
197
+ lost: account.lost.toAsset,
198
+ gained: account.gained.toAsset
199
+ )
200
+ }
104
201
  }
105
202
  }
106
203
 
204
+ public func submitTrade(serviceTradeID: String) throws -> Promise<Trade> {
205
+ throw RNClientError.badInitialization(message: "Not implemented.")
206
+ }
207
+
107
208
  public func deleteUser() throws -> Promise<Void> {
108
209
  .async {
109
210
  try await self.viewModel.candleClient.deleteUser()
@@ -125,7 +226,7 @@ final class HybridRNCandle: HybridRNCandleSpec {
125
226
  let result = try await self.viewModel.candleClient.executeTool(
126
227
  tool: RNToolCall(name: tool.name, arguments: tool.arguments)
127
228
  )
128
- return try self.encodeToJSONString(result)
229
+ return try result.encodedToJSONString
129
230
  }
130
231
  }
131
232
 
@@ -177,51 +278,255 @@ final class HybridRNCandle: HybridRNCandleSpec {
177
278
  }
178
279
  }
179
280
 
180
- enum RNClientError: Error {
181
- case badEncoding
182
- case badInitialization(message: String)
183
- }
184
-
185
281
  struct RNToolCall: ToolCallRequest, Codable {
186
282
  let name: String
187
283
  let arguments: String
188
284
  }
189
285
 
190
- private func encodeToJSONString<T: Encodable>(_ value: T) throws -> String {
191
- let data = try JSONEncoder().encode(value)
192
- if let string = String(data: data, encoding: .utf8) {
193
- return string
286
+ }
287
+
288
+ extension Encodable {
289
+ var encodedToJSONString: String {
290
+ get throws {
291
+ let data = try JSONEncoder().encode(self)
292
+ if let string = String(data: data, encoding: .utf8) {
293
+ return string
294
+ }
295
+ throw RNClientError.badEncoding
194
296
  }
195
- throw RNClientError.badEncoding
196
297
  }
298
+ }
197
299
 
198
- private func toLinkedAccount(_ account: Candle.Models.LinkedAccount) -> LinkedAccount {
199
- let service: Service = toRNService(service: account.service)
200
- switch account.details {
300
+ extension Candle.Models.LinkedAccount {
301
+ var toLinkedAccount: LinkedAccount {
302
+ let service: Service = self.service.toService
303
+ switch details {
201
304
  case .ActiveLinkedAccountDetails(let details):
202
305
  return LinkedAccount(
203
- serviceUserID: account.serviceUserID,
306
+ linkedAccountID: linkedAccountID,
307
+ service: service,
308
+ serviceUserID: serviceUserID,
204
309
  details: .init(
205
- state: .active,
206
- username: details.username,
207
- legalName: details.legalName,
208
- accountOpened: details.accountOpened
209
- ),
210
- linkedAccountID: account.linkedAccountID,
211
- service: service
310
+ activeLinkedAccountDetails: .init(
311
+ state: details.state.rawValue,
312
+ accountOpened: details.accountOpened,
313
+ username: details.username,
314
+ emailAddress: details.emailAddress,
315
+ legalName: details.legalName), inactiveLinkedAccountDetails: nil)
212
316
  )
213
- case .InactiveLinkedAccountDetails:
317
+ case .InactiveLinkedAccountDetails(let details):
214
318
  return LinkedAccount(
215
- serviceUserID: account.serviceUserID,
216
- details: nil,
217
- linkedAccountID: account.linkedAccountID,
218
- service: service
319
+ linkedAccountID: linkedAccountID,
320
+ service: service,
321
+ serviceUserID: serviceUserID,
322
+ details: .init(
323
+ activeLinkedAccountDetails: nil,
324
+ inactiveLinkedAccountDetails: .init(state: details.state.rawValue))
219
325
  )
220
326
  }
221
327
  }
328
+ }
329
+
330
+ extension Models.MerchantCounterparty {
331
+ var toLocation: MerchantLocation? {
332
+ if let location {
333
+ return .init(
334
+ countryCode: location.countryCode, countrySubdivisionCode: location.countrySubdivisionCode,
335
+ localityName: location.localityName)
336
+ }
337
+ return nil
338
+ }
339
+ }
340
+
341
+ extension Models.Trade {
342
+ var toCounterparty: Counterparty {
343
+ switch counterparty {
344
+ case .MerchantCounterparty(let merchant):
345
+ return .init(
346
+ merchantCounterparty: .init(
347
+ kind: merchant.kind.rawValue,
348
+ name: merchant.name, logoURL: merchant.logoURL,
349
+ location: merchant.toLocation
350
+ ),
351
+ userCounterparty: nil,
352
+ serviceCounterparty: nil
353
+ )
354
+ case .ServiceCounterparty(let service):
355
+ return .init(
356
+ merchantCounterparty: nil,
357
+ userCounterparty: nil,
358
+ serviceCounterparty: .init(
359
+ kind: service.kind.rawValue,
360
+ service: service.service.toService
361
+ )
362
+ )
363
+ case .UserCounterparty(let user):
364
+ return .init(
365
+ merchantCounterparty: nil,
366
+ userCounterparty: .init(
367
+ kind: user.kind.rawValue,
368
+ legalName: user.legalName,
369
+ avatarURL: user.avatarURL,
370
+ username: user.username
371
+ ),
372
+ serviceCounterparty: nil
373
+ )
374
+ }
375
+ }
376
+ }
377
+
378
+ extension Models.TradeAsset {
379
+ var toAsset: TradeAsset {
380
+ switch self {
381
+ case .FiatAsset(let fiatAsset):
382
+ return .init(
383
+ fiatAsset: .init(
384
+ assetKind: fiatAsset.assetKind.rawValue,
385
+ serviceTradeID: fiatAsset.serviceTradeID,
386
+ serviceAccountID: fiatAsset.serviceAccountID,
387
+ currencyCode: fiatAsset.currencyCode,
388
+ amount: fiatAsset.amount,
389
+ linkedAccountID: fiatAsset.linkedAccountID,
390
+ service: fiatAsset.service.toService
391
+ ),
392
+ marketTradeAsset: nil,
393
+ transportAsset: nil,
394
+ otherAsset: nil,
395
+ nothingAsset: nil
396
+ )
397
+ case .MarketTradeAsset(let marketAsset):
398
+ return .init(
399
+ fiatAsset: nil,
400
+ marketTradeAsset: .init(
401
+ assetKind: marketAsset.assetKind.rawValue,
402
+ serviceAccountID: marketAsset.serviceAccountID,
403
+ serviceAssetID: marketAsset.serviceAssetID,
404
+ symbol: marketAsset.symbol,
405
+ amount: marketAsset.amount,
406
+ serviceTradeID: marketAsset.serviceTradeID,
407
+ linkedAccountID: marketAsset.linkedAccountID,
408
+ name: marketAsset.name,
409
+ color: marketAsset.color,
410
+ logoURL: marketAsset.logoURL,
411
+ service: marketAsset.service.toService
412
+ ),
413
+ transportAsset: nil,
414
+ otherAsset: nil,
415
+ nothingAsset: nil
416
+ )
417
+ case .TransportAsset(let transportAsset):
418
+ return .init(
419
+ fiatAsset: nil,
420
+ marketTradeAsset: nil,
421
+ transportAsset: .init(
422
+ assetKind: transportAsset.assetKind.rawValue,
423
+ serviceTradeID: transportAsset.serviceTradeID,
424
+ serviceAssetID: transportAsset.serviceAssetID,
425
+ name: transportAsset.name,
426
+ description: transportAsset.description,
427
+ imageURL: transportAsset.imageURL,
428
+ originCoordinates: .init(
429
+ latitude: transportAsset.originCoordinates.latitude,
430
+ longitude: transportAsset.originCoordinates.longitude
431
+ ),
432
+ originAddress: .init(value: transportAsset.originAddress.value),
433
+ destinationCoordinates: .init(
434
+ latitude: transportAsset.destinationCoordinates.latitude,
435
+ longitude: transportAsset.destinationCoordinates.longitude
436
+ ),
437
+ destinationAddress: .init(value: transportAsset.destinationAddress.value),
438
+ seats: transportAsset.seats,
439
+ linkedAccountID: transportAsset.linkedAccountID,
440
+ service: transportAsset.service.toService
441
+ ),
442
+ otherAsset: nil,
443
+ nothingAsset: nil
444
+ )
445
+ case .OtherAsset(let otherAsset):
446
+ return .init(
447
+ fiatAsset: nil,
448
+ marketTradeAsset: nil,
449
+ transportAsset: nil,
450
+ otherAsset: .init(assetKind: otherAsset.assetKind.rawValue),
451
+ nothingAsset: nil
452
+ )
453
+ case .NothingAsset(let nothingAsset):
454
+ return .init(
455
+ fiatAsset: nil,
456
+ marketTradeAsset: nil,
457
+ transportAsset: nil,
458
+ otherAsset: nil,
459
+ nothingAsset: .init(assetKind: nothingAsset.assetKind.rawValue)
460
+ )
461
+ }
462
+ }
463
+ }
464
+
465
+ extension TradeQuoteRequest {
466
+ var toGained: Models.TradeAssetQuoteRequest {
467
+ get throws {
468
+ if let fiatAssetQuoteRequest = gained.fiatAssetQuoteRequest {
469
+ return Models.TradeAssetQuoteRequest.FiatAssetQuoteRequest(
470
+ .init(
471
+ assetKind: .fiat,
472
+ serviceAccountID: fiatAssetQuoteRequest.serviceAccountID,
473
+ currencyCode: fiatAssetQuoteRequest.currencyCode,
474
+ amount: fiatAssetQuoteRequest.amount
475
+ )
476
+ )
477
+ } else if let marketAssetQuoteRequest = gained.marketAssetQuoteRequest {
478
+ return Models.TradeAssetQuoteRequest.MarketAssetQuoteRequest(
479
+ .init(
480
+ assetKind: .init(rawValue: marketAssetQuoteRequest.assetKind) ?? .stock,
481
+ serviceAccountID: marketAssetQuoteRequest.serviceAccountID,
482
+ serviceAssetID: marketAssetQuoteRequest.serviceAssetID,
483
+ symbol: marketAssetQuoteRequest.symbol,
484
+ amount: marketAssetQuoteRequest.amount
485
+ )
486
+ )
487
+ } else if gained.nothingAssetQuoteRequest != nil {
488
+ return Models.TradeAssetQuoteRequest.NothingAssetQuoteRequest(
489
+ .init(assetKind: .nothing)
490
+ )
491
+ } else if let transportAssetQuoteRequest = gained.transportAssetQuoteRequest {
492
+ return Models.TradeAssetQuoteRequest.TransportAssetQuoteRequest(
493
+ .init(
494
+ assetKind: .transport,
495
+ serviceAssetID: transportAssetQuoteRequest.serviceAssetID,
496
+ originCoordinates: transportAssetQuoteRequest.originCoordinates?.toCoordinates,
497
+ originAddress: transportAssetQuoteRequest.originAddress?.toAddress,
498
+ destinationCoordinates: transportAssetQuoteRequest.destinationCoordinates?
499
+ .toCoordinates,
500
+ destinationAddress: transportAssetQuoteRequest.destinationAddress?.toAddress,
501
+ seats: transportAssetQuoteRequest.seats
502
+ )
503
+ )
504
+ } else {
505
+ throw RNClientError.badInitialization(
506
+ message: "Internal Candle Error: corrupted trade quote request.")
507
+ }
508
+ }
509
+ }
510
+ }
511
+
512
+ extension Address {
513
+ var toAddress: Models.Address {
514
+ return .init(value: value)
515
+ }
516
+ }
517
+
518
+ extension Coordinates {
519
+ var toCoordinates: Models.Coordinates {
520
+ return .init(
521
+ latitude: latitude,
522
+ longitude: longitude
523
+ )
524
+ }
525
+ }
222
526
 
223
- func toRNService(service: Candle.Models.Service) -> Service {
224
- switch service {
527
+ extension Service {
528
+ var toService: Models.Service {
529
+ switch self {
225
530
  case .apple:
226
531
  return .apple
227
532
  case .cashApp:
@@ -385,3 +690,209 @@ final class HybridRNCandle: HybridRNCandleSpec {
385
690
  }
386
691
  }
387
692
  }
693
+
694
+ extension Models.Service {
695
+ var toService: Service {
696
+ switch self {
697
+ case .apple:
698
+ return .apple
699
+ case .cashApp:
700
+ return .cashApp
701
+ case .sandbox:
702
+ return .sandbox
703
+ case .robinhood:
704
+ return .robinhood
705
+ case .uber:
706
+ return .uber
707
+ case .lyft:
708
+ return .lyft
709
+ case .venmo:
710
+ return .venmo
711
+ case .chime:
712
+ return .chime
713
+ case .paypal:
714
+ return .paypal
715
+ case .coinbase:
716
+ return .coinbase
717
+ case .discover:
718
+ return .discover
719
+ case .americanExpress:
720
+ return .americanExpress
721
+ case .jpmorganChase:
722
+ return .jpmorganChase
723
+ case .bankOfAmerica:
724
+ return .bankOfAmerica
725
+ case .capitalOne:
726
+ return .capitalOne
727
+ case .citibank:
728
+ return .citibank
729
+ case .vanguard:
730
+ return .vanguard
731
+ case .wellsFargo:
732
+ return .wellsFargo
733
+ case .charlesSchwab:
734
+ return .charlesSchwab
735
+ case .kalshi:
736
+ return .kalshi
737
+ case .experian:
738
+ return .experian
739
+ case .waymo:
740
+ return .waymo
741
+ case .revel:
742
+ return .revel
743
+ case .turo:
744
+ return .turo
745
+ case .getaround:
746
+ return .getaround
747
+ case .zipcar:
748
+ return .zipcar
749
+ case .airbnb:
750
+ return .airbnb
751
+ case .americanAirlines:
752
+ return .americanAirlines
753
+ case .delta:
754
+ return .delta
755
+ case .united:
756
+ return .united
757
+ case .jetblue:
758
+ return .jetblue
759
+ case .southwest:
760
+ return .southwest
761
+ case .hawaiian:
762
+ return .hawaiian
763
+ case .hotels:
764
+ return .hotels
765
+ case .geico:
766
+ return .geico
767
+ case .progressive:
768
+ return .progressive
769
+ case .aaa:
770
+ return .aaa
771
+ case .stateFarm:
772
+ return .stateFarm
773
+ case .hertz:
774
+ return .hertz
775
+ case .avis:
776
+ return .avis
777
+ case .tesla:
778
+ return .tesla
779
+ case .doordash:
780
+ return .doordash
781
+ case .uberEats:
782
+ return .uberEats
783
+ case .grubhub:
784
+ return .grubhub
785
+ case .resy:
786
+ return .resy
787
+ case .opentable:
788
+ return .opentable
789
+ case .starbucks:
790
+ return .starbucks
791
+ case .blueBottle:
792
+ return .blueBottle
793
+ case .costco:
794
+ return .costco
795
+ case .amazon:
796
+ return .amazon
797
+ case .walmart:
798
+ return .walmart
799
+ case .wholeFoods:
800
+ return .wholeFoods
801
+ case .mcdonalds:
802
+ return .mcdonalds
803
+ case .chipotle:
804
+ return .chipotle
805
+ case .sweetgreen:
806
+ return .sweetgreen
807
+ case .snapchat:
808
+ return .snapchat
809
+ case .x:
810
+ return .x
811
+ case .facebook:
812
+ return .facebook
813
+ case .instagram:
814
+ return .instagram
815
+ case .signal:
816
+ return .signal
817
+ case .whatsapp:
818
+ return .whatsapp
819
+ case .messenger:
820
+ return .messenger
821
+ case .linkedin:
822
+ return .linkedin
823
+ case .discord:
824
+ return .discord
825
+ case .messages:
826
+ return .messages
827
+ case .telegram:
828
+ return .telegram
829
+ case .reddit:
830
+ return .reddit
831
+ case .pinterest:
832
+ return .pinterest
833
+ case .newYorkTimes:
834
+ return .newYorkTimes
835
+ case .washingtonPost:
836
+ return .washingtonPost
837
+ case .wallStreetJournal:
838
+ return .wallStreetJournal
839
+ case .cnn:
840
+ return .cnn
841
+ case .yahoo:
842
+ return .yahoo
843
+ case .fox:
844
+ return .fox
845
+ case .perplexity:
846
+ return .perplexity
847
+ case .openai:
848
+ return .openai
849
+ case .polymarket:
850
+ return .polymarket
851
+ case .espn:
852
+ return .espn
853
+ case .youtube:
854
+ return .youtube
855
+ case .netflix:
856
+ return .netflix
857
+ }
858
+ }
859
+ }
860
+
861
+ extension AssetAccountKind {
862
+ var asCandleModel: Models.GetAssetAccounts.Input.Query.AssetKindPayload {
863
+ switch self {
864
+ case .fiat:
865
+ return .fiat
866
+ case .stock:
867
+ return .stock
868
+ case .crypto:
869
+ return .crypto
870
+ }
871
+ }
872
+ }
873
+
874
+ extension Candle.Components.Schemas.LegalAccountKind {
875
+ var toRNModel: LegalAccountKind {
876
+ switch self {
877
+ case .individual:
878
+ return .individual
879
+ case .joint:
880
+ return .joint
881
+ case .rothIra:
882
+ return .rothira
883
+ case .traditionalIra:
884
+ return .traditionalira
885
+ }
886
+ }
887
+ }
888
+
889
+ extension Candle.Components.Schemas.ACHAccountKind {
890
+ var toRNModel: ACHAccountKind {
891
+ switch self {
892
+ case .checking:
893
+ return .checking
894
+ case .savings:
895
+ return .savings
896
+ }
897
+ }
898
+ }