react-native-candle 0.1.19 → 0.1.21

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 (54) hide show
  1. package/ReactNativeCandle.podspec +1 -1
  2. package/ios/Sources/CandleActionViewModel.swift +13 -0
  3. package/ios/Sources/CandleTradeExecutionSheetWrapper.swift +31 -0
  4. package/ios/Sources/HostingViewController.swift +7 -0
  5. package/ios/Sources/RNCandle.swift +300 -84
  6. package/lib/commonjs/index.js +140 -15
  7. package/lib/commonjs/index.js.map +1 -1
  8. package/lib/module/index.js +140 -15
  9. package/lib/module/index.js.map +1 -1
  10. package/lib/typescript/commonjs/src/index.d.ts +46 -13
  11. package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
  12. package/lib/typescript/commonjs/src/specs/RNCandle.nitro.d.ts +50 -2
  13. package/lib/typescript/commonjs/src/specs/RNCandle.nitro.d.ts.map +1 -1
  14. package/lib/typescript/module/src/index.d.ts +46 -13
  15. package/lib/typescript/module/src/index.d.ts.map +1 -1
  16. package/lib/typescript/module/src/specs/RNCandle.nitro.d.ts +50 -2
  17. package/lib/typescript/module/src/specs/RNCandle.nitro.d.ts.map +1 -1
  18. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Bridge.cpp +24 -8
  19. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Bridge.hpp +271 -113
  20. package/nitrogen/generated/ios/ReactNativeCandle-Swift-Cxx-Umbrella.hpp +30 -3
  21. package/nitrogen/generated/ios/c++/HybridRNCandleSpecSwift.hpp +106 -57
  22. package/nitrogen/generated/ios/swift/AssetAccountRef.swift +55 -0
  23. package/nitrogen/generated/ios/swift/FiatAssetRef.swift +75 -0
  24. package/nitrogen/generated/ios/swift/Func_void_AssetAccount.swift +44 -0
  25. package/nitrogen/generated/ios/swift/Func_void_LinkedAccount.swift +5 -5
  26. package/nitrogen/generated/ios/swift/Func_void_TradeExecutionResult.swift +46 -0
  27. package/nitrogen/generated/ios/swift/HybridRNCandleSpec.swift +7 -2
  28. package/nitrogen/generated/ios/swift/HybridRNCandleSpec_cxx.swift +86 -24
  29. package/nitrogen/generated/ios/swift/LinkedAccountRef.swift +33 -0
  30. package/nitrogen/generated/ios/swift/MarketTradeAssetRef.swift +55 -0
  31. package/nitrogen/generated/ios/swift/NothingAssetRef.swift +33 -0
  32. package/nitrogen/generated/ios/swift/OtherAssetRef.swift +33 -0
  33. package/nitrogen/generated/ios/swift/TradeAssetRef.swift +176 -0
  34. package/nitrogen/generated/ios/swift/TradeExecutionResult.swift +82 -0
  35. package/nitrogen/generated/ios/swift/TradeQuote.swift +13 -2
  36. package/nitrogen/generated/ios/swift/TradeRef.swift +44 -0
  37. package/nitrogen/generated/ios/swift/TransportAssetRef.swift +55 -0
  38. package/nitrogen/generated/shared/c++/AssetAccountRef.hpp +77 -0
  39. package/nitrogen/generated/shared/c++/FiatAssetRef.hpp +78 -0
  40. package/nitrogen/generated/shared/c++/HybridRNCandleSpec.cpp +4 -1
  41. package/nitrogen/generated/shared/c++/HybridRNCandleSpec.hpp +20 -8
  42. package/nitrogen/generated/shared/c++/{ExecuteTradeRequest.hpp → LinkedAccountRef.hpp} +11 -15
  43. package/nitrogen/generated/shared/c++/MarketTradeAssetRef.hpp +77 -0
  44. package/nitrogen/generated/shared/c++/NothingAssetRef.hpp +69 -0
  45. package/nitrogen/generated/shared/c++/OtherAssetRef.hpp +69 -0
  46. package/nitrogen/generated/shared/c++/TradeAssetRef.hpp +99 -0
  47. package/nitrogen/generated/shared/c++/TradeExecutionResult.hpp +76 -0
  48. package/nitrogen/generated/shared/c++/TradeQuote.hpp +7 -2
  49. package/nitrogen/generated/shared/c++/TradeRef.hpp +74 -0
  50. package/nitrogen/generated/shared/c++/TransportAssetRef.hpp +77 -0
  51. package/package.json +1 -1
  52. package/src/index.ts +199 -33
  53. package/src/specs/RNCandle.nitro.ts +64 -2
  54. package/nitrogen/generated/ios/swift/ExecuteTradeRequest.swift +0 -44
