@onramper/onramper-react-native 1.2.2-1 → 1.3.0
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.
- package/CHANGELOG.md +193 -0
- package/README.md +45 -3
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/arm64-apple-ios.swiftinterface +107 -4
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/OnramperSDK +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/DWARF/OnramperSDK +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/OnramperSDK.yml +3560 -2684
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +107 -4
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/Modules/OnramperSDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +107 -4
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/OnramperSDK +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/DWARF/OnramperSDK +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/Relocations/aarch64/OnramperSDK.yml +3560 -2684
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/OnramperSDK.yml +3523 -2651
- package/ios/HybridOnramperCheckoutButton.swift +1 -1
- package/ios/HybridOnramperNitro.swift +140 -78
- package/ios/OnramperSDKBridge.swift +19 -2
- package/ios/PreparedIntentRegistry.swift +124 -6
- package/ios/SDKLogRelay.swift +41 -0
- package/lib/commonjs/OnramperClient.js +66 -5
- package/lib/commonjs/OnramperClient.js.map +1 -1
- package/lib/commonjs/errors.js +19 -5
- package/lib/commonjs/errors.js.map +1 -1
- package/lib/module/OnramperClient.js +66 -5
- package/lib/module/OnramperClient.js.map +1 -1
- package/lib/module/errors.js +19 -5
- package/lib/module/errors.js.map +1 -1
- package/lib/typescript/commonjs/src/OnramperClient.d.ts +5 -1
- package/lib/typescript/commonjs/src/OnramperClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/errors.d.ts +6 -1
- package/lib/typescript/commonjs/src/errors.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/events.d.ts +10 -0
- package/lib/typescript/commonjs/src/events.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/index.d.ts +1 -1
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/specs/OnramperNitro.nitro.d.ts +3 -0
- package/lib/typescript/commonjs/src/specs/OnramperNitro.nitro.d.ts.map +1 -1
- package/lib/typescript/commonjs/src/types.d.ts +32 -3
- package/lib/typescript/commonjs/src/types.d.ts.map +1 -1
- package/lib/typescript/module/src/OnramperClient.d.ts +5 -1
- package/lib/typescript/module/src/OnramperClient.d.ts.map +1 -1
- package/lib/typescript/module/src/errors.d.ts +6 -1
- package/lib/typescript/module/src/errors.d.ts.map +1 -1
- package/lib/typescript/module/src/events.d.ts +10 -0
- package/lib/typescript/module/src/events.d.ts.map +1 -1
- package/lib/typescript/module/src/index.d.ts +1 -1
- package/lib/typescript/module/src/index.d.ts.map +1 -1
- package/lib/typescript/module/src/specs/OnramperNitro.nitro.d.ts +3 -0
- package/lib/typescript/module/src/specs/OnramperNitro.nitro.d.ts.map +1 -1
- package/lib/typescript/module/src/types.d.ts +32 -3
- package/lib/typescript/module/src/types.d.ts.map +1 -1
- package/nitrogen/generated/ios/OnramperReactNative-Swift-Cxx-Bridge.cpp +3 -3
- package/nitrogen/generated/ios/OnramperReactNative-Swift-Cxx-Bridge.hpp +7 -7
- package/nitrogen/generated/ios/c++/HybridOnramperNitroSpecSwift.hpp +6 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +5 -5
- package/nitrogen/generated/ios/swift/HybridOnramperNitroSpec.swift +1 -0
- package/nitrogen/generated/ios/swift/HybridOnramperNitroSpec_cxx.swift +27 -11
- package/nitrogen/generated/ios/swift/OnramperNitroConfig.swift +16 -6
- package/nitrogen/generated/shared/c++/HybridOnramperNitroSpec.cpp +1 -0
- package/nitrogen/generated/shared/c++/HybridOnramperNitroSpec.hpp +1 -0
- package/nitrogen/generated/shared/c++/OnramperNitroConfig.hpp +10 -2
- package/package.json +3 -2
- package/src/OnramperClient.ts +67 -4
- package/src/errors.ts +29 -6
- package/src/events.ts +5 -0
- package/src/index.ts +3 -0
- package/src/specs/OnramperNitro.nitro.ts +3 -0
- package/src/types.ts +36 -3
|
@@ -84,7 +84,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
|
|
87
|
-
|
|
87
|
+
|
|
88
88
|
|
|
89
89
|
/**
|
|
90
90
|
* Get the memory size of the Swift class (plus size of any other allocations)
|
|
@@ -121,7 +121,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
121
121
|
}
|
|
122
122
|
|
|
123
123
|
// Properties
|
|
124
|
-
|
|
124
|
+
|
|
125
125
|
|
|
126
126
|
// Methods
|
|
127
127
|
@inline(__always)
|
|
@@ -142,7 +142,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
142
142
|
return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
|
|
143
143
|
}
|
|
144
144
|
}
|
|
145
|
-
|
|
145
|
+
|
|
146
146
|
@inline(__always)
|
|
147
147
|
public final func initialize(sessionId: std.string, sessionToken: std.string) -> bridge.Result_std__shared_ptr_Promise_void___ {
|
|
148
148
|
do {
|
|
@@ -161,7 +161,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
161
161
|
return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
|
|
162
162
|
}
|
|
163
163
|
}
|
|
164
|
-
|
|
164
|
+
|
|
165
165
|
@inline(__always)
|
|
166
166
|
public final func reset() -> bridge.Result_std__shared_ptr_Promise_void___ {
|
|
167
167
|
do {
|
|
@@ -180,7 +180,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
180
180
|
return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
|
|
181
181
|
}
|
|
182
182
|
}
|
|
183
|
-
|
|
183
|
+
|
|
184
184
|
@inline(__always)
|
|
185
185
|
public final func signOut() -> bridge.Result_std__shared_ptr_Promise_void___ {
|
|
186
186
|
do {
|
|
@@ -199,7 +199,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
199
199
|
return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
|
|
200
200
|
}
|
|
201
201
|
}
|
|
202
|
-
|
|
202
|
+
|
|
203
203
|
@inline(__always)
|
|
204
204
|
public final func getCheckoutRequirements(requestJson: std.string, prefillJson: std.string, styleJson: std.string) -> bridge.Result_std__shared_ptr_Promise_PreparedIntentResult___ {
|
|
205
205
|
do {
|
|
@@ -218,7 +218,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
218
218
|
return bridge.create_Result_std__shared_ptr_Promise_PreparedIntentResult___(__exceptionPtr)
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
|
-
|
|
221
|
+
|
|
222
222
|
@inline(__always)
|
|
223
223
|
public final func cancelPreparedIntent(intentHandle: std.string) -> bridge.Result_std__shared_ptr_Promise_void___ {
|
|
224
224
|
do {
|
|
@@ -237,7 +237,23 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
237
237
|
return bridge.create_Result_std__shared_ptr_Promise_void___(__exceptionPtr)
|
|
238
238
|
}
|
|
239
239
|
}
|
|
240
|
-
|
|
240
|
+
|
|
241
|
+
@inline(__always)
|
|
242
|
+
public final func setLogListener(onLog: bridge.Func_void_std__string) -> bridge.Result_void_ {
|
|
243
|
+
do {
|
|
244
|
+
try self.__implementation.setLogListener(onLog: { () -> (String) -> Void in
|
|
245
|
+
let __wrappedFunction = bridge.wrap_Func_void_std__string(onLog)
|
|
246
|
+
return { (__recordJson: String) -> Void in
|
|
247
|
+
__wrappedFunction.call(std.string(__recordJson))
|
|
248
|
+
}
|
|
249
|
+
}())
|
|
250
|
+
return bridge.create_Result_void_()
|
|
251
|
+
} catch (let __error) {
|
|
252
|
+
let __exceptionPtr = __error.toCpp()
|
|
253
|
+
return bridge.create_Result_void_(__exceptionPtr)
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
241
257
|
@inline(__always)
|
|
242
258
|
public final func setStateListener(onState: bridge.Func_void_std__string) -> bridge.Result_void_ {
|
|
243
259
|
do {
|
|
@@ -253,7 +269,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
253
269
|
return bridge.create_Result_void_(__exceptionPtr)
|
|
254
270
|
}
|
|
255
271
|
}
|
|
256
|
-
|
|
272
|
+
|
|
257
273
|
@inline(__always)
|
|
258
274
|
public final func setEventListener(onEvent: bridge.Func_void_std__string) -> bridge.Result_void_ {
|
|
259
275
|
do {
|
|
@@ -269,7 +285,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
269
285
|
return bridge.create_Result_void_(__exceptionPtr)
|
|
270
286
|
}
|
|
271
287
|
}
|
|
272
|
-
|
|
288
|
+
|
|
273
289
|
@inline(__always)
|
|
274
290
|
public final func setTransactionIdListener(onTransactionId: bridge.Func_void_std__optional_std__string_) -> bridge.Result_void_ {
|
|
275
291
|
do {
|
|
@@ -291,7 +307,7 @@ open class HybridOnramperNitroSpec_cxx {
|
|
|
291
307
|
return bridge.create_Result_void_(__exceptionPtr)
|
|
292
308
|
}
|
|
293
309
|
}
|
|
294
|
-
|
|
310
|
+
|
|
295
311
|
@inline(__always)
|
|
296
312
|
public final func setSessionExpirationHandler(handler: bridge.Func_std__shared_ptr_Promise_std__shared_ptr_Promise_NitroSessionCredentials____) -> bridge.Result_void_ {
|
|
297
313
|
do {
|
|
@@ -18,32 +18,42 @@ public extension OnramperNitroConfig {
|
|
|
18
18
|
/**
|
|
19
19
|
* Create a new instance of `OnramperNitroConfig`.
|
|
20
20
|
*/
|
|
21
|
-
init(apiKey: String, clientId: String, environment: String, theme: String, logLevel: String) {
|
|
22
|
-
self.init(std.string(apiKey), std.string(clientId), std.string(environment), std.string(theme), std.string(logLevel))
|
|
21
|
+
init(apiKey: String, clientId: String, environment: String, theme: String, logLevel: String, isEventLoggingEnabled: Bool, isEventConsoleLoggingEnabled: Bool) {
|
|
22
|
+
self.init(std.string(apiKey), std.string(clientId), std.string(environment), std.string(theme), std.string(logLevel), isEventLoggingEnabled, isEventConsoleLoggingEnabled)
|
|
23
23
|
}
|
|
24
24
|
|
|
25
25
|
@inline(__always)
|
|
26
26
|
var apiKey: String {
|
|
27
27
|
return String(self.__apiKey)
|
|
28
28
|
}
|
|
29
|
-
|
|
29
|
+
|
|
30
30
|
@inline(__always)
|
|
31
31
|
var clientId: String {
|
|
32
32
|
return String(self.__clientId)
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
|
|
35
35
|
@inline(__always)
|
|
36
36
|
var environment: String {
|
|
37
37
|
return String(self.__environment)
|
|
38
38
|
}
|
|
39
|
-
|
|
39
|
+
|
|
40
40
|
@inline(__always)
|
|
41
41
|
var theme: String {
|
|
42
42
|
return String(self.__theme)
|
|
43
43
|
}
|
|
44
|
-
|
|
44
|
+
|
|
45
45
|
@inline(__always)
|
|
46
46
|
var logLevel: String {
|
|
47
47
|
return String(self.__logLevel)
|
|
48
48
|
}
|
|
49
|
+
|
|
50
|
+
@inline(__always)
|
|
51
|
+
var isEventLoggingEnabled: Bool {
|
|
52
|
+
return self.__isEventLoggingEnabled
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
@inline(__always)
|
|
56
|
+
var isEventConsoleLoggingEnabled: Bool {
|
|
57
|
+
return self.__isEventConsoleLoggingEnabled
|
|
58
|
+
}
|
|
49
59
|
}
|
|
@@ -20,6 +20,7 @@ namespace margelo::nitro::onramper {
|
|
|
20
20
|
prototype.registerHybridMethod("signOut", &HybridOnramperNitroSpec::signOut);
|
|
21
21
|
prototype.registerHybridMethod("getCheckoutRequirements", &HybridOnramperNitroSpec::getCheckoutRequirements);
|
|
22
22
|
prototype.registerHybridMethod("cancelPreparedIntent", &HybridOnramperNitroSpec::cancelPreparedIntent);
|
|
23
|
+
prototype.registerHybridMethod("setLogListener", &HybridOnramperNitroSpec::setLogListener);
|
|
23
24
|
prototype.registerHybridMethod("setStateListener", &HybridOnramperNitroSpec::setStateListener);
|
|
24
25
|
prototype.registerHybridMethod("setEventListener", &HybridOnramperNitroSpec::setEventListener);
|
|
25
26
|
prototype.registerHybridMethod("setTransactionIdListener", &HybridOnramperNitroSpec::setTransactionIdListener);
|
|
@@ -65,6 +65,7 @@ namespace margelo::nitro::onramper {
|
|
|
65
65
|
virtual std::shared_ptr<Promise<void>> signOut() = 0;
|
|
66
66
|
virtual std::shared_ptr<Promise<PreparedIntentResult>> getCheckoutRequirements(const std::string& requestJson, const std::string& prefillJson, const std::string& styleJson) = 0;
|
|
67
67
|
virtual std::shared_ptr<Promise<void>> cancelPreparedIntent(const std::string& intentHandle) = 0;
|
|
68
|
+
virtual void setLogListener(const std::function<void(const std::string& /* recordJson */)>& onLog) = 0;
|
|
68
69
|
virtual void setStateListener(const std::function<void(const std::string& /* stateJson */)>& onState) = 0;
|
|
69
70
|
virtual void setEventListener(const std::function<void(const std::string& /* eventJson */)>& onEvent) = 0;
|
|
70
71
|
virtual void setTransactionIdListener(const std::function<void(const std::optional<std::string>& /* transactionId */)>& onTransactionId) = 0;
|
|
@@ -44,10 +44,12 @@ namespace margelo::nitro::onramper {
|
|
|
44
44
|
std::string environment SWIFT_PRIVATE;
|
|
45
45
|
std::string theme SWIFT_PRIVATE;
|
|
46
46
|
std::string logLevel SWIFT_PRIVATE;
|
|
47
|
+
bool isEventLoggingEnabled SWIFT_PRIVATE;
|
|
48
|
+
bool isEventConsoleLoggingEnabled SWIFT_PRIVATE;
|
|
47
49
|
|
|
48
50
|
public:
|
|
49
51
|
OnramperNitroConfig() = default;
|
|
50
|
-
explicit OnramperNitroConfig(std::string apiKey, std::string clientId, std::string environment, std::string theme, std::string logLevel): apiKey(apiKey), clientId(clientId), environment(environment), theme(theme), logLevel(logLevel) {}
|
|
52
|
+
explicit OnramperNitroConfig(std::string apiKey, std::string clientId, std::string environment, std::string theme, std::string logLevel, bool isEventLoggingEnabled, bool isEventConsoleLoggingEnabled): apiKey(apiKey), clientId(clientId), environment(environment), theme(theme), logLevel(logLevel), isEventLoggingEnabled(isEventLoggingEnabled), isEventConsoleLoggingEnabled(isEventConsoleLoggingEnabled) {}
|
|
51
53
|
|
|
52
54
|
public:
|
|
53
55
|
friend bool operator==(const OnramperNitroConfig& lhs, const OnramperNitroConfig& rhs) = default;
|
|
@@ -67,7 +69,9 @@ namespace margelo::nitro {
|
|
|
67
69
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "clientId"))),
|
|
68
70
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "environment"))),
|
|
69
71
|
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "theme"))),
|
|
70
|
-
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "logLevel")))
|
|
72
|
+
JSIConverter<std::string>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "logLevel"))),
|
|
73
|
+
JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isEventLoggingEnabled"))),
|
|
74
|
+
JSIConverter<bool>::fromJSI(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isEventConsoleLoggingEnabled")))
|
|
71
75
|
);
|
|
72
76
|
}
|
|
73
77
|
static inline jsi::Value toJSI(jsi::Runtime& runtime, const margelo::nitro::onramper::OnramperNitroConfig& arg) {
|
|
@@ -77,6 +81,8 @@ namespace margelo::nitro {
|
|
|
77
81
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "environment"), JSIConverter<std::string>::toJSI(runtime, arg.environment));
|
|
78
82
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "theme"), JSIConverter<std::string>::toJSI(runtime, arg.theme));
|
|
79
83
|
obj.setProperty(runtime, PropNameIDCache::get(runtime, "logLevel"), JSIConverter<std::string>::toJSI(runtime, arg.logLevel));
|
|
84
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "isEventLoggingEnabled"), JSIConverter<bool>::toJSI(runtime, arg.isEventLoggingEnabled));
|
|
85
|
+
obj.setProperty(runtime, PropNameIDCache::get(runtime, "isEventConsoleLoggingEnabled"), JSIConverter<bool>::toJSI(runtime, arg.isEventConsoleLoggingEnabled));
|
|
80
86
|
return obj;
|
|
81
87
|
}
|
|
82
88
|
static inline bool canConvert(jsi::Runtime& runtime, const jsi::Value& value) {
|
|
@@ -92,6 +98,8 @@ namespace margelo::nitro {
|
|
|
92
98
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "environment")))) return false;
|
|
93
99
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "theme")))) return false;
|
|
94
100
|
if (!JSIConverter<std::string>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "logLevel")))) return false;
|
|
101
|
+
if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isEventLoggingEnabled")))) return false;
|
|
102
|
+
if (!JSIConverter<bool>::canConvert(runtime, obj.getProperty(runtime, PropNameIDCache::get(runtime, "isEventConsoleLoggingEnabled")))) return false;
|
|
95
103
|
return true;
|
|
96
104
|
}
|
|
97
105
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onramper/onramper-react-native",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.3.0",
|
|
4
4
|
"description": "React Native wrapper for the Onramper iOS SDK",
|
|
5
5
|
"main": "./lib/commonjs/index.js",
|
|
6
6
|
"module": "./lib/module/index.js",
|
|
@@ -41,6 +41,7 @@
|
|
|
41
41
|
"lint": "biome check src",
|
|
42
42
|
"format": "biome format --write src",
|
|
43
43
|
"test": "jest",
|
|
44
|
+
"test:native": "bash scripts/test-native.sh",
|
|
44
45
|
"typecheck": "tsc --noEmit",
|
|
45
46
|
"nitrogen": "nitrogen && node scripts/sync-view-config.js",
|
|
46
47
|
"prepare": "bob build",
|
|
@@ -64,7 +65,7 @@
|
|
|
64
65
|
"license": "Apache-2.0",
|
|
65
66
|
"homepage": "https://github.com/onramper/onramper-react-native#readme",
|
|
66
67
|
"onramperSDK": {
|
|
67
|
-
"checksum": "
|
|
68
|
+
"checksum": "7611f869eab69109b317bb2b81e23c99f9d6f108bb6425ed2aace5cc4d5ad766"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
71
|
"react": ">=19.0.0",
|
package/src/OnramperClient.ts
CHANGED
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
CheckoutButtonStyle,
|
|
9
9
|
CheckoutRequest,
|
|
10
10
|
OnramperConfiguration,
|
|
11
|
+
OnramperLogRecord,
|
|
11
12
|
OnramperState,
|
|
12
13
|
OnramperUserPrefill,
|
|
13
14
|
QuoteResponse,
|
|
@@ -42,10 +43,24 @@ export class OnramperClient {
|
|
|
42
43
|
// Resolved when the constructor-issued configure() completes. Public methods
|
|
43
44
|
// that need the native client await this first.
|
|
44
45
|
private readonly configured: Promise<void>;
|
|
46
|
+
private destroyed = false;
|
|
45
47
|
|
|
46
48
|
constructor(config: OnramperConfiguration) {
|
|
49
|
+
if (config.logHandler) {
|
|
50
|
+
const handler = config.logHandler;
|
|
51
|
+
this.native.setLogListener((json) => {
|
|
52
|
+
if (this.destroyed) return;
|
|
53
|
+
try {
|
|
54
|
+
handler(JSON.parse(json) as OnramperLogRecord);
|
|
55
|
+
} catch {
|
|
56
|
+
// Diagnostics must never interrupt checkout; do not log callback data.
|
|
57
|
+
console.warn('Onramper logHandler failed.');
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
}
|
|
47
61
|
// Single native state callback → update the mirror + fan out to listeners.
|
|
48
62
|
this.native.setStateListener((json) => {
|
|
63
|
+
if (this.destroyed) return;
|
|
49
64
|
const s = JSON.parse(json) as OnramperState;
|
|
50
65
|
this.state = s;
|
|
51
66
|
if (s.kind === 'failed') this.lastError = OnramperError.from(s.error);
|
|
@@ -55,6 +70,7 @@ export class OnramperClient {
|
|
|
55
70
|
// Single native checkout-event callback → keep the transaction ID mirror
|
|
56
71
|
// synchronized at finalization, then fan out to checkout listeners.
|
|
57
72
|
this.native.setEventListener((json) => {
|
|
73
|
+
if (this.destroyed) return;
|
|
58
74
|
const e = JSON.parse(json) as CheckoutEvent;
|
|
59
75
|
if (e.type === 'checkoutFinalized') {
|
|
60
76
|
this.updateCurrentTransactionId(e.response.onramperTransactionId);
|
|
@@ -63,6 +79,7 @@ export class OnramperClient {
|
|
|
63
79
|
});
|
|
64
80
|
|
|
65
81
|
this.native.setTransactionIdListener((transactionId) => {
|
|
82
|
+
if (this.destroyed) return;
|
|
66
83
|
// The SDK transiently publishes nil while re-preparing after the payment
|
|
67
84
|
// sheet is dismissed. The finalized transaction ID remains durable across
|
|
68
85
|
// that attempt change; only explicit reset()/signOut() clear the JS mirror.
|
|
@@ -73,7 +90,9 @@ export class OnramperClient {
|
|
|
73
90
|
// Nitro stores the async callback natively and awaits it directly — no
|
|
74
91
|
// event round-trip needed.
|
|
75
92
|
this.native.setSessionExpirationHandler(async () => {
|
|
93
|
+
this.assertActive();
|
|
76
94
|
const creds = await config.onSessionExpired();
|
|
95
|
+
this.assertActive();
|
|
77
96
|
return { sessionId: creds.sessionId, sessionToken: creds.sessionToken };
|
|
78
97
|
});
|
|
79
98
|
|
|
@@ -84,10 +103,12 @@ export class OnramperClient {
|
|
|
84
103
|
environment: config.environment,
|
|
85
104
|
theme: config.theme ?? 'system',
|
|
86
105
|
logLevel: config.logLevel ?? 'off',
|
|
106
|
+
isEventLoggingEnabled: config.isEventLoggingEnabled ?? false,
|
|
107
|
+
isEventConsoleLoggingEnabled: config.isEventConsoleLoggingEnabled ?? false,
|
|
87
108
|
})
|
|
88
109
|
.catch((e: unknown) => {
|
|
89
110
|
const err = OnramperError.from(e);
|
|
90
|
-
this.lastError = err;
|
|
111
|
+
if (!this.destroyed) this.lastError = err;
|
|
91
112
|
throw err;
|
|
92
113
|
});
|
|
93
114
|
// Swallow the unhandled-rejection warning when no one awaits .configured
|
|
@@ -95,11 +116,23 @@ export class OnramperClient {
|
|
|
95
116
|
this.configured.catch(() => undefined);
|
|
96
117
|
}
|
|
97
118
|
|
|
119
|
+
private assertActive(): void {
|
|
120
|
+
if (this.destroyed) {
|
|
121
|
+
throw new OnramperError({
|
|
122
|
+
code: 'clientDestroyed',
|
|
123
|
+
message: 'This OnramperClient has been destroyed. Create a new client before making SDK calls.',
|
|
124
|
+
userMessage: 'This checkout session has ended. Please reopen checkout.',
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
98
129
|
private updateCurrentTransactionId(next: string | null): void {
|
|
130
|
+
if (this.destroyed) return;
|
|
99
131
|
if (next === this.currentTransactionId) return;
|
|
100
132
|
|
|
101
133
|
this.currentTransactionId = next;
|
|
102
134
|
for (const fn of [...this.transactionIdListeners]) {
|
|
135
|
+
if (this.destroyed) break;
|
|
103
136
|
try {
|
|
104
137
|
fn(next);
|
|
105
138
|
} catch (error: unknown) {
|
|
@@ -110,19 +143,27 @@ export class OnramperClient {
|
|
|
110
143
|
|
|
111
144
|
async initialize(creds: SessionCredentials): Promise<void> {
|
|
112
145
|
try {
|
|
146
|
+
this.assertActive();
|
|
113
147
|
await this.configured;
|
|
148
|
+
this.assertActive();
|
|
114
149
|
await this.native.initialize(creds.sessionId, creds.sessionToken);
|
|
150
|
+
this.assertActive();
|
|
115
151
|
} catch (e: unknown) {
|
|
152
|
+
this.assertActive();
|
|
116
153
|
throw OnramperError.from(e);
|
|
117
154
|
}
|
|
118
155
|
}
|
|
119
156
|
|
|
120
157
|
async reset(): Promise<void> {
|
|
121
158
|
try {
|
|
159
|
+
this.assertActive();
|
|
122
160
|
await this.configured;
|
|
161
|
+
this.assertActive();
|
|
123
162
|
await this.native.reset();
|
|
163
|
+
this.assertActive();
|
|
124
164
|
this.updateCurrentTransactionId(null);
|
|
125
165
|
} catch (e: unknown) {
|
|
166
|
+
this.assertActive();
|
|
126
167
|
throw OnramperError.from(e);
|
|
127
168
|
}
|
|
128
169
|
}
|
|
@@ -135,10 +176,14 @@ export class OnramperClient {
|
|
|
135
176
|
*/
|
|
136
177
|
async signOut(): Promise<void> {
|
|
137
178
|
try {
|
|
179
|
+
this.assertActive();
|
|
138
180
|
await this.configured;
|
|
181
|
+
this.assertActive();
|
|
139
182
|
await this.native.signOut();
|
|
183
|
+
this.assertActive();
|
|
140
184
|
this.updateCurrentTransactionId(null);
|
|
141
185
|
} catch (e: unknown) {
|
|
186
|
+
this.assertActive();
|
|
142
187
|
throw OnramperError.from(e);
|
|
143
188
|
}
|
|
144
189
|
}
|
|
@@ -147,6 +192,8 @@ export class OnramperClient {
|
|
|
147
192
|
* Fetches checkout requirements + quote and returns a native checkout button
|
|
148
193
|
* to render plus the quote. The button handles login / finalize / webview
|
|
149
194
|
* internally; outcomes surface via the event stream (`addEventListener`).
|
|
195
|
+
* A newer preparation, reset, or sign-out invalidates older unmounted buttons
|
|
196
|
+
* and rejects obsolete in-flight preparations with `intentInvalidated`.
|
|
150
197
|
*
|
|
151
198
|
* Pass `prefill` to pre-populate the OnramperID sign-in and additional-info
|
|
152
199
|
* screens with values you already know about the user. It is best-effort and
|
|
@@ -164,27 +211,39 @@ export class OnramperClient {
|
|
|
164
211
|
prefill: OnramperUserPrefill = {},
|
|
165
212
|
): Promise<GetCheckoutRequirementsResult> {
|
|
166
213
|
try {
|
|
214
|
+
this.assertActive();
|
|
167
215
|
await this.configured;
|
|
216
|
+
this.assertActive();
|
|
168
217
|
const result = await this.native.getCheckoutRequirements(
|
|
169
218
|
JSON.stringify(request),
|
|
170
219
|
JSON.stringify(prefill),
|
|
171
220
|
JSON.stringify(buttonStyle),
|
|
172
221
|
);
|
|
222
|
+
this.assertActive();
|
|
173
223
|
const quote = JSON.parse(result.quoteJson) as QuoteResponse;
|
|
174
224
|
const button = createElement(CheckoutButton, { intentHandle: result.intentHandle });
|
|
175
225
|
return { button, quote };
|
|
176
226
|
} catch (e: unknown) {
|
|
227
|
+
this.assertActive();
|
|
177
228
|
throw OnramperError.from(e);
|
|
178
229
|
}
|
|
179
230
|
}
|
|
180
231
|
|
|
181
232
|
/** Discards a prepared intent (e.g. if the user navigates away before checkout). */
|
|
182
|
-
cancelPreparedIntent(intentHandle: string): Promise<void> {
|
|
183
|
-
|
|
233
|
+
async cancelPreparedIntent(intentHandle: string): Promise<void> {
|
|
234
|
+
try {
|
|
235
|
+
this.assertActive();
|
|
236
|
+
await this.native.cancelPreparedIntent(intentHandle);
|
|
237
|
+
this.assertActive();
|
|
238
|
+
} catch (e: unknown) {
|
|
239
|
+
this.assertActive();
|
|
240
|
+
throw OnramperError.from(e);
|
|
241
|
+
}
|
|
184
242
|
}
|
|
185
243
|
|
|
186
244
|
/** Subscribe to state changes. Returns an unsubscribe function. */
|
|
187
245
|
addStateListener(fn: (state: OnramperState) => void): () => void {
|
|
246
|
+
this.assertActive();
|
|
188
247
|
this.stateListeners.add(fn);
|
|
189
248
|
return () => {
|
|
190
249
|
this.stateListeners.delete(fn);
|
|
@@ -193,6 +252,7 @@ export class OnramperClient {
|
|
|
193
252
|
|
|
194
253
|
/** Subscribe to the durable Onramper transaction ID. Successful reset/signOut publish null. */
|
|
195
254
|
addTransactionIdListener(fn: (transactionId: string | null) => void): () => void {
|
|
255
|
+
this.assertActive();
|
|
196
256
|
this.transactionIdListeners.add(fn);
|
|
197
257
|
return () => {
|
|
198
258
|
this.transactionIdListeners.delete(fn);
|
|
@@ -201,6 +261,7 @@ export class OnramperClient {
|
|
|
201
261
|
|
|
202
262
|
/** Subscribe to a specific checkout event. Returns an unsubscribe function. */
|
|
203
263
|
addEventListener<K extends EventName>(name: K, fn: (e: EventPayload<K>) => void): () => void {
|
|
264
|
+
this.assertActive();
|
|
204
265
|
const wrapper = (e: CheckoutEvent) => {
|
|
205
266
|
if (e.type === name) fn(e as EventPayload<K>);
|
|
206
267
|
};
|
|
@@ -210,8 +271,10 @@ export class OnramperClient {
|
|
|
210
271
|
};
|
|
211
272
|
}
|
|
212
273
|
|
|
213
|
-
/**
|
|
274
|
+
/** Idempotent teardown. Further operations reject with `clientDestroyed`; create a new client to restart. */
|
|
214
275
|
destroy(): void {
|
|
276
|
+
if (this.destroyed) return;
|
|
277
|
+
this.destroyed = true;
|
|
215
278
|
this.stateListeners.clear();
|
|
216
279
|
this.eventListeners.clear();
|
|
217
280
|
this.transactionIdListeners.clear();
|
package/src/errors.ts
CHANGED
|
@@ -8,6 +8,9 @@ export type OnramperErrorCode =
|
|
|
8
8
|
| 'networkError'
|
|
9
9
|
| 'decodingError'
|
|
10
10
|
| 'timeout'
|
|
11
|
+
| 'paymentFailed'
|
|
12
|
+
| 'providerFailed'
|
|
13
|
+
| 'applePayNotConfigured'
|
|
11
14
|
| 'requirementNotSatisfied'
|
|
12
15
|
| 'amountOutOfRange'
|
|
13
16
|
| 'oidcFlowCancelled'
|
|
@@ -26,42 +29,62 @@ export type OnramperErrorCode =
|
|
|
26
29
|
| 'deviceBlocked'
|
|
27
30
|
| 'securityStorageFailed'
|
|
28
31
|
| 'securityTrustFailed'
|
|
29
|
-
//
|
|
32
|
+
// Wrapper lifecycle and platform codes
|
|
30
33
|
| 'platformUnsupported'
|
|
31
34
|
| 'intentInvalidated'
|
|
32
35
|
| 'intentAlreadyConsumed'
|
|
33
36
|
| 'clientAlreadyConfigured'
|
|
37
|
+
| 'clientDestroyed'
|
|
34
38
|
| 'sessionExpirationHandlerFailed';
|
|
35
39
|
|
|
36
40
|
export interface OnramperErrorPayload {
|
|
37
41
|
code: OnramperErrorCode;
|
|
38
42
|
message: string;
|
|
43
|
+
/** Customer-facing SDK copy; optional for backwards-compatible payload construction. */
|
|
44
|
+
userMessage?: string;
|
|
45
|
+
supportCode?: string;
|
|
39
46
|
info?: Record<string, unknown>;
|
|
40
47
|
}
|
|
41
48
|
|
|
42
49
|
export class OnramperError extends Error implements OnramperErrorPayload {
|
|
43
50
|
readonly code: OnramperErrorCode;
|
|
51
|
+
readonly userMessage: string;
|
|
52
|
+
readonly supportCode: string;
|
|
44
53
|
readonly info?: Record<string, unknown>;
|
|
45
54
|
|
|
46
55
|
constructor(payload: OnramperErrorPayload) {
|
|
47
56
|
super(payload.message);
|
|
48
57
|
this.name = 'OnramperError';
|
|
49
58
|
this.code = payload.code;
|
|
59
|
+
this.userMessage = payload.userMessage ?? 'Something went wrong. Please try again.';
|
|
60
|
+
this.supportCode = payload.supportCode ?? payload.code;
|
|
50
61
|
this.info = payload.info;
|
|
51
62
|
}
|
|
52
63
|
|
|
53
64
|
static from(value: unknown): OnramperError {
|
|
54
65
|
if (value instanceof OnramperError) return value;
|
|
66
|
+
// Nitro transports Swift exceptions as message-only JS Errors. Our native
|
|
67
|
+
// bridge encodes SDK errors explicitly so Promise rejections retain the
|
|
68
|
+
// same fields as failed events, without consulting unrelated client state.
|
|
69
|
+
const message = value instanceof Error ? value.message : typeof value === 'string' ? value : undefined;
|
|
70
|
+
if (message?.startsWith('ONRAMPER_ERROR:')) {
|
|
71
|
+
try {
|
|
72
|
+
const payload = JSON.parse(message.slice('ONRAMPER_ERROR:'.length));
|
|
73
|
+
if (payload && typeof payload.code === 'string' && typeof payload.message === 'string') {
|
|
74
|
+
return OnramperError.from(payload);
|
|
75
|
+
}
|
|
76
|
+
} catch {
|
|
77
|
+
// A malformed/non-SDK error falls back to the ordinary error path.
|
|
78
|
+
}
|
|
79
|
+
}
|
|
55
80
|
if (value && typeof value === 'object') {
|
|
56
|
-
|
|
57
|
-
// `{ code, message, info? }` object. Thrown promise rejections surface
|
|
58
|
-
// as a JS Error with just a message; we default the code in that case
|
|
59
|
-
// (the structured error is also available on `client.state` / lastError).
|
|
60
|
-
const v = value as { code?: string; message?: string; info?: Record<string, unknown> };
|
|
81
|
+
const v = value as Partial<OnramperErrorPayload>;
|
|
61
82
|
return new OnramperError({
|
|
62
83
|
code: (v.code ?? 'unrecoverable') as OnramperErrorCode,
|
|
63
84
|
message: v.message ?? 'Unknown error',
|
|
64
85
|
info: v.info,
|
|
86
|
+
userMessage: typeof v.userMessage === 'string' ? v.userMessage : undefined,
|
|
87
|
+
supportCode: typeof v.supportCode === 'string' ? v.supportCode : undefined,
|
|
65
88
|
});
|
|
66
89
|
}
|
|
67
90
|
return new OnramperError({ code: 'unrecoverable', message: String(value) });
|
package/src/events.ts
CHANGED
|
@@ -16,6 +16,11 @@ export type CheckoutEvent =
|
|
|
16
16
|
| { type: 'providerReady' }
|
|
17
17
|
| { type: 'paymentAuthorized' }
|
|
18
18
|
| { type: 'paymentProcessing' }
|
|
19
|
+
/** Accepted but not settled; use currentTransactionId to track the payment. */
|
|
20
|
+
| { type: 'paymentPending' }
|
|
21
|
+
| { type: 'challengeStarted' }
|
|
22
|
+
| { type: 'challengeCompleted' }
|
|
23
|
+
| { type: 'customerOnboardingRequired' }
|
|
19
24
|
| { type: 'paymentCancelled' }
|
|
20
25
|
| { type: 'providerError'; reason: string };
|
|
21
26
|
|
package/src/index.ts
CHANGED
|
@@ -8,6 +8,8 @@ export interface OnramperNitroConfig {
|
|
|
8
8
|
environment: string; // 'development' | 'production'
|
|
9
9
|
theme: string; // 'system' | 'light' | 'dark'
|
|
10
10
|
logLevel: string; // 'off' | 'error' | 'info' | 'debug'
|
|
11
|
+
isEventLoggingEnabled: boolean;
|
|
12
|
+
isEventConsoleLoggingEnabled: boolean;
|
|
11
13
|
}
|
|
12
14
|
|
|
13
15
|
// Mirrors OnramperSDK.SessionCredentials. Named with a Nitro prefix to avoid a
|
|
@@ -50,6 +52,7 @@ export interface OnramperNitro extends HybridObject<{ ios: 'swift' }> {
|
|
|
50
52
|
cancelPreparedIntent(intentHandle: string): Promise<void>;
|
|
51
53
|
|
|
52
54
|
// Single native callback per stream; the JS wrapper fans out to multiple listeners.
|
|
55
|
+
setLogListener(onLog: (recordJson: string) => void): void;
|
|
53
56
|
setStateListener(onState: (stateJson: string) => void): void;
|
|
54
57
|
setEventListener(onEvent: (eventJson: string) => void): void;
|
|
55
58
|
// Mirrors OnramperSDK.$currentTransactionId. `undefined` represents native nil.
|
package/src/types.ts
CHANGED
|
@@ -5,6 +5,16 @@ import type { OnramperErrorPayload } from './errors';
|
|
|
5
5
|
|
|
6
6
|
export type OnramperEnvironment = 'development' | 'production';
|
|
7
7
|
export type OnramperLogLevel = 'off' | 'error' | 'info' | 'debug';
|
|
8
|
+
/** A sanitized native SDK diagnostic. Timestamp is Unix milliseconds. */
|
|
9
|
+
export interface OnramperLogRecord {
|
|
10
|
+
timestamp: number;
|
|
11
|
+
level: OnramperLogLevel;
|
|
12
|
+
category: string;
|
|
13
|
+
event: string;
|
|
14
|
+
context: Record<string, string>;
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
export type OnramperTheme = 'system' | 'light' | 'dark';
|
|
9
19
|
|
|
10
20
|
export type TransactionType = 'buy' | 'sell';
|
|
@@ -20,12 +30,16 @@ export interface OnramperConfiguration {
|
|
|
20
30
|
environment: OnramperEnvironment;
|
|
21
31
|
theme?: OnramperTheme;
|
|
22
32
|
logLevel?: OnramperLogLevel;
|
|
33
|
+
/** Receives native records in JS; system Console output is preserved. Off unless logLevel enables it. */
|
|
34
|
+
logHandler?: (record: OnramperLogRecord) => void;
|
|
35
|
+
/** Opt-in provider-event telemetry to the BFF. Defaults to false. */
|
|
36
|
+
isEventLoggingEnabled?: boolean;
|
|
37
|
+
/** Emit provider events at info even when logLevel is lower. Defaults to false. */
|
|
38
|
+
isEventConsoleLoggingEnabled?: boolean;
|
|
23
39
|
/**
|
|
24
40
|
* Called by the SDK when the session token expires and needs to be re-issued.
|
|
25
41
|
*
|
|
26
|
-
* May be synchronous or async
|
|
27
|
-
* round-trip (`onSessionExpired` → `provideSessionCredentials`) so Promises
|
|
28
|
-
* are awaited normally. Throw or reject to signal that no fresh credentials
|
|
42
|
+
* May be synchronous or async; the Nitro bridge awaits the callback directly. Throw or reject to signal that no fresh credentials
|
|
29
43
|
* are available; the SDK will surface `userTokenRefreshFailed`.
|
|
30
44
|
*/
|
|
31
45
|
onSessionExpired: () => SessionCredentials | Promise<SessionCredentials>;
|
|
@@ -67,6 +81,23 @@ export interface QuoteResponse {
|
|
|
67
81
|
networkFee: number;
|
|
68
82
|
transactionFee: number;
|
|
69
83
|
recommendations?: string[];
|
|
84
|
+
providerContext?: Record<string, ProviderJSONValue>;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** JSON values used in provider-specific quote metadata (including booleans and limits). */
|
|
88
|
+
export type ProviderJSONValue =
|
|
89
|
+
| string
|
|
90
|
+
| number
|
|
91
|
+
| boolean
|
|
92
|
+
| null
|
|
93
|
+
| ProviderJSONValue[]
|
|
94
|
+
| { [key: string]: ProviderJSONValue };
|
|
95
|
+
|
|
96
|
+
export interface PaymentDisclosure {
|
|
97
|
+
code: string;
|
|
98
|
+
version: string;
|
|
99
|
+
contentMarkdown: string;
|
|
100
|
+
contentHtml: string;
|
|
70
101
|
}
|
|
71
102
|
|
|
72
103
|
// Mirrors Swift `OnramperUserPrefill`. Values you already know about the user,
|
|
@@ -111,6 +142,7 @@ export interface HeadlessCheckoutData {
|
|
|
111
142
|
checkoutPaymentType: CheckoutPaymentType;
|
|
112
143
|
url: string;
|
|
113
144
|
renderType: RenderType;
|
|
145
|
+
providerBootstrap?: { framesBaseUrl?: string };
|
|
114
146
|
}
|
|
115
147
|
|
|
116
148
|
export interface CheckoutFinalizeResponse {
|
|
@@ -181,6 +213,7 @@ export type OnramperState =
|
|
|
181
213
|
| { kind: 'readyToCheckout' }
|
|
182
214
|
| { kind: 'finalizing' }
|
|
183
215
|
| { kind: 'rendering'; url: string; renderType: RenderType; paymentType: CheckoutPaymentType }
|
|
216
|
+
| { kind: 'paymentPending' }
|
|
184
217
|
| { kind: 'completed' }
|
|
185
218
|
| { kind: 'failed'; error: OnramperErrorPayload };
|
|
186
219
|
|