@kuvarpay/sdk 1.4.1 → 1.5.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 (5) hide show
  1. package/README.md +132 -12
  2. package/index.d.ts +224 -8
  3. package/index.js +486 -45
  4. package/index.mjs +430 -35
  5. package/package.json +4 -1
package/README.md CHANGED
@@ -1,6 +1,14 @@
1
1
  # KuvarPay Server SDK
2
2
 
3
- Official Node.js SDK for integrating **KuvarPay**, the ultimate fiat gateway for the crypto economy. This SDK allows you to handle checkout sessions, direct crypto-to-fiat transactions, recurring subscriptions, and split payments with ease.
3
+ Official Node.js SDK for **KuvarPay** — the payments gateway bridging crypto and local-currency rails. Collect from customers in **crypto _or_ local currency**, pay out to **bank / mobile money**, and run subscriptions and split payments — all from your backend.
4
+
5
+ **Capabilities**
6
+ - **Collect in crypto** — checkout sessions + crypto deposit addresses (USDT, USDC, BTC, … across BSC, Ethereum, Polygon, Tron, Solana, and more).
7
+ - **Collect in local currency (fiat)** — customers pay by bank transfer or mobile money (NGN, KES, GHS, ZAR, UGX, …); you still settle in your chosen currency. See [Fiat Collection](#-fiat-collection-pay-with-local-currency).
8
+ - **Pay out (fiat Sends)** — send to a recipient's bank account or mobile-money wallet, debited from your USD balance. See [Payouts](#-payouts-sends--secret-key-only).
9
+ - **Subscriptions** — fixed & metered recurring billing.
10
+ - **Split payments** — distribute revenue across subaccounts (bank / mobile money / crypto).
11
+ - **Hosted-checkout controls** — restrict rails, crypto tokens, and fiat countries (per business or per session).
4
12
 
5
13
  Detailed documentation is available at [developers.kuvarpay.com](https://developers.kuvarpay.com).
6
14
 
@@ -87,31 +95,143 @@ The SDK defaults to the KuvarPay Production API (`https://payment.kuvarpay.com`)
87
95
 
88
96
  | Method | Description |
89
97
  | :--- | :--- |
90
- | `getBanks(currency)` | List supported settlement banks for a specific currency. |
98
+ | `getBanks({ country? \| currency?, type? })` | List a corridor's **primary-rail** payment methods (banks / mobile money). Pass a country (ISO-2) or currency (ISO-4217). |
91
99
  | `resolveBankAccount(data)` | Verify bank account names before creating subaccounts. |
92
100
 
101
+ ### 🌍 Fiat Collection (Pay with Local Currency)
102
+
103
+ | Method | Description |
104
+ | :--- | :--- |
105
+ | **`createFiatPayment(data)`** | **One-shot**: checkout session + fiat transaction + wait for the deposit. Returns `{ sessionId, transactionId, depositId, nextAction, quote, paymentInstructions }`. |
106
+ | `getFiatCountries()` | Supported corridors. `code` is a **currency**; use **`countryCode`** (ISO-2) for any `country` param, and filter on `depositAvailable`. |
107
+ | `getFiatMethods({ country \| currency, type? })` | Banks / mobile-money operators. Takes ISO-2 `country` **or** ISO-4217 `currency`. Each entry carries a `methodId`. Unknown corridor → `{ methods: [] }`, not an error. |
108
+ | `getFiatCheckoutQuote({ amount, baseCurrency, currency, country })` | Preview the local amount a customer pays. |
109
+ | `createFiatTransaction(data)` | Create a fiat collection on a checkout session. |
110
+ | `waitForFiatDeposit(sessionId, options?)` | Bounded poll until the deposit attaches. Rejects with `FIAT_DEPOSIT_TIMEOUT`. |
111
+ | `getFiatDeposit(depositId)` | Poll a fiat deposit's status (self-reconciles with the provider on each read). |
112
+ | `submitFiatDepositAction(depositId, action, otp?)` | Drive the next step (`CONFIRM_QUOTE` / `SUBMIT_OTP`). |
113
+
114
+ The one-shot mirrors `createDirectPayment` but stops at the **quote** rather
115
+ than returning a ready-to-pay artifact: confirming locks the FX rate and fires
116
+ the customer's payment prompt, and the gateway withholds `paymentInstructions`
117
+ until then. Show `quote`, confirm, then show instructions.
118
+
119
+ ```javascript
120
+ const { methods } = await kv.getFiatMethods({ country: 'KE', type: 'mobile_money' });
121
+
122
+ const payment = await kv.createFiatPayment({
123
+ amount: 5000, currency: 'NGN', // you settle in NGN
124
+ fromCurrency: 'KES', country: 'KE', // customer pays in KES
125
+ methodId: methods[0].methodId,
126
+ phone: '+254701234567',
127
+ callbackUrl: 'https://your.app/webhooks',
128
+ });
129
+
130
+ if (payment.nextAction === 'CONFIRM_QUOTE') {
131
+ await kv.submitFiatDepositAction(payment.depositId, 'CONFIRM_QUOTE');
132
+ }
133
+ // Completion arrives on the payment.confirmed webhook — same as crypto.
134
+ ```
135
+
136
+ #### Tracking a fiat deposit — three ways
137
+
138
+ | Channel | For | How |
139
+ | :--- | :--- | :--- |
140
+ | **Webhook** | Any backend | Set `callbackUrl`; KuvarPay POSTs the final status. The canonical "done" signal — verify with `verifyWebhookSignature`. |
141
+ | **Polling** | Headless / server-side | `getSessionStatus(sessionId).fiatDeposit` → `getFiatDeposit(depositId)`. No browser required. |
142
+ | **SSE** | Browser checkout | Real-time `transaction.ready` push (the hosted checkout uses it) — a latency optimization, never a requirement. |
143
+
144
+ Server-side deposit flow with **no SSE** — poll the session for the `fiatDeposit` projection, confirm the quote, then poll the deposit to completion:
145
+
146
+ ```javascript
147
+ // 1. Create a session (+ webhook) and a fiat collection on it. createFiatPayment
148
+ // does steps 1-2 in one call; the long-hand is shown here for clarity.
149
+ const session = await kv.createCheckoutSession({ amount: 5, currency: 'USD', callbackUrl: 'https://you.com/webhook' });
150
+ await kv.createFiatTransaction({ checkoutSessionId: session.sessionId, fromCurrency: 'KES', country: 'KE', methodId, phone: '+2547...' });
151
+
152
+ // 2. The deposit is created async by the worker — wait for it to attach.
153
+ // Bounded with backoff; rejects with code FIAT_DEPOSIT_TIMEOUT on expiry.
154
+ const deposit = await kv.waitForFiatDeposit(session.sessionId, { timeoutMs: 30000 });
155
+
156
+ // 3. Confirm the quote → returns paymentInstructions (account/MoMo to pay, or fires the STK push).
157
+ const confirmed = await kv.submitFiatDepositAction(deposit.depositId, 'CONFIRM_QUOTE');
158
+ console.log(confirmed.paymentInstructions);
159
+
160
+ // 4. Customer pays. The payment.confirmed webhook is the canonical signal —
161
+ // only block like this if you genuinely need a synchronous result.
162
+ const settled = await kv.waitForFiatDeposit(session.sessionId, {
163
+ until: d => ['CREDITED', 'EXPIRED', 'REFUNDED', 'FAILED'].includes(String(d.status).toUpperCase()),
164
+ timeoutMs: 600000, // customers take minutes, not seconds
165
+ pollIntervalMs: 5000,
166
+ });
167
+ ```
168
+
169
+ ### 💸 Payouts (Sends) — Secret key only
170
+
171
+ Payouts move money **out** of your USD balance to a recipient's bank or mobile-money account. The gateway **rejects client/publishable keys** on these endpoints — they must only ever run server-side with your secret key. Payouts settle asynchronously; listen for the completion **webhook** (verify it with `verifyWebhookSignature`), or poll `getFiatSend(sendId)` for server-side reconciliation.
172
+
173
+ | Method | Description |
174
+ | :--- | :--- |
175
+ | `getFiatMethods({ country, type?, direction: 'outbound' })` | List payout (outbound) banks / mobile-money operators. |
176
+ | `resolveRecipient({ methodId, accountNumber?, phone? })` | Name-enquiry on a payout recipient before sending. |
177
+ | `createFiatSend(data)` | Initiate a bank / mobile-money payout (USD-debited). |
178
+ | `getFiatSend(sendId)` | Poll a payout's status (`PROCESSING` → `COMPLETED`/`FAILED`/`REFUNDED`). |
179
+
180
+ ```javascript
181
+ // Discover payout methods, then verify the recipient name before sending.
182
+ const { methods } = await kv.getFiatMethods({ country: 'NG', type: 'bank', direction: 'outbound' });
183
+ const recipient = await kv.resolveRecipient({ methodId: methods[0].methodId, accountNumber: '0123456789' });
184
+
185
+ // Fiat payout: recipient receives exactly 50,000 NGN; USD debited from your balance.
186
+ if (recipient.resolved) {
187
+ const { sendId } = await kv.createFiatSend({
188
+ destinationCountry: 'NG',
189
+ destinationCurrency: 'NGN',
190
+ destinationAmount: 50000,
191
+ recipient: { methodId: methods[0].methodId, accountNumber: '0123456789', accountName: recipient.accountName },
192
+ narration: 'Vendor payout',
193
+ });
194
+
195
+ // Prefer the completion webhook; getFiatSend is available for reconciliation.
196
+ const send = await kv.getFiatSend(sendId);
197
+ console.log(send.status); // PROCESSING | COMPLETED | FAILED | REFUNDED
198
+ }
199
+ ```
200
+
201
+ > `ownerType`/`ownerId` default to your business (`MERCHANT` + your `businessId`), so you don't need to pass them.
202
+
93
203
  ---
94
204
 
95
205
  ## 🔒 Security: Webhook Verification
96
206
 
97
- Verify that incoming webhooks are genuinely from KuvarPay using HMAC-SHA256:
207
+ Verify that incoming webhooks are genuinely from KuvarPay using HMAC-SHA256.
208
+
209
+ Two things matter: verify against the **raw** request body (the signature is
210
+ computed over the exact bytes sent, so a re-serialized `req.body` will not
211
+ match), and pass your **webhook secret** as the third argument.
98
212
 
99
213
  ```javascript
100
- app.post('/webhooks/kuvarpay', (req, res) => {
214
+ // Mount the raw body parser on the webhook route only.
215
+ app.post('/webhooks/kuvarpay', express.raw({ type: 'application/json' }), (req, res) => {
101
216
  const signature = req.headers['x-kuvarpay-signature'];
102
- const payload = req.body; // Raw body object
103
217
 
104
- const isValid = kv.verifyWebhookSignature(payload, signature);
218
+ // req.body is a Buffer here — that is what gets signed.
219
+ const isValid = kv.verifyWebhookSignature(req.body, signature, process.env.KUVARPAY_WEBHOOK_SECRET);
105
220
 
106
- if (isValid) {
107
- // Process payment (e.g. status === 'completed')
108
- res.status(200).send();
109
- } else {
110
- res.status(401).send('Invalid signature');
111
- }
221
+ if (!isValid) return res.status(401).send('Invalid signature');
222
+
223
+ const event = JSON.parse(req.body.toString('utf8'));
224
+ // Process payment (e.g. event.event === 'payment.confirmed')
225
+ res.status(200).send();
112
226
  });
113
227
  ```
114
228
 
229
+ The gateway sends the header as `sha256=<hex>`. `verifyWebhookSignature`
230
+ strips that prefix for you and accepts a bare hex digest too, so pass the
231
+ header through unmodified. It returns `false` on a bad or malformed
232
+ signature and never throws — always reply `2xx` once you have accepted an
233
+ event, since any `5xx` is treated as a failed delivery and retried.
234
+
115
235
  ---
116
236
 
117
237
  ## 🧩 TypeScript Support
package/index.d.ts CHANGED
@@ -6,10 +6,66 @@ export interface KuvarPayServerConfig {
6
6
  fetchImpl?: (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
7
7
  }
8
8
 
9
+ /**
10
+ * Linked fiat-deposit projection attached to a checkout session, so a
11
+ * server-side integrator can track a local-currency payment by polling
12
+ * `getSessionStatus()` instead of relying on the browser SSE stream.
13
+ * `null` for crypto checkouts or before a fiat transaction is created.
14
+ */
15
+ /**
16
+ * The next step the payer must take on a fiat deposit, as derived by the
17
+ * gateway. `CONFIRM_QUOTE` and `ENTER_OTP` are driven via
18
+ * `submitFiatDepositAction`; `ENTER_PIN` needs no API call (the customer
19
+ * approves on their handset) — keep polling. `NONE` means nothing is pending.
20
+ *
21
+ * Widened with `(string & {})` so a new server-side value cannot break a build,
22
+ * while literal autocomplete still works.
23
+ */
24
+ export type FiatNextAction =
25
+ | 'CONFIRM_QUOTE'
26
+ | 'ENTER_OTP'
27
+ | 'ENTER_PIN'
28
+ | 'NONE'
29
+ | (string & {});
30
+
31
+ export interface FiatCountry {
32
+ /** ISO-4217 currency code (KES, NGN, …). NOT a country code. */
33
+ code: string;
34
+ /** Currency display name ("Kenyan Shillings"). */
35
+ name: string;
36
+ /** Country display name ("Kenya"). May echo the currency on un-backfilled rows. */
37
+ country: string;
38
+ /** Resolved ISO-3166 alpha-2 ("KE"). Use this for any `country` parameter. */
39
+ countryCode: string | null;
40
+ symbol?: string;
41
+ flag?: string;
42
+ supportsBank?: boolean;
43
+ supportsMobileMoney?: boolean;
44
+ /** Corridor has no active provider — neither deposit nor payout works. */
45
+ comingSoon?: boolean;
46
+ /** A collection (deposit) channel is live right now. Filter on this. */
47
+ depositAvailable?: boolean;
48
+ }
49
+
50
+ export interface FiatDepositProjection {
51
+ depositId: string;
52
+ status: string;
53
+ nextAction: FiatNextAction | null;
54
+ paymentInstructions: any | null;
55
+ quote: any | null;
56
+ channelKind?: 'mobile_money' | 'bank' | null;
57
+ currency?: string | null;
58
+ depositedAmount?: number | null;
59
+ creditedAmountUsd?: number | null;
60
+ expiresAt?: string | null;
61
+ }
62
+
9
63
  export interface SessionStatusResult {
10
64
  sessionId: string;
11
65
  status?: string;
12
66
  transactionId: string | null;
67
+ /** Fiat deposit projection (poll this for headless/no-SSE integrations). */
68
+ fiatDeposit?: FiatDepositProjection | null;
13
69
  metadata?: Record<string, any>;
14
70
  raw: any;
15
71
  }
@@ -30,16 +86,39 @@ export interface VerifyPaymentResult {
30
86
  raw: any;
31
87
  }
32
88
 
89
+ export interface CreateSubaccountRequest {
90
+ business_name: string;
91
+ percentage_charge?: number | string;
92
+ currency?: string;
93
+ account_name?: string;
94
+ settlement_bank?: string;
95
+ account_number?: string;
96
+ mobile_money_number?: string;
97
+ mobile_money_provider?: string;
98
+ crypto_currency?: string;
99
+ crypto_network?: string;
100
+ wallet_address?: string;
101
+ primary_contact_email?: string;
102
+ primary_contact_phone?: string;
103
+ description?: string;
104
+ metadata?: Record<string, any>;
105
+ type?: string | 'BANK_TRANSFER' | 'MOBILE_MONEY' | 'CRYPTO';
106
+ [key: string]: any;
107
+ }
108
+
33
109
  export class KuvarPayServer {
34
110
  constructor(config?: KuvarPayServerConfig);
35
111
  getSessionStatus(sessionId: string): Promise<SessionStatusResult>;
36
112
  getTransactionStatus(transactionId: string): Promise<TransactionStatusResult>;
37
113
  getTransactionStatusByReference(reference: string): Promise<any>;
114
+ updateTransactionStatus(transactionId: string, data: Record<string, any>): Promise<any>;
115
+ /** Sandbox only. */
116
+ demoPay(transactionId: string): Promise<any>;
38
117
  verifyPayment(sessionId: string): Promise<VerifyPaymentResult>;
39
118
  verifyWebhookSignature(payload: string | Buffer, signature: string, secret: string): boolean;
40
119
 
41
120
  // Payments
42
- getCurrencies(params?: Record<string, any>): Promise<any>;
121
+ getCurrencies(params?: { network?: string; ticker?: string; search?: string; scope?: 'stablecoins' | 'popular' | 'all'; limit?: number; offset?: number; [key: string]: any }): Promise<any>;
43
122
  calculatePayment(data: { fromCurrency: string; fromNetwork: string; toCurrency: string; toAmount: number }): Promise<any>;
44
123
  createCheckoutSession(checkoutSessionData: {
45
124
  amount: number;
@@ -53,6 +132,16 @@ export class KuvarPayServer {
53
132
  subaccount?: string;
54
133
  split_code?: string;
55
134
  metadata?: Record<string, any>;
135
+ /**
136
+ * Per-session hosted-checkout controls — override the merchant's dashboard
137
+ * defaults for this session. Omit to inherit the business defaults.
138
+ */
139
+ checkoutConfig?: {
140
+ methods?: Array<'crypto' | 'fiat'>; // which rails to offer
141
+ cryptoScope?: 'stablecoins' | 'popular' | 'all';
142
+ cryptoAllowlist?: string[] | null; // token keys "TICKER|network"; overrides scope
143
+ fiatCountries?: string[] | null; // ISO-3166 alpha-2 allow-list
144
+ };
56
145
  [key: string]: any;
57
146
  }): Promise<{ sessionId: string; authToken?: string; approvalUrl?: string; raw: any }>;
58
147
 
@@ -69,6 +158,10 @@ export class KuvarPayServer {
69
158
  metadata?: Record<string, any>;
70
159
  subaccount?: string;
71
160
  splitCode?: string;
161
+ /** FIAT rail only (fromNetwork: 'FIAT'). `country` is required by the gateway. */
162
+ country?: string;
163
+ methodId?: string;
164
+ phone?: string;
72
165
  [key: string]: any;
73
166
  }): Promise<any>;
74
167
 
@@ -95,13 +188,11 @@ export class KuvarPayServer {
95
188
  }): Promise<any>;
96
189
 
97
190
  getOptimalTransferFee(amount: number, currency?: string): Promise<any>;
98
- sendInvoiceEmail(sessionId: string): Promise<any>;
99
191
 
100
- // Subaccounts
101
- createSubaccount(subaccountData: Record<string, any>): Promise<any>;
192
+ createSubaccount(subaccountData: CreateSubaccountRequest): Promise<any>;
102
193
  listSubaccounts(params?: { page?: number; perPage?: number }): Promise<any>;
103
194
  getSubaccount(code: string): Promise<any>;
104
- updateSubaccount(code: string, subaccountData: Record<string, any>): Promise<any>;
195
+ updateSubaccount(code: string, subaccountData: Partial<CreateSubaccountRequest>): Promise<any>;
105
196
  deleteSubaccount(code: string): Promise<any>;
106
197
 
107
198
  // Split Groups
@@ -139,14 +230,139 @@ export class KuvarPayServer {
139
230
  revokeRelayAuthorization(body: Record<string, any>): Promise<any>;
140
231
 
141
232
  // Renewal
142
- createRenewalCheckoutSession(body: Record<string, any>): Promise<any>;
233
+ createRenewalCheckoutSession(body: { subscriptionId?: string; id?: string; [key: string]: any }): Promise<any>;
143
234
  renewSubscription(subscriptionId: string, body?: Record<string, any>): Promise<any>;
144
235
 
145
236
  // Banks
146
- getBanks(currency: string, options?: { type?: 'bank' | 'mobile_money'; country?: string }): Promise<any>;
147
- getBanks(params?: { currency?: string; type?: 'bank' | 'mobile_money'; country?: string }): Promise<any>;
237
+ getBanks(currency: string, options?: { type?: 'bank' | 'mobile_money'; direction?: 'inbound' | 'outbound' }): Promise<{ methods: Array<{ methodId: string; name: string; currency: string; type: 'bank' | 'mobile_money'; manualInput?: boolean; minAmount?: number | null; maxAmount?: number | null }> }>;
238
+ getBanks(params: { country?: string; currency?: string; type?: 'bank' | 'mobile_money'; direction?: 'inbound' | 'outbound' }): Promise<{ methods: Array<{ methodId: string; name: string; currency: string; type: 'bank' | 'mobile_money'; manualInput?: boolean; minAmount?: number | null; maxAmount?: number | null }> }>;
148
239
  resolveBankAccount(data: { bank_code: string; account_number: string; country_code?: string }): Promise<any>;
149
240
 
241
+ // Fiat collection (Pay with Local Currency)
242
+ /**
243
+ * Supported corridors. Note `code` is an ISO-4217 CURRENCY and `country` is
244
+ * a display name — use **`countryCode`** wherever an ISO-2 is required
245
+ * (`getFiatMethods`, `createFiatPayment`, `createFiatTransaction`). The SDK
246
+ * guarantees `countryCode` even on gateways that don't yet return it.
247
+ * Only corridors with `depositAvailable` can accept a collection.
248
+ */
249
+ getFiatCountries(): Promise<{ success: boolean; countries: FiatCountry[] }>;
250
+ /**
251
+ * Accepts an ISO-3166 alpha-2 country ("KE") or an ISO-4217 currency
252
+ * ("KES"). Note `getFiatCountries()` returns its identifier as `code`,
253
+ * which is a CURRENCY — pass it as `currency`, or as `country` and the SDK
254
+ * will route 3-letter codes correctly.
255
+ */
256
+ getFiatMethods(params: { country?: string; currency?: string; type?: 'bank' | 'mobile_money'; sandbox?: boolean; direction?: 'inbound' | 'outbound' }): Promise<{ methods: Array<{ methodId: string; name: string; currency: string; type: 'bank' | 'mobile_money'; manualInput?: boolean; minAmount?: number | null; maxAmount?: number | null }> }>;
257
+ getFiatCheckoutQuote(params: { amount: number; baseCurrency: string; currency: string; country: string }): Promise<any>;
258
+ createFiatTransaction(data: {
259
+ checkoutSessionId: string;
260
+ fromCurrency: string;
261
+ country: string;
262
+ methodId?: string;
263
+ phone?: string;
264
+ customerEmail?: string;
265
+ customerName?: string;
266
+ [key: string]: any;
267
+ }): Promise<any>;
268
+ getFiatDeposit(depositId: string): Promise<any>;
269
+ submitFiatDepositAction(depositId: string, action: 'CONFIRM_QUOTE' | 'SUBMIT_OTP', otp?: string): Promise<any>;
270
+ simulateFiatDepositComplete(depositId: string): Promise<any>;
271
+
272
+ /**
273
+ * Poll a checkout session until its fiat deposit projection appears.
274
+ * Bounded by `timeoutMs` with backoff; rejects with an Error carrying
275
+ * `code: 'FIAT_DEPOSIT_TIMEOUT'` and `lastDeposit` on expiry.
276
+ */
277
+ waitForFiatDeposit(
278
+ sessionId: string,
279
+ options?: {
280
+ timeoutMs?: number;
281
+ pollIntervalMs?: number;
282
+ maxIntervalMs?: number;
283
+ /** Defaults to "deposit exists". e.g. `d => d.status === 'CREDITED'`. */
284
+ until?: (deposit: FiatDepositProjection) => boolean;
285
+ }
286
+ ): Promise<FiatDepositProjection>;
287
+
288
+ /**
289
+ * One-shot local-currency collection: checkout session + fiat transaction +
290
+ * wait for the deposit. Stops at the quote unless `autoConfirmQuote` is set —
291
+ * confirming locks the FX rate and fires the customer's payment prompt, and
292
+ * `paymentInstructions` stay null until it happens.
293
+ */
294
+ createFiatPayment(data: {
295
+ amount: number;
296
+ currency: string;
297
+ fromCurrency: string;
298
+ country: string;
299
+ methodId?: string;
300
+ phone?: string;
301
+ description?: string;
302
+ customerEmail?: string;
303
+ customerName?: string;
304
+ redirectUrl?: string;
305
+ callbackUrl?: string;
306
+ expiresIn?: number;
307
+ metadata?: Record<string, any>;
308
+ subaccount?: string;
309
+ split_code?: string;
310
+ /** Skip the poll and return as soon as the transaction is created. */
311
+ waitForDeposit?: boolean;
312
+ /** Confirm the quote automatically. Off by default — this charges. */
313
+ autoConfirmQuote?: boolean;
314
+ timeoutMs?: number;
315
+ pollIntervalMs?: number;
316
+ }): Promise<{
317
+ sessionId: string;
318
+ transactionId: string | null;
319
+ depositId: string | null;
320
+ nextAction: FiatNextAction | null;
321
+ quote: any | null;
322
+ paymentInstructions: any | null;
323
+ deposit: FiatDepositProjection | null;
324
+ session: any;
325
+ transaction: any;
326
+ }>;
327
+
328
+ // Payouts (Sends) — SECRET key only. Money OUT of your USD balance.
329
+ resolveRecipient(data: { methodId: string; accountNumber?: string; phone?: string }): Promise<{
330
+ supported: boolean;
331
+ resolved: boolean;
332
+ accountName: string | null;
333
+ bankName?: string;
334
+ reason?: string | null;
335
+ }>;
336
+ createFiatSend(data: {
337
+ destinationCountry: string;
338
+ destinationCurrency: string;
339
+ recipient: {
340
+ methodId: string;
341
+ accountNumber?: string;
342
+ accountName?: string;
343
+ phone?: string;
344
+ manualInput?: Record<string, any>;
345
+ };
346
+ sourceAmountUsd?: number;
347
+ destinationAmount?: number;
348
+ depositId?: string;
349
+ narration?: string;
350
+ metadata?: Record<string, any>;
351
+ ownerType?: 'MERCHANT' | 'USER';
352
+ ownerId?: string;
353
+ }): Promise<{ sendId: string }>;
354
+ getFiatSend(sendId: string): Promise<{
355
+ sendId: string;
356
+ status: 'PROCESSING' | 'COMPLETED' | 'FAILED' | 'REFUNDED' | 'DISPUTED' | string;
357
+ sourceAmountUsd: number;
358
+ destinationCountry: string;
359
+ destinationCurrency: string;
360
+ destinationAmount: number | null;
361
+ settledAt: string | null;
362
+ createdAt: string;
363
+ updatedAt: string;
364
+ }>;
365
+
150
366
  // Sandbox
151
367
  startSandboxSimulator(): Promise<any>;
152
368
  stopSandboxSimulator(): Promise<any>;