@onramper/onramper-react-native 1.0.1
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 +21 -0
- package/LICENSE +202 -0
- package/NOTICE +5 -0
- package/OnramperReactNative.podspec +36 -0
- package/README.md +114 -0
- package/app.plugin.js +51 -0
- package/ios/Frameworks/LICENSE +202 -0
- package/ios/Frameworks/NOTICE +5 -0
- package/ios/Frameworks/OnramperSDK.xcframework/Info.plist +48 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/Info.plist +0 -0
- 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 +548 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/OnramperSDK +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/OnramperSDK_OnramperSDK.bundle/Info.plist +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/OnramperSDK_OnramperSDK.bundle/PrivacyInfo.xcprivacy +27 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/OnramperSDK.framework/PrivacyInfo.xcprivacy +27 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64/dSYMs/OnramperSDK.framework.dSYM/Contents/Info.plist +20 -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 +2518 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/Info.plist +0 -0
- 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 +548 -0
- 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 +548 -0
- 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/OnramperSDK.framework/OnramperSDK_OnramperSDK.bundle/Info.plist +0 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/OnramperSDK_OnramperSDK.bundle/PrivacyInfo.xcprivacy +27 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/OnramperSDK.framework/PrivacyInfo.xcprivacy +27 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/OnramperSDK.framework.dSYM/Contents/Info.plist +20 -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 +2518 -0
- package/ios/Frameworks/OnramperSDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/OnramperSDK.framework.dSYM/Contents/Resources/Relocations/x86_64/OnramperSDK.yml +2487 -0
- package/ios/HybridOnramperCheckoutButton.swift +112 -0
- package/ios/HybridOnramperNitro.swift +194 -0
- package/ios/OnramperCheckoutBridge.swift +88 -0
- package/ios/OnramperSDKBridge.swift +185 -0
- package/ios/PreparedIntentRegistry.swift +78 -0
- package/lib/commonjs/OnramperCheckoutButtonView.js +16 -0
- package/lib/commonjs/OnramperCheckoutButtonView.js.map +1 -0
- package/lib/commonjs/OnramperClient.js +161 -0
- package/lib/commonjs/OnramperClient.js.map +1 -0
- package/lib/commonjs/OnramperNative.js +22 -0
- package/lib/commonjs/OnramperNative.js.map +1 -0
- package/lib/commonjs/errors.js +35 -0
- package/lib/commonjs/errors.js.map +1 -0
- package/lib/commonjs/events.js +6 -0
- package/lib/commonjs/events.js.map +1 -0
- package/lib/commonjs/generated/OnramperCheckoutButtonConfig.json +10 -0
- package/lib/commonjs/index.js +27 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/specs/OnramperCheckoutButton.nitro.js +6 -0
- package/lib/commonjs/specs/OnramperCheckoutButton.nitro.js.map +1 -0
- package/lib/commonjs/specs/OnramperNitro.nitro.js +6 -0
- package/lib/commonjs/specs/OnramperNitro.nitro.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/module/OnramperCheckoutButtonView.js +11 -0
- package/lib/module/OnramperCheckoutButtonView.js.map +1 -0
- package/lib/module/OnramperClient.js +156 -0
- package/lib/module/OnramperClient.js.map +1 -0
- package/lib/module/OnramperNative.js +18 -0
- package/lib/module/OnramperNative.js.map +1 -0
- package/lib/module/errors.js +30 -0
- package/lib/module/errors.js.map +1 -0
- package/lib/module/events.js +4 -0
- package/lib/module/events.js.map +1 -0
- package/lib/module/generated/OnramperCheckoutButtonConfig.json +10 -0
- package/lib/module/index.js +8 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/specs/OnramperCheckoutButton.nitro.js +4 -0
- package/lib/module/specs/OnramperCheckoutButton.nitro.js.map +1 -0
- package/lib/module/specs/OnramperNitro.nitro.js +4 -0
- package/lib/module/specs/OnramperNitro.nitro.js.map +1 -0
- package/lib/module/types.js +4 -0
- package/lib/module/types.js.map +1 -0
- package/lib/typescript/commonjs/package.json +1 -0
- package/lib/typescript/commonjs/src/OnramperCheckoutButtonView.d.ts +9 -0
- package/lib/typescript/commonjs/src/OnramperCheckoutButtonView.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/OnramperClient.d.ts +49 -0
- package/lib/typescript/commonjs/src/OnramperClient.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/OnramperNative.d.ts +9 -0
- package/lib/typescript/commonjs/src/OnramperNative.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/errors.d.ts +13 -0
- package/lib/typescript/commonjs/src/errors.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/events.d.ts +48 -0
- package/lib/typescript/commonjs/src/events.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/index.d.ts +9 -0
- package/lib/typescript/commonjs/src/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/specs/OnramperCheckoutButton.nitro.d.ts +10 -0
- package/lib/typescript/commonjs/src/specs/OnramperCheckoutButton.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/specs/OnramperNitro.nitro.d.ts +39 -0
- package/lib/typescript/commonjs/src/specs/OnramperNitro.nitro.d.ts.map +1 -0
- package/lib/typescript/commonjs/src/types.d.ts +127 -0
- package/lib/typescript/commonjs/src/types.d.ts.map +1 -0
- package/lib/typescript/module/package.json +1 -0
- package/lib/typescript/module/src/OnramperCheckoutButtonView.d.ts +9 -0
- package/lib/typescript/module/src/OnramperCheckoutButtonView.d.ts.map +1 -0
- package/lib/typescript/module/src/OnramperClient.d.ts +49 -0
- package/lib/typescript/module/src/OnramperClient.d.ts.map +1 -0
- package/lib/typescript/module/src/OnramperNative.d.ts +9 -0
- package/lib/typescript/module/src/OnramperNative.d.ts.map +1 -0
- package/lib/typescript/module/src/errors.d.ts +13 -0
- package/lib/typescript/module/src/errors.d.ts.map +1 -0
- package/lib/typescript/module/src/events.d.ts +48 -0
- package/lib/typescript/module/src/events.d.ts.map +1 -0
- package/lib/typescript/module/src/index.d.ts +9 -0
- package/lib/typescript/module/src/index.d.ts.map +1 -0
- package/lib/typescript/module/src/specs/OnramperCheckoutButton.nitro.d.ts +10 -0
- package/lib/typescript/module/src/specs/OnramperCheckoutButton.nitro.d.ts.map +1 -0
- package/lib/typescript/module/src/specs/OnramperNitro.nitro.d.ts +39 -0
- package/lib/typescript/module/src/specs/OnramperNitro.nitro.d.ts.map +1 -0
- package/lib/typescript/module/src/types.d.ts +127 -0
- package/lib/typescript/module/src/types.d.ts.map +1 -0
- package/nitro.json +19 -0
- package/nitrogen/generated/.gitattributes +1 -0
- package/nitrogen/generated/ios/OnramperReactNative+autolinking.rb +62 -0
- package/nitrogen/generated/ios/OnramperReactNative-Swift-Cxx-Bridge.cpp +107 -0
- package/nitrogen/generated/ios/OnramperReactNative-Swift-Cxx-Bridge.hpp +299 -0
- package/nitrogen/generated/ios/OnramperReactNative-Swift-Cxx-Umbrella.hpp +60 -0
- package/nitrogen/generated/ios/OnramperReactNativeAutolinking.mm +41 -0
- package/nitrogen/generated/ios/OnramperReactNativeAutolinking.swift +38 -0
- package/nitrogen/generated/ios/c++/HybridOnramperCheckoutButtonSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridOnramperCheckoutButtonSpecSwift.hpp +81 -0
- package/nitrogen/generated/ios/c++/HybridOnramperNitroSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridOnramperNitroSpecSwift.hpp +150 -0
- package/nitrogen/generated/ios/c++/views/HybridOnramperCheckoutButtonComponent.mm +122 -0
- package/nitrogen/generated/ios/swift/Func_std__shared_ptr_Promise_std__shared_ptr_Promise_NitroSessionCredentials____.swift +61 -0
- package/nitrogen/generated/ios/swift/Func_void.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_NitroSessionCredentials.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PreparedIntentResult.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__shared_ptr_Promise_NitroSessionCredentials__.swift +66 -0
- package/nitrogen/generated/ios/swift/Func_void_std__string.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridOnramperCheckoutButtonSpec.swift +55 -0
- package/nitrogen/generated/ios/swift/HybridOnramperCheckoutButtonSpec_cxx.swift +156 -0
- package/nitrogen/generated/ios/swift/HybridOnramperNitroSpec.swift +63 -0
- package/nitrogen/generated/ios/swift/HybridOnramperNitroSpec_cxx.swift +309 -0
- package/nitrogen/generated/ios/swift/NitroSessionCredentials.swift +34 -0
- package/nitrogen/generated/ios/swift/OnramperNitroConfig.swift +49 -0
- package/nitrogen/generated/ios/swift/PreparedIntentResult.swift +34 -0
- package/nitrogen/generated/shared/c++/HybridOnramperCheckoutButtonSpec.cpp +22 -0
- package/nitrogen/generated/shared/c++/HybridOnramperCheckoutButtonSpec.hpp +63 -0
- package/nitrogen/generated/shared/c++/HybridOnramperNitroSpec.cpp +29 -0
- package/nitrogen/generated/shared/c++/HybridOnramperNitroSpec.hpp +80 -0
- package/nitrogen/generated/shared/c++/NitroSessionCredentials.hpp +87 -0
- package/nitrogen/generated/shared/c++/OnramperNitroConfig.hpp +99 -0
- package/nitrogen/generated/shared/c++/PreparedIntentResult.hpp +87 -0
- package/nitrogen/generated/shared/c++/views/HybridOnramperCheckoutButtonComponent.cpp +83 -0
- package/nitrogen/generated/shared/c++/views/HybridOnramperCheckoutButtonComponent.hpp +111 -0
- package/nitrogen/generated/shared/json/OnramperCheckoutButtonConfig.json +10 -0
- package/package.json +107 -0
- package/src/OnramperCheckoutButtonView.tsx +15 -0
- package/src/OnramperClient.ts +170 -0
- package/src/OnramperNative.ts +19 -0
- package/src/errors.ts +69 -0
- package/src/events.ts +23 -0
- package/src/generated/OnramperCheckoutButtonConfig.json +10 -0
- package/src/index.ts +30 -0
- package/src/specs/OnramperCheckoutButton.nitro.ts +16 -0
- package/src/specs/OnramperNitro.nitro.ts +60 -0
- package/src/types.ts +133 -0
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
import { type ReactElement, createElement } from 'react';
|
|
2
|
+
|
|
3
|
+
import { OnramperCheckoutButtonView } from './OnramperCheckoutButtonView';
|
|
4
|
+
import { createOnramperNative } from './OnramperNative';
|
|
5
|
+
import { OnramperError } from './errors';
|
|
6
|
+
import type { CheckoutEvent, EventName, EventPayload } from './events';
|
|
7
|
+
import type {
|
|
8
|
+
CheckoutButtonStyle,
|
|
9
|
+
CheckoutRequest,
|
|
10
|
+
OnramperConfiguration,
|
|
11
|
+
OnramperState,
|
|
12
|
+
QuoteResponse,
|
|
13
|
+
SessionCredentials,
|
|
14
|
+
} from './types';
|
|
15
|
+
|
|
16
|
+
export interface GetCheckoutRequirementsResult {
|
|
17
|
+
/** A native checkout button element to render. Tapping it drives login, finalize, and the payment webview internally. */
|
|
18
|
+
button: ReactElement;
|
|
19
|
+
/** The quote (rate, fees, payout) returned with the checkout intent. */
|
|
20
|
+
quote: QuoteResponse;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Typed, public entry point to the Onramper SDK. Wraps the native Nitro hybrid
|
|
25
|
+
* object: state and checkout events arrive as JSON strings over single native
|
|
26
|
+
* callbacks and are parsed here into the typed `OnramperState` / `CheckoutEvent`
|
|
27
|
+
* unions, then fanned out to any number of listeners.
|
|
28
|
+
*/
|
|
29
|
+
export class OnramperClient {
|
|
30
|
+
state: OnramperState = { kind: 'idle' };
|
|
31
|
+
lastError: OnramperError | null = null;
|
|
32
|
+
|
|
33
|
+
// Each client owns its own native instance (and thus its own SDK client).
|
|
34
|
+
private readonly native = createOnramperNative();
|
|
35
|
+
|
|
36
|
+
private readonly stateListeners = new Set<(state: OnramperState) => void>();
|
|
37
|
+
private readonly eventListeners = new Set<(event: CheckoutEvent) => void>();
|
|
38
|
+
|
|
39
|
+
// Resolved when the constructor-issued configure() completes. Public methods
|
|
40
|
+
// that need the native client await this first.
|
|
41
|
+
private readonly configured: Promise<void>;
|
|
42
|
+
|
|
43
|
+
constructor(config: OnramperConfiguration) {
|
|
44
|
+
// Single native state callback → update the mirror + fan out to listeners.
|
|
45
|
+
this.native.setStateListener((json) => {
|
|
46
|
+
const s = JSON.parse(json) as OnramperState;
|
|
47
|
+
this.state = s;
|
|
48
|
+
if (s.kind === 'failed') this.lastError = OnramperError.from(s.error);
|
|
49
|
+
for (const fn of this.stateListeners) fn(s);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
// Single native checkout-event callback → fan out to listeners.
|
|
53
|
+
this.native.setEventListener((json) => {
|
|
54
|
+
const e = JSON.parse(json) as CheckoutEvent;
|
|
55
|
+
for (const fn of this.eventListeners) fn(e);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
// The SDK calls this when its session expires; return fresh credentials.
|
|
59
|
+
// Nitro stores the async callback natively and awaits it directly — no
|
|
60
|
+
// event round-trip needed.
|
|
61
|
+
this.native.setSessionExpirationHandler(async () => {
|
|
62
|
+
const creds = await config.onSessionExpired();
|
|
63
|
+
return { sessionId: creds.sessionId, sessionToken: creds.sessionToken };
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
this.configured = this.native
|
|
67
|
+
.configure({
|
|
68
|
+
apiKey: config.apiKey,
|
|
69
|
+
clientId: config.clientId,
|
|
70
|
+
environment: config.environment,
|
|
71
|
+
theme: config.theme ?? 'system',
|
|
72
|
+
logLevel: config.logLevel ?? 'off',
|
|
73
|
+
})
|
|
74
|
+
.catch((e: unknown) => {
|
|
75
|
+
const err = OnramperError.from(e);
|
|
76
|
+
this.lastError = err;
|
|
77
|
+
throw err;
|
|
78
|
+
});
|
|
79
|
+
// Swallow the unhandled-rejection warning when no one awaits .configured
|
|
80
|
+
// before calling initialize(). The error still surfaces via initialize().
|
|
81
|
+
this.configured.catch(() => undefined);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
async initialize(creds: SessionCredentials): Promise<void> {
|
|
85
|
+
try {
|
|
86
|
+
await this.configured;
|
|
87
|
+
await this.native.initialize(creds.sessionId, creds.sessionToken);
|
|
88
|
+
} catch (e: unknown) {
|
|
89
|
+
throw OnramperError.from(e);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
async reset(): Promise<void> {
|
|
94
|
+
try {
|
|
95
|
+
await this.configured;
|
|
96
|
+
await this.native.reset();
|
|
97
|
+
} catch (e: unknown) {
|
|
98
|
+
throw OnramperError.from(e);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Signs the OnramperID user out by clearing stored OIDC tokens. The next
|
|
104
|
+
* checkout that requires user_info will re-trigger the login flow. Also
|
|
105
|
+
* resets in-flight checkout state. Does NOT clear the partner-scoped SDK
|
|
106
|
+
* session — re-calling `initialize` is only needed if that session expired.
|
|
107
|
+
*/
|
|
108
|
+
async signOut(): Promise<void> {
|
|
109
|
+
try {
|
|
110
|
+
await this.configured;
|
|
111
|
+
await this.native.signOut();
|
|
112
|
+
} catch (e: unknown) {
|
|
113
|
+
throw OnramperError.from(e);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Fetches checkout requirements + quote and returns a native checkout button
|
|
119
|
+
* to render plus the quote. The button handles login / finalize / webview
|
|
120
|
+
* internally; outcomes surface via the event stream (`addEventListener`).
|
|
121
|
+
*/
|
|
122
|
+
async getCheckoutRequirements(
|
|
123
|
+
request: CheckoutRequest,
|
|
124
|
+
buttonStyle: CheckoutButtonStyle = {},
|
|
125
|
+
): Promise<GetCheckoutRequirementsResult> {
|
|
126
|
+
try {
|
|
127
|
+
await this.configured;
|
|
128
|
+
const result = await this.native.getCheckoutRequirements(JSON.stringify(request), JSON.stringify(buttonStyle));
|
|
129
|
+
const quote = JSON.parse(result.quoteJson) as QuoteResponse;
|
|
130
|
+
const button = createElement(OnramperCheckoutButtonView, {
|
|
131
|
+
intentHandle: result.intentHandle,
|
|
132
|
+
style: { width: '100%', minHeight: 56 },
|
|
133
|
+
});
|
|
134
|
+
return { button, quote };
|
|
135
|
+
} catch (e: unknown) {
|
|
136
|
+
throw OnramperError.from(e);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/** Discards a prepared intent (e.g. if the user navigates away before checkout). */
|
|
141
|
+
cancelPreparedIntent(intentHandle: string): Promise<void> {
|
|
142
|
+
return this.native.cancelPreparedIntent(intentHandle);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/** Subscribe to state changes. Returns an unsubscribe function. */
|
|
146
|
+
addStateListener(fn: (state: OnramperState) => void): () => void {
|
|
147
|
+
this.stateListeners.add(fn);
|
|
148
|
+
return () => {
|
|
149
|
+
this.stateListeners.delete(fn);
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Subscribe to a specific checkout event. Returns an unsubscribe function. */
|
|
154
|
+
addEventListener<K extends EventName>(name: K, fn: (e: EventPayload<K>) => void): () => void {
|
|
155
|
+
const wrapper = (e: CheckoutEvent) => {
|
|
156
|
+
if (e.type === name) fn(e as EventPayload<K>);
|
|
157
|
+
};
|
|
158
|
+
this.eventListeners.add(wrapper);
|
|
159
|
+
return () => {
|
|
160
|
+
this.eventListeners.delete(wrapper);
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/** Tear down: clears JS listeners and releases the native callbacks + SDK client. */
|
|
165
|
+
destroy(): void {
|
|
166
|
+
this.stateListeners.clear();
|
|
167
|
+
this.eventListeners.clear();
|
|
168
|
+
this.native.dispose();
|
|
169
|
+
}
|
|
170
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Platform } from 'react-native';
|
|
2
|
+
import { NitroModules } from 'react-native-nitro-modules';
|
|
3
|
+
import type { OnramperNitro } from './specs/OnramperNitro.nitro';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Creates a fresh native Onramper Nitro hybrid object. Each `OnramperClient`
|
|
7
|
+
* owns its own instance, so its listeners and the underlying SDK client are
|
|
8
|
+
* isolated per client and torn down by `destroy()` → `dispose()`.
|
|
9
|
+
*/
|
|
10
|
+
export function createOnramperNative(): OnramperNitro {
|
|
11
|
+
// iOS-only in this release. Fail with a clear message rather than the opaque
|
|
12
|
+
// "hybrid object not found" Nitro would throw on platforms without a native impl.
|
|
13
|
+
if (Platform.OS !== 'ios') {
|
|
14
|
+
throw new Error(`Onramper React Native is iOS-only in this release; it is not supported on ${Platform.OS}.`);
|
|
15
|
+
}
|
|
16
|
+
return NitroModules.createHybridObject<OnramperNitro>('OnramperNitro');
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { OnramperNitro };
|
package/src/errors.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
export type OnramperErrorCode =
|
|
2
|
+
// Mirrors Sources/OnramperSDK/Errors/OnramperError.swift cases
|
|
3
|
+
| 'notInitialized'
|
|
4
|
+
| 'initializationFailed'
|
|
5
|
+
| 'attestationFailed'
|
|
6
|
+
| 'invalidStateTransition'
|
|
7
|
+
| 'invalidState'
|
|
8
|
+
| 'networkError'
|
|
9
|
+
| 'decodingError'
|
|
10
|
+
| 'timeout'
|
|
11
|
+
| 'requirementNotSatisfied'
|
|
12
|
+
| 'amountOutOfRange'
|
|
13
|
+
| 'oidcFlowCancelled'
|
|
14
|
+
| 'oidcTokenExchangeFailed'
|
|
15
|
+
| 'oidcFlowFailed'
|
|
16
|
+
| 'userTokenInvalid'
|
|
17
|
+
| 'userTokenRefreshFailed'
|
|
18
|
+
| 'webviewLoadFailed'
|
|
19
|
+
| 'deepLinkFailed'
|
|
20
|
+
| 'invalidRequest'
|
|
21
|
+
| 'quoteUnavailable'
|
|
22
|
+
| 'checkoutForbidden'
|
|
23
|
+
| 'temporaryFailure'
|
|
24
|
+
| 'unrecoverable'
|
|
25
|
+
| 'configurationError'
|
|
26
|
+
| 'deviceBlocked'
|
|
27
|
+
| 'securityStorageFailed'
|
|
28
|
+
| 'securityTrustFailed'
|
|
29
|
+
// JS-only codes
|
|
30
|
+
| 'platformUnsupported'
|
|
31
|
+
| 'intentInvalidated'
|
|
32
|
+
| 'intentAlreadyConsumed'
|
|
33
|
+
| 'clientAlreadyConfigured'
|
|
34
|
+
| 'sessionExpirationHandlerFailed';
|
|
35
|
+
|
|
36
|
+
export interface OnramperErrorPayload {
|
|
37
|
+
code: OnramperErrorCode;
|
|
38
|
+
message: string;
|
|
39
|
+
info?: Record<string, unknown>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export class OnramperError extends Error implements OnramperErrorPayload {
|
|
43
|
+
readonly code: OnramperErrorCode;
|
|
44
|
+
readonly info?: Record<string, unknown>;
|
|
45
|
+
|
|
46
|
+
constructor(payload: OnramperErrorPayload) {
|
|
47
|
+
super(payload.message);
|
|
48
|
+
this.name = 'OnramperError';
|
|
49
|
+
this.code = payload.code;
|
|
50
|
+
this.info = payload.info;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
static from(value: unknown): OnramperError {
|
|
54
|
+
if (value instanceof OnramperError) return value;
|
|
55
|
+
if (value && typeof value === 'object') {
|
|
56
|
+
// Structured errors (from the `.failed` state) arrive as a plain
|
|
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> };
|
|
61
|
+
return new OnramperError({
|
|
62
|
+
code: (v.code ?? 'unrecoverable') as OnramperErrorCode,
|
|
63
|
+
message: v.message ?? 'Unknown error',
|
|
64
|
+
info: v.info,
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
return new OnramperError({ code: 'unrecoverable', message: String(value) });
|
|
68
|
+
}
|
|
69
|
+
}
|
package/src/events.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { OnramperErrorPayload } from './errors';
|
|
2
|
+
import type { CheckoutFinalizeResponse, CheckoutRequirement, OnramperState, RenderType } from './types';
|
|
3
|
+
|
|
4
|
+
export type CheckoutEvent =
|
|
5
|
+
| { type: 'stateChanged'; state: OnramperState }
|
|
6
|
+
| { type: 'checkoutStarted'; intentId: string }
|
|
7
|
+
| { type: 'loginRequired'; requirements: CheckoutRequirement[] }
|
|
8
|
+
| { type: 'readyToCheckout' }
|
|
9
|
+
| { type: 'requirementSatisfied'; requirementType: string }
|
|
10
|
+
| { type: 'checkoutFinalized'; response: CheckoutFinalizeResponse }
|
|
11
|
+
| { type: 'renderingStarted'; url: string; renderType: RenderType }
|
|
12
|
+
| { type: 'completed'; checkoutId: string }
|
|
13
|
+
| { type: 'failed'; error: OnramperErrorPayload }
|
|
14
|
+
| { type: 'cancelled' }
|
|
15
|
+
// Provider-lifecycle events from third-party checkout webviews.
|
|
16
|
+
| { type: 'providerReady' }
|
|
17
|
+
| { type: 'paymentAuthorized' }
|
|
18
|
+
| { type: 'paymentProcessing' }
|
|
19
|
+
| { type: 'paymentCancelled' }
|
|
20
|
+
| { type: 'providerError'; reason: string };
|
|
21
|
+
|
|
22
|
+
export type EventName = CheckoutEvent['type'];
|
|
23
|
+
export type EventPayload<K extends EventName> = Extract<CheckoutEvent, { type: K }>;
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// Public API re-exports.
|
|
2
|
+
|
|
3
|
+
export { OnramperClient } from './OnramperClient';
|
|
4
|
+
export type { GetCheckoutRequirementsResult } from './OnramperClient';
|
|
5
|
+
export { OnramperCheckoutButtonView } from './OnramperCheckoutButtonView';
|
|
6
|
+
export type { OnramperCheckoutButtonViewProps } from './OnramperCheckoutButtonView';
|
|
7
|
+
export { OnramperError } from './errors';
|
|
8
|
+
export type { OnramperErrorCode, OnramperErrorPayload } from './errors';
|
|
9
|
+
export type {
|
|
10
|
+
CheckoutButtonStyle,
|
|
11
|
+
CheckoutFinalizeResponse,
|
|
12
|
+
CheckoutRequest,
|
|
13
|
+
CheckoutPaymentType,
|
|
14
|
+
CheckoutRequirement,
|
|
15
|
+
HeadlessCheckoutData,
|
|
16
|
+
OnramperConfiguration,
|
|
17
|
+
OnramperEnvironment,
|
|
18
|
+
OnramperLogLevel,
|
|
19
|
+
OnramperState,
|
|
20
|
+
OnramperTheme,
|
|
21
|
+
QuoteError,
|
|
22
|
+
QuoteResponse,
|
|
23
|
+
RenderType,
|
|
24
|
+
SessionCredentials,
|
|
25
|
+
ToSItem,
|
|
26
|
+
TransactionType,
|
|
27
|
+
UserInfoField,
|
|
28
|
+
WalletInfo,
|
|
29
|
+
} from './types';
|
|
30
|
+
export type { CheckoutEvent, EventName, EventPayload } from './events';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { HybridView, HybridViewMethods, HybridViewProps } from 'react-native-nitro-modules';
|
|
2
|
+
|
|
3
|
+
// The native checkout button. Renders the SwiftUI OnramperCheckoutButton that
|
|
4
|
+
// getCheckoutRequirements() stashed under `intentHandle`, hosted via
|
|
5
|
+
// UIHostingController. iOS-only (Android is a platformUnsupported stub).
|
|
6
|
+
export interface OnramperCheckoutButtonProps extends HybridViewProps {
|
|
7
|
+
intentHandle: string;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface OnramperCheckoutButtonMethods extends HybridViewMethods {}
|
|
11
|
+
|
|
12
|
+
export type OnramperCheckoutButton = HybridView<
|
|
13
|
+
OnramperCheckoutButtonProps,
|
|
14
|
+
OnramperCheckoutButtonMethods,
|
|
15
|
+
{ ios: 'swift' }
|
|
16
|
+
>;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import type { HybridObject } from 'react-native-nitro-modules';
|
|
2
|
+
|
|
3
|
+
// Plain config passed to configure(). String unions are validated on the Swift
|
|
4
|
+
// side against the SDK's Environment/Theme/LogLevel enums.
|
|
5
|
+
export interface OnramperNitroConfig {
|
|
6
|
+
apiKey: string;
|
|
7
|
+
clientId: string;
|
|
8
|
+
environment: string; // 'development' | 'production'
|
|
9
|
+
theme: string; // 'system' | 'light' | 'dark'
|
|
10
|
+
logLevel: string; // 'off' | 'error' | 'info' | 'debug'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Mirrors OnramperSDK.SessionCredentials. Named with a Nitro prefix to avoid a
|
|
14
|
+
// Swift type clash with the SDK's own `SessionCredentials`.
|
|
15
|
+
export interface NitroSessionCredentials {
|
|
16
|
+
sessionId: string;
|
|
17
|
+
sessionToken: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Result of getCheckoutRequirements: a handle the OnramperCheckoutButton view
|
|
21
|
+
// renders by, plus the quote (JSON-encoded QuoteResponse, parsed in JS).
|
|
22
|
+
export interface PreparedIntentResult {
|
|
23
|
+
intentHandle: string;
|
|
24
|
+
quoteJson: string;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Native bridge to OnramperSDK's `OnramperClient`. The public, typed JS API
|
|
29
|
+
* (`OnramperClient`) wraps this.
|
|
30
|
+
*
|
|
31
|
+
* State and checkout events are delivered as JSON strings (the SDK's
|
|
32
|
+
* `OnramperState`/`CheckoutEvent` are non-Codable Swift enums; the Swift side
|
|
33
|
+
* hand-maps each case to a dict and JSON-encodes it). The JS wrapper parses
|
|
34
|
+
* them back into the fully-typed `OnramperState`/`CheckoutEvent` unions.
|
|
35
|
+
*/
|
|
36
|
+
export interface OnramperNitro extends HybridObject<{ ios: 'swift' }> {
|
|
37
|
+
configure(config: OnramperNitroConfig): Promise<void>;
|
|
38
|
+
initialize(sessionId: string, sessionToken: string): Promise<void>;
|
|
39
|
+
reset(): Promise<void>;
|
|
40
|
+
signOut(): Promise<void>;
|
|
41
|
+
|
|
42
|
+
// Fetches checkout requirements + quote, stores the SDK's SwiftUI checkout
|
|
43
|
+
// button under a handle, and returns the handle + JSON-encoded quote. The
|
|
44
|
+
// OnramperCheckoutButton Nitro view renders the stored button by handle.
|
|
45
|
+
// `requestJson` is a JSON CheckoutRequest; `styleJson` a JSON CheckoutButtonStyle.
|
|
46
|
+
getCheckoutRequirements(requestJson: string, styleJson: string): Promise<PreparedIntentResult>;
|
|
47
|
+
cancelPreparedIntent(intentHandle: string): Promise<void>;
|
|
48
|
+
|
|
49
|
+
// Single native callback per stream; the JS wrapper fans out to multiple listeners.
|
|
50
|
+
setStateListener(onState: (stateJson: string) => void): void;
|
|
51
|
+
setEventListener(onEvent: (eventJson: string) => void): void;
|
|
52
|
+
|
|
53
|
+
// The SDK's sessionExpirationHandler, as a stored async callback that returns
|
|
54
|
+
// fresh credentials. Replaces the Expo-era onSessionExpired/provide/fail dance.
|
|
55
|
+
setSessionExpirationHandler(handler: () => Promise<NitroSessionCredentials>): void;
|
|
56
|
+
|
|
57
|
+
// NOTE: every HybridObject has a built-in `dispose()`; we override it natively
|
|
58
|
+
// (in HybridOnramperNitro.swift) to release stored callbacks + the SDK client.
|
|
59
|
+
// It must NOT be declared here — nitrogen rejects re-declaring dispose().
|
|
60
|
+
}
|
package/src/types.ts
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
// Mirrors Swift Codable structs in OnramperSDK. Source of truth is the Swift SDK
|
|
2
|
+
// at the bundled version. Do not add fields that don't exist there.
|
|
3
|
+
|
|
4
|
+
import type { OnramperErrorPayload } from './errors';
|
|
5
|
+
|
|
6
|
+
export type OnramperEnvironment = 'development' | 'production';
|
|
7
|
+
export type OnramperLogLevel = 'off' | 'error' | 'info' | 'debug';
|
|
8
|
+
export type OnramperTheme = 'system' | 'light' | 'dark';
|
|
9
|
+
|
|
10
|
+
export type TransactionType = 'buy' | 'sell';
|
|
11
|
+
|
|
12
|
+
export interface SessionCredentials {
|
|
13
|
+
sessionId: string;
|
|
14
|
+
sessionToken: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface OnramperConfiguration {
|
|
18
|
+
apiKey: string;
|
|
19
|
+
clientId: string;
|
|
20
|
+
environment: OnramperEnvironment;
|
|
21
|
+
theme?: OnramperTheme;
|
|
22
|
+
logLevel?: OnramperLogLevel;
|
|
23
|
+
/**
|
|
24
|
+
* Called by the SDK when the session token expires and needs to be re-issued.
|
|
25
|
+
*
|
|
26
|
+
* May be synchronous or async — under the hood the bridge uses an event
|
|
27
|
+
* round-trip (`onSessionExpired` → `provideSessionCredentials`) so Promises
|
|
28
|
+
* are awaited normally. Throw or reject to signal that no fresh credentials
|
|
29
|
+
* are available; the SDK will surface `userTokenRefreshFailed`.
|
|
30
|
+
*/
|
|
31
|
+
onSessionExpired: () => SessionCredentials | Promise<SessionCredentials>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export interface WalletInfo {
|
|
35
|
+
network: string;
|
|
36
|
+
address: string;
|
|
37
|
+
memo?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Flattened from the Swift nesting (CheckoutIntentRequest → OnramperTransactionData).
|
|
41
|
+
// The bridge re-nests before handing to the SDK. ISO codes (`source`, `destination`,
|
|
42
|
+
// `country`, `subdivision`) are lowercased by the SDK; pass either case.
|
|
43
|
+
export interface CheckoutRequest {
|
|
44
|
+
source: string;
|
|
45
|
+
destination?: string;
|
|
46
|
+
amount: number;
|
|
47
|
+
type: TransactionType;
|
|
48
|
+
country?: string;
|
|
49
|
+
subdivision?: string;
|
|
50
|
+
paymentMethod: string;
|
|
51
|
+
wallet: WalletInfo;
|
|
52
|
+
onlyOnramps?: string[];
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// Mirrors Swift QuoteResponse exactly — all fields optional because the BFF
|
|
56
|
+
// can return a partial quote with `errors` populated when the onramp can't
|
|
57
|
+
// honor the request. Integrators must handle nulls.
|
|
58
|
+
export interface QuoteResponse {
|
|
59
|
+
quoteId?: string;
|
|
60
|
+
ramp?: string;
|
|
61
|
+
rate?: number;
|
|
62
|
+
networkFee?: number;
|
|
63
|
+
transactionFee?: number;
|
|
64
|
+
payout?: number;
|
|
65
|
+
paymentMethod?: string;
|
|
66
|
+
recommendations?: string[];
|
|
67
|
+
errors?: QuoteError[];
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export interface QuoteError {
|
|
71
|
+
type: string;
|
|
72
|
+
message: string;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export interface CheckoutButtonStyle {
|
|
76
|
+
backgroundColor?: string; // hex #RRGGBB or #RRGGBBAA
|
|
77
|
+
foregroundColor?: string;
|
|
78
|
+
borderRadius?: number;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// Mirrors Swift `RenderType` raw values from Models/SharedTypes.swift.
|
|
82
|
+
export type RenderType = 'webview' | 'deeplink';
|
|
83
|
+
// Mirrors Swift `CheckoutPaymentType` raw values from Models/SharedTypes.swift.
|
|
84
|
+
export type CheckoutPaymentType = 'applepay' | 'revolutpay';
|
|
85
|
+
|
|
86
|
+
// Mirrors Swift `CheckoutFinalizeResponse` / `HeadlessCheckoutData`
|
|
87
|
+
// (Sources/OnramperSDK/Models/CheckoutFinalizeResponse.swift).
|
|
88
|
+
export interface HeadlessCheckoutData {
|
|
89
|
+
checkoutPaymentType: CheckoutPaymentType;
|
|
90
|
+
url: string;
|
|
91
|
+
renderType: RenderType;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface CheckoutFinalizeResponse {
|
|
95
|
+
headlessCheckoutId: string;
|
|
96
|
+
headlessCheckoutData: HeadlessCheckoutData;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// Checkout requirements surfaced by the BFF and bridged through JSON.
|
|
100
|
+
// Shape mirrors Sources/OnramperSDK/Models/CheckoutIntentResponse.swift.
|
|
101
|
+
export type CheckoutRequirement =
|
|
102
|
+
| { type: 'tos'; providerId: string; items: ToSItem[] }
|
|
103
|
+
| { type: 'amount_limit'; providerId: string; minAmountLimit?: number; maxAmountLimit?: number }
|
|
104
|
+
| { type: 'user_info'; providerId: string; fields: UserInfoField[] };
|
|
105
|
+
|
|
106
|
+
export interface ToSItem {
|
|
107
|
+
type: 'tos' | 'privacy_policy' | 'user_agreement';
|
|
108
|
+
required: boolean;
|
|
109
|
+
satisfied: boolean;
|
|
110
|
+
url?: string;
|
|
111
|
+
content?: string;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export interface UserInfoField {
|
|
115
|
+
type: string; // backend can extend; safer to leave open
|
|
116
|
+
required: boolean;
|
|
117
|
+
// other fields omitted for v1 — extend later if needed
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
export type OnramperState =
|
|
121
|
+
| { kind: 'idle' }
|
|
122
|
+
| { kind: 'initializing' }
|
|
123
|
+
| { kind: 'ready' }
|
|
124
|
+
| { kind: 'checkoutPreparing' }
|
|
125
|
+
| { kind: 'requireLogin'; requirements: CheckoutRequirement[] }
|
|
126
|
+
| { kind: 'authenticating' }
|
|
127
|
+
| { kind: 'readyToCheckout' }
|
|
128
|
+
| { kind: 'finalizing' }
|
|
129
|
+
| { kind: 'rendering'; url: string; renderType: RenderType; paymentType: CheckoutPaymentType }
|
|
130
|
+
| { kind: 'completed' }
|
|
131
|
+
| { kind: 'failed'; error: OnramperErrorPayload };
|
|
132
|
+
|
|
133
|
+
export type { OnramperErrorPayload };
|