@rhinestone/deposit-modal 0.19.0 → 0.20.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.
Files changed (83) hide show
  1. package/README.md +154 -61
  2. package/dist/BankOnrampStep-3SNUX6V2.cjs +435 -0
  3. package/dist/BankOnrampStep-4D24HVHV.mjs +435 -0
  4. package/dist/{DepositModalReown-UITYXJ6W.cjs → DepositModalReown-7EHOJTFW.cjs} +21 -20
  5. package/dist/{DepositModalReown-XBNY6QCI.mjs → DepositModalReown-SYQ2SCHC.mjs} +6 -5
  6. package/dist/WithdrawModal-LLJLEYXZ.cjs +12 -0
  7. package/dist/WithdrawModal-LXDIT4UV.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-FTWKAJGN.mjs → chunk-2FOPO4N5.mjs} +1 -1
  13. package/dist/{chunk-EG4H7OMC.cjs → chunk-CIVFT5KR.cjs} +171 -130
  14. package/dist/{chunk-PYOC6K24.cjs → chunk-D3R3O4CY.cjs} +1 -1
  15. package/dist/chunk-E7IMWVMN.mjs +346 -0
  16. package/dist/chunk-EJDBIWNH.mjs +113 -0
  17. package/dist/chunk-FKJ6EJHH.cjs +346 -0
  18. package/dist/{chunk-LVCD6RHF.cjs → chunk-FVJKUTHF.cjs} +2 -2
  19. package/dist/{chunk-NITKDXHR.mjs → chunk-FW7ZMXQS.mjs} +849 -674
  20. package/dist/chunk-G264OM23.cjs +224 -0
  21. package/dist/chunk-IPHKBBUV.cjs +113 -0
  22. package/dist/{chunk-BIL4ENC3.mjs → chunk-IPKT3FU6.mjs} +73 -32
  23. package/dist/chunk-JPX4MEHV.mjs +19 -0
  24. package/dist/{chunk-HMUGY66O.cjs → chunk-KXSU24RU.cjs} +1569 -1019
  25. package/dist/{chunk-ISLVD5HQ.cjs → chunk-LVMNNMOZ.cjs} +10 -5
  26. package/dist/chunk-O5OW4S7L.cjs +19 -0
  27. package/dist/{chunk-5NWLS5BQ.mjs → chunk-OZPMRTW3.mjs} +1511 -961
  28. package/dist/{chunk-OCWSMLOP.cjs → chunk-PVFEZ3UG.cjs} +1164 -989
  29. package/dist/{chunk-ZGHVJ2XM.mjs → chunk-YQCRXJIL.mjs} +8 -3
  30. package/dist/chunk-YY4ZOAH5.mjs +224 -0
  31. package/dist/{chunk-X6N2XPTO.mjs → chunk-ZOJMB5TZ.mjs} +1 -1
  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-BOxa1DE-.d.ts → types-BEEMfNi2.d.cts} +24 -4
  64. package/dist/{types-BShYNpvO.d.cts → types-DQDUqzsZ.d.ts} +24 -4
  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,17 @@ 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
+ > Forward `GET /onramp/providers` with the key too: the modal offers only the
321
+ > onramps your project has (Cash and exchange rows, bank details). Without it,
322
+ > every row your props enable is offered, as before.
323
+
297
324
  Host CSP must allow Swapped's domains:
298
325
 
