paj_ramp 1.3.2 → 1.4.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 (33) hide show
  1. package/README.md +58 -40
  2. package/__tests__/session.test.ts +38 -0
  3. package/examples/README.md +141 -0
  4. package/examples/basic-offramp/.env.example +24 -0
  5. package/examples/basic-offramp/README.md +186 -0
  6. package/examples/basic-offramp/index.ts +117 -0
  7. package/examples/basic-offramp/package-lock.json +54 -0
  8. package/examples/basic-offramp/package.json +13 -0
  9. package/examples/basic-onramp/.env.example +24 -0
  10. package/examples/basic-onramp/README.md +161 -0
  11. package/examples/basic-onramp/index.ts +165 -0
  12. package/examples/basic-onramp/package-lock.json +46 -0
  13. package/examples/basic-onramp/package.json +13 -0
  14. package/examples/webhook-integration/.env.example +25 -0
  15. package/examples/webhook-integration/README.md +266 -0
  16. package/examples/webhook-integration/package-lock.json +798 -0
  17. package/examples/webhook-integration/package.json +15 -0
  18. package/examples/webhook-integration/server.js +184 -0
  19. package/lib/off_ramp/directCreateOrder.ts +25 -40
  20. package/lib/on_ramp/createOrder.ts +19 -20
  21. package/lib/utility/session/initiate.ts +8 -7
  22. package/lib/utility/session/verify.ts +5 -5
  23. package/lib/utility/transaction/getAllTransactions.ts +6 -8
  24. package/lib/utility/transaction/getTransaction.ts +10 -20
  25. package/package.json +2 -1
  26. package/sdk.ts +29 -22
  27. package/utils/api.ts +2 -0
  28. package/utils/enums.ts +18 -14
  29. package/__tests__/getTXPoolAddress.test.ts +0 -24
  30. package/lib/utility/deprecated/addWallet.ts +0 -33
  31. package/lib/utility/deprecated/getTXPoolAddress.ts +0 -22
  32. package/lib/utility/deprecated/getWallet.ts +0 -34
  33. package/lib/utility/deprecated/switchWalletBankAccount.ts +0 -25
package/README.md CHANGED
@@ -17,10 +17,10 @@ yarn add paj_ramp
17
17
  ### Initialize SDK (select environment: "staging" | "production")
18
18
 
19
19
  ```typescript
20
- import { initializeSDK } from 'paj_ramp';
20
+ import { initializeSDK } from "paj_ramp";
21
21
 
22
22
  // Selects the environment you want to work with
23
- initializeSDK('staging'); // or production
23
+ initializeSDK("staging"); // or production
24
24
  ```
25
25
 
26
26
  ### Initiate Session