@@ -30,7 +30,7 @@ Pod::Spec.new do |s|
30
30
  load 'nitrogen/generated/ios/ReactNativeCandle+autolinking.rb'
31
31
  add_nitrogen_files(s)
32
32
 
33
- s.dependency 'Candle', '3.0.241-beta'
33
+ s.dependency 'Candle', '3.0.258-beta'
34
34
  s.dependency 'React-jsi'
35
35
  s.dependency 'React-callinvoker'
36
36
  install_modules_dependencies(s)
@@ -0,0 +1,13 @@
1
+ import Candle
2
+ import Combine
3
+
4
+ @available(iOS 17.0, *)
5
+ final class CandleActionViewModel: ObservableObject {
6
+
7
+ @Published var tradeQuote: Models.TradeQuote?
8
+ @Published var tradeResult: Result<Candle.Models.Trade, Candle.Models.ExecuteTrade.Error>?
9
+
10
+ init(tradeQuote: Models.TradeQuote?) {
11
+ self.tradeQuote = tradeQuote
12
+ }
13
+ }
@@ -0,0 +1,31 @@
1
+ import Candle
2
+ import SwiftUI
3
+
4
+ @available(iOS 17.0, *)
5
+ struct CandleTradeExecutionSheetWrapper: View {
6
+
7
+ let candleClient: CandleClient
8
+
9
+ @ObservedObject var viewModel: CandleActionViewModel
10
+ let presentationBackground: PresentationBackground
11
+
12
+ var toCandlePresentationBackground: AnyShapeStyle {
13
+ switch presentationBackground {
14
+ case .default:
15
+ return AnyShapeStyle(Material.regular)
16
+ case .blur:
17
+ return AnyShapeStyle(Material.ultraThick)
18
+ }
19
+ }
20
+
21
+ var body: some View {
22
+ Color.clear
23
+ .candleTradeExecutionSheet(
24
+ item: $viewModel.tradeQuote,
25
+ presentationBackground: toCandlePresentationBackground
26
+ ) { result in
27
+ viewModel.tradeResult = result
28
+ }
29
+ .environment(candleClient)
30
+ }
31
+ }
@@ -8,6 +8,13 @@ extension UIViewController {
8
8
  child.view.pinEdges(to: view)
9
9
  child.didMove(toParent: self)
10
10
  }
11
+
12
+ func embedOnTop(_ child: UIViewController) {
13
+ addChild(child)
14
+ view.insertSubview(child.view, aboveSubview: view)
15
+ child.view.pinEdges(to: view)
16
+ child.didMove(toParent: self)
17
+ }
11
18
  }
12
19
 
13
20
  extension UIView {
@@ -91,12 +91,75 @@ final class HybridRNCandle: HybridRNCandleSpec {
91
91
  }
92
92
  }
93
93
 
