@recoilpay/intent-core 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -33,7 +33,7 @@ await session.confirm(); // switch chain → approve →
33
33
 
34
34
  | Field | Meaning |
35
35
  |---|---|
36
- | `phase` | `idle` · `parsing` · `offTemplate` · `invalid` · `needsWallet` · `quoting` · `quoted` · `switchingChain` · `approving` · `signing` · `submitting` · `tracking` · `done` · `error` |
36
+ | `phase` | `idle` · `parsing` · `offTemplate` · `invalid` · `needsWallet` · `quoting` · `quoted` · `switchingChain` · `approving` · `signing` · `submitting` · `tracking` · `done` · `offramp` · `error` |
37
37
  | `ready` | The supported-asset list has loaded, so input can be accepted |
38
38
  | `hint` | When `offTemplate`, a sentence template to show the user |
39
39
  | `issues` | When `invalid`: every problem at once, each with `field`, `kind` and a user-facing `message` |
@@ -76,6 +76,47 @@ createIntentSession({
76
76
  });
77
77
  ```
78
78
 
79
+ ## Cash out to a bank (testnet)
80
+
81
+ A cash-out has its own session, because it collects bank details and can
82
+ take hours: the solver pays out over a bank rail, then the user confirms the
83
+ money arrived.
84
+
85
+ ```ts
86
+ import { createIntentSession, createOfframpSession, NG_BANKS, viemWallet } from '@recoilpay/intent-core';
87
+
88
+ await session.run('cash out 50 USDC on Base Sepolia to NGN');
89
+ // state.phase === 'offramp'; state.offramp is the resolved request
90
+
91
+ const offramp = createOfframpSession({ wallet: viemWallet(walletClient) });
92
+ await offramp.quote(session.getState().offramp!);
93
+ // offramp.getState().preview: payAmount, receiveAmount (₦), fee, rate, paymentWindowSecs
94
+
95
+ await offramp.confirm({ rail: 'ng.nip', bankCode: '058', account: '0123456789', name: 'Ada Obi' });
96
+ // switch chain → approve → open → sign the lock → the solver's relay locks it
97
+ // phase: 'awaitingFiat' → 'awaitingConfirmation' (the solver says it paid)
98
+
99
+ await offramp.confirmReceived(); // or offramp.dispute('Nothing arrived')
100
+ // phase: 'settled'
101
+ ```
102
+
103
+ - **Bank details stay private.** They are sealed in the browser to the
104
+ matched solver's key; the aggregator stores only the envelope and a salted
105
+ commitment. Never put them in the sentence: parsing goes to Hugging Face,
106
+ so `parseIntent` refuses text that looks like an account number.
107
+ - **Nothing is signed on trust.** Before asking the wallet to sign the lock,
108
+ the session checks it names the asset, amount, chain, escrow, solver,
109
+ payout and bank details the user chose (`checkLock`).
110
+ - **Your silence never pays the solver.** The escrow releases when the user
111
+ confirms, or on a provider-verified payout; if the user never answers, the
112
+ trade goes to an admin, not to the solver.
113
+ - **Keep `payeeSalt`.** With the bank details it proves which account the
114
+ solver was told to pay, if there is a dispute.
115
+ - **Resume** a trade after a reload with `offramp.resume(tradeId)`.
116
+ - Confirming and disputing use `IntentWallet.signMessage` (`viemWallet`
117
+ provides it). The messages are `fiatConfirmMessage` and
118
+ `fiatDisputeMessage`.
119
+
79
120
  ## Building your own flow
80
121
 
81
122
  Every step is exported on its own: `createApiClient` (parse, chains, supported assets, quotes, orders), `validateIntent`, `resolveIntent`, `buildQuoteRequest`, `signQuote`, the Permit2 helpers, and `interopAddress` (ERC-7930 encoding). The aggregator API is documented at https://docs.recoilpay.com/integrate/.