monime-package 1.0.4 → 1.0.6

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
@@ -1,9 +1,11 @@
1
1
 
2
2
  # monime-package
3
3
 
4
- A **TypeScript SDK for Monime**, providing a lightweight, typed client for common Monime endpoints. Simplifies requests, headers, and error handling so your code stays clean and type-safe.
4
+ Official, lightweight TypeScript SDK for Monime. It provides a typed client for common Monime endpoints with consistent results and simple ergonomics.
5
5
 
6
- ![TypeScript](https://img.shields.io/badge/TypeScript-4.9-blue.svg)
6
+ ![npm version](https://img.shields.io/npm/v/monime-package.svg)
7
+ ![npm downloads](https://img.shields.io/npm/dm/monime-package.svg)
8
+ ![TypeScript](https://img.shields.io/badge/TypeScript-5.9-blue.svg)
7
9
  ![Node.js](https://img.shields.io/badge/Node.js-%3E=14-green.svg)
8
10
  ![License](https://img.shields.io/badge/license-MIT-lightgrey.svg)
9
11
 
@@ -13,27 +15,41 @@ Package: `monime-package`
13
15
 
14
16
  ## Table of Contents
15
17
 
16
- * [Features](#features)
17
- * [Installation](#installation)
18
- * [Environment Variables](#environment-variables)
19
- * [Quick Start](#quick-start)
20
- * [Client API](#client-api)
21
- * [Examples](#examples)
22
- * [Migration from Old Helpers](#migration-from-old-helpers)
23
- * [Folder Structure](#folder-structure)
24
- * [Error Handling](#error-handling)
25
- * [Contributing](#contributing)
26
- * [License](#license)
18
+ - **[Features](#features)**
19
+ - **[Installation](#installation)**
20
+ - **[Environment Variables](#environment-variables)**
21
+ - **[Quick Start](#quick-start)**
22
+ - **[API Reference](#api-reference)**
23
+ - **[Financial Accounts](#financial-accounts)**
24
+ - **[Internal Transfers](#internal-transfers)**
25
+ - **[Payment Codes](#payment-codes)**
26
+ - **[Payouts](#payouts)**
27
+ - **[Financial Transactions](#financial-transactions)**
28
+ - **[Checkout Sessions](#checkout-sessions)**
29
+ - **[Configuration](#configuration)**
30
+ - **[Complete Examples](#complete-examples)**
31
+ - **[TypeScript Types](#typescript-types)**
32
+ - **[Idempotency](#idempotency)**
33
+ - **[Pagination](#pagination)**
34
+ - **[Migration from Old Helpers](#migration-from-old-helpers)**
35
+ - **[Error Handling](#error-handling)**
36
+ - **[Security](#security)**
37
+ - **[Contributing](#contributing)**
38
+ - **[Support](#support)**
39
+ - **[License](#license)**
27
40
 
28
41
  ---
29
42
 
30
43
  ## Features
31
44
 
32
- * Full **TypeScript support** with typed request/response objects
33
- * Lightweight client wrapper around Monime endpoints
34
- * Predictable return shape: `{ success: boolean, data?, error? }`
35
- * Single client instance handles credentials automatically
36
- * Minimal dependencies (`axios` only)
45
+ - **Typed** request/response objects for safer integrations
46
+ - **Predictable** return shape: `{ success, data?, error? }`
47
+ - **Client-based** auth: set credentials once per instance
48
+ - **Minimal deps** (`axios`) and small surface area
49
+ - **Full API coverage** for all Monime endpoints
50
+ - **Mobile Money support** (Africell, Orange, etc.)
51
+ - **Bank transfers** and digital wallet integrations
52
+ - **Checkout sessions** for hosted payment pages
37
53
 
38
54
  ---
39
55
 
@@ -65,170 +81,876 @@ You can also pass credentials directly when creating the client.
65
81
  ### Create a client
66
82
 
67
83
  ```ts
68
- import { createClient } from 'monime-package'
84
+ import { createClient } from "monime-package";
69
85
 
70
86
  const client = createClient({
71
- monimeSpaceeId: process.env.MONIME_SPACE_ID!,
87
+ monimeSpaceId: process.env.MONIME_SPACE_ID!,
72
88
  accessToken: process.env.MONIME_ACCESS_TOKEN!,
73
- })
89
+ });
74
90
  ```
75
91
 
76
- Now all methods automatically use the client’s credentials.
92
+ Now all methods use the client’s credentials automatically.
93
+
94
+ ### Import styles
95
+
96
+ ```ts
97
+ // ESM / TypeScript
98
+ import { createClient, type DestinationOption } from "monime-package";
99
+
100
+ // CommonJS
101
+ // const { createClient } = require("monime-package");
102
+ ```
77
103
 
78
104
  ---
79
105
 
80
- ## Client API
106
+ ## API Reference
81
107
 
82
- All methods return:
108
+ All methods return the same envelope:
83
109
 
84
110
  ```ts
85
111
  type Result<T> = {
86
- success: boolean
87
- data?: T
88
- error?: Error
89
- }
112
+ success: boolean;
113
+ data?: T;
114
+ error?: Error;
115
+ };
90
116
  ```
91
117
 
118
+ The client exposes namespaced APIs under `client.<module>`. Below is the complete API reference:
119
+
92
120
  ### Financial Accounts
93
121
 
122
+ Manage digital wallets and financial accounts.
123
+
124
+ ```ts
125
+ // Create a new financial account
126
+ client.financialAccount.create(name: string): Promise<Result<CreateFinancialAccount>>
127
+
128
+ // Get account details by ID
129
+ client.financialAccount.get(financialAccountId: string): Promise<Result<GetFinancialAccount>>
130
+
131
+ // List all financial accounts
132
+ client.financialAccount.getAll(): Promise<Result<AllFinancialAccount>>
133
+ ```
134
+
135
+ **Parameters:**
136
+ - `name`: Account name (required)
137
+ - `financialAccountId`: Unique account identifier (required)
138
+
139
+ **Example:**
94
140
  ```ts
95
- client.createFinancialAccount(name: string): Promise<Result<CreateFinancialAccount>>
96
- client.getFinancialAccount(financialAccountId: string): Promise<Result<GetFinancialAccount>>
141
+ // Create account
142
+ const account = await client.financialAccount.create("My Wallet");
143
+ if (account.success) {
144
+ console.log("Account ID:", account.data.result.id);
145
+ console.log("Balance:", account.data.result.balance.available.value);
146
+ }
147
+
148
+ // Get account details
149
+ const details = await client.financialAccount.get("fa-123456");
97
150
  ```
98
151
 
99
152
  ### Internal Transfers
100
153
 
154
+ Transfer funds between your financial accounts.
155
+
101
156
  ```ts
102
- client.createInternalTransfer(
157
+ // Create internal transfer
158
+ client.internalTransfer.create(
103
159
  sourceAccount: string,
104
160
  destinationAccount: string,
105
- amount: number
161
+ amount: number,
106
162
  ): Promise<Result<CreateInternalTransfer>>
163
+
164
+ // Get transfer details
165
+ client.internalTransfer.get(internalTransferId: string): Promise<Result<InternalTransfer>>
166
+
167
+ // List all transfers
168
+ client.internalTransfer.getAll(): Promise<Result<AllInternalTransfers>>
169
+
170
+ // Cancel/delete a transfer
171
+ client.internalTransfer.delete(internalTransferId: string): Promise<{ success: boolean; error?: Error }>
172
+ ```
173
+
174
+ **Parameters:**
175
+ - `sourceAccount`: Source financial account ID (required)
176
+ - `destinationAccount`: Destination financial account ID (required)
177
+ - `amount`: Transfer amount in SLE (required, must be > 0)
178
+ - `internalTransferId`: Transfer ID for get/delete operations (required)
179
+
180
+ **Example:**
181
+ ```ts
182
+ // Transfer 1000 SLE between accounts
183
+ const transfer = await client.internalTransfer.create("fa-source", "fa-dest", 1000);
184
+ if (transfer.success) {
185
+ console.log("Transfer ID:", transfer.data.result.id);
186
+ console.log("Status:", transfer.data.result.status);
187
+ }
107
188
  ```
108
189
 
109
190
  ### Payment Codes
110
191
 
192
+ Generate USSD payment codes for mobile money transactions.
193
+
111
194
  ```ts
112
- client.createPaymentCode(
195
+ // Create payment code
196
+ client.paymentCode.create(
113
197
  paymentName: string,
114
198
  amount: number,
115
199
  financialAccount: string,
116
200
  username: string,
117
- phoneNumber: string
201
+ phoneNumber: string,
118
202
  ): Promise<Result<CreatePaymentCode>>
119
203
 
120
- client.deletePaymentCode(paymentCodeId: string): Promise<Result<DeletePaymentCode>>
204
+ // Get payment code details
205
+ client.paymentCode.get(paymentCodeId: string): Promise<Result<GetOne>>
206
+
207
+ // List all payment codes
208
+ client.paymentCode.getAll(): Promise<Result<GetAllPaymentCode>>
209
+
210
+ // Delete payment code
211
+ client.paymentCode.delete(paymentCodeId: string): Promise<{ success: boolean; error?: Error }>
212
+ ```
213
+
214
+ **Parameters:**
215
+ - `paymentName`: Description for the payment (required)
216
+ - `amount`: Payment amount in SLE (required, must be > 0)
217
+ - `financialAccount`: Target financial account ID (required)
218
+ - `username`: Customer name (required)
219
+ - `phoneNumber`: Authorized phone number (required)
220
+ - `paymentCodeId`: Payment code ID for get/delete operations (required)
221
+
222
+ **Example:**
223
+ ```ts
224
+ // Create USSD payment code
225
+ const paymentCode = await client.paymentCode.create(
226
+ "Order #12345",
227
+ 5000, // 50.00 SLE
228
+ "fa-123456",
229
+ "John Doe",
230
+ "0771234567"
231
+ );
232
+
233
+ if (paymentCode.success) {
234
+ console.log("USSD Code:", paymentCode.data.result.ussdCode);
235
+ console.log("Expires at:", paymentCode.data.result.expireTime);
236
+ }
121
237
  ```
122
238
 
123
239
  ### Payouts
124
240
 
241
+ Send money to mobile money providers, banks, or wallets.
242
+
125
243
  ```ts
126
- client.createPayout(
244
+ // Create payout
245
+ client.payout.create(
127
246
  amount: number,
128
- phoneNumber: string,
129
- sourceAccount: string
247
+ destination: DestinationOption,
248
+ sourceAccount: string,
130
249
  ): Promise<Result<CreatePayout>>
250
+
251
+ // List all payouts
252
+ client.payout.get(): Promise<Result<GetAll>>
253
+
254
+ // Get specific payout
255
+ client.payout.getOne(payoutId: string): Promise<Result<GetOnePayout>>
256
+
257
+ // Cancel payout
258
+ client.payout.delete(payoutId: string): Promise<{ success: boolean; error?: Error }>
259
+ ```
260
+
261
+ **Destination Types:**
262
+ ```ts
263
+ type DestinationOption =
264
+ | { type: "momo"; providerId: "m17" | "m18"; phoneNumber: string }
265
+ | { type: "bank"; providerId: "b01" | "b02" | "b03"; accountNumber: string }
266
+ | { type: "wallet"; providerId: "w01" | "w02"; walletId: string };
267
+ ```
268
+
269
+ **Parameters:**
270
+ - `amount`: Payout amount in SLE (required, must be > 0)
271
+ - `destination`: Payout destination (required)
272
+ - `sourceAccount`: Source financial account ID (required)
273
+ - `payoutId`: Payout ID for get/delete operations (required)
274
+
275
+ **Example:**
276
+ ```ts
277
+ // Mobile money payout
278
+ const mobileMoneyPayout = await client.payout.create(
279
+ 10000, // 100.00 SLE
280
+ { type: "momo", providerId: "m17", phoneNumber: "0771234567" },
281
+ "fa-123456"
282
+ );
283
+
284
+ // Bank transfer payout
285
+ const bankPayout = await client.payout.create(
286
+ 50000, // 500.00 SLE
287
+ { type: "bank", providerId: "b01", accountNumber: "1234567890" },
288
+ "fa-123456"
289
+ );
131
290
  ```
132
291
 
133
- > Provider is inferred automatically from the phone number prefix.
292
+ ### Financial Transactions
293
+
294
+ Query transaction history and details.
295
+
296
+ ```ts
297
+ // Get transaction details
298
+ client.financialTransaction.get(transactionId: string): Promise<Result<GetTransaction>>
299
+
300
+ // List all transactions
301
+ client.financialTransaction.getAll(): Promise<Result<AllTransaction>>
302
+ ```
303
+
304
+ **Parameters:**
305
+ - `transactionId`: Transaction ID (required)
306
+
307
+ **Example:**
308
+ ```ts
309
+ // Get all transactions
310
+ const transactions = await client.financialTransaction.getAll();
311
+ if (transactions.success) {
312
+ transactions.data.result.forEach(tx => {
313
+ console.log(`${tx.type}: ${tx.amount.value} ${tx.amount.currency}`);
314
+ });
315
+ }
316
+ ```
317
+
318
+ ### Checkout Sessions
319
+
320
+ Create hosted payment pages for seamless customer payments.
321
+
322
+ ```ts
323
+ // Create checkout session
324
+ client.checkoutSession.create(
325
+ name: string,
326
+ amount: number,
327
+ quantity: number,
328
+ successUrl: string,
329
+ cancelUrl: string,
330
+ description?: string,
331
+ financialAccountId?: string,
332
+ primaryColor?: string,
333
+ images?: string[],
334
+ ): Promise<Result<CreateCheckout>>
335
+
336
+ // List all checkout sessions
337
+ client.checkoutSession.get(): Promise<Result<AllCheckout>>
338
+
339
+ // Get specific checkout session
340
+ client.checkoutSession.getOne(checkoutId: string): Promise<Result<OneCheckout>>
341
+
342
+ // Delete checkout session
343
+ client.checkoutSession.delete(checkoutId: string): Promise<{ success: boolean; error?: Error }>
344
+ ```
345
+
346
+ **Parameters:**
347
+ - `name`: Product/service name (required)
348
+ - `amount`: Price per item in SLE (required)
349
+ - `quantity`: Number of items (required)
350
+ - `successUrl`: Redirect URL after successful payment (required)
351
+ - `cancelUrl`: Redirect URL when payment is cancelled (required)
352
+ - `description`: Product description (optional)
353
+ - `financialAccountId`: Target account for payments (optional)
354
+ - `primaryColor`: Brand color in hex format (optional)
355
+ - `images`: Product image URLs (optional)
356
+ - `checkoutId`: Checkout session ID for get/delete operations (required)
357
+
358
+ **Example:**
359
+ ```ts
360
+ // Create checkout for e-commerce
361
+ const checkout = await client.checkoutSession.create(
362
+ "Premium Subscription",
363
+ 2500, // 25.00 SLE per month
364
+ 1,
365
+ "https://myapp.com/success",
366
+ "https://myapp.com/cancel",
367
+ "Monthly premium subscription",
368
+ "fa-123456",
369
+ "#3B82F6", // Blue color
370
+ ["https://myapp.com/images/premium.jpg"]
371
+ );
372
+
373
+ if (checkout.success) {
374
+ // Redirect customer to checkout page
375
+ console.log("Checkout URL:", checkout.data.result.redirectUrl);
376
+ console.log("Order Number:", checkout.data.result.orderNumber);
377
+ }
378
+ ```
134
379
 
135
380
  ---
136
381
 
137
- ## Examples
382
+ ## Configuration
138
383
 
139
- ### Create a financial account
384
+ The client accepts the following options (see `src/client.ts`):
140
385
 
141
386
  ```ts
142
- const account = await client.createFinancialAccount('App Wallet')
143
- if (!account.success) throw account.error
144
- console.log(account.data)
387
+ type ClientOptions = {
388
+ monimeSpaceId: string; // Your Monime Space ID
389
+ accessToken: string; // Your Monime API token
390
+ };
145
391
  ```
146
392
 
147
- ### Get account details
393
+ - **Authentication**: Both values are required. Prefer environment variables.
394
+ - **Headers**: SDK automatically sets `Authorization` and `Monime-Space-Id` for each call.
395
+
396
+ ---
397
+
398
+ ## Complete Examples
399
+
400
+ Here are comprehensive examples showing real-world usage patterns:
401
+
402
+ ### Complete E-commerce Integration
148
403
 
149
404
  ```ts
150
- const details = await client.getFinancialAccount(account.data!.result.id)
151
- console.log(details)
405
+ import { createClient, type DestinationOption } from "monime-package";
406
+
407
+ // Initialize client
408
+ const client = createClient({
409
+ monimeSpaceId: process.env.MONIME_SPACE_ID!,
410
+ accessToken: process.env.MONIME_ACCESS_TOKEN!,
411
+ });
412
+
413
+ // Create business account
414
+ const businessAccount = await client.financialAccount.create("E-commerce Store");
415
+ if (!businessAccount.success) {
416
+ throw new Error(`Failed to create account: ${businessAccount.error?.message}`);
417
+ }
418
+
419
+ const accountId = businessAccount.data!.result.id;
420
+ console.log(`Created account: ${accountId}`);
421
+ console.log(`Balance: ${businessAccount.data!.result.balance.available.value} SLE`);
422
+
423
+ // Create checkout session for customer
424
+ const checkout = await client.checkoutSession.create(
425
+ "Digital Camera",
426
+ 45000, // 450.00 SLE
427
+ 1,
428
+ "https://store.com/success",
429
+ "https://store.com/cancel",
430
+ "Professional DSLR Camera with lens kit",
431
+ accountId,
432
+ "#2563EB", // Brand blue
433
+ ["https://store.com/camera.jpg"]
434
+ );
435
+
436
+ if (checkout.success) {
437
+ console.log(`Checkout created: ${checkout.data!.result.id}`);
438
+ console.log(`Payment URL: ${checkout.data!.result.redirectUrl}`);
439
+ console.log(`Order: ${checkout.data!.result.orderNumber}`);
440
+ }
152
441
  ```
153
442
 
154
- ### Internal transfer
443
+ ### Payment Processing Workflow
155
444
 
156
445
  ```ts
157
- const transfer = await client.createInternalTransfer('acc-src', 'acc-dest', 5000)
158
- if (!transfer.success) console.error(transfer.error)
159
- else console.log(transfer.data)
446
+ // 1. Generate USSD payment code for customer
447
+ const paymentCode = await client.paymentCode.create(
448
+ "Invoice #INV-2024-001",
449
+ 15000, // 150.00 SLE
450
+ accountId,
451
+ "Customer Name",
452
+ "0771234567"
453
+ );
454
+
455
+ if (paymentCode.success) {
456
+ console.log(`USSD Code: ${paymentCode.data!.result.ussdCode}`);
457
+ console.log(`Expires: ${paymentCode.data!.result.expireTime}`);
458
+
459
+ // Send USSD code to customer via SMS/email
460
+ await sendToCustomer(paymentCode.data!.result.ussdCode);
461
+ }
462
+
463
+ // 2. Monitor payment status
464
+ const checkPaymentStatus = async (codeId: string) => {
465
+ const status = await client.paymentCode.get(codeId);
466
+ if (status.success) {
467
+ console.log(`Payment Status: ${status.data!.result.status}`);
468
+ return status.data!.result.status === 'completed';
469
+ }
470
+ return false;
471
+ };
472
+
473
+ // 3. Process payout to supplier after payment received
474
+ const paySupplier = async () => {
475
+ const payout = await client.payout.create(
476
+ 8000, // 80.00 SLE to supplier
477
+ {
478
+ type: "momo",
479
+ providerId: "m17",
480
+ phoneNumber: "0779876543"
481
+ },
482
+ accountId
483
+ );
484
+
485
+ if (payout.success) {
486
+ console.log(`Payout ID: ${payout.data!.result.id}`);
487
+ console.log(`Status: ${payout.data!.result.status}`);
488
+ console.log(`Fees: ${payout.data!.result.fees.map(f => `${f.code}: ${f.amount.value}`)}`);
489
+ }
490
+ };
160
491
  ```
161
492
 
162
- ### Create payment code
493
+ ### Multi-Account Management
163
494
 
164
495
  ```ts
165
- const code = await client.createPaymentCode('Order-001', 5, 'financial-account-id', 'Alice', '0771234567')
166
- if (!code.success) console.error(code.error)
167
- else console.log('Payment code:', code.data)
496
+ // Create multiple accounts for different purposes
497
+ const accounts = await Promise.all([
498
+ client.financialAccount.create("Sales Revenue"),
499
+ client.financialAccount.create("Operating Expenses"),
500
+ client.financialAccount.create("Tax Reserve"),
501
+ ]);
502
+
503
+ // Check if all accounts were created successfully
504
+ if (accounts.every(acc => acc.success)) {
505
+ const [salesAccount, expensesAccount, taxAccount] = accounts.map(acc => acc.data!.result.id);
506
+
507
+ // Distribute revenue: 70% operations, 30% tax reserve
508
+ const revenue = 100000; // 1000.00 SLE
509
+
510
+ const transfers = await Promise.all([
511
+ client.internalTransfer.create(salesAccount, expensesAccount, revenue * 0.7),
512
+ client.internalTransfer.create(salesAccount, taxAccount, revenue * 0.3),
513
+ ]);
514
+
515
+ transfers.forEach((transfer, index) => {
516
+ const purpose = index === 0 ? 'operations' : 'tax reserve';
517
+ if (transfer.success) {
518
+ console.log(`${purpose} transfer: ${transfer.data!.result.id}`);
519
+ }
520
+ });
521
+ }
168
522
  ```
169
523
 
170
- ### Delete payment code
524
+ ### Transaction Monitoring & Reporting
171
525
 
172
526
  ```ts
173
- const deleted = await client.deletePaymentCode('payment-code-id')
174
- console.log(deleted.success)
527
+ // Get all transactions for reporting
528
+ const transactions = await client.financialTransaction.getAll();
529
+
530
+ if (transactions.success) {
531
+ const txs = transactions.data!.result;
532
+
533
+ // Group transactions by type
534
+ const summary = txs.reduce((acc, tx) => {
535
+ acc[tx.type] = (acc[tx.type] || 0) + tx.amount.value;
536
+ return acc;
537
+ }, {} as Record<string, number>);
538
+
539
+ console.log('Transaction Summary:', summary);
540
+
541
+ // Find large transactions (> 50,000 SLE)
542
+ const largeTransactions = txs.filter(tx => Math.abs(tx.amount.value) > 50000);
543
+ console.log(`Large transactions: ${largeTransactions.length}`);
544
+
545
+ // Check account balances after transactions
546
+ const accountIds = [...new Set(txs.map(tx => tx.financialAccount.id))];
547
+
548
+ for (const accountId of accountIds) {
549
+ const account = await client.financialAccount.get(accountId);
550
+ if (account.success) {
551
+ console.log(`Account ${accountId}: ${account.data!.result.balance.available.value} SLE`);
552
+ }
553
+ }
554
+ }
175
555
  ```
176
556
 
177
- ### Payout (mobile money)
557
+ ### Error Handling Best Practices
178
558
 
179
559
  ```ts
180
- const payout = await client.createPayout(1000, '0771234567', 'source-account-id')
181
- if (!payout.success) console.error(payout.error)
182
- else console.log('Payout:', payout.data)
560
+ // Robust error handling with retries
561
+ const createTransferWithRetry = async (
562
+ sourceAccount: string,
563
+ destinationAccount: string,
564
+ amount: number,
565
+ maxRetries = 3
566
+ ) => {
567
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
568
+ const transfer = await client.internalTransfer.create(sourceAccount, destinationAccount, amount);
569
+
570
+ if (transfer.success) {
571
+ return transfer;
572
+ }
573
+
574
+ // Log the error
575
+ console.error(`Transfer attempt ${attempt} failed:`, transfer.error?.message);
576
+
577
+ // Don't retry on validation errors
578
+ if (transfer.error?.message?.includes('validation')) {
579
+ throw transfer.error;
580
+ }
581
+
582
+ // Wait before retrying (exponential backoff)
583
+ if (attempt < maxRetries) {
584
+ await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
585
+ }
586
+ }
587
+
588
+ throw new Error(`Transfer failed after ${maxRetries} attempts`);
589
+ };
590
+
591
+ // Usage
592
+ try {
593
+ const transfer = await createTransferWithRetry("fa-source", "fa-dest", 10000);
594
+ console.log("Transfer successful:", transfer.data!.result.id);
595
+ } catch (error) {
596
+ console.error("Transfer failed permanently:", error.message);
597
+ }
183
598
  ```
184
599
 
185
600
  ---
186
601
 
602
+ ## Idempotency
603
+
604
+ For POST endpoints, the SDK automatically attaches an `Idempotency-Key` header. This helps prevent duplicate requests if you retry the same call. Keys are generated per module instance.
605
+
606
+ ---
607
+
608
+ ## Pagination
609
+
610
+ List endpoints return a `pagination` object in `data?.pagination` when available, including a `next` cursor/URL. The SDK currently returns this information as-is; use the `next` value to fetch subsequent pages if needed.
611
+
612
+ ---
613
+
187
614
  ## Migration from Old Helpers
188
615
 
189
- Previously, you had to pass `monimeSpaceId` and `accessToken` into every function:
616
+ Previously, you called standalone helpers and passed credentials on every call:
190
617
 
191
618
  ```ts
192
- createFinancialAccount('name', MONIME_SPACE_ID, MONIME_ACCESS_TOKEN)
619
+ // old (example)
620
+ createFinancialAccount("name", MONIME_SPACE_ID, MONIME_ACCESS_TOKEN);
193
621
  ```
194
622
 
195
- Now, create a client once:
623
+ Now, instantiate a client once and use namespaced methods. Credentials are stored internally:
196
624
 
197
625
  ```ts
198
- const client = createClient({ monimeSpaceeId, accessToken })
199
- client.createFinancialAccount('name') // credentials auto-applied
626
+ const client = createClient({ monimeSpaceId, accessToken });
627
+ await client.financialAccount.create("name");
200
628
  ```
201
629
 
202
630
  ---
203
631
 
204
- ## Folder Structure
205
632
 
633
+ ## Error Handling
634
+
635
+ - **Standard envelope**: every call returns `{ success, data?, error? }`.
636
+ - **Validation**: inputs are validated (e.g. non-empty IDs, positive amounts) and will short-circuit with `success: false` + `Error`.
637
+ - **Axios errors**: when available, `axios` errors are propagated. You can check details with `axios.isAxiosError(error)`.
638
+
639
+ ---
640
+
641
+ ## Security
642
+
643
+ - Do not commit tokens. Use environment variables or a secret manager.
644
+ - Restrict tokens to the least privileges necessary.
645
+
646
+ ---
647
+
648
+ ## Versioning
649
+
650
+ This project follows semantic versioning (SemVer). See releases for notable changes.
651
+
652
+ ---
653
+
654
+ ## Support
655
+
656
+ - File issues and feature requests at the repository: `https://github.com/Walon-Foundation/monime-package/issues`.
657
+ - For production incidents, rotate credentials if you suspect exposure.
658
+
659
+ ## TypeScript Types
660
+
661
+ All result payload types are exported from the package for complete type safety:
662
+
663
+ ```ts
664
+ import type {
665
+ // Core types
666
+ ClientOptions,
667
+
668
+ // Financial Account types
669
+ CreateFinancialAccount,
670
+ GetFinancialAccount,
671
+ AllFinancialAccount,
672
+
673
+ // Internal Transfer types
674
+ CreateInternalTransfer,
675
+ InternalTransfer,
676
+ AllInternalTransfers,
677
+
678
+ // Payment Code types
679
+ CreatePaymentCode,
680
+ GetAllPaymentCode,
681
+ GetOne,
682
+
683
+ // Payout types
684
+ DestinationOption,
685
+ CreatePayout,
686
+ GetAll,
687
+ GetOnePayout,
688
+
689
+ // Financial Transaction types
690
+ GetTransaction,
691
+ AllTransaction,
692
+
693
+ // Checkout Session types
694
+ CreateCheckout,
695
+ AllCheckout,
696
+ OneCheckout,
697
+ } from "monime-package";
698
+ ```
699
+
700
+ ### Core Type Definitions
701
+
702
+ #### Result Envelope
703
+ All API responses follow this consistent pattern:
704
+ ```ts
705
+ type Result<T> = {
706
+ success: boolean;
707
+ data?: T;
708
+ error?: Error;
709
+ };
710
+ ```
711
+
712
+ #### Client Configuration
713
+ ```ts
714
+ type ClientOptions = {
715
+ monimeSpaceId: string; // Your Monime Space ID
716
+ accessToken: string; // Your API access token
717
+ };
206
718
  ```
207
- .
208
- ├── LICENSE
209
- ├── README.md
210
- ├── package.json
211
- ├── tsconfig.json
212
- ├── tsup.config.ts
213
- ├── src
214
- │ ├── index.ts # entry point
215
- │ └── modules
216
- │ ├── financialAccount.ts
217
- │ ├── financialAccountTypes.ts
218
- │ ├── internalTransfer.ts
219
- │ ├── internalTransferTypes.ts
220
- │ ├── paymentCode.ts
221
- │ ├── paymentCodeTypes.ts
222
- │ ├── payout.ts
223
- │ └── payoutTypes.ts
719
+
720
+ #### Destination Options for Payouts
721
+ ```ts
722
+ type DestinationOption =
723
+ | {
724
+ type: "momo";
725
+ providerId: "m17" | "m18"; // MTN, Orange Money
726
+ phoneNumber: string;
727
+ }
728
+ | {
729
+ type: "bank";
730
+ providerId: "b01" | "b02" | "b03"; // Bank codes
731
+ accountNumber: string;
732
+ }
733
+ | {
734
+ type: "wallet";
735
+ providerId: "w01" | "w02"; // Wallet provider codes
736
+ walletId: string;
737
+ };
224
738
  ```
225
739
 
226
- ---
740
+ ### Response Type Details
227
741
 
228
- ## Error Handling
742
+ #### Financial Account Types
743
+ ```ts
744
+ // Account creation/retrieval response
745
+ interface CreateFinancialAccount {
746
+ success: boolean;
747
+ messages: string[];
748
+ result: {
749
+ id: string; // Unique account ID
750
+ uvan: string; // Internal identifier
751
+ name: string; // Account name
752
+ currency: string; // Always "SLE" (Sierra Leone)
753
+ reference: string; // Account reference
754
+ description: string; // Account description
755
+ balance: {
756
+ available: {
757
+ currency: string;
758
+ value: number; // Balance in cents (SLE)
759
+ };
760
+ };
761
+ createTime: string; // ISO timestamp
762
+ updateTime: string; // ISO timestamp
763
+ };
764
+ }
765
+ ```
766
+
767
+ #### Internal Transfer Types
768
+ ```ts
769
+ interface CreateInternalTransfer {
770
+ success: boolean;
771
+ messages: string[];
772
+ result: {
773
+ id: string; // Transfer ID
774
+ status: string; // Transfer status
775
+ amount: {
776
+ currency: string;
777
+ value: number; // Amount in cents
778
+ };
779
+ sourceFinancialAccount: { id: string };
780
+ destinationFinancialAccount: { id: string };
781
+ financialTransactionReference: string;
782
+ description: string;
783
+ failureDetail: {
784
+ code: string;
785
+ message: string;
786
+ };
787
+ ownershipGraph: {
788
+ owner: {
789
+ id: string;
790
+ type: string;
791
+ owner: {
792
+ id: string;
793
+ type: string;
794
+ };
795
+ };
796
+ };
797
+ createTime: string;
798
+ updateTime: string;
799
+ };
800
+ }
801
+ ```
229
802
 
230
- * Network/API errors are returned as `error` in the `{ success, data?, error? }` object.
231
- * Use `axios.isAxiosError(error)` to inspect response details if needed.
803
+ #### Payment Code Types
804
+ ```ts
805
+ interface CreatePaymentCode {
806
+ success: boolean;
807
+ messages: string[];
808
+ result: {
809
+ id: string;
810
+ mode: string; // "recurrent"
811
+ status: string; // Payment status
812
+ name: string; // Payment name
813
+ amount: {
814
+ currency: string;
815
+ value: number; // Amount in cents
816
+ };
817
+ enable: boolean;
818
+ expireTime: string; // ISO timestamp
819
+ customer: { name: string };
820
+ ussdCode: string; // USSD code for payment
821
+ reference: string;
822
+ authorizedProviders: string[];
823
+ authorizedPhoneNumber: string;
824
+ recurrentPaymentTarget: {
825
+ expectedPaymentCount: number;
826
+ expectedPaymentTotal: {
827
+ currency: string;
828
+ value: number;
829
+ };
830
+ };
831
+ financialAccountId: string;
832
+ processedPaymentData: {
833
+ amount: { currency: string; value: number };
834
+ orderId: string;
835
+ paymentId: string;
836
+ orderNumber: string;
837
+ channelData: {
838
+ providerId: string;
839
+ accountId: string;
840
+ reference: string;
841
+ };
842
+ financialTransactionReference: string;
843
+ };
844
+ createTime: string;
845
+ updateTime: string;
846
+ ownershipGraph: OwnershipGraph;
847
+ };
848
+ }
849
+ ```
850
+
851
+ #### Checkout Session Types
852
+ ```ts
853
+ interface CreateCheckout {
854
+ success: boolean;
855
+ messages: string[];
856
+ result: {
857
+ id: string;
858
+ status: string;
859
+ name: string;
860
+ orderNumber: string; // Generated order number
861
+ reference: string;
862
+ description: string;
863
+ redirectUrl: string; // Checkout page URL
864
+ cancelUrl: string;
865
+ successUrl: string;
866
+ lineItems: {
867
+ data: Array<{
868
+ type: string;
869
+ id: string;
870
+ name: string;
871
+ price: { currency: string; value: number };
872
+ quantity: number;
873
+ reference: string;
874
+ description: string;
875
+ images: string[];
876
+ }>;
877
+ };
878
+ financialAccountId: string;
879
+ brandingOptions: {
880
+ primaryColor: string;
881
+ };
882
+ expireTime: string;
883
+ createTime: string;
884
+ ownershipGraph: OwnershipGraph;
885
+ };
886
+ }
887
+ ```
888
+
889
+ #### Common Types
890
+ ```ts
891
+ // Pagination for list responses
892
+ interface Pagination {
893
+ count: number; // Total count
894
+ next: string; // Next page URL/cursor
895
+ }
896
+
897
+ // Ownership information
898
+ interface OwnershipGraph {
899
+ owner: {
900
+ id: string;
901
+ type: string;
902
+ owner: {
903
+ id: string;
904
+ type: string;
905
+ };
906
+ };
907
+ }
908
+
909
+ // Amount representation
910
+ interface Amount {
911
+ currency: string; // Always "SLE"
912
+ value: number; // Amount in cents (multiply by 100 for SLE)
913
+ }
914
+ ```
915
+
916
+ ### Type Usage Examples
917
+
918
+ ```ts
919
+ // Type-safe account creation
920
+ const createAccountTyped = async (name: string): Promise<CreateFinancialAccount | null> => {
921
+ const result = await client.financialAccount.create(name);
922
+ return result.success ? result.data! : null;
923
+ };
924
+
925
+ // Type-safe payout with validation
926
+ const createMobileMoneyPayout = async (
927
+ amount: number,
928
+ phoneNumber: string,
929
+ sourceAccount: string
930
+ ): Promise<CreatePayout | null> => {
931
+ const destination: DestinationOption = {
932
+ type: "momo",
933
+ providerId: "m17",
934
+ phoneNumber,
935
+ };
936
+
937
+ const result = await client.payout.create(amount, destination, sourceAccount);
938
+ return result.success ? result.data! : null;
939
+ };
940
+
941
+ // Type-safe transaction processing
942
+ const processTransactions = async (): Promise<void> => {
943
+ const txResult = await client.financialTransaction.getAll();
944
+
945
+ if (txResult.success && txResult.data) {
946
+ const transactions: AllTransaction = txResult.data;
947
+
948
+ transactions.result.forEach((tx: GetTransaction['result']) => {
949
+ console.log(`Transaction ${tx.id}: ${tx.amount.value / 100} ${tx.amount.currency}`);
950
+ });
951
+ }
952
+ };
953
+ ```
232
954
 
233
955
  ---
234
956