94
+ public func candleTradeExecutionSheet(
95
+ tradeQuote: TradeQuote,
96
+ presentationBackground: PresentationBackground,
97
+ completion: @escaping (TradeExecutionResult) -> Void
98
+ ) throws {
99
+ Task { @MainActor in
100
+ let wrapperView = CandleTradeExecutionSheetWrapper(
101
+ candleClient: try viewModel.candleClient,
102
+ viewModel: .init(tradeQuote: nil),
103
+ presentationBackground: presentationBackground
104
+ )
105
+
106
+ let hostingVC = UIHostingController(rootView: wrapperView)
107
+ hostingVC.view.backgroundColor = .clear
108
+ guard
109
+ let rootHostingVC = UIApplication.keyWindow?
110
+ .rootViewController
111
+ else {
112
+ throw RNClientError.badInitialization(
113
+ message:
114
+ "\(#function) \(#line): Candle client was not initialized."
115
+ )
116
+ }
117
+ rootHostingVC.embedOnTop(hostingVC)
118
+ let tradeQuote = try tradeQuote.toCandleModel
119
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) {
120
+ wrapperView.viewModel.tradeQuote = tradeQuote
121
+ }
122
+ wrapperView.viewModel.$tradeQuote
123
+ .dropFirst()
124
+ .receive(on: RunLoop.main)
125
+ .sink { [weak hostingVC] trade in
126
+ if trade == nil {
127
+ DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) {
128
+ hostingVC?.willMove(toParent: nil)
129
+ hostingVC?.view.removeFromSuperview()
130
+ hostingVC?.removeFromParent()
131
+ }
132
+ }
133
+ }
134
+ .store(in: &cancellables)
135
+
136
+ wrapperView.viewModel.$tradeResult
137
+ .receive(on: RunLoop.main)
138
+ .sink { result in
139
+ switch result {
140
+ case .success(let trade):
141
+ completion(
142
+ .init(
143
+ trade: trade.toTrade,
144
+ error: nil
145
+ )
146
+ )
147
+ case .failure(let error):
148
+ completion(.init(trade: nil, error: "We encountered an error: \(error)"))
149
+ case .none:
150
+ break
151
+ }
152
+ }
153
+ .store(in: &cancellables)
154
+ }
155
+ }
156
+
94
157
  // MARK: - Public
95
158
 
96
- public func unlinkAccount(linkedAccountID: String) throws -> Promise<Void> {
159
+ public func unlinkAccount(ref: LinkedAccountRef) throws -> Promise<Void> {
97
160
  .async {
98
161
  try await self.viewModel.candleClient.unlinkAccount(
99
- linkedAccountID: linkedAccountID)
162
+ path: .init(linkedAccountID: ref.linkedAccountID))
100
163
  }
101
164
  }
102
165
 
@@ -108,6 +171,14 @@ final class HybridRNCandle: HybridRNCandleSpec {
108
171
  }
109
172
  }
110
173
 
174
+ public func getLinkedAccount(ref: LinkedAccountRef) throws -> Promise<LinkedAccount> {
175
+ .async {
176
+ let account = try await self.viewModel.candleClient.getLinkedAccount(
177
+ ref: .init(linkedAccountID: ref.linkedAccountID))
178
+ return account.toLinkedAccount
179
+ }
180
+ }
181
+
111
182
  public func getAssetAccounts(query: AssetAccountQuery) throws -> Promise<
112
183
  [AssetAccount]
113
184
  > {
@@ -119,57 +190,32 @@ final class HybridRNCandle: HybridRNCandleSpec {
119
190
  assetKind: query.assetKind?.asCandleModel
120
191
  )
121
192
  )
122
- return accounts.map { model in
123
- let legalAccountKind = model.legalAccountKind.toRNModel
124
- switch model.details {
125
- case .FiatAccountDetails(let fiatDetails):
126
- let ach = fiatDetails.ach.map { details in
127
- ACHDetails(
128
- accountNumber: details.accountNumber,
129
- routingNumber: details.routingNumber,
130
- accountKind: details.accountKind.toRNModel
131
- )
132
- }
193
+ return accounts.map(\.toRNModel)
194
+ }
195
+ }
133
196
 
