@rhinestone/deposit-modal 0.19.0 → 0.20.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.
Files changed (83) hide show
  1. package/README.md +151 -61
  2. package/dist/BankOnrampStep-JG32OCM2.mjs +435 -0
  3. package/dist/BankOnrampStep-NPGXAA7U.cjs +435 -0
  4. package/dist/{DepositModalReown-XBNY6QCI.mjs → DepositModalReown-3FGTPER6.mjs} +6 -5
  5. package/dist/{DepositModalReown-UITYXJ6W.cjs → DepositModalReown-ALVWADG7.cjs} +21 -20
  6. package/dist/WithdrawModal-5YWFJSYY.cjs +12 -0
  7. package/dist/WithdrawModal-LL4Z5WZP.mjs +12 -0
  8. package/dist/{bearer-transport-CVHNBgoV.d.cts → bearer-transport-DZyeDG64.d.cts} +5 -1
  9. package/dist/{bearer-transport-CVHNBgoV.d.ts → bearer-transport-DZyeDG64.d.ts} +5 -1
  10. package/dist/{caip-BMi-9t09.d.cts → caip-nwFFL46o.d.cts} +2 -2
  11. package/dist/{caip-BMi-9t09.d.ts → caip-nwFFL46o.d.ts} +2 -2
  12. package/dist/{chunk-NITKDXHR.mjs → chunk-247GJH57.mjs} +480 -272
  13. package/dist/{chunk-FTWKAJGN.mjs → chunk-2FOPO4N5.mjs} +1 -1
  14. package/dist/{chunk-5NWLS5BQ.mjs → chunk-32ERBFMO.mjs} +1432 -961
  15. package/dist/chunk-5QUWEFD4.mjs +19 -0
  16. package/dist/chunk-6CTJFR3T.mjs +113 -0
  17. package/dist/{chunk-X6N2XPTO.mjs → chunk-B2LZQIGB.mjs} +1 -1
  18. package/dist/{chunk-EG4H7OMC.cjs → chunk-BTEG2VNZ.cjs} +171 -130
  19. package/dist/{chunk-HMUGY66O.cjs → chunk-CXRH5MKO.cjs} +1502 -1031
  20. package/dist/chunk-E7IMWVMN.mjs +346 -0
  21. package/dist/{chunk-PYOC6K24.cjs → chunk-EKFXUF5A.cjs} +1 -1
  22. package/dist/chunk-FKJ6EJHH.cjs +346 -0
  23. package/dist/chunk-FMUSY563.cjs +19 -0
  24. package/dist/{chunk-LVCD6RHF.cjs → chunk-FVJKUTHF.cjs} +2 -2
  25. package/dist/chunk-G264OM23.cjs +224 -0
  26. package/dist/{chunk-BIL4ENC3.mjs → chunk-HP7S7AD6.mjs} +73 -32
  27. package/dist/{chunk-ISLVD5HQ.cjs → chunk-OPT5EW6L.cjs} +10 -5
  28. package/dist/chunk-PYRXOP2Y.cjs +113 -0
  29. package/dist/{chunk-ZGHVJ2XM.mjs → chunk-XBJCZYBX.mjs} +8 -3
  30. package/dist/chunk-YY4ZOAH5.mjs +224 -0
  31. package/dist/{chunk-OCWSMLOP.cjs → chunk-Z4RBTNKX.cjs} +980 -772
  32. package/dist/compliance.cjs +4 -7
  33. package/dist/compliance.d.cts +26 -3
  34. package/dist/compliance.d.ts +26 -3
  35. package/dist/compliance.mjs +6 -9
  36. package/dist/constants-BQDxVNgr.d.cts +29 -0
  37. package/dist/constants-DjGQW5N5.d.ts +29 -0
  38. package/dist/constants.cjs +3 -37
  39. package/dist/constants.d.cts +4 -20
  40. package/dist/constants.d.ts +4 -20
  41. package/dist/constants.mjs +4 -38
  42. package/dist/deposit.cjs +7 -6
  43. package/dist/deposit.d.cts +5 -3
  44. package/dist/deposit.d.ts +5 -3
  45. package/dist/deposit.mjs +6 -5
  46. package/dist/embed.cjs +21 -20
  47. package/dist/embed.d.cts +3 -2
  48. package/dist/embed.d.ts +3 -2
  49. package/dist/embed.mjs +7 -6
  50. package/dist/index.cjs +8 -35
  51. package/dist/index.d.cts +5 -3
  52. package/dist/index.d.ts +5 -3
  53. package/dist/index.mjs +9 -36
  54. package/dist/onramp.cjs +4 -33
  55. package/dist/onramp.d.cts +51 -33
  56. package/dist/onramp.d.ts +51 -33
  57. package/dist/onramp.mjs +5 -34
  58. package/dist/polymarket.cjs +6 -6
  59. package/dist/polymarket.mjs +2 -2
  60. package/dist/ramp-types-HYWd7CW0.d.cts +108 -0
  61. package/dist/ramp-types-HYWd7CW0.d.ts +108 -0
  62. package/dist/styles.css +255 -0
  63. package/dist/{types-BShYNpvO.d.cts → types-BxSrazbq.d.ts} +20 -2
  64. package/dist/{types-BOxa1DE-.d.ts → types-CixUBhrM.d.cts} +20 -2
  65. package/dist/withdraw.cjs +6 -5
  66. package/dist/withdraw.d.cts +4 -3
  67. package/dist/withdraw.d.ts +4 -3
  68. package/dist/withdraw.mjs +5 -4
  69. package/package.json +9 -17
  70. package/dist/WithdrawModal-DY6A55OA.mjs +0 -11
  71. package/dist/WithdrawModal-V42OK7L3.cjs +0 -11
  72. package/dist/chunk-ADEWTBSN.cjs +0 -19
  73. package/dist/chunk-EAGMY3QE.mjs +0 -962
  74. package/dist/chunk-OY5N3E6L.cjs +0 -962
  75. package/dist/chunk-PP4QE32S.mjs +0 -19
  76. package/dist/constants-BT4ctuHo.d.cts +0 -64
  77. package/dist/constants-D21ZdNOP.d.ts +0 -64
  78. package/dist/offramp.cjs +0 -25
  79. package/dist/offramp.d.cts +0 -28
  80. package/dist/offramp.d.ts +0 -28
  81. package/dist/offramp.mjs +0 -25
  82. package/dist/ramp-types-C6aUz4SZ.d.cts +0 -43
  83. package/dist/ramp-types-C6aUz4SZ.d.ts +0 -43
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # @rhinestone/deposit-modal
2
2
 