299
326
  ```
@@ -308,9 +335,92 @@ frame-src https://widget.swapped.com https://sandbox.swapped.com https://connect
308
335
  | `enableQrTransfer` | `boolean` | `true` | Show the Transfer Crypto / QR row. Set false for fiat-only. |
309
336
  | `fiatMethods` | `FiatMethodsConfig` | regional | Optional exact subset of standard `payment_group`s. Providing it opts out of regional personalization; empty means none. |
310
337
 
338
+ ### Bank transfer accounts (Noah)
339
+
340
+ > **Preview.** Your proxy must forward these on the customer bearer before you ship
341
+ > a modal with `bankOnramp`: `GET /compliance/status`, `POST /compliance/verification`,
342
+ > `GET /onramp/options`, `POST`/`GET /onramp/accounts`,
343
+ > `GET /onramp/accounts/:id[/details]` and `GET /onramp/orders[/:id]`. A missing one
344
+ > 404s at the proxy. [`deposit-widget-proxy`](https://github.com/rhinestonewtf/deposit-widget-proxy)
345
+ > forwards all of them.
346
+ >
347
+ > The prop is opt-in and inert unless you pass it. Treat it as unstable until
348
+ > this note is removed.
349
+
350
+ Pass `bankOnramp` to use reusable USD/EUR account details when Noah is provisioned
351
+ for your organization. Integrator KYB happens directly with Noah; Rhinestone
352
+ enables provisioning after Noah confirms it. Card and Apple Pay continue through Swapped. A customer who has
353
+ not been verified is taken through hosted verification first; an existing active
354
+ account is resumed; otherwise the account is configured once. There is no account
355
+ selection: the customer's one account opens directly.
356
+
357
+ Rhinestone chooses the currency from the residence the customer declares during
358
+ verification: EUR inside SEPA, USD elsewhere. It is not configurable, and it does
359
+ not follow the customer's location. The options are read again once the customer
360
+ is approved, because only then is the residence known.
361
+
362
+ The modal checks `GET /onramp/options?provider=noah` before customer verification. A 404
363
+ (provisioning disabled, a declared residence Noah doesn't serve, or an older proxy)
364
+ routes bank transfer through Swapped. When Swapped's regional list has no bank transfer
365
+ either, the customer returns to the Cash methods with a notice and the row hidden.
366
+ A successful response keeps Noah exclusive, even when no currencies are available.
367
+ Authentication and service errors show a retry instead of switching providers.
368
+
369
+ Bank transfers appear in History, including transfers that never become chain
370
+ deposits. The History icon stays available during Noah verification and bank details;
371
+ new activity adds a dot without navigating away.
372
+ Opening History acknowledges that activity and clears the bank notification;
373
+ only a subsequent new transfer or stage change adds it again.
374
+ After entering the bank journey, History refreshes `GET /onramp/orders?provider=noah` every 30 seconds while the modal
375
+ is open and visible, and on focus or opening History. Discovery continues after a
376
+ transfer finishes so the next one is detected. A linked deposit shares the entry
377
+ and shows final settlement separately from the provider's delivery.
378
+ Each bank-transfer entry shows its amount, date and latest status rather than
379
+ individual provider stages. "Settled" means crypto reached the deposit account;
380
+ "Completed" requires the linked deposit's final settlement to complete.
381
+ Expanded fiat entries use the same explorer links as crypto History: the
382
+ incoming crypto deposit and, when available, final settlement on its destination
383
+ chain. No on-chain link is shown for a fiat-only or sub-fee transfer.
384
+
385
+ ```tsx
386
+ <DepositModal
387
+ bankOnramp={{
388
+ supportUrl: "https://your-app.example/support", // Optional bank-transfer help.
389
+ getSession: (smartAccount) =>
390
+ authenticatedSessionClient.getCustomerSession({ smartAccount }),
391
+ }}
392
+ // ...
393
+ />
394
+ ```
395
+
396
+ `getSession` must call your authenticated server endpoint, which mints a
397
+ short-lived customer session with `createCustomerSessionHandler`. It is called
398
+ for every request; do not put the Rhinestone API key in the browser.
399
+
400
+ Bank instructions render inside the modal from `GET /onramp/accounts/:id/details`
401
+ on the customer bearer: separate transfer rails (SWIFT, ACH, Wire, SEPA), copy
402
+ controls, an optional payment reference, and the last-quoted fee with its
403
+ capture date. The modal holds coordinates only in component state and clears
404
+ them on exit. Do not send them to analytics or persist them in the host
405
+ application. A `409` means the account predates snapshot capture and the
406
+ processor backfill has not run; the customer is told to check back. Only identity
407
+ verification uses Noah's hosted page.
408
+
409
+ `bankOnramp` enables Cash when `fiatMethods` is omitted. When an exact
410
+ `fiatMethods` subset is provided, it must include
411
+ `{ "bank-transfer": true }`. The proxy must forward the `/onramp/options`,
412
+ `/onramp/accounts` and `/onramp/orders` customer routes with the bearer token
413
+ and without attaching its API key.
414
+
415
+ Hosts with a strict CSP must allow Noah Checkout:
416
+
417
+ ```
418
+ frame-src https://checkout.noah.com https://checkout.sandbox.noah.com;
419
+ ```
420
+
311
421
  ## Fund from Exchange (Swapped Connect)
312
422
 
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.
423
+ 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
424
 
315
425
  ```tsx
316
426
  <DepositModal
@@ -362,7 +472,7 @@ integration now posts analytics too, so it needs the `connect-src` above.
362
472
  Upgrading from 0.8.x is a breaking change on both modals.