134
- let wire = fiatDetails.wire.map { details in
135
- WireDetails(
136
- accountNumber: details.accountNumber,
137
- routingNumber: details.routingNumber
138
- )
139
- }
140
- return AssetAccount(
141
- legalAccountKind: legalAccountKind,
142
- nickname: model.nickname,
143
- details: .init(
144
- fiatAccountDetails: .init(
145
- assetKind: fiatDetails.assetKind.rawValue,
146
- serviceAccountID: fiatDetails.serviceAccountID,
147
- currencyCode: fiatDetails.currencyCode,
148
- balance: fiatDetails.balance,
149
- ach: ach,
150
- wire: wire,
151
- linkedAccountID: fiatDetails.linkedAccountID,
152
- service: fiatDetails.service.toService),
153
- marketAccountDetails: nil
154
- )
155
- )
156
- case .MarketAccountDetails(let marketDetails):
157
- return AssetAccount(
158
- legalAccountKind: legalAccountKind,
159
- nickname: model.nickname,
160
- details: .init(
161
- fiatAccountDetails: nil,
162
- marketAccountDetails: .init(
163
- assetKind: marketDetails.assetKind.rawValue,
164
- serviceAccountID: marketDetails
165
- .serviceAccountID,
166
- linkedAccountID: marketDetails.linkedAccountID,
167
- service: marketDetails.service.toService
168
- )
169
- )
170
- )
171
- }
172
- }
197
+ public func getAssetAccount(ref: AssetAccountRef) throws -> Promise<AssetAccount> {
198
+ .async {
199
+ let account = try await self.viewModel.candleClient.getAssetAccount(
200
+ ref: .init(
201
+ linkedAccountID: ref.linkedAccountID,
202
+ assetKind: .init(rawValue: ref.assetKind)!,
203
+ serviceAccountID: ref.serviceAccountID
204
+ )
205
+ )
206
+ return account.toRNModel
207
+ }
208
+ }
209
+
210
+ public func getTrade(ref: TradeRef) throws -> Promise<Trade> {
211
+ .async {
212
+ let trade = try await self.viewModel.candleClient.getTrade(
213
+ ref: .init(
214
+ lost: try ref.lost.toTradeAssetRef,
215
+ gained: try ref.gained.toTradeAssetRef
216
+ )
217
+ )
218
+ return trade.toTrade
173
219
  }
174
220
  }
175
221
 
@@ -183,15 +229,7 @@ final class HybridRNCandle: HybridRNCandleSpec {
183
229
  lostAssetKind: query.toLostAssetKind,
184
230
  counterpartyKind: query.toCounterpartyKindPayload
185
231
  ))
186
- return trades.map { trade in
187
- return Trade(
188
- dateTime: trade.dateTime,
189
- state: TradeState(fromString: trade.state.rawValue)!,
190
- counterparty: trade.toCounterparty,
191
- lost: trade.lost.toAsset,
192
- gained: trade.gained.toAsset
193
- )
194
- }
232
+ return trades.map(\.toTrade)
195
233
  }
196
234
  }
197
235
 
@@ -209,31 +247,13 @@ final class HybridRNCandle: HybridRNCandleSpec {
209
247
  return accounts.map { account in
210
248
  TradeQuote(
211
249
  lost: account.lost.toAsset,
212
- gained: account.gained.toAsset
250
+ gained: account.gained.toAsset,
251
+ context: account.context
213
252
  )
214
253
  }
215
254
  }
216
255
  }
217
256
 