3
- React modal for cross-chain deposits and withdrawals via Rhinestone smart accounts.
3
+ React modal for Rhinestone Deposits: accept deposits from any chain, asset or payment method, and let users withdraw the same way.
4
4
 
5
- **[Documentation](https://docs.rhinestone.dev/deposits/widget/quickstart)** ·
6
- [Deposit modal](https://docs.rhinestone.dev/deposits/widget/deposit-modal) ·
7
- [Withdraw modal](https://docs.rhinestone.dev/deposits/widget/withdraw-modal) ·
8
- [Backend proxy](https://docs.rhinestone.dev/deposits/widget/backend) ·
9
- [Migration guide](https://docs.rhinestone.dev/deposits/widget/migration)
5
+ **[Documentation](https://docs.rhinestone.dev/deposits/overview/widget/quickstart)** ·
6
+ [Deposit modal](https://docs.rhinestone.dev/deposits/overview/widget/widget-configuration) ·
7
+ [Withdraw modal](https://docs.rhinestone.dev/deposits/crypto/withdraw-funds) ·
8
+ [Backend proxy](https://docs.rhinestone.dev/deposits/overview/widget/backend-setup) ·
9
+ [Migration guide](https://docs.rhinestone.dev/deposits/overview/widget/migration-guide)
10
10
 
11
11
  This README covers the common integrations. The full props reference lives in the
12
12
  docs.
@@ -43,6 +43,22 @@ console error pointing at the CSP. Hosts without an explicit `img-src` (or with
43
43
  > sufficient. They now come from the CDN, which drops ~20 kB (brotli) from the
44
44
  > bundle and gives every Rhinestone surface one source of truth.
45
45
 
46
+ ### Token metadata (`/assets`)
47
+
48
+ Token symbols, decimals, logos and USD prices come from the processor's asset
49
+ endpoint, looked up by exact chain and token address. **Your proxy must forward
50
+ both `GET /assets` and `QUERY /assets`** for new modal metadata and price
51
+ lookups. Explicit CORS `allowMethods` must include `GET` and `QUERY`. Small
52
+ batches use GET; larger ones use QUERY; a failed QUERY retries as GET sub-batches.
53
+ The browser modal does not use an API key.
54
+
55
+ Without `/assets`, prices are unavailable: request failures no longer fall
56
+ back to `GET /prices` or invent a price. Token logos render as text badges,
57
+ and symbols still come from the chain catalog and your QR token list. A
58
+ withdrawal of a token neither the catalog nor `/assets` knows is blocked
59
+ rather than signed with guessed decimals. Older modal releases may still use
60
+ the supported public `/prices` proxy route; do not remove it for those clients.
61
+
46
62
  All three modals also post session analytics to Rhinestone (see
47
63
  [Analytics](#analytics)), so a host with an explicit `connect-src` must allow the
48
64
  orchestrator alongside its own proxy:
@@ -216,7 +232,7 @@ signature, so there is no privilege for a page to borrow.
216
232
 
217
233
  **Your proxy must forward `POST /deposits/recover`**, alongside the `GET /deposits`
218
234
  used for the lookup. Both are in the
219
- [reference proxy](https://docs.rhinestone.dev/deposits/widget/backend); a proxy
235
+ [reference proxy](https://docs.rhinestone.dev/deposits/overview/widget/backend-setup); a proxy
220
236
  missing the recover route 404s the recovery rather than degrading.
221
237
 
222
238
  Two properties fall out of signing that are worth knowing:
@@ -294,6 +310,14 @@ The flow: user picks a fiat option → modal registers a Rhinestone smart accoun
294
310
  - **Sponsored** (client has a funded sponsor pool for the source chain): user receives 1:1 — the on-ramped amount lands on the target chain exactly.
295
311
  - **Unsponsored**: the bridging cost is deducted from the on-ramped amount and shown as a "Bridging cost" line on the success screen.
296
312
 
313
+ > **Proxy routes.** Card and exchange checkouts use the unified ramp routes with
314
+ > your API key attached: `POST /onramp/orders`,
315
+ > `GET /onramp/options?provider=swapped` and `GET /onramp/orders/:id`. The last
316
+ > two are also bank customer routes: forward them with the key only when the
317
+ > request carries no `Authorization` header, and never key-forward the list
318
+ > `GET /onramp/orders`. [`deposit-widget-proxy`](https://github.com/rhinestonewtf/deposit-widget-proxy)
319
+ > does this from #38. Keep the `/onramp/swapped/*` routes for older modal versions.
320
+
297
321
  Host CSP must allow Swapped's domains:
298
322
 
299
323
  ```
@@ -308,9 +332,92 @@ frame-src https://widget.swapped.com https://sandbox.swapped.com https://connect
308
332
  | `enableQrTransfer` | `boolean` | `true` | Show the Transfer Crypto / QR row. Set false for fiat-only. |
309
333
  | `fiatMethods` | `FiatMethodsConfig` | regional | Optional exact subset of standard `payment_group`s. Providing it opts out of regional personalization; empty means none. |
310
334
 
335
+ ### Bank transfer accounts (Noah)
336
+
337
+ > **Preview.** Your proxy must forward these on the customer bearer before you ship
338
+ > a modal with `bankOnramp`: `GET /compliance/status`, `POST /compliance/verification`,
339
+ > `GET /onramp/options`, `POST`/`GET /onramp/accounts`,
340
+ > `GET /onramp/accounts/:id[/details]` and `GET /onramp/orders[/:id]`. A missing one
341
+ > 404s at the proxy. [`deposit-widget-proxy`](https://github.com/rhinestonewtf/deposit-widget-proxy)
342
+ > forwards all of them.
343
+ >
344
+ > The prop is opt-in and inert unless you pass it. Treat it as unstable until
345
+ > this note is removed.
346
+
347
+ Pass `bankOnramp` to use reusable USD/EUR account details when Noah is provisioned
348
+ for your organization. Integrator KYB happens directly with Noah; Rhinestone
349
+ enables provisioning after Noah confirms it. Card and Apple Pay continue through Swapped. A customer who has
350
+ not been verified is taken through hosted verification first; an existing active
351
+ account is resumed; otherwise the account is configured once. There is no account
352
+ selection: the customer's one account opens directly.
353
+
354
+ Rhinestone chooses the currency from the residence the customer declares during
355
+ verification: EUR inside SEPA, USD elsewhere. It is not configurable, and it does
356
+ not follow the customer's location. The options are read again once the customer
357
+ is approved, because only then is the residence known.
358
+
359
+ The modal checks `GET /onramp/options?provider=noah` before customer verification. A 404
360
+ (provisioning disabled, a declared residence Noah doesn't serve, or an older proxy)
361
+ routes bank transfer through Swapped. When Swapped's regional list has no bank transfer
362
+ either, the customer returns to the Cash methods with a notice and the row hidden.
363
+ A successful response keeps Noah exclusive, even when no currencies are available.
364
+ Authentication and service errors show a retry instead of switching providers.
365
+
366
+ Bank transfers appear in History, including transfers that never become chain
367
+ deposits. The History icon stays available during Noah verification and bank details;
368
+ new activity adds a dot without navigating away.
369
+ Opening History acknowledges that activity and clears the bank notification;
370
+ only a subsequent new transfer or stage change adds it again.
371
+ After entering the bank journey, History refreshes `GET /onramp/orders?provider=noah` every 30 seconds while the modal
372
+ is open and visible, and on focus or opening History. Discovery continues after a
373
+ transfer finishes so the next one is detected. A linked deposit shares the entry
374
+ and shows final settlement separately from the provider's delivery.
375
+ Each bank-transfer entry shows its amount, date and latest status rather than
376
+ individual provider stages. "Settled" means crypto reached the deposit account;
377
+ "Completed" requires the linked deposit's final settlement to complete.
378
+ Expanded fiat entries use the same explorer links as crypto History: the
379
+ incoming crypto deposit and, when available, final settlement on its destination
380
+ chain. No on-chain link is shown for a fiat-only or sub-fee transfer.
381
+
382
+ ```tsx
383
+ <DepositModal
384
+ bankOnramp={{
385
+ supportUrl: "https://your-app.example/support", // Optional bank-transfer help.
386
+ getSession: (smartAccount) =>
387
+ authenticatedSessionClient.getCustomerSession({ smartAccount }),
388
+ }}
389
+ // ...
390
+ />
391
+ ```
392
+
393
+ `getSession` must call your authenticated server endpoint, which mints a
394
+ short-lived customer session with `createCustomerSessionHandler`. It is called
395
+ for every request; do not put the Rhinestone API key in the browser.
396
+
397
+ Bank instructions render inside the modal from `GET /onramp/accounts/:id/details`
398
+ on the customer bearer: separate transfer rails (SWIFT, ACH, Wire, SEPA), copy
399
+ controls, an optional payment reference, and the last-quoted fee with its
400
+ capture date. The modal holds coordinates only in component state and clears
401
+ them on exit. Do not send them to analytics or persist them in the host
402
+ application. A `409` means the account predates snapshot capture and the
403
+ processor backfill has not run; the customer is told to check back. Only identity
404
+ verification uses Noah's hosted page.
405
+
406
+ `bankOnramp` enables Cash when `fiatMethods` is omitted. When an exact
407
+ `fiatMethods` subset is provided, it must include
408
+ `{ "bank-transfer": true }`. The proxy must forward the `/onramp/options`,
409
+ `/onramp/accounts` and `/onramp/orders` customer routes with the bearer token
410
+ and without attaching its API key.
411
+
412
+ Hosts with a strict CSP must allow Noah Checkout:
413
+
414
+ ```
415
+ frame-src https://checkout.noah.com https://checkout.sandbox.noah.com;
416
+ ```
417
+
311
418
  ## Fund from Exchange (Swapped Connect)
312
419
 
313
- Pass `enableExchangeConnect` to expose a "Fund from Exchange" row alongside the existing options. Clicking it opens an exchange picker backed by `/onramp/swapped/connect-exchanges`; after the user picks an exchange, the modal embeds Swapped's Connect iframe for that selected `connection`, signs in, and Swapped pulls the crypto on-chain to the smart account.
420
+ Pass `enableExchangeConnect` to expose a "Fund from Exchange" row alongside the existing options. Clicking it opens an exchange picker backed by `GET /onramp/options?provider=swapped&kind=exchange` (see the proxy routes under [Fiat on-ramp](#fiat-on-ramp-swapped)); after the user picks an exchange, the modal embeds Swapped's Connect iframe for that selected `connection`, signs in, and Swapped pulls the crypto on-chain to the smart account.
314
421
 
315
422
  ```tsx
316
423
  <DepositModal
@@ -362,7 +469,7 @@ integration now posts analytics too, so it needs the `connect-src` above.
362
469
  Upgrading from 0.8.x is a breaking change on both modals.
363
470
 
364
471
  See [`MIGRATION.md`](./MIGRATION.md), or the same guide
365
- [in the docs](https://docs.rhinestone.dev/deposits/widget/migration).
472
+ [in the docs](https://docs.rhinestone.dev/deposits/overview/widget/migration-guide).
366
473
 
367
474
  ## Contributing
368
475
 
@@ -373,9 +480,9 @@ Local setup, the release process and where the docs live are in
373
480
 
374
481
  MIT
375
482
 
376
- ## Onramp and offramp services
483
+ ## Onramp service
377
484
 
378
- Deploy an updated `deposit-widget-proxy` before enabling these opt-in clients.
485
+ Deploy an updated `deposit-widget-proxy` before enabling this opt-in client.
379
486
  Custom proxies must allow Authorization in CORS and forward customer routes
380
487
  without injecting `x-api-key`. Never proxy `POST /compliance/sessions` publicly.
381
488
 
@@ -386,12 +493,11 @@ and returns `{ externalCustomerId, smartAccount? }` from trusted server state.
386
493
  Mount its returned handler on your authenticated POST endpoint. It returns only
387
494
  the 15-minute `token` and `expiresAt`, with no-store response headers.
388
495
 
389
- Use separate scoped clients for onramp and offramp. The transport is internal;
390
- the package does not expose a generic customer service or arbitrary request method.
496
+ The client is scoped to the customer's bearer. The transport is internal; the
497
+ package does not expose a generic customer service or arbitrary request method.
391
498
 
392
499
  ```ts
393
500
  import { createOnrampService } from '@rhinestone/deposit-modal/onramp';
394
- import { createOfframpService } from '@rhinestone/deposit-modal/offramp';
395
501
  import { getComplianceStatus } from '@rhinestone/deposit-modal/compliance';
396
502
 
397
503
  const options = {
@@ -399,60 +505,44 @@ const options = {
399
505
  getSession: () => authenticatedSessionClient.getCustomerSession(),
400
506
  };
401
507
  const onramp = createOnrampService(options);
402
- const offramp = createOfframpService(options);
403
- const setup = await onramp.createSetup({
404
- purpose: 'account_setup',
405
- country: 'DE',
406
- currency: 'EUR',
407
- paymentMethod: 'bank_transfer',
408
- });
508
+ // Exactly one option, by region: EUR inside SEPA, USD elsewhere.
509
+ const { options: available } = await onramp.getOptions();
510
+ const { account } = await onramp.createAccount({ currency: available[0].currency });
409
511
  // Setup completes in this call and returns the account it configured.
410
512
  // Show the customer their bank details through a separate, repeatable call:
411
- const { nextAction } = await onramp.getAccountDetails(setup.account.id);
513
+ const { bankDetails } = await onramp.getAccountDetails(account.id);
514
+ // Each transfer into the account becomes an order, tracked stage by stage:
515
+ const { items: orders } = await onramp.listOrders({ limit: 10 });
412
516
  const status = await getComplianceStatus(options);
413
517
  ```
414
518
 
415
- The onramp client has `createSetup`, `getSetup`, `getOptions`, `listAccounts`,
416
- `getAccount`, `getAccountDetails`, `listPayments` and `getPayment`. The offramp
417
- client has session/options/payment methods, without accounts.
519
+ The client has `getOptions`, `createAccount`, `listAccounts`, `getAccount`,
520
+ `getAccountDetails` and `listOrders`, on the unified
521
+ `/onramp/options`, `/onramp/accounts` and `/onramp/orders` routes.
418
522
  `getComplianceStatus` retains the existing `/compliance/status` read separately;
419
- it is not a preliminary step. Shared types include `RampSession` (offramp),
420
- `OnrampSetup`, `RampOption` and `RampCurrency`.
421
- `CustomerSession` remains the browser bearer/expiry pair. Catch `ScopedRequestError`
422
- and inspect its `status` for HTTP failures; response bodies are not included.
523
+ it is not a preliminary step. Shared types include `OnrampOrder` (with its
524
+ `ReceiptStage`, `ConversionStage`, `DeliveryStage` and `ReturnStage`),
525
+ `OnrampAccount`, `RampOption` and `RampCurrency`. `CustomerSession` remains the
526
+ browser bearer/expiry pair. Catch `ScopedRequestError` and inspect its `status`
527
+ for HTTP failures; response bodies are not included.
423
528
 
424
- The three lightweight subpaths replace the unpublished `/customer` entry point.
425
- They do not import React, wallet connectors or the server-only token helper.
529
+ The lightweight subpaths do not import React, wallet connectors or the
530
+ server-only token helper.
426
531
 
427
532
  `getSession` is called per request. Keep tokens in memory, scoped to the logged-in
428
- user, and refresh them through your authenticated server. The clients reject
429
- expired sessions and never fall back to an application key. They make no calls
533
+ user, and refresh them through your authenticated server. The client rejects
534
+ expired sessions and never falls back to an application key. It makes no calls
430
535
  until explicitly invoked, so existing modals and Swapped flows remain unchanged.
431
- There is no preliminary capability request. Support/recovery methods belong to
432
- the future provider lifecycle implementation and are not exposed here.
433
-
434
- **An onramp setup is not a session.** It completes in the call that creates it
435
- and returns `{ id, account }` — no status to poll, no expiry, no `nextAction`.
436
- Bank details are read separately through `getAccountDetails`, because a customer
437
- reads them before every transfer while setup happens once; that call returns a
438
- hosted address and never the coordinates themselves. An offramp session keeps
439
- `RampSession` with its status, expiry and `nextAction`, because it really is one
440
- interaction.
441
-
442
- Routes are scoped to the provider that serves them — `/onramp/noah/*` and
443
- `/offramp/noah/*` here, while the existing Swapped flows keep their own paths.
444
- A proxy must allow each one explicitly; an unlisted path 404s before reaching
445
- the processor.
446
-
447
- The initial contracts support EUR/USD bank transfers only. Onramp setup
448
- uses `purpose: 'account_setup'` without an amount; the actual transfer determines
449
- fiat sent. Offramp hosted beneficiary collection uses
450
- `purpose: 'beneficiary_collection'`, separately from quoting and funding.
451
- Offramp options use `amount` as decimal fiat major units the recipient receives.
452
- No crypto-input quoting is exposed. Accounts return safe references/config/status,
453
- not bank instructions. Hosted interaction completion never means payment
454
- settlement; funding, payout and late returns have independent status fields.
455
-
456
- The provider adapter and journey execution are not connected by this release.
457
- Expect 503 until those implementations are deployed. Render hosted URLs only
458
- after the journey's iframe presentation has been verified; do not log/store URLs.
536
+
537
+ **An account setup is not a session.** It completes in the call that creates it
538
+ and returns `{ account }` — no status to poll, no expiry, no `nextAction`. Bank
539
+ details are read separately through `getAccountDetails`, because a customer
540
+ reads them before every transfer while setup happens once; that call returns
541
+ the stored instructions (`OnrampBankDetails`) and never calls the provider.
542
+
543
+ **An order is complete only once its crypto landed.** `stages.delivery` is
544
+ `submitted` when the provider reports the transfer and `completed`, with a
545
+ `depositId`, only once chain ingestion saw it. Show "delivered" for nothing
546
+ weaker. The initial contracts support EUR/USD bank transfers only; setup takes
547
+ a currency and no amount, because the actual transfer determines fiat sent. Do
548
+ not log or store hosted URLs.