363
473
 
364
474
  See [`MIGRATION.md`](./MIGRATION.md), or the same guide
365
- [in the docs](https://docs.rhinestone.dev/deposits/widget/migration).
475
+ [in the docs](https://docs.rhinestone.dev/deposits/overview/widget/migration-guide).
366
476
 
367
477
  ## Contributing
368
478
 
@@ -373,9 +483,9 @@ Local setup, the release process and where the docs live are in
373
483
 
374
484
  MIT
375
485
 
376
- ## Onramp and offramp services
486
+ ## Onramp service
377
487
 
378
- Deploy an updated `deposit-widget-proxy` before enabling these opt-in clients.
488
+ Deploy an updated `deposit-widget-proxy` before enabling this opt-in client.
379
489
  Custom proxies must allow Authorization in CORS and forward customer routes
380
490
  without injecting `x-api-key`. Never proxy `POST /compliance/sessions` publicly.
381
491
 
@@ -386,12 +496,11 @@ and returns `{ externalCustomerId, smartAccount? }` from trusted server state.
386
496
  Mount its returned handler on your authenticated POST endpoint. It returns only
387
497
  the 15-minute `token` and `expiresAt`, with no-store response headers.
388
498
 
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.
499
+ The client is scoped to the customer's bearer. The transport is internal; the
500
+ package does not expose a generic customer service or arbitrary request method.
391
501
 
392
502
  ```ts
393
503
  import { createOnrampService } from '@rhinestone/deposit-modal/onramp';
394
- import { createOfframpService } from '@rhinestone/deposit-modal/offramp';
395
504
  import { getComplianceStatus } from '@rhinestone/deposit-modal/compliance';
396
505
 
397
506
  const options = {
@@ -399,60 +508,44 @@ const options = {
399
508
  getSession: () => authenticatedSessionClient.getCustomerSession(),
400
509
  };
401
510
  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
- });
511
+ // Exactly one option, by region: EUR inside SEPA, USD elsewhere.
512
+ const { options: available } = await onramp.getOptions();
513
+ const { account } = await onramp.createAccount({ currency: available[0].currency });
409
514
  // Setup completes in this call and returns the account it configured.
410
515
  // Show the customer their bank details through a separate, repeatable call:
411
- const { nextAction } = await onramp.getAccountDetails(setup.account.id);
516
+ const { bankDetails } = await onramp.getAccountDetails(account.id);
517
+ // Each transfer into the account becomes an order, tracked stage by stage:
518
+ const { items: orders } = await onramp.listOrders({ limit: 10 });
412
519
  const status = await getComplianceStatus(options);
413
520
  ```
414
521
 
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.
522
+ The client has `getOptions`, `createAccount`, `listAccounts`, `getAccount`,
523
+ `getAccountDetails` and `listOrders`, on the unified
524
+ `/onramp/options`, `/onramp/accounts` and `/onramp/orders` routes.
418
525
  `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.
526
+ it is not a preliminary step. Shared types include `OnrampOrder` (with its
527
+ `ReceiptStage`, `ConversionStage`, `DeliveryStage` and `ReturnStage`),
528
+ `OnrampAccount`, `RampOption` and `RampCurrency`. `CustomerSession` remains the
529
+ browser bearer/expiry pair. Catch `ScopedRequestError` and inspect its `status`
530
+ for HTTP failures; response bodies are not included.
423
531
 
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.
532
+ The lightweight subpaths do not import React, wallet connectors or the
533
+ server-only token helper.
426
534
 
427
535
  `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
536
+ user, and refresh them through your authenticated server. The client rejects
537
+ expired sessions and never falls back to an application key. It makes no calls
430
538
  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.
539
+
540
+ **An account setup is not a session.** It completes in the call that creates it
541
+ and returns `{ account }` — no status to poll, no expiry, no `nextAction`. Bank
542
+ details are read separately through `getAccountDetails`, because a customer
543
+ reads them before every transfer while setup happens once; that call returns
544
+ the stored instructions (`OnrampBankDetails`) and never calls the provider.
545
+
546
+ **An order is complete only once its crypto landed.** `stages.delivery` is
547
+ `submitted` when the provider reports the transfer and `completed`, with a
548
+ `depositId`, only once chain ingestion saw it. Show "delivered" for nothing
549
+ weaker. The initial contracts support EUR/USD bank transfers only; setup takes
550
+ a currency and no amount, because the actual transfer determines fiat sent. Do
551
+ not log or store hosted URLs.