218
- public func executeTrade(request: ExecuteTradeRequest) throws -> Promise<
219
- Trade
220
- > {
221
- .async {
222
- let trade = try await self.viewModel.candleClient.executeTrade(
223
- context: .init(
224
- linkedAccountID: request.linkedAccountID,
225
- context: request.context)
226
- )
227
- return Trade(
228
- dateTime: trade.dateTime,
229
- state: trade.state.toRNModel,
230
- counterparty: trade.toCounterparty,
231
- lost: trade.lost.toAsset,
232
- gained: trade.gained.toAsset
233
- )
234
- }
235
- }
236
-
237
257
  public func deleteUser() throws -> Promise<Void> {
238
258
  .async {
239
259
  try await self.viewModel.candleClient.deleteUser()
@@ -500,6 +520,18 @@ extension Models.TradeAsset {
500
520
  }
501
521
  }
502
522
 
523
+ extension Models.Trade {
524
+ var toTrade: Trade {
525
+ .init(
526
+ dateTime: dateTime,
527
+ state: state.toRNModel,
528
+ counterparty: toCounterparty,
529
+ lost: lost.toAsset,
530
+ gained: gained.toAsset
531
+ )
532
+ }
533
+ }
534
+
503
535
  extension TradeQuoteRequest {
504
536
  var toGained: Models.TradeAssetQuoteRequest {
505
537
  get throws {
@@ -516,11 +548,15 @@ extension TradeQuoteRequest {
516
548
  } else if let marketAssetQuoteRequest = gained
517
549
  .marketAssetQuoteRequest
518
550
  {
551
+ guard
552
+ let assetKind = Models.MarketAssetQuoteRequest.AssetKindPayload(
553
+ rawValue: marketAssetQuoteRequest.assetKind)
554
+ else {
555
+ throw RNClientError.badEncoding
556
+ }
519
557
  return Models.TradeAssetQuoteRequest.MarketAssetQuoteRequest(
520
558
  .init(
521
- assetKind: .init(
522
- rawValue: marketAssetQuoteRequest.assetKind)
523
- ?? .stock,
559
+ assetKind: assetKind,
524
560
  serviceAccountID: marketAssetQuoteRequest
525
561
  .serviceAccountID,
526
562
  serviceAssetID: marketAssetQuoteRequest.serviceAssetID,
@@ -989,3 +1025,183 @@ extension TradeQuery {
989
1025
  return nil
990
1026
  }
991
1027
  }
1028
+
1029
+ extension Models.AssetAccount {
1030
+ var toRNModel: AssetAccount {
1031
+ let legalAccountKind = legalAccountKind.toRNModel
1032
+ switch details {
1033
+ case .FiatAccountDetails(let fiatDetails):
1034
+ let ach = fiatDetails.ach.map { details in
1035
+ ACHDetails(
1036
+ accountNumber: details.accountNumber,
1037
+ routingNumber: details.routingNumber,
1038
+ accountKind: details.accountKind.toRNModel
1039
+ )
1040
+ }
1041
+
1042
+ let wire = fiatDetails.wire.map { details in
1043
+ WireDetails(
1044
+ accountNumber: details.accountNumber,
1045
+ routingNumber: details.routingNumber
1046
+ )
1047
+ }
1048
+ return AssetAccount(
1049
+ legalAccountKind: legalAccountKind,
1050
+ nickname: nickname,
1051
+ details: .init(
1052
+ fiatAccountDetails: .init(
1053
+ assetKind: fiatDetails.assetKind.rawValue,
1054
+ serviceAccountID: fiatDetails.serviceAccountID,
1055
+ currencyCode: fiatDetails.currencyCode,
1056
+ balance: fiatDetails.balance,
1057
+ ach: ach,
1058
+ wire: wire,
1059
+ linkedAccountID: fiatDetails.linkedAccountID,
1060
+ service: fiatDetails.service.toService),
1061
+ marketAccountDetails: nil
1062
+ )
1063
+ )
1064
+ case .MarketAccountDetails(let marketDetails):
1065
+ return AssetAccount(
1066
+ legalAccountKind: legalAccountKind,
1067
+ nickname: nickname,
1068
+ details: .init(
1069
+ fiatAccountDetails: nil,
1070
+ marketAccountDetails: .init(
1071
+ assetKind: marketDetails.assetKind.rawValue,
1072
+ serviceAccountID: marketDetails
1073
+ .serviceAccountID,
1074
+ linkedAccountID: marketDetails.linkedAccountID,
1075
+ service: marketDetails.service.toService
1076
+ )
1077
+ )
1078
+ )
1079
+ }
1080
+ }
1081
+ }
1082
+
1083
+ extension TradeAssetRef {
1084
+ var toTradeAssetRef: Models.TradeAssetRef {
1085
+ get throws {
1086
+ if let fiatAssetRef {
1087
+ return .FiatAssetRef(
1088
+ .init(
1089
+ assetKind: .fiat,
1090
+ serviceTradeID: fiatAssetRef.serviceTradeID,
1091
+ linkedAccountID: fiatAssetRef.linkedAccountID
1092
+ )
1093
+ )
1094
+ } else if let nothingAssetRef {
1095
+ return .NothingAsset(.init(assetKind: .nothing))
1096
+ } else if let marketTradeAssetRef {
1097
+ guard
1098
+ let assetKind = Models.MarketAssetRef.AssetKindPayload.init(
1099
+ rawValue: marketTradeAssetRef.assetKind)
1100
+ else {
1101
+ throw RNClientError.badEncoding
1102
+ }
1103
+ return .MarketAssetRef(
1104
+ .init(
1105
+ assetKind: assetKind,
1106
+ serviceTradeID: marketTradeAssetRef.serviceTradeID,
1107
+ linkedAccountID: marketTradeAssetRef.linkedAccountID
1108
+ )
1109
+ )
1110
+ } else if let otherAssetRef {
1111
+ return .OtherAsset(
1112
+ .init(assetKind: .other)
1113
+ )
1114
+ } else if let transportAssetRef {
1115
+ return .TransportAssetRef(
1116
+ .init(
1117
+ assetKind: .transport,
1118
+ serviceTradeID: transportAssetRef.serviceTradeID,
1119
+ linkedAccountID: transportAssetRef.linkedAccountID
1120
+ )
1121
+ )
1122
+ } else {
1123
+ throw RNClientError.badEncoding
1124
+ }
1125
+ }
1126
+ }
1127
+ }
1128
+
1129
+ extension TradeAsset {
1130
+ var toCandleModel: Models.TradeAsset {
1131
+ get throws {
1132
+ if let fiat = fiatAsset {
1133
+ return .FiatAsset(
1134
+ .init(
1135
+ assetKind: .fiat,
1136
+ serviceTradeID: fiat.serviceTradeID,
1137
+ serviceAccountID: fiat.serviceAccountID,
1138
+ currencyCode: fiat.currencyCode,
1139
+ amount: fiat.amount,
1140
+ linkedAccountID: fiat.linkedAccountID,
1141
+ service: fiat.service.toService
1142
+ )
1143
+ )
1144
+ } else if let market = marketTradeAsset {
1145
+ guard let assetKind = Models.MarketTradeAsset.AssetKindPayload(rawValue: market.assetKind)
1146
+ else {
1147
+ throw RNClientError.badEncoding
1148
+ }
1149
+ return .MarketTradeAsset(
1150
+ .init(
1151
+ assetKind: assetKind,
1152
+ serviceAccountID: market.serviceAccountID,
1153
+ serviceAssetID: market.serviceAssetID,
1154
+ symbol: market.symbol,
1155
+ amount: market.amount,
1156
+ serviceTradeID: market.serviceTradeID,
1157
+ linkedAccountID: market.linkedAccountID,
1158
+ service: market.service.toService,
1159
+ name: market.name,
1160
+ color: market.color,
1161
+ logoURL: market.logoURL
1162
+ )
1163
+ )
1164
+ } else if let transport = transportAsset {
1165
+ return .TransportAsset(
1166
+ .init(
1167
+ assetKind: .transport,
1168
+ serviceTradeID: transport.serviceTradeID,
1169
+ serviceAssetID: transport.serviceAssetID,
1170
+ name: transport.name,
1171
+ description: transport.description,
1172
+ imageURL: transport.imageURL,
1173
+ originCoordinates: .init(
1174
+ latitude: transport.originCoordinates.latitude,
1175
+ longitude: transport.originCoordinates.longitude
1176
+ ),
1177
+ originAddress: .init(value: transport.originAddress.value),
1178
+ destinationCoordinates: .init(
1179
+ latitude: transport.destinationCoordinates.latitude,
1180
+ longitude: transport.destinationCoordinates.longitude
1181
+ ),
1182
+ destinationAddress: .init(value: transport.destinationAddress.value),
1183
+ seats: transport.seats,
1184
+ linkedAccountID: transport.linkedAccountID,
1185
+ service: transport.service.toService
1186
+ )
1187
+ )
1188
+ } else if otherAsset != nil {
1189
+ return .OtherAsset(.init(assetKind: .other))
1190
+ } else {
1191
+ return .NothingAsset(.init(assetKind: .nothing))
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+
1197
+ extension TradeQuote {
1198
+ var toCandleModel: Models.TradeQuote {
1199
+ get throws {
1200
+ .init(
1201
+ lost: try lost.toCandleModel,
1202
+ gained: try gained.toCandleModel,
1203
+ context: context
1204
+ )
1205
+ }
1206
+ }
1207
+ }