@swype-org/deposit-mobile 0.2.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/README.md +450 -0
- package/dist/chunk-QIPX2XQS.js +481 -0
- package/dist/chunk-QIPX2XQS.js.map +1 -0
- package/dist/index.cjs +495 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +139 -0
- package/dist/index.d.ts +139 -0
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -0
- package/dist/react-native.cjs +531 -0
- package/dist/react-native.cjs.map +1 -0
- package/dist/react-native.d.cts +70 -0
- package/dist/react-native.d.ts +70 -0
- package/dist/react-native.js +49 -0
- package/dist/react-native.js.map +1 -0
- package/dist/types-Df_KwICF.d.cts +179 -0
- package/dist/types-Df_KwICF.d.ts +179 -0
- package/package.json +67 -0
|
@@ -0,0 +1,531 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
|
|
5
|
+
// src/react-native.ts
|
|
6
|
+
|
|
7
|
+
// src/deep-link.ts
|
|
8
|
+
var DEFAULT_CALLBACK_PATH = "/swype/callback";
|
|
9
|
+
function isSwypeCallback(url, callbackScheme, callbackPath) {
|
|
10
|
+
const path = callbackPath ?? DEFAULT_CALLBACK_PATH;
|
|
11
|
+
const prefix = `${callbackScheme}://${path}`.replace(/^([^:]+):\/\/\//, "$1://");
|
|
12
|
+
const normalised = url.replace(/^([^:]+):\/\/\//, "$1://");
|
|
13
|
+
return normalised.startsWith(prefix);
|
|
14
|
+
}
|
|
15
|
+
function parseDeepLink(url, callbackScheme, callbackPath) {
|
|
16
|
+
if (!isSwypeCallback(url, callbackScheme, callbackPath)) {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const queryStart = url.indexOf("?");
|
|
20
|
+
if (queryStart === -1) {
|
|
21
|
+
return null;
|
|
22
|
+
}
|
|
23
|
+
const params = new URLSearchParams(url.slice(queryStart + 1));
|
|
24
|
+
const transferId = params.get("transferId");
|
|
25
|
+
const transferStatus = params.get("transferStatus");
|
|
26
|
+
if (!transferId || !transferStatus) {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
const result = { transferId, transferStatus };
|
|
30
|
+
const amount = params.get("amount");
|
|
31
|
+
if (amount != null) result.amount = Number(amount);
|
|
32
|
+
const currency = params.get("currency");
|
|
33
|
+
if (currency != null) result.currency = currency;
|
|
34
|
+
const chainId = params.get("chainId");
|
|
35
|
+
if (chainId != null) result.chainId = chainId;
|
|
36
|
+
const address = params.get("address");
|
|
37
|
+
if (address != null) result.address = address;
|
|
38
|
+
const token = params.get("token");
|
|
39
|
+
if (token != null) result.token = token;
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
function toTransferSummary(result) {
|
|
43
|
+
const summary = {
|
|
44
|
+
id: result.transferId,
|
|
45
|
+
status: result.transferStatus
|
|
46
|
+
};
|
|
47
|
+
if (result.amount != null && result.currency != null) {
|
|
48
|
+
summary.amount = {
|
|
49
|
+
amount: result.amount,
|
|
50
|
+
currency: result.currency
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (result.chainId != null && result.address != null) {
|
|
54
|
+
summary.destinations = [
|
|
55
|
+
{
|
|
56
|
+
chainId: result.chainId,
|
|
57
|
+
address: result.address,
|
|
58
|
+
token: result.token ? { address: result.token } : void 0
|
|
59
|
+
}
|
|
60
|
+
];
|
|
61
|
+
}
|
|
62
|
+
return summary;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// src/errors.ts
|
|
66
|
+
var DepositError = class extends Error {
|
|
67
|
+
code;
|
|
68
|
+
constructor(code, message) {
|
|
69
|
+
super(message);
|
|
70
|
+
this.name = "DepositError";
|
|
71
|
+
this.code = code;
|
|
72
|
+
}
|
|
73
|
+
};
|
|
74
|
+
var DISPLAY_MESSAGES = {
|
|
75
|
+
BROWSER_FAILED: "Unable to open the payment browser. Please try again.",
|
|
76
|
+
BROWSER_DISMISSED: "The payment browser was closed before the transfer completed.",
|
|
77
|
+
DEEP_LINK_INVALID: "The payment callback was malformed. Please try again.",
|
|
78
|
+
SIGNER_REQUEST_FAILED: "Unable to start the payment. Please try again.",
|
|
79
|
+
SIGNER_NETWORK_ERROR: "Unable to reach the payment server. Check your connection and try again.",
|
|
80
|
+
SIGNER_RESPONSE_INVALID: "The payment server returned an unexpected response.",
|
|
81
|
+
SIGNER_TIMEOUT: "The payment server took too long to respond. Please try again.",
|
|
82
|
+
FLOW_TIMEOUT: "The payment flow timed out. Please try again.",
|
|
83
|
+
INVALID_REQUEST: "Invalid payment request. Please check your input."
|
|
84
|
+
};
|
|
85
|
+
function getDisplayMessage(error) {
|
|
86
|
+
return DISPLAY_MESSAGES[error.code] ?? error.message;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// src/signer.ts
|
|
90
|
+
var DEFAULT_SIGNER_TIMEOUT_MS = 15e3;
|
|
91
|
+
async function callSigner(signer, request, timeoutMs) {
|
|
92
|
+
const timeout = timeoutMs ?? DEFAULT_SIGNER_TIMEOUT_MS;
|
|
93
|
+
const body = typeof signer === "function" ? await invokeSignerFunction(signer, request, timeout) : await invokeSignerUrl(signer, request, timeout);
|
|
94
|
+
validateSignerResponse(body);
|
|
95
|
+
return body;
|
|
96
|
+
}
|
|
97
|
+
async function invokeSignerUrl(signerUrl, request, timeoutMs) {
|
|
98
|
+
let response;
|
|
99
|
+
const controller = new AbortController();
|
|
100
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
101
|
+
try {
|
|
102
|
+
response = await fetch(signerUrl, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: { "Content-Type": "application/json" },
|
|
105
|
+
body: JSON.stringify(request),
|
|
106
|
+
signal: controller.signal
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
if (controller.signal.aborted) {
|
|
110
|
+
throw new DepositError(
|
|
111
|
+
"SIGNER_TIMEOUT",
|
|
112
|
+
`Signer did not respond within ${timeoutMs}ms.`
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
throw new DepositError(
|
|
116
|
+
"SIGNER_NETWORK_ERROR",
|
|
117
|
+
"Unable to reach the merchant signer. Check the signer URL and network connectivity."
|
|
118
|
+
);
|
|
119
|
+
} finally {
|
|
120
|
+
clearTimeout(timer);
|
|
121
|
+
}
|
|
122
|
+
const body = await response.json().catch(() => null);
|
|
123
|
+
if (!response.ok) {
|
|
124
|
+
const detail = body?.error ?? `Signer returned HTTP ${response.status}.`;
|
|
125
|
+
throw new DepositError("SIGNER_REQUEST_FAILED", detail);
|
|
126
|
+
}
|
|
127
|
+
return body;
|
|
128
|
+
}
|
|
129
|
+
async function invokeSignerFunction(signer, request, timeoutMs) {
|
|
130
|
+
return new Promise((resolve, reject) => {
|
|
131
|
+
const timer = setTimeout(
|
|
132
|
+
() => reject(new DepositError("SIGNER_TIMEOUT", `Signer did not respond within ${timeoutMs}ms.`)),
|
|
133
|
+
timeoutMs
|
|
134
|
+
);
|
|
135
|
+
signer(request).then(
|
|
136
|
+
(result) => {
|
|
137
|
+
clearTimeout(timer);
|
|
138
|
+
resolve(result);
|
|
139
|
+
},
|
|
140
|
+
(err) => {
|
|
141
|
+
clearTimeout(timer);
|
|
142
|
+
if (err instanceof DepositError) {
|
|
143
|
+
reject(err);
|
|
144
|
+
} else {
|
|
145
|
+
reject(new DepositError(
|
|
146
|
+
"SIGNER_REQUEST_FAILED",
|
|
147
|
+
err instanceof Error ? err.message : "Signer function threw an error."
|
|
148
|
+
));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
);
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
function validateSignerResponse(body) {
|
|
155
|
+
const obj = body;
|
|
156
|
+
if (!obj || typeof obj.merchantId !== "string" || typeof obj.payload !== "string" || typeof obj.signature !== "string" || !obj.preview || typeof obj.preview !== "object") {
|
|
157
|
+
throw new DepositError(
|
|
158
|
+
"SIGNER_RESPONSE_INVALID",
|
|
159
|
+
"Signer response is missing required fields (merchantId, payload, signature, preview)."
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// src/validation.ts
|
|
165
|
+
var EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;
|
|
166
|
+
var TOKEN_ADDRESS_RE = /^0x[a-fA-F0-9]{1,40}$/;
|
|
167
|
+
function validateDepositRequest(request) {
|
|
168
|
+
if (!Number.isFinite(request.amount) || request.amount <= 0) {
|
|
169
|
+
throw new DepositError("INVALID_REQUEST", "amount must be a positive number.");
|
|
170
|
+
}
|
|
171
|
+
if (!Number.isInteger(request.chainId) || request.chainId <= 0) {
|
|
172
|
+
throw new DepositError("INVALID_REQUEST", "chainId must be a positive integer.");
|
|
173
|
+
}
|
|
174
|
+
if (!EVM_ADDRESS_RE.test(request.address)) {
|
|
175
|
+
throw new DepositError(
|
|
176
|
+
"INVALID_REQUEST",
|
|
177
|
+
"address must be a 0x-prefixed, 40-character hex string."
|
|
178
|
+
);
|
|
179
|
+
}
|
|
180
|
+
if (typeof request.token !== "string" || !TOKEN_ADDRESS_RE.test(request.token)) {
|
|
181
|
+
throw new DepositError("INVALID_REQUEST", "token must be a 0x-prefixed hex address.");
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
function buildSignerRequest(request, callbackScheme, webviewBaseUrl) {
|
|
185
|
+
const base = {
|
|
186
|
+
amount: request.amount,
|
|
187
|
+
chainId: request.chainId,
|
|
188
|
+
address: request.address,
|
|
189
|
+
token: request.token,
|
|
190
|
+
callbackScheme,
|
|
191
|
+
url: webviewBaseUrl,
|
|
192
|
+
version: "v1"
|
|
193
|
+
};
|
|
194
|
+
if (request.reference) base.reference = request.reference;
|
|
195
|
+
if (request.metadata && Object.keys(request.metadata).length > 0) {
|
|
196
|
+
base.metadata = request.metadata;
|
|
197
|
+
}
|
|
198
|
+
return base;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
// src/mobile-deposit.ts
|
|
202
|
+
var DEFAULT_WEBVIEW_BASE_URL = "https://pay-staging.tryblink.xyz";
|
|
203
|
+
var MobileDeposit = class {
|
|
204
|
+
config;
|
|
205
|
+
requestId = 0;
|
|
206
|
+
destroyed = false;
|
|
207
|
+
_status = "idle";
|
|
208
|
+
_result = null;
|
|
209
|
+
_error = null;
|
|
210
|
+
flowTimer = null;
|
|
211
|
+
lastSignerResponse = null;
|
|
212
|
+
pendingResolve = null;
|
|
213
|
+
pendingReject = null;
|
|
214
|
+
pendingRequestId = null;
|
|
215
|
+
listeners = {
|
|
216
|
+
complete: /* @__PURE__ */ new Set(),
|
|
217
|
+
error: /* @__PURE__ */ new Set(),
|
|
218
|
+
dismiss: /* @__PURE__ */ new Set(),
|
|
219
|
+
"status-change": /* @__PURE__ */ new Set()
|
|
220
|
+
};
|
|
221
|
+
/** Current phase of the deposit flow. */
|
|
222
|
+
get status() {
|
|
223
|
+
return this._status;
|
|
224
|
+
}
|
|
225
|
+
/** Last successful {@link DepositResult}, available when `status === 'completed'`. */
|
|
226
|
+
get result() {
|
|
227
|
+
return this._result;
|
|
228
|
+
}
|
|
229
|
+
/** Last {@link DepositError}, available when `status === 'error'`. */
|
|
230
|
+
get error() {
|
|
231
|
+
return this._error;
|
|
232
|
+
}
|
|
233
|
+
/** Whether a deposit flow is currently in progress. */
|
|
234
|
+
get isActive() {
|
|
235
|
+
return this._status === "signer-loading" || this._status === "browser-active";
|
|
236
|
+
}
|
|
237
|
+
constructor(config) {
|
|
238
|
+
if (!config.signer || typeof config.signer !== "string" && typeof config.signer !== "function") {
|
|
239
|
+
throw new DepositError("INVALID_REQUEST", "MobileDepositConfig.signer is required (URL string or SignerFunction).");
|
|
240
|
+
}
|
|
241
|
+
if (!config.callbackScheme || typeof config.callbackScheme !== "string") {
|
|
242
|
+
throw new DepositError("INVALID_REQUEST", "MobileDepositConfig.callbackScheme is required.");
|
|
243
|
+
}
|
|
244
|
+
if (typeof config.openUrl !== "function") {
|
|
245
|
+
throw new DepositError("INVALID_REQUEST", "MobileDepositConfig.openUrl must be a function.");
|
|
246
|
+
}
|
|
247
|
+
this.config = config;
|
|
248
|
+
this.log("MobileDeposit instance created", {
|
|
249
|
+
signer: typeof config.signer === "string" ? config.signer : "<function>",
|
|
250
|
+
callbackScheme: config.callbackScheme
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Open the hosted payment flow for the given deposit.
|
|
255
|
+
*
|
|
256
|
+
* The returned Promise resolves when the user completes the payment (via
|
|
257
|
+
* deep link callback) and rejects with a {@link DepositError} on failure.
|
|
258
|
+
*
|
|
259
|
+
* The merchant must listen for incoming deep links and pass them to
|
|
260
|
+
* {@link handleDeepLink} for the promise to resolve.
|
|
261
|
+
*/
|
|
262
|
+
requestDeposit(request) {
|
|
263
|
+
if (this.destroyed) {
|
|
264
|
+
return Promise.reject(
|
|
265
|
+
new DepositError("INVALID_REQUEST", "This MobileDeposit instance has been destroyed.")
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
validateDepositRequest(request);
|
|
269
|
+
this.log("requestDeposit called", { amount: request.amount, token: request.token, chainId: request.chainId });
|
|
270
|
+
this.requestId += 1;
|
|
271
|
+
const currentRequestId = this.requestId;
|
|
272
|
+
this.cleanup();
|
|
273
|
+
this._result = null;
|
|
274
|
+
this._error = null;
|
|
275
|
+
this.setStatus("signer-loading");
|
|
276
|
+
return new Promise((resolve, reject) => {
|
|
277
|
+
const settle = (fn) => {
|
|
278
|
+
if (this.requestId !== currentRequestId) return;
|
|
279
|
+
fn();
|
|
280
|
+
};
|
|
281
|
+
const onComplete = (result) => {
|
|
282
|
+
settle(() => {
|
|
283
|
+
this.cleanup();
|
|
284
|
+
this._result = result;
|
|
285
|
+
this._error = null;
|
|
286
|
+
this.setStatus("completed");
|
|
287
|
+
this.emit("complete", result);
|
|
288
|
+
resolve(result);
|
|
289
|
+
});
|
|
290
|
+
};
|
|
291
|
+
const onError = (error) => {
|
|
292
|
+
settle(() => {
|
|
293
|
+
this.cleanup();
|
|
294
|
+
this._error = error;
|
|
295
|
+
this.setStatus("error");
|
|
296
|
+
this.emit("error", error);
|
|
297
|
+
reject(error);
|
|
298
|
+
});
|
|
299
|
+
};
|
|
300
|
+
this.pendingResolve = onComplete;
|
|
301
|
+
this.pendingReject = onError;
|
|
302
|
+
this.pendingRequestId = currentRequestId;
|
|
303
|
+
if (this.config.flowTimeoutMs != null && this.config.flowTimeoutMs > 0) {
|
|
304
|
+
this.flowTimer = setTimeout(() => {
|
|
305
|
+
onError(
|
|
306
|
+
new DepositError(
|
|
307
|
+
"FLOW_TIMEOUT",
|
|
308
|
+
`The payment flow did not complete within ${this.config.flowTimeoutMs}ms.`
|
|
309
|
+
)
|
|
310
|
+
);
|
|
311
|
+
}, this.config.flowTimeoutMs);
|
|
312
|
+
}
|
|
313
|
+
this.runSignerFlow(request, currentRequestId, onError);
|
|
314
|
+
});
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Feed an incoming deep link URL to the SDK.
|
|
318
|
+
*
|
|
319
|
+
* Returns `true` if the URL was a valid Swype callback and the SDK handled
|
|
320
|
+
* it. Returns `false` if the URL did not match the expected callback pattern
|
|
321
|
+
* (the merchant should handle it themselves).
|
|
322
|
+
*
|
|
323
|
+
* Typically called from `Linking.addEventListener('url', ...)` or the
|
|
324
|
+
* equivalent deep link handler on the platform.
|
|
325
|
+
*/
|
|
326
|
+
handleDeepLink(url) {
|
|
327
|
+
this.log("handleDeepLink called", { url });
|
|
328
|
+
const parsed = parseDeepLink(
|
|
329
|
+
url,
|
|
330
|
+
this.config.callbackScheme,
|
|
331
|
+
this.config.callbackPath
|
|
332
|
+
);
|
|
333
|
+
if (!parsed) {
|
|
334
|
+
this.log("URL does not match expected callback pattern");
|
|
335
|
+
return false;
|
|
336
|
+
}
|
|
337
|
+
if (!this.pendingResolve) {
|
|
338
|
+
this.log("Received callback but no pending request");
|
|
339
|
+
return true;
|
|
340
|
+
}
|
|
341
|
+
const transfer = toTransferSummary(parsed);
|
|
342
|
+
this.log("Deep link parsed", { transferId: transfer.id, status: transfer.status });
|
|
343
|
+
const depositResult = { transfer };
|
|
344
|
+
if (this.lastSignerResponse?.preview) {
|
|
345
|
+
depositResult.idempotencyKey = this.lastSignerResponse.preview.idempotencyKey;
|
|
346
|
+
depositResult.preview = {
|
|
347
|
+
amount: this.lastSignerResponse.preview.amount,
|
|
348
|
+
chainId: this.lastSignerResponse.preview.chainId,
|
|
349
|
+
address: this.lastSignerResponse.preview.address,
|
|
350
|
+
token: this.lastSignerResponse.preview.token
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
this.pendingResolve(depositResult);
|
|
354
|
+
return true;
|
|
355
|
+
}
|
|
356
|
+
/** Register an event listener. */
|
|
357
|
+
on(event, handler) {
|
|
358
|
+
this.listeners[event].add(handler);
|
|
359
|
+
return this;
|
|
360
|
+
}
|
|
361
|
+
/** Remove a previously registered event listener. */
|
|
362
|
+
off(event, handler) {
|
|
363
|
+
this.listeners[event].delete(handler);
|
|
364
|
+
return this;
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Cancel the current flow. Rejects the pending promise with
|
|
368
|
+
* `BROWSER_DISMISSED` and resets to idle.
|
|
369
|
+
*/
|
|
370
|
+
close() {
|
|
371
|
+
this.log("close() called");
|
|
372
|
+
const reject = this.pendingReject;
|
|
373
|
+
this.cleanup();
|
|
374
|
+
this.setStatus("idle");
|
|
375
|
+
this.emit("dismiss");
|
|
376
|
+
if (reject) {
|
|
377
|
+
reject(
|
|
378
|
+
new DepositError("BROWSER_DISMISSED", "The payment flow was cancelled.")
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
/** Tear down the instance and release all resources. */
|
|
383
|
+
destroy() {
|
|
384
|
+
this.log("destroy() called");
|
|
385
|
+
this.cleanup();
|
|
386
|
+
this.setStatus("idle");
|
|
387
|
+
this.destroyed = true;
|
|
388
|
+
for (const set of Object.values(this.listeners)) {
|
|
389
|
+
set.clear();
|
|
390
|
+
}
|
|
391
|
+
}
|
|
392
|
+
// ── Private ──────────────────────────────────────────────────────────
|
|
393
|
+
log(message, data) {
|
|
394
|
+
if (!this.config.debug) return;
|
|
395
|
+
if (data) {
|
|
396
|
+
console.debug(`[SwypeMobileDeposit] ${message}`, data);
|
|
397
|
+
} else {
|
|
398
|
+
console.debug(`[SwypeMobileDeposit] ${message}`);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
setStatus(status) {
|
|
402
|
+
if (this._status === status) return;
|
|
403
|
+
this.log(`Status: ${this._status} \u2192 ${status}`);
|
|
404
|
+
this._status = status;
|
|
405
|
+
this.emit("status-change", status);
|
|
406
|
+
}
|
|
407
|
+
async runSignerFlow(request, requestId, onError) {
|
|
408
|
+
try {
|
|
409
|
+
const webviewBaseUrl = this.config.webviewBaseUrl ?? DEFAULT_WEBVIEW_BASE_URL;
|
|
410
|
+
this.log("Calling signer", {
|
|
411
|
+
signer: typeof this.config.signer === "string" ? this.config.signer : "<function>"
|
|
412
|
+
});
|
|
413
|
+
const signerRequest = buildSignerRequest(request, this.config.callbackScheme, webviewBaseUrl);
|
|
414
|
+
const signerResponse = await callSigner(
|
|
415
|
+
this.config.signer,
|
|
416
|
+
signerRequest,
|
|
417
|
+
this.config.signerTimeoutMs
|
|
418
|
+
);
|
|
419
|
+
this.lastSignerResponse = signerResponse;
|
|
420
|
+
this.log("Signer responded", { merchantId: signerResponse.merchantId });
|
|
421
|
+
if (this.requestId !== requestId) {
|
|
422
|
+
this.log("Request superseded");
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
425
|
+
const hostedUrl = new URL(webviewBaseUrl);
|
|
426
|
+
hostedUrl.searchParams.set("merchantId", signerResponse.merchantId);
|
|
427
|
+
hostedUrl.searchParams.set("payload", signerResponse.payload);
|
|
428
|
+
hostedUrl.searchParams.set("signature", signerResponse.signature);
|
|
429
|
+
const targetUrl = hostedUrl.toString();
|
|
430
|
+
this.setStatus("browser-active");
|
|
431
|
+
this.log("Opening in-app browser", { url: targetUrl });
|
|
432
|
+
try {
|
|
433
|
+
await this.config.openUrl(targetUrl);
|
|
434
|
+
} catch (err) {
|
|
435
|
+
if (this.requestId !== requestId) return;
|
|
436
|
+
onError(
|
|
437
|
+
new DepositError(
|
|
438
|
+
"BROWSER_FAILED",
|
|
439
|
+
err instanceof Error ? err.message : "Failed to open the payment browser."
|
|
440
|
+
)
|
|
441
|
+
);
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
444
|
+
if (this.requestId === requestId && this.pendingResolve) {
|
|
445
|
+
this.log("Browser dismissed without deep link callback");
|
|
446
|
+
this.emit("dismiss");
|
|
447
|
+
}
|
|
448
|
+
} catch (err) {
|
|
449
|
+
if (this.requestId !== requestId) return;
|
|
450
|
+
this.log("Signer flow failed", { error: err instanceof Error ? err.message : String(err) });
|
|
451
|
+
if (err instanceof DepositError) {
|
|
452
|
+
onError(err);
|
|
453
|
+
} else {
|
|
454
|
+
onError(
|
|
455
|
+
new DepositError(
|
|
456
|
+
"SIGNER_NETWORK_ERROR",
|
|
457
|
+
err instanceof Error ? err.message : "Unknown signer error."
|
|
458
|
+
)
|
|
459
|
+
);
|
|
460
|
+
}
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
cleanup() {
|
|
464
|
+
if (this.flowTimer) {
|
|
465
|
+
clearTimeout(this.flowTimer);
|
|
466
|
+
this.flowTimer = null;
|
|
467
|
+
}
|
|
468
|
+
this.pendingResolve = null;
|
|
469
|
+
this.pendingReject = null;
|
|
470
|
+
this.pendingRequestId = null;
|
|
471
|
+
this.lastSignerResponse = null;
|
|
472
|
+
}
|
|
473
|
+
emit(event, ...args) {
|
|
474
|
+
for (const handler of this.listeners[event]) {
|
|
475
|
+
try {
|
|
476
|
+
handler(...args);
|
|
477
|
+
} catch {
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// src/react-native.ts
|
|
484
|
+
function useBlinkMobileDeposit(config) {
|
|
485
|
+
const depositRef = react.useRef(null);
|
|
486
|
+
const [status, setStatus] = react.useState("idle");
|
|
487
|
+
const [result, setResult] = react.useState(null);
|
|
488
|
+
const [error, setError] = react.useState(null);
|
|
489
|
+
if (!depositRef.current) {
|
|
490
|
+
depositRef.current = new MobileDeposit(config);
|
|
491
|
+
}
|
|
492
|
+
react.useEffect(() => {
|
|
493
|
+
const deposit = depositRef.current;
|
|
494
|
+
const onStatusChange = (s) => setStatus(s);
|
|
495
|
+
const onComplete = (r) => {
|
|
496
|
+
setResult(r);
|
|
497
|
+
setError(null);
|
|
498
|
+
};
|
|
499
|
+
const onError = (e) => setError(e);
|
|
500
|
+
deposit.on("status-change", onStatusChange);
|
|
501
|
+
deposit.on("complete", onComplete);
|
|
502
|
+
deposit.on("error", onError);
|
|
503
|
+
return () => {
|
|
504
|
+
deposit.off("status-change", onStatusChange);
|
|
505
|
+
deposit.off("complete", onComplete);
|
|
506
|
+
deposit.off("error", onError);
|
|
507
|
+
deposit.destroy();
|
|
508
|
+
depositRef.current = null;
|
|
509
|
+
};
|
|
510
|
+
}, []);
|
|
511
|
+
const requestDeposit = react.useCallback(
|
|
512
|
+
(request) => depositRef.current.requestDeposit(request),
|
|
513
|
+
[]
|
|
514
|
+
);
|
|
515
|
+
const handleDeepLink = react.useCallback(
|
|
516
|
+
(url) => depositRef.current?.handleDeepLink(url) ?? false,
|
|
517
|
+
[]
|
|
518
|
+
);
|
|
519
|
+
const close = react.useCallback(() => depositRef.current?.close(), []);
|
|
520
|
+
const displayMessage = error ? getDisplayMessage(error) : null;
|
|
521
|
+
const isActive = status === "signer-loading" || status === "browser-active";
|
|
522
|
+
return { status, result, error, displayMessage, isActive, requestDeposit, handleDeepLink, close };
|
|
523
|
+
}
|
|
524
|
+
var useSwypeMobileCheckout = useBlinkMobileDeposit;
|
|
525
|
+
|
|
526
|
+
exports.DepositError = DepositError;
|
|
527
|
+
exports.getDisplayMessage = getDisplayMessage;
|
|
528
|
+
exports.useBlinkMobileDeposit = useBlinkMobileDeposit;
|
|
529
|
+
exports.useSwypeMobileCheckout = useSwypeMobileCheckout;
|
|
530
|
+
//# sourceMappingURL=react-native.cjs.map
|
|
531
|
+
//# sourceMappingURL=react-native.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/deep-link.ts","../src/errors.ts","../src/signer.ts","../src/validation.ts","../src/mobile-deposit.ts","../src/react-native.ts"],"names":["useRef","useState","useEffect","useCallback"],"mappings":"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","file":"react-native.cjs","sourcesContent":["import type { TransferSummary } from './types.ts';\n\nconst DEFAULT_CALLBACK_PATH = '/swype/callback';\n\n/**\n * Parsed result from a Swype deep link callback.\n *\n * @internal\n */\nexport interface DeepLinkResult {\n transferId: string;\n transferStatus: string;\n amount?: number;\n currency?: string;\n chainId?: string;\n address?: string;\n token?: string;\n}\n\n/**\n * Check whether a URL matches the expected Swype callback deep link pattern.\n */\nexport function isSwypeCallback(\n url: string,\n callbackScheme: string,\n callbackPath?: string,\n): boolean {\n const path = callbackPath ?? DEFAULT_CALLBACK_PATH;\n const prefix = `${callbackScheme}://${path}`.replace(/^([^:]+):\\/\\/\\//, '$1://');\n const normalised = url.replace(/^([^:]+):\\/\\/\\//, '$1://');\n return normalised.startsWith(prefix);\n}\n\n/**\n * Parse a Swype callback deep link URL into a {@link DeepLinkResult}.\n *\n * Returns `null` if the URL does not match the expected scheme/path or is\n * missing the required `transferId` parameter.\n *\n * Expected format:\n * ```\n * {scheme}://{path}?transferId=xxx&transferStatus=completed&amount=50¤cy=USD&chainId=8453&address=0x...&token=USDC\n * ```\n */\nexport function parseDeepLink(\n url: string,\n callbackScheme: string,\n callbackPath?: string,\n): DeepLinkResult | null {\n if (!isSwypeCallback(url, callbackScheme, callbackPath)) {\n return null;\n }\n\n const queryStart = url.indexOf('?');\n if (queryStart === -1) {\n return null;\n }\n\n const params = new URLSearchParams(url.slice(queryStart + 1));\n\n const transferId = params.get('transferId');\n const transferStatus = params.get('transferStatus');\n\n if (!transferId || !transferStatus) {\n return null;\n }\n\n const result: DeepLinkResult = { transferId, transferStatus };\n\n const amount = params.get('amount');\n if (amount != null) result.amount = Number(amount);\n\n const currency = params.get('currency');\n if (currency != null) result.currency = currency;\n\n const chainId = params.get('chainId');\n if (chainId != null) result.chainId = chainId;\n\n const address = params.get('address');\n if (address != null) result.address = address;\n\n const token = params.get('token');\n if (token != null) result.token = token;\n\n return result;\n}\n\n/**\n * Convert a parsed deep link result into a {@link TransferSummary}.\n *\n * @internal\n */\nexport function toTransferSummary(result: DeepLinkResult): TransferSummary {\n const summary: TransferSummary = {\n id: result.transferId,\n status: result.transferStatus,\n };\n\n if (result.amount != null && result.currency != null) {\n summary.amount = {\n amount: result.amount,\n currency: result.currency,\n };\n }\n\n if (result.chainId != null && result.address != null) {\n summary.destinations = [\n {\n chainId: result.chainId,\n address: result.address,\n token: result.token ? { address: result.token } : undefined,\n },\n ];\n }\n\n return summary;\n}\n","export type DepositMobileErrorCode =\n | 'BROWSER_FAILED'\n | 'BROWSER_DISMISSED'\n | 'DEEP_LINK_INVALID'\n | 'SIGNER_REQUEST_FAILED'\n | 'SIGNER_NETWORK_ERROR'\n | 'SIGNER_RESPONSE_INVALID'\n | 'SIGNER_TIMEOUT'\n | 'FLOW_TIMEOUT'\n | 'INVALID_REQUEST';\n\n/**\n * Structured error thrown by the mobile deposit SDK.\n *\n * Every error carries a machine-readable {@link code} so merchants can\n * branch on failure mode without parsing message strings.\n */\nexport class DepositError extends Error {\n readonly code: DepositMobileErrorCode;\n\n constructor(code: DepositMobileErrorCode, message: string) {\n super(message);\n this.name = 'DepositError';\n this.code = code;\n }\n}\n\nconst DISPLAY_MESSAGES: Record<DepositMobileErrorCode, string> = {\n BROWSER_FAILED:\n 'Unable to open the payment browser. Please try again.',\n BROWSER_DISMISSED:\n 'The payment browser was closed before the transfer completed.',\n DEEP_LINK_INVALID:\n 'The payment callback was malformed. Please try again.',\n SIGNER_REQUEST_FAILED:\n 'Unable to start the payment. Please try again.',\n SIGNER_NETWORK_ERROR:\n 'Unable to reach the payment server. Check your connection and try again.',\n SIGNER_RESPONSE_INVALID:\n 'The payment server returned an unexpected response.',\n SIGNER_TIMEOUT:\n 'The payment server took too long to respond. Please try again.',\n FLOW_TIMEOUT:\n 'The payment flow timed out. Please try again.',\n INVALID_REQUEST:\n 'Invalid payment request. Please check your input.',\n};\n\n/**\n * Return a user-friendly display string for a {@link DepositError}.\n *\n * Merchants can show this directly in their UI without maintaining their own\n * copy for each error code.\n */\nexport function getDisplayMessage(error: DepositError): string {\n return DISPLAY_MESSAGES[error.code] ?? error.message;\n}\n\n/** @deprecated Use {@link DepositMobileErrorCode} instead. */\nexport type CheckoutErrorCode = DepositMobileErrorCode;\n\n/** @deprecated Use {@link DepositError} instead. */\nexport const CheckoutError = DepositError;\n","import { DepositError } from './errors.ts';\nimport type { SignerFunction, SignerRequest, SignerResponse } from './types.ts';\n\nconst DEFAULT_SIGNER_TIMEOUT_MS = 15_000;\n\n/**\n * Invoke the merchant signer and return the validated response.\n *\n * When `signer` is a URL string the SDK performs a `POST` with a JSON body.\n * When `signer` is a function the SDK delegates entirely to it.\n * In both cases a timeout wrapper is applied via `timeoutMs`.\n */\nexport async function callSigner(\n signer: string | SignerFunction,\n request: SignerRequest,\n timeoutMs?: number,\n): Promise<SignerResponse> {\n const timeout = timeoutMs ?? DEFAULT_SIGNER_TIMEOUT_MS;\n\n const body: SignerResponse =\n typeof signer === 'function'\n ? await invokeSignerFunction(signer, request, timeout)\n : await invokeSignerUrl(signer, request, timeout);\n\n validateSignerResponse(body);\n return body;\n}\n\nasync function invokeSignerUrl(\n signerUrl: string,\n request: SignerRequest,\n timeoutMs: number,\n): Promise<SignerResponse> {\n let response: Response;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n try {\n response = await fetch(signerUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(request),\n signal: controller.signal,\n });\n } catch (err) {\n if (controller.signal.aborted) {\n throw new DepositError(\n 'SIGNER_TIMEOUT',\n `Signer did not respond within ${timeoutMs}ms.`,\n );\n }\n throw new DepositError(\n 'SIGNER_NETWORK_ERROR',\n 'Unable to reach the merchant signer. Check the signer URL and network connectivity.',\n );\n } finally {\n clearTimeout(timer);\n }\n\n const body = await response.json().catch(() => null) as\n | (Partial<SignerResponse> & { error?: string })\n | null;\n\n if (!response.ok) {\n const detail = body?.error ?? `Signer returned HTTP ${response.status}.`;\n throw new DepositError('SIGNER_REQUEST_FAILED', detail);\n }\n\n return body as SignerResponse;\n}\n\nasync function invokeSignerFunction(\n signer: SignerFunction,\n request: SignerRequest,\n timeoutMs: number,\n): Promise<SignerResponse> {\n return new Promise<SignerResponse>((resolve, reject) => {\n const timer = setTimeout(\n () => reject(new DepositError('SIGNER_TIMEOUT', `Signer did not respond within ${timeoutMs}ms.`)),\n timeoutMs,\n );\n\n signer(request).then(\n (result) => { clearTimeout(timer); resolve(result); },\n (err) => {\n clearTimeout(timer);\n if (err instanceof DepositError) {\n reject(err);\n } else {\n reject(new DepositError(\n 'SIGNER_REQUEST_FAILED',\n err instanceof Error ? err.message : 'Signer function threw an error.',\n ));\n }\n },\n );\n });\n}\n\nfunction validateSignerResponse(body: unknown): asserts body is SignerResponse {\n const obj = body as Partial<SignerResponse> | null | undefined;\n if (\n !obj ||\n typeof obj.merchantId !== 'string' ||\n typeof obj.payload !== 'string' ||\n typeof obj.signature !== 'string' ||\n !obj.preview ||\n typeof obj.preview !== 'object'\n ) {\n throw new DepositError(\n 'SIGNER_RESPONSE_INVALID',\n 'Signer response is missing required fields (merchantId, payload, signature, preview).',\n );\n }\n}\n","import { DepositError } from './errors.ts';\nimport type { DepositRequest, SignerRequest } from './types.ts';\n\nconst EVM_ADDRESS_RE = /^0x[a-fA-F0-9]{40}$/;\nconst TOKEN_ADDRESS_RE = /^0x[a-fA-F0-9]{1,40}$/;\n\nexport function validateDepositRequest(request: DepositRequest): void {\n if (!Number.isFinite(request.amount) || request.amount <= 0) {\n throw new DepositError('INVALID_REQUEST', 'amount must be a positive number.');\n }\n\n if (!Number.isInteger(request.chainId) || request.chainId <= 0) {\n throw new DepositError('INVALID_REQUEST', 'chainId must be a positive integer.');\n }\n\n if (!EVM_ADDRESS_RE.test(request.address)) {\n throw new DepositError(\n 'INVALID_REQUEST',\n 'address must be a 0x-prefixed, 40-character hex string.',\n );\n }\n\n if (typeof request.token !== 'string' || !TOKEN_ADDRESS_RE.test(request.token)) {\n throw new DepositError('INVALID_REQUEST', 'token must be a 0x-prefixed hex address.');\n }\n}\n\nexport function buildSignerRequest(\n request: DepositRequest,\n callbackScheme: string,\n webviewBaseUrl: string,\n): SignerRequest {\n const base: SignerRequest = {\n amount: request.amount,\n chainId: request.chainId,\n address: request.address,\n token: request.token,\n callbackScheme,\n url: webviewBaseUrl,\n version: 'v1',\n };\n\n if (request.reference) base.reference = request.reference;\n if (request.metadata && Object.keys(request.metadata).length > 0) {\n base.metadata = request.metadata;\n }\n\n return base;\n}\n","import { parseDeepLink, toTransferSummary } from './deep-link.ts';\nimport { DepositError } from './errors.ts';\nimport { callSigner } from './signer.ts';\nimport { validateDepositRequest, buildSignerRequest } from './validation.ts';\nimport type {\n MobileDepositConfig,\n MobileDepositStatus,\n DepositRequest,\n DepositResult,\n SignerResponse,\n} from './types.ts';\n\nexport const DEFAULT_WEBVIEW_BASE_URL = 'https://pay-staging.tryblink.xyz';\n\ntype EventMap = {\n complete: (result: DepositResult) => void;\n error: (error: DepositError) => void;\n dismiss: () => void;\n 'status-change': (status: MobileDepositStatus) => void;\n};\n\ntype EventName = keyof EventMap;\n\n/**\n * Mobile deposit SDK.\n *\n * Opens a hosted payment flow in an in-app browser, waits for the result\n * via deep link callback, and resolves when the user completes payment.\n *\n * ```ts\n * const deposit = new MobileDeposit({\n * signer: 'https://api.merchant.com/sign-payment',\n * callbackScheme: 'myapp',\n * openUrl: (url) => WebBrowser.openBrowserAsync(url),\n * });\n *\n * // When a deep link arrives, pass it to the SDK:\n * Linking.addEventListener('url', ({ url }) => deposit.handleDeepLink(url));\n *\n * // Start a deposit:\n * const result = await deposit.requestDeposit({\n * amount: 50,\n * chainId: 8453,\n * address: '0x...',\n * token: '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913',\n * });\n * ```\n */\nexport class MobileDeposit {\n private readonly config: MobileDepositConfig;\n private requestId = 0;\n private destroyed = false;\n private _status: MobileDepositStatus = 'idle';\n private _result: DepositResult | null = null;\n private _error: DepositError | null = null;\n private flowTimer: ReturnType<typeof setTimeout> | null = null;\n private lastSignerResponse: SignerResponse | null = null;\n private pendingResolve: ((result: DepositResult) => void) | null = null;\n private pendingReject: ((error: DepositError) => void) | null = null;\n private pendingRequestId: number | null = null;\n private listeners: { [K in EventName]: Set<EventMap[K]> } = {\n complete: new Set(),\n error: new Set(),\n dismiss: new Set(),\n 'status-change': new Set(),\n };\n\n /** Current phase of the deposit flow. */\n get status(): MobileDepositStatus {\n return this._status;\n }\n\n /** Last successful {@link DepositResult}, available when `status === 'completed'`. */\n get result(): DepositResult | null {\n return this._result;\n }\n\n /** Last {@link DepositError}, available when `status === 'error'`. */\n get error(): DepositError | null {\n return this._error;\n }\n\n /** Whether a deposit flow is currently in progress. */\n get isActive(): boolean {\n return this._status === 'signer-loading' || this._status === 'browser-active';\n }\n\n constructor(config: MobileDepositConfig) {\n if (!config.signer || (typeof config.signer !== 'string' && typeof config.signer !== 'function')) {\n throw new DepositError('INVALID_REQUEST', 'MobileDepositConfig.signer is required (URL string or SignerFunction).');\n }\n if (!config.callbackScheme || typeof config.callbackScheme !== 'string') {\n throw new DepositError('INVALID_REQUEST', 'MobileDepositConfig.callbackScheme is required.');\n }\n if (typeof config.openUrl !== 'function') {\n throw new DepositError('INVALID_REQUEST', 'MobileDepositConfig.openUrl must be a function.');\n }\n this.config = config;\n this.log('MobileDeposit instance created', {\n signer: typeof config.signer === 'string' ? config.signer : '<function>',\n callbackScheme: config.callbackScheme,\n });\n }\n\n /**\n * Open the hosted payment flow for the given deposit.\n *\n * The returned Promise resolves when the user completes the payment (via\n * deep link callback) and rejects with a {@link DepositError} on failure.\n *\n * The merchant must listen for incoming deep links and pass them to\n * {@link handleDeepLink} for the promise to resolve.\n */\n requestDeposit(request: DepositRequest): Promise<DepositResult> {\n if (this.destroyed) {\n return Promise.reject(\n new DepositError('INVALID_REQUEST', 'This MobileDeposit instance has been destroyed.'),\n );\n }\n\n validateDepositRequest(request);\n this.log('requestDeposit called', { amount: request.amount, token: request.token, chainId: request.chainId });\n\n this.requestId += 1;\n const currentRequestId = this.requestId;\n\n this.cleanup();\n\n this._result = null;\n this._error = null;\n this.setStatus('signer-loading');\n\n return new Promise<DepositResult>((resolve, reject) => {\n const settle = (fn: () => void) => {\n if (this.requestId !== currentRequestId) return;\n fn();\n };\n\n const onComplete = (result: DepositResult) => {\n settle(() => {\n this.cleanup();\n this._result = result;\n this._error = null;\n this.setStatus('completed');\n this.emit('complete', result);\n resolve(result);\n });\n };\n\n const onError = (error: DepositError) => {\n settle(() => {\n this.cleanup();\n this._error = error;\n this.setStatus('error');\n this.emit('error', error);\n reject(error);\n });\n };\n\n this.pendingResolve = onComplete;\n this.pendingReject = onError;\n this.pendingRequestId = currentRequestId;\n\n if (this.config.flowTimeoutMs != null && this.config.flowTimeoutMs > 0) {\n this.flowTimer = setTimeout(() => {\n onError(\n new DepositError(\n 'FLOW_TIMEOUT',\n `The payment flow did not complete within ${this.config.flowTimeoutMs}ms.`,\n ),\n );\n }, this.config.flowTimeoutMs);\n }\n\n this.runSignerFlow(request, currentRequestId, onError);\n });\n }\n\n /**\n * Feed an incoming deep link URL to the SDK.\n *\n * Returns `true` if the URL was a valid Swype callback and the SDK handled\n * it. Returns `false` if the URL did not match the expected callback pattern\n * (the merchant should handle it themselves).\n *\n * Typically called from `Linking.addEventListener('url', ...)` or the\n * equivalent deep link handler on the platform.\n */\n handleDeepLink(url: string): boolean {\n this.log('handleDeepLink called', { url });\n\n const parsed = parseDeepLink(\n url,\n this.config.callbackScheme,\n this.config.callbackPath,\n );\n\n if (!parsed) {\n this.log('URL does not match expected callback pattern');\n return false;\n }\n\n if (!this.pendingResolve) {\n this.log('Received callback but no pending request');\n return true;\n }\n\n const transfer = toTransferSummary(parsed);\n this.log('Deep link parsed', { transferId: transfer.id, status: transfer.status });\n\n const depositResult: DepositResult = { transfer };\n if (this.lastSignerResponse?.preview) {\n depositResult.idempotencyKey = this.lastSignerResponse.preview.idempotencyKey;\n depositResult.preview = {\n amount: this.lastSignerResponse.preview.amount,\n chainId: this.lastSignerResponse.preview.chainId,\n address: this.lastSignerResponse.preview.address,\n token: this.lastSignerResponse.preview.token,\n };\n }\n\n this.pendingResolve(depositResult);\n return true;\n }\n\n /** Register an event listener. */\n on<K extends EventName>(event: K, handler: EventMap[K]): this {\n this.listeners[event].add(handler);\n return this;\n }\n\n /** Remove a previously registered event listener. */\n off<K extends EventName>(event: K, handler: EventMap[K]): this {\n this.listeners[event].delete(handler);\n return this;\n }\n\n /**\n * Cancel the current flow. Rejects the pending promise with\n * `BROWSER_DISMISSED` and resets to idle.\n */\n close(): void {\n this.log('close() called');\n const reject = this.pendingReject;\n this.cleanup();\n this.setStatus('idle');\n this.emit('dismiss');\n if (reject) {\n reject(\n new DepositError('BROWSER_DISMISSED', 'The payment flow was cancelled.'),\n );\n }\n }\n\n /** Tear down the instance and release all resources. */\n destroy(): void {\n this.log('destroy() called');\n this.cleanup();\n this.setStatus('idle');\n this.destroyed = true;\n for (const set of Object.values(this.listeners)) {\n (set as Set<unknown>).clear();\n }\n }\n\n // ── Private ──────────────────────────────────────────────────────────\n\n private log(message: string, data?: Record<string, unknown>): void {\n if (!this.config.debug) return;\n if (data) {\n console.debug(`[SwypeMobileDeposit] ${message}`, data);\n } else {\n console.debug(`[SwypeMobileDeposit] ${message}`);\n }\n }\n\n private setStatus(status: MobileDepositStatus): void {\n if (this._status === status) return;\n this.log(`Status: ${this._status} → ${status}`);\n this._status = status;\n this.emit('status-change', status);\n }\n\n private async runSignerFlow(\n request: DepositRequest,\n requestId: number,\n onError: (error: DepositError) => void,\n ): Promise<void> {\n try {\n const webviewBaseUrl = this.config.webviewBaseUrl ?? DEFAULT_WEBVIEW_BASE_URL;\n this.log('Calling signer', {\n signer: typeof this.config.signer === 'string' ? this.config.signer : '<function>',\n });\n const signerRequest = buildSignerRequest(request, this.config.callbackScheme, webviewBaseUrl);\n const signerResponse = await callSigner(\n this.config.signer,\n signerRequest,\n this.config.signerTimeoutMs,\n );\n this.lastSignerResponse = signerResponse;\n this.log('Signer responded', { merchantId: signerResponse.merchantId });\n\n if (this.requestId !== requestId) {\n this.log('Request superseded');\n return;\n }\n\n const hostedUrl = new URL(webviewBaseUrl);\n hostedUrl.searchParams.set('merchantId', signerResponse.merchantId);\n hostedUrl.searchParams.set('payload', signerResponse.payload);\n hostedUrl.searchParams.set('signature', signerResponse.signature);\n const targetUrl = hostedUrl.toString();\n\n this.setStatus('browser-active');\n this.log('Opening in-app browser', { url: targetUrl });\n\n try {\n await this.config.openUrl(targetUrl);\n } catch (err) {\n if (this.requestId !== requestId) return;\n onError(\n new DepositError(\n 'BROWSER_FAILED',\n err instanceof Error ? err.message : 'Failed to open the payment browser.',\n ),\n );\n return;\n }\n\n if (this.requestId === requestId && this.pendingResolve) {\n this.log('Browser dismissed without deep link callback');\n this.emit('dismiss');\n }\n } catch (err) {\n if (this.requestId !== requestId) return;\n\n this.log('Signer flow failed', { error: err instanceof Error ? err.message : String(err) });\n\n if (err instanceof DepositError) {\n onError(err);\n } else {\n onError(\n new DepositError(\n 'SIGNER_NETWORK_ERROR',\n err instanceof Error ? err.message : 'Unknown signer error.',\n ),\n );\n }\n }\n }\n\n private cleanup(): void {\n if (this.flowTimer) {\n clearTimeout(this.flowTimer);\n this.flowTimer = null;\n }\n\n this.pendingResolve = null;\n this.pendingReject = null;\n this.pendingRequestId = null;\n this.lastSignerResponse = null;\n }\n\n private emit<K extends EventName>(event: K, ...args: Parameters<EventMap[K]>): void {\n for (const handler of this.listeners[event]) {\n try {\n (handler as (...a: unknown[]) => void)(...args);\n } catch {\n // Swallow listener errors to avoid breaking the SDK flow.\n }\n }\n }\n}\n\n/** @deprecated Use {@link MobileDeposit} instead. */\nexport const MobileCheckout = MobileDeposit;\n","import { useCallback, useEffect, useRef, useState } from 'react';\n\nimport { MobileDeposit } from './mobile-deposit.ts';\nimport { DepositError, getDisplayMessage } from './errors.ts';\nimport type {\n MobileDepositConfig,\n MobileDepositStatus,\n DepositRequest,\n DepositResult,\n} from './types.ts';\n\nexport type { MobileDepositConfig, MobileDepositStatus, DepositRequest, DepositResult };\nexport { DepositError, getDisplayMessage };\n\ninterface UseBlinkMobileDepositReturn {\n /** Current phase of the deposit flow. */\n status: MobileDepositStatus;\n /** Last successful deposit result, or `null`. */\n result: DepositResult | null;\n /** Last deposit error, or `null`. */\n error: DepositError | null;\n /** User-friendly error message derived from the current error, or `null`. */\n displayMessage: string | null;\n /** Whether a deposit flow is currently in progress. */\n isActive: boolean;\n /** Start a deposit flow. */\n requestDeposit: (request: DepositRequest) => Promise<DepositResult>;\n /**\n * Pass an incoming deep link URL to the SDK. Returns `true` if the URL\n * was a Swype callback, `false` otherwise.\n *\n * Call this from your deep link listener (e.g. `Linking.addEventListener`).\n */\n handleDeepLink: (url: string) => boolean;\n /** Cancel the current flow and reset to idle. */\n close: () => void;\n}\n\n/**\n * React / React Native hook that wraps {@link MobileDeposit} with reactive state.\n *\n * ```tsx\n * import { useBlinkMobileDeposit } from '@swype-org/deposit-mobile/react-native';\n * import * as Linking from 'expo-linking';\n * import * as WebBrowser from 'expo-web-browser';\n *\n * function DepositButton() {\n * const { status, result, error, displayMessage, requestDeposit, handleDeepLink } =\n * useBlinkMobileDeposit({\n * signer: 'https://api.merchant.com/sign-payment',\n * callbackScheme: 'myapp',\n * openUrl: (url) => WebBrowser.openBrowserAsync(url).then(() => {}),\n * });\n *\n * useEffect(() => {\n * const sub = Linking.addEventListener('url', ({ url }) => handleDeepLink(url));\n * return () => sub.remove();\n * }, [handleDeepLink]);\n *\n * return (\n * <>\n * <Button\n * title={status === 'signer-loading' ? 'Preparing…' : 'Deposit $50'}\n * disabled={status === 'signer-loading'}\n * onPress={() =>\n * requestDeposit({ amount: 50, chainId: 8453, address: '0x...', token: 'USDC' })\n * }\n * />\n * {error && <Text>{displayMessage}</Text>}\n * {result && <Text>Transfer {result.transfer.id} complete!</Text>}\n * </>\n * );\n * }\n * ```\n */\nexport function useBlinkMobileDeposit(\n config: MobileDepositConfig,\n): UseBlinkMobileDepositReturn {\n const depositRef = useRef<MobileDeposit | null>(null);\n const [status, setStatus] = useState<MobileDepositStatus>('idle');\n const [result, setResult] = useState<DepositResult | null>(null);\n const [error, setError] = useState<DepositError | null>(null);\n\n if (!depositRef.current) {\n depositRef.current = new MobileDeposit(config);\n }\n\n useEffect(() => {\n const deposit = depositRef.current!;\n\n const onStatusChange = (s: MobileDepositStatus) => setStatus(s);\n const onComplete = (r: DepositResult) => {\n setResult(r);\n setError(null);\n };\n const onError = (e: DepositError) => setError(e);\n\n deposit.on('status-change', onStatusChange);\n deposit.on('complete', onComplete);\n deposit.on('error', onError);\n\n return () => {\n deposit.off('status-change', onStatusChange);\n deposit.off('complete', onComplete);\n deposit.off('error', onError);\n deposit.destroy();\n depositRef.current = null;\n };\n }, []);\n\n const requestDeposit = useCallback(\n (request: DepositRequest) => depositRef.current!.requestDeposit(request),\n [],\n );\n\n const handleDeepLink = useCallback(\n (url: string) => depositRef.current?.handleDeepLink(url) ?? false,\n [],\n );\n\n const close = useCallback(() => depositRef.current?.close(), []);\n\n const displayMessage = error ? getDisplayMessage(error) : null;\n const isActive = status === 'signer-loading' || status === 'browser-active';\n\n return { status, result, error, displayMessage, isActive, requestDeposit, handleDeepLink, close };\n}\n\n/** @deprecated Use {@link useBlinkMobileDeposit} instead. */\nexport const useSwypeMobileCheckout = useBlinkMobileDeposit;\n\n/** @deprecated Use {@link UseBlinkMobileDepositReturn} instead. */\nexport type UseSwypeMobileCheckoutReturn = UseBlinkMobileDepositReturn;\n"]}
|