@@ -40,13 +40,13 @@ const initiated = await initiate(
40
40
  ### Verify Session
41
41
 
42
42
  ```typescript
43
- import { verify } from 'paj_ramp';
43
+ import { verify } from "paj_ramp";
44
44
 
45
45
  // You can get otp by either adding your phone number or email address
46
46
  // Phone number must start with a country code
47
47
  const verified = await verify(
48
- 'your_email@gmail.com', // or +2349053231563
49
- 'otp',
48
+ "your_email@gmail.com", // or +2349053231563
49
+ "otp",
50
50
  {
51
51
  uuid: string,
52
52
  device: string,
@@ -55,7 +55,7 @@ const verified = await verify(
55
55
  browser: string, //chrome
56
56
  ip: string,
57
57
  },
58
- 'business_api_key'
58
+ "business_api_key"
59
59
  );
60
60
  /* Response: {
61
61
  email?: string,
@@ -66,6 +66,24 @@ token: string
66
66
  } */
67
67
  ```
68
68
 
69
+ ## 📚 Examples
70
+
71
+ Check out our [examples directory](./examples) for complete, runnable examples:
72
+
73
+ - **[Basic Onramp](./examples/basic-onramp)** - Simple onramp transaction flow showing how users can buy crypto with fiat
74
+ - **[Basic Offramp](./examples/basic-offramp)** - Simple offramp transaction flow showing how users can sell crypto for fiat
75
+ - **[Webhook Integration](./examples/webhook-integration)** - Express server with webhook handling for real-time order updates
76
+
77
+ Each example includes its own README with detailed setup instructions. Perfect for understanding how to integrate PAJ Ramp into your application!
78
+
79
+ ```bash
80
+ cd examples/basic-onramp
81
+ npm install
82
+ cp .env.example .env
83
+ # Edit .env with your credentials
84
+ npm start
85
+ ```
86
+
69
87
  ## Utility Endpoints
70
88
 
71
89
  ### Handle Rate:
@@ -73,7 +91,7 @@ token: string
73
91
  **_Get All Rate_**
74
92
 
75
93
  ```typescript
76
- import { getAllRate } from 'paj_ramp';
94
+ import { getAllRate } from "paj_ramp";
77
95
 
78
96
  const rate = await getAllRate();
79
97
  /*
@@ -99,7 +117,7 @@ Response:
99
117
  **_Get Rate by Amount_**
100
118
 
101
119
  ```typescript
102
- import { getRateByAmount } from 'paj_ramp';
120
+ import { getRateByAmount } from "paj_ramp";
103
121
 
104
122
  const rate = await getRateByAmount(50000);
105
123
  /*
@@ -122,7 +140,7 @@ Response:
122
140
  **_Get Rate by Rate Type_**
123
141
 
124
142
  ```typescript
125
- import { getRateByType, RateType } from 'paj_ramp';
143
+ import { getRateByType, RateType } from "paj_ramp";
126
144
 
127
145
  const rate = await getRateByType(RateType.offRamp); // or RateType.onRamp
128
146
 
@@ -140,9 +158,9 @@ Response:
140
158
  **_Get Token Value from Amount and Mint Token_**
141
159
 
142
160
  ```typescript
143
- import { getTokenValue } from 'paj_ramp';
161
+ import { getTokenValue } from "paj_ramp";
144
162
 
145
- const tokenValue = await getTokenValue(50000, 'token_mint_address');
163
+ const tokenValue = await getTokenValue(50000, "token_mint_address");
146
164
  /*
147
165
  Response:
148
166
  {
@@ -158,21 +176,21 @@ Response:
158
176
  **_Get Banks_**
159
177
 
160
178
  ```typescript
161
- import { getBanks } from 'paj_ramp';
179
+ import { getBanks } from "paj_ramp";
162
180
 
163
- const banks = await getBanks('token');
181
+ const banks = await getBanks("token");
164
182
  // Response: [ { id: string, name: string, country: string } ]
165
183
  ```
166
184
 
167
185
  **_Resolve Bank Account_**
168
186
 
169
187
  ```typescript
170
- import { resolveBankAccount } from 'paj_ramp';
188
+ import { resolveBankAccount } from "paj_ramp";
171
189
 
172
190
  const resolvedBankAccount = await resolveBankAccount(
173
- 'token',
174
- 'bank_id',
175
- 'account_number'
191
+ "token",
192
+ "bank_id",
193
+ "account_number"
176
194
  );
177
195
  // Response: { accountName: string, accountNumber: string, bank: { id: string, name: string, code: string, country: string } }
178
196
  ```
@@ -180,12 +198,12 @@ const resolvedBankAccount = await resolveBankAccount(
180
198
  **_Add Bank Account_**
181
199
 
182
200
  ```typescript
183
- import { addBankAccount } from 'paj_ramp';
201
+ import { addBankAccount } from "paj_ramp";
184
202
 
185
203
  const addedBankAccount = await addBankAccount(
186
- 'token',
187
- 'bank_id',
188
- 'account_number'
204
+ "token",
205
+ "bank_id",
206
+ "account_number"
189
207
  );
190
208
  // Response: { id: string, accountName: string, accountNumber: string, bank: string }
191
209
  ```
@@ -193,9 +211,9 @@ const addedBankAccount = await addBankAccount(
193
211
  **_Get Bank Accounts_**
194
212
 
195
213
  ```typescript
196
- import { getBankAccounts } from 'paj_ramp';
214
+ import { getBankAccounts } from "paj_ramp";
197
215
 
198
- const accounts = await getBankAccounts('token');
216
+ const accounts = await getBankAccounts("token");
199
217
  // Response: [ { id: string, accountName: string, accountNumber: string, bank: string } ]
200
218
  ```
201
219
 
@@ -204,9 +222,9 @@ const accounts = await getBankAccounts('token');
204
222
  **_Get All Transactions_**
205
223
 
206
224
  ```typescript
207
- import { getAllTransactions } from 'paj_ramp';
225
+ import { getAllTransactions } from "paj_ramp";
208
226
 
209
- const transactions = await getAllTransactions('token_from_verification');
227
+ const transactions = await getAllTransactions("token_from_verification");
210
228
  /* Response: [{
211
229
  id: string;
212
230
  address: string;
@@ -216,7 +234,7 @@ amount: number;
216
234
  usdcAmount: number;
217
235
  fiatAmount: number;
218
236
  sender: string;
219
- receipiant: string;
237
+ receipient: string;
220
238
  rate: number;
221
239
  status: TransactionStatus;
222
240
  transactionType: TransactionType;
@@ -227,11 +245,11 @@ createdAt: string | Date;
227
245
  **_Get Transaction_**
228
246
 
229
247
  ```typescript
230
- import { getTransaction } from 'paj_ramp';
248
+ import { getTransaction } from "paj_ramp";
231
249
 
232
250
  const transactions = await getTransaction(
233
- 'token_from_verification',
234
- 'transaction_id'
251
+ "token_from_verification",
252
+ "transaction_id"
235
253
  );
236
254
  /* Response: {
237
255
  id: string;
@@ -242,7 +260,7 @@ amount: number;
242
260
  usdcAmount: number;
243
261
  fiatAmount: number;
244
262
  sender: string;
245
- receipiant: string;
263
+ receipint: string;
246
264
  rate: number;
247
265
  status: TransactionStatus;
248
266
  transactionType: TransactionType;
@@ -276,7 +294,7 @@ amount: number,
276
294
  usdcAmount: number,
277
295
  fiatAmount: number,
278
296
  sender: string,
279
- receipiant: string,
297
+ receipint: string,
280
298
  rate: number,
281
299
  status: TransactionStatus,
282
300
  transactionType: TransactionType
@@ -288,16 +306,16 @@ transactionType: TransactionType
288
306
  ### Usage Example
289
307
 
290
308
  ```typescript
291
- import { createOrder } from 'paj_ramp';
309
+ import { createOrder } from "paj_ramp";
292
310
 
293
311
  const order = await createOrder({
294
312
  fiatAmount: 10000,
295
- currency: 'NGN',
296
- recipient: 'wallet_address_here',
297
- mint: 'token_mint_address_here',
298
- chain: 'SOLANA', //ethereum, polygon, etc
299
- webhookURL: 'your_webhook_url',
300
- token: 'token_from_verification',
313
+ currency: "NGN",
314
+ recipient: "wallet_address_here",
315
+ mint: "token_mint_address_here",
316
+ chain: "SOLANA", //ethereum, polygon, etc
317
+ webhookURL: "your_webhook_url",
318
+ token: "token_from_verification",
301
319
  });
302
320
  // Response: { id: string, accountNumber: string, accountName: string, fiatAmount: number, bank: string }
303
321
  ```
@@ -317,7 +335,7 @@ const order = await createOrder({
317
335
  usdcAmount: number;
318
336
  fiatAmount: number;
319
337
  sender: string;
320
- receipiant: string;
338
+ receipient: string;
321
339
  rate: number;
322
340
  status: TransactionStatus; // eg. INIT, PAID, COMPLETED
323
341
  transactionType: TransactionType; // ON_RAMP or OFF_RAMP
@@ -332,7 +350,7 @@ import {
332
350
  TransactionStatus, // INIT, etc
333
351
  TransactionType, // ON_RAMP, etc
334
352
  Currency, // NGN
335
- } from 'paj_ramp';
353
+ } from "paj_ramp";
336
354
  ```
337
355
 
338
356
  <!--
@@ -0,0 +1,38 @@
1
+ import { initiate } from "../lib/utility/session/initiate";
2
+ import { deviceSignatureType, verify } from "../lib/utility/session/verify";
3
+ import * as api from "../utils/api";
4
+
5
+ describe("Session", () => {
6
+ const mockEmail = "matthew.chukwuemeka@gmail.com";
7
+ const ApiKey = "ApiKey";
8
+
9
+ afterEach(() => {
10
+ jest.restoreAllMocks();
11
+ });
12
+
13
+ it("should return session when API call succeeds", async () => {
14
+ jest.spyOn(api, "get").mockResolvedValue({ email: mockEmail });
15
+
16
+ const result = await initiate(mockEmail, ApiKey);
17
+ expect(result).toEqual({ email: mockEmail });
18
+ });
19
+
20
+ it("should throw an error when API call fails", async () => {
21
+ const error = new Error("API Failure");
22
+ jest.spyOn(api, "get").mockRejectedValue(error);
23
+
24
+ await expect(initiate(mockEmail, ApiKey)).rejects.toThrow("API Failure");
25
+ });
26
+
27
+ it("Should verify session when API call succeeds", async () => {
28
+ jest.spyOn(api, "get").mockResolvedValue({ email: mockEmail });
29
+
30
+ const device: deviceSignatureType = {
31
+ uuid: "uuid",
32
+ device: "device",
33
+ os: "os",
34
+ };
35
+ const result = await verify(mockEmail, "OTP", device, ApiKey);
36
+ expect(result).toEqual({ email: mockEmail });
37
+ });
38
+ });
@@ -0,0 +1,141 @@
1
+ # PAJ Ramp SDK Examples
2
+
3
+ This directory contains complete, runnable examples demonstrating how to use the PAJ Ramp SDK in real-world scenarios.
4
+
5
+ ## 📚 Available Examples
6
+
7
+ ### [Basic Onramp](./basic-onramp)
8
+
9
+ **Difficulty:** Beginner
10
+ **What you'll learn:**
11
+
12
+ - Session management (initiate & verify)
13
+ - Creating onramp orders
14
+ - Handling bank account details for payment
15
+
16
+ Perfect for: Understanding the basic onramp flow where users buy crypto with fiat.
17
+
18
+ ---
19
+
20
+ ### [Basic Offramp](./basic-offramp)
21
+
22
+ **Difficulty:** Beginner
23
+ **What you'll learn:**
24
+
25
+ - Bank account verification and management
26
+ - Creating offramp orders
27
+ - Converting crypto to fiat
28
+
29
+ Perfect for: Understanding the reverse flow where users sell crypto for fiat.
30
+
31
+ ---
32
+
33
+ ### [Webhook Integration](./webhook-integration)
34
+
35
+ **Difficulty:** Intermediate
36
+ **What you'll learn:**
37
+
38
+ - Setting up webhook endpoints
39
+ - Handling order status updates in real-time
40
+ - Building a REST API for order tracking
41
+ - Production-ready webhook patterns
42
+
43
+ Perfect for: Building production applications that need real-time order updates.
44
+
45
+ ---
46
+
47
+ ## 🚀 Quick Start
48
+
49
+ Each example is self-contained with its own dependencies and README. To run any example:
50
+
51
+ ```bash
52
+ cd examples/[example-name]
53
+ npm install
54
+ cp .env.example .env
55
+ # Edit .env with your credentials
56
+ npm start
57
+ ```
58
+
59
+ ## 📋 Prerequisites
60
+
61
+ All examples require:
62
+
63
+ - Node.js 16 or higher
64
+ - A PAJ business API key ([Get one here](https://paj.cash))
65
+ - Basic knowledge of JavaScript/Node.js
66
+
67
+ Specific examples may have additional requirements (documented in their READMEs).
68
+
69
+ ## 🎯 Learning Path
70
+
71
+ We recommend exploring the examples in this order:
72
+
73
+ 1. **Start with [Basic Onramp](./basic-onramp)**
74
+ Understand the fundamental flow of creating onramp orders
75
+
76
+ 2. **Then try [Basic Offramp](./basic-offramp)**
77
+ Learn the reverse process and bank account management
78
+
79
+ 3. **Finally explore [Webhook Integration](./webhook-integration)**
80
+ Build production-ready integrations with real-time updates
81
+
82
+ ## 💡 Example Structure
83
+
84
+ Each example follows this structure:
85
+
86
+ ```
87
+ example-name/
88
+ ├── package.json # Dependencies and scripts
89
+ ├── index.js (or server.js) # Main application code
90
+ ├── .env.example # Environment variables template
91
+ └── README.md # Detailed documentation
92
+ ```
93
+
94
+ ## 🔑 Getting Your API Key
95
+
96
+ To run these examples, you'll need a PAJ business API key:
97
+
98
+ 1. Sign up at [paj.cash](https://paj.cash)
99
+ 2. Complete business verification
100
+ 3. Generate your API key from the dashboard
101
+ 4. Add it to each example's `.env` file
102
+
103
+ ## 🌍 Environment
104
+
105
+ All examples support both staging and production environments:
106
+
107
+ - **Staging**: For testing and development
108
+ - **Production**: For live transactions
109
+
110
+ Configure the environment in each example's `.env` file.
111
+
112
+ ## 🆘 Getting Help
113
+
114
+ - 📖 Read the [main SDK documentation](../README.md)
115
+ - 🐛 [Report issues](https://github.com/paj-cash/paj_ramp/issues)
116
+ - 💬 [Join our Discord](https://discord.gg/pajcash) (if available)
117
+ - 📧 Email: support@paj.cash
118
+
119
+ ## 🤝 Contributing
120
+
121
+ Have an example you'd like to add? We welcome contributions!
122
+
123
+ 1. Fork the repository
124
+ 2. Create a new example following the existing structure
125
+ 3. Submit a pull request
126
+
127
+ Good example ideas:
128
+
129
+ - Next.js/React integration
130
+ - Mobile app integration (React Native)
131
+ - Advanced error handling patterns
132
+ - Multi-currency support
133
+ - Automated testing examples
134
+
135
+ ## 📄 License
136
+
137
+ All examples are provided under the MIT License, same as the main SDK.
138
+
139
+ ---
140
+
141
+ **Happy coding! 🎉**
@@ -0,0 +1,24 @@
1
+ # Get your API key from PAJ dashboard
2
+ BUSINESS_API_KEY=e1f7b0c0-79f2-4912-ad60-efd46434db5a
3
+
4
+ # User credentials
5
+ USER_EMAIL=example@gmail.com
6
+
7
+ # OTP from email (you'll receive this after running the script once)
8
+ OTP=1112
9
+
10
+ # Your bank details (where you want to receive fiat)
11
+ BANK_ID=68781788c3ddffabdd90a96d
12
+ ACCOUNT_NUMBER=0025635480
13
+
14
+ # Token mint address (e.g., USDC on Solana)
15
+ # USDC: EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
16
+ TOKEN_MINT=EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v
17
+ TOKEN_AMOUNT=1
18
+
19
+ # Your webhook URL (where you'll receive order status updates)
20
+ WEBHOOK_URL=https://your-domain.com/webhook
21
+
22
+ # Optional: Customize amount and currency
23
+ FIAT_AMOUNT=3000
24
+ CURRENCY=NGN
@@ -0,0 +1,186 @@
1
+ # Basic Offramp Example
2
+
3
+ This example demonstrates a complete offramp flow using the PAJ Ramp SDK, where a user can sell crypto tokens for fiat currency.
4
+
5
+ ## What This Example Shows
6
+
7
+ - 🔧 Initializing the SDK
8
+ - 📧 Session management (initiate and verify)
9
+ - 🏦 Fetching available banks
10
+ - 🔍 Resolving and verifying bank account details
11
+ - ➕ Adding bank account to user profile
12
+ - 💸 Creating an offramp order
13
+ - 📋 Handling order details and next steps
14
+
15
+ ## Prerequisites
16
+
17
+ - Node.js 16 or higher
18
+ - A PAJ business API key
19
+ - A valid email address or phone number
20
+ - Your bank account details for receiving fiat
21
+ - Crypto tokens to sell
22
+ - A webhook endpoint (optional for testing)
23
+
24
+ ## Setup
25
+
26
+ 1. **Install dependencies:**
27
+
28
+ ```bash
29
+ npm install
30
+ ```
31
+
32
+ 2. **Copy the environment file:**
33
+
34
+ ```bash
35
+ cp .env.example .env
36
+ ```
37
+
38
+ 3. **Fill in your credentials in `.env`:**
39
+
40
+ - `BUSINESS_API_KEY`: Your PAJ business API key
41
+ - `USER_EMAIL`: Your email address
42
+ - `ACCOUNT_NUMBER`: Your bank account number
43
+
44
+ 4. **Run the example (first time to get OTP and see available banks):**
45
+
46
+ ```bash
47
+ npm start
48
+ ```
49
+
50
+ 5. **Add OTP and BANK_ID to `.env`:**
51
+ The script will show available banks. Copy the bank ID you want to use:
52
+
53
+ ```
54
+ OTP=123456
55
+ BANK_ID=your_bank_id_from_the_list
56
+ ```
57
+
58
+ 6. **Run again to complete the flow:**
59
+ ```bash
60
+ npm start
61
+ ```
62
+
63
+ ## Expected Output
64
+
65
+ ```
66
+ 🚀 Initializing PAJ Ramp SDK...
67
+
68
+ 📧 Initiating session...
69
+ ✅ OTP sent to: your_email@example.com
70
+
71
+ 🔐 Verifying session with OTP...
72
+ ✅ Session verified successfully!
73
+
74
+ 🏦 Fetching available banks...
75
+ ✅ Found 15 banks
76
+ First few banks: GTBank, Access Bank, First Bank
77
+
78
+ 🔍 Resolving bank account...
79
+ ✅ Bank account verified!
80
+ Account Name: John Doe
81
+ Account Number: 1234567890
82
+ Bank: GTBank
83
+
84
+ ➕ Adding bank account to profile...
85
+ ✅ Bank account added to profile
86
+ Saved Account ID: abc123...
87
+
88
+ 💸 Creating offramp order...
89
+
90
+ ✅ Offramp order created successfully!
91
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
92
+ 📋 Order Details:
93
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
94
+ Order ID: xyz789...
95
+ Status: INIT
96
+ Crypto Amount: 6.55
97
+ USDC Amount: 6.55
98
+ Fiat Amount: 10000 NGN
99
+ Rate: 1525
100
+ Recipient: 1234567890
101
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
102
+
103
+ 📝 Next Steps:
104
+ 1. Send 6.55 tokens to address: SoLxxx...
105
+ 2. Your webhook will receive status updates
106
+ 3. Once tokens are received and confirmed, fiat will be sent to your bank account
107
+ ```
108
+
109
+ ## How It Works
110
+
111
+ ### 1. SDK Initialization
112
+
113
+ ```javascript
114
+ initializeSDK("staging"); // or 'production'
115
+ ```
116
+
117
+ ### 2. Session Management
118
+
119
+ ```javascript
120
+ const initiated = await initiate(email, apiKey);
121
+ const verified = await verify(email, otp, deviceInfo, apiKey);
122
+ ```
123
+
124
+ ### 3. Bank Account Setup
125
+
126
+ ```javascript
127
+ // Get available banks
128
+ const banks = await getBanks(token);
129
+
130
+ // Verify account exists
131
+ const resolved = await resolveBankAccount(token, bankId, accountNumber);
132
+
133
+ // Save to profile
134
+ const added = await addBankAccount(token, bankId, accountNumber);
135
+ ```
136
+
137
+ ### 4. Create Offramp Order
138
+
139
+ ```javascript
140
+ const order = await offRampCreateOrder(
141
+ token,
142
+ bankAccountId,
143
+ accountNumber,
144
+ "NGN",
145
+ 10000,
146
+ tokenMint,
147
+ webhookUrl
148
+ );
149
+ ```
150
+
151
+ ### 5. Send Tokens
152
+
153
+ Transfer the specified amount of tokens to the address provided in the order. The system will:
154
+
155
+ - Detect the token transfer
156
+ - Verify the transaction
157
+ - Send updates to your webhook
158
+ - Transfer fiat to your bank account
159
+
160
+ ## Next Steps
161
+
162
+ - Check out the [webhook integration example](../webhook-integration) to see how to handle status updates
163
+ - See the [basic onramp example](../basic-onramp) for the reverse flow
164
+ - Read the [main documentation](../../README.md) for all available features
165
+
166
+ ## Troubleshooting
167
+
168
+ ### "OTP not found in .env file"
169
+
170
+ Run the script once without OTP to receive it via email, then add it to `.env`.
171
+
172
+ ### "BANK_ID and ACCOUNT_NUMBER are required"
173
+
174
+ The script will list available banks. Choose one and add its ID to `.env`.
175
+
176
+ ### "Bank account not found"
177
+
178
+ Verify that your account number is correct and belongs to the selected bank.
179
+
180
+ ### "Invalid API key"
181
+
182
+ Ensure your `BUSINESS_API_KEY` is correct and active.
183
+
184
+ ## Support
185
+
186
+ For issues or questions, please visit the [GitHub repository](https://github.com/paj-cash/paj_ramp).