@kuvarpay/sdk 1.4.2 → 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.
- package/README.md +132 -12
- package/index.d.ts +202 -5
- package/index.js +485 -44
- package/index.mjs +430 -35
- 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
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
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
|
}
|
|
@@ -55,11 +111,14 @@ export class KuvarPayServer {
|
|
|
55
111
|
getSessionStatus(sessionId: string): Promise<SessionStatusResult>;
|
|
56
112
|
getTransactionStatus(transactionId: string): Promise<TransactionStatusResult>;
|
|
57
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>;
|
|
58
117
|
verifyPayment(sessionId: string): Promise<VerifyPaymentResult>;
|
|
59
118
|
verifyWebhookSignature(payload: string | Buffer, signature: string, secret: string): boolean;
|
|
60
119
|
|
|
61
120
|
// Payments
|
|
62
|
-
getCurrencies(params?:
|
|
121
|
+
getCurrencies(params?: { network?: string; ticker?: string; search?: string; scope?: 'stablecoins' | 'popular' | 'all'; limit?: number; offset?: number; [key: string]: any }): Promise<any>;
|
|
63
122
|
calculatePayment(data: { fromCurrency: string; fromNetwork: string; toCurrency: string; toAmount: number }): Promise<any>;
|
|
64
123
|
createCheckoutSession(checkoutSessionData: {
|
|
65
124
|
amount: number;
|
|
@@ -73,6 +132,16 @@ export class KuvarPayServer {
|
|
|
73
132
|
subaccount?: string;
|
|
74
133
|
split_code?: string;
|
|
75
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
|
+
};
|
|
76
145
|
[key: string]: any;
|
|
77
146
|
}): Promise<{ sessionId: string; authToken?: string; approvalUrl?: string; raw: any }>;
|
|
78
147
|
|
|
@@ -89,6 +158,10 @@ export class KuvarPayServer {
|
|
|
89
158
|
metadata?: Record<string, any>;
|
|
90
159
|
subaccount?: string;
|
|
91
160
|
splitCode?: string;
|
|
161
|
+
/** FIAT rail only (fromNetwork: 'FIAT'). `country` is required by the gateway. */
|
|
162
|
+
country?: string;
|
|
163
|
+
methodId?: string;
|
|
164
|
+
phone?: string;
|
|
92
165
|
[key: string]: any;
|
|
93
166
|
}): Promise<any>;
|
|
94
167
|
|
|
@@ -115,7 +188,6 @@ export class KuvarPayServer {
|
|
|
115
188
|
}): Promise<any>;
|
|
116
189
|
|
|
117
190
|
getOptimalTransferFee(amount: number, currency?: string): Promise<any>;
|
|
118
|
-
sendInvoiceEmail(sessionId: string): Promise<any>;
|
|
119
191
|
|
|
120
192
|
createSubaccount(subaccountData: CreateSubaccountRequest): Promise<any>;
|
|
121
193
|
listSubaccounts(params?: { page?: number; perPage?: number }): Promise<any>;
|
|
@@ -158,14 +230,139 @@ export class KuvarPayServer {
|
|
|
158
230
|
revokeRelayAuthorization(body: Record<string, any>): Promise<any>;
|
|
159
231
|
|
|
160
232
|
// Renewal
|
|
161
|
-
createRenewalCheckoutSession(body:
|
|
233
|
+
createRenewalCheckoutSession(body: { subscriptionId?: string; id?: string; [key: string]: any }): Promise<any>;
|
|
162
234
|
renewSubscription(subscriptionId: string, body?: Record<string, any>): Promise<any>;
|
|
163
235
|
|
|
164
236
|
// Banks
|
|
165
|
-
getBanks(currency: string, options?: { type?: 'bank' | 'mobile_money';
|
|
166
|
-
getBanks(params
|
|
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 }> }>;
|
|
167
239
|
resolveBankAccount(data: { bank_code: string; account_number: string; country_code?: string }): Promise<any>;
|
|
168
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
|
+
|
|
169
366
|
// Sandbox
|
|
170
367
|
startSandboxSimulator(): Promise<any>;
|
|
171
368
|
stopSandboxSimulator(): Promise<any>;
|