carbon-baas-sdk 1.0.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.
@@ -0,0 +1,18 @@
1
+ interface InitiatePayoutRequest {
2
+ amount: number;
3
+ source: {
4
+ account_number: string;
5
+ };
6
+ beneficiary: {
7
+ bank_code: string;
8
+ bank_name: string;
9
+ account_number: string;
10
+ account_name: string;
11
+ };
12
+ reference: string;
13
+ meta_data: object;
14
+ remark: string;
15
+ }
16
+ export declare function initiatePayout(payoutData: InitiatePayoutRequest): Promise<any>;
17
+ export declare function fetchPayout(payoutId: string): Promise<any>;
18
+ export {};
@@ -0,0 +1,2 @@
1
+ export declare function verifyTransaction(accountNumber: string, reference: string): Promise<any>;
2
+ export declare function fetchTransactions(accountNumber: string, page?: number, limit?: number): Promise<any>;
package/dist/util.d.ts ADDED
@@ -0,0 +1 @@
1
+ export declare function handleError(error: any): any;
@@ -0,0 +1,8 @@
1
+ interface UpdateWebhookRequest {
2
+ url: string;
3
+ }
4
+ export declare function fetchWebhook(): Promise<any>;
5
+ export declare function updateWebhook(data: UpdateWebhookRequest): Promise<any>;
6
+ export declare function fetchWebhookHistory(page?: number, limit?: number): Promise<any>;
7
+ export declare function resendWebhookEvent(eventId: string): Promise<any>;
8
+ export {};
@@ -0,0 +1,48 @@
1
+ // Import the SDK
2
+ const carbon = require('../dist/index.umd.js');
3
+ const dotenv = require('dotenv');
4
+ dotenv.config({ path: '../.env' });
5
+
6
+ // Initialize the SDK
7
+ carbon.initialize(process.env.CARBON_API_KEY, process.env.ENV);
8
+
9
+
10
+ // Example function to create a customer
11
+ async function exampleCreateCustomer() {
12
+ const customerData = {
13
+ first_name: 'John',
14
+ last_name: 'Doe',
15
+ email: 'john.doe@example.com',
16
+ phone: '+1234567890',
17
+ dob: '1990-01-01',
18
+ gender: 'male',
19
+ street: '123 Main St',
20
+ city: 'Ikeja',
21
+ state: 'Lagos State',
22
+ country: 'NG',
23
+ bvn: '1234567890',
24
+ nin: '12345678901', //optional
25
+ };
26
+
27
+ try {
28
+ const newCustomer = await carbon.createCustomer(customerData);
29
+ console.log('Customer created:', newCustomer);
30
+ return newCustomer;
31
+ } catch (error) {
32
+ console.error('Error creating customer:', error);
33
+ }
34
+ }
35
+
36
+ // Example function to fetch a customer
37
+ async function exampleFetchCustomers() {
38
+ try {
39
+ const customers = await carbon.fetchCustomers();
40
+ console.log('Customers:', customers);
41
+ } catch (error) {
42
+ console.error('Error fetching customers:', error);
43
+ }
44
+ }
45
+
46
+ // Run the examples
47
+ exampleFetchCustomers();
48
+
@@ -0,0 +1,74 @@
1
+ import { MCPClient } from '../src';
2
+ import { MCPAgent } from '../src/agents/mcp-agent';
3
+ import { MCPResponse } from '../src/core/mcp-types';
4
+ import dotenv from 'dotenv';
5
+
6
+ // Load environment variables
7
+ dotenv.config();
8
+
9
+ async function testMCP() {
10
+ try {
11
+ // Initialize MCP client
12
+ const mcpClient = new MCPClient({
13
+ apiKey: process.env.CARBON_API_KEY || '',
14
+ mode: 'sandbox',
15
+ defaultCurrency: 'NGN',
16
+ supportedCurrencies: [
17
+ { code: 'NGN', name: 'Nigerian Naira', symbol: '₦' },
18
+ { code: 'USD', name: 'US Dollar', symbol: '$' },
19
+ ],
20
+ });
21
+
22
+ // Initialize MCP agent
23
+ const mcpAgent = new MCPAgent(mcpClient);
24
+
25
+ // Test commands
26
+ const commands = [
27
+ 'create customer called Tech Corp with email tech@example.com and phone 2348012345678',
28
+ 'fetch customers',
29
+ 'create account for Tech Corp',
30
+ 'check balance for account 1234567890',
31
+ 'fetch banks',
32
+ 'check uptime for banks'
33
+ ];
34
+
35
+ console.log('Starting MCP tests...\n');
36
+
37
+ let context: MCPResponse | undefined;
38
+
39
+ for (const command of commands) {
40
+ console.log(`\nExecuting command: "${command}"`);
41
+ try {
42
+ // Pass context from previous interaction
43
+ const result = await mcpAgent.processCommand(command);
44
+ console.log('Result:', JSON.stringify({
45
+ message: result.message,
46
+ metadata: result.metadata,
47
+ suggestedActions: result.suggestedActions || []
48
+ }, null, 2));
49
+
50
+ // Store context for next interaction
51
+ context = result;
52
+
53
+ const suggestedActions = result.suggestedActions || [];
54
+ if (suggestedActions.length > 0) {
55
+ console.log('Suggested next actions:', suggestedActions);
56
+ }
57
+
58
+ const availableTools = result.availableTools || [];
59
+ if (availableTools.length > 0) {
60
+ console.log('Available tools:', availableTools.map(t => t.name));
61
+ }
62
+ } catch (error) {
63
+ console.error(`Error processing command "${command}":`, error);
64
+ }
65
+ console.log('-'.repeat(80));
66
+ }
67
+
68
+ } catch (error) {
69
+ console.error('Test failed:', error);
70
+ }
71
+ }
72
+
73
+ // Run the test
74
+ testMCP().catch(console.error);
package/jest.config.js ADDED
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ testMatch: ['**/tests/**/*.test.ts'],
5
+ transform: {
6
+ '^.+\\.tsx?$': 'ts-jest',
7
+ },
8
+ };
package/package.json ADDED
@@ -0,0 +1,34 @@
1
+ {
2
+ "name": "carbon-baas-sdk",
3
+ "version": "1.0.0",
4
+ "description": "## Welcome to our API Developer Documentation\n\nCarbon aims to unlock the full potential of your business with a feature-rich account designed for growth.\n\n## Integrations\n\nWe aim to provide our APIs for developers and businesses to offer financial services to their existing customer base through REST APIs without doing the heavy lifting. Our API has predictable resource-oriented URLs, accepts form-encoded request bodies, returns JSON-encoded responses, and uses standard HTTP response codes, authentication, and verbs.\n\n### Authentication\n\n`Authorization : API Key`\n\nHeader \n`x-carbon-key : value`\n\n`x-carbon-key` can be generated via developer page on Carbon Business\n\n| Enviroment | URL |\n| --- | --- |\n| Live | |\n| Sandbox | [https://carbonapistagingsecure.getcarbon.co/baas/api](https://carbonapistagingsecure.getcarbon.co/baas/api) |\n\n### **Handling Errors**\n\nWe use the conventional HTTP response codes to indicate the success or failure of an API request. \nCodes in the 2xx range indicate success. Codes in the 4xx range indicate an error that failed given the information provided (e.g., a required parameter was omitted, etc.). Codes in the 5xx range indicate an error with our servers.\n\n| Error | Description |\n| --- | --- |\n| 400 - Bad Request | The request was unacceptable, often due to missing a required parameter. |\n| 401 - Unauthorized | Not a valid API key was provided. |\n| 402 - Request Failed | The parameters were valid but the request failed. |\n| 403 - Forbidden | The API key doesn't have permission to perform the request. |\n| 404 - Not Found | The requested resource doesn't exist. |\n| 429 - Too Many Requests | Too many requests hit the API |\n| 500, 502, 503, 504 - Server Errors | System Error |",
5
+ "main": "dist/index.cjs.js",
6
+ "module": "dist/index.esm.js",
7
+ "browser": "dist/index.umd.js",
8
+ "scripts": {
9
+ "build": "rollup -c",
10
+ "test": "jest --coverage"
11
+ },
12
+ "keywords": [
13
+ "getcarbon",
14
+ "carbon business"
15
+ ],
16
+ "author": "",
17
+ "license": "ISC",
18
+ "dependencies": {
19
+ "@types/node": "^22.13.10",
20
+ "axios": "^1.8.3",
21
+ "dotenv": "^16.4.7",
22
+ "typescript": "^5.8.2"
23
+ },
24
+ "devDependencies": {
25
+ "@rollup/plugin-commonjs": "^28.0.3",
26
+ "@rollup/plugin-json": "^6.1.0",
27
+ "@rollup/plugin-node-resolve": "^16.0.1",
28
+ "@types/jest": "^29.5.14",
29
+ "jest": "^29.7.0",
30
+ "rollup": "^4.35.0",
31
+ "rollup-plugin-typescript2": "^0.36.0",
32
+ "ts-jest": "^29.2.6"
33
+ }
34
+ }
@@ -0,0 +1,34 @@
1
+ import commonjs from '@rollup/plugin-commonjs';
2
+ import resolve from '@rollup/plugin-node-resolve';
3
+ import typescript from 'rollup-plugin-typescript2';
4
+ import json from '@rollup/plugin-json';
5
+
6
+ export default {
7
+ input: 'src/index.ts',
8
+ output: [
9
+ {
10
+ file: 'dist/index.cjs.js',
11
+ format: 'cjs',
12
+ sourcemap: true,
13
+ },
14
+ {
15
+ file: 'dist/index.esm.js',
16
+ format: 'esm',
17
+ sourcemap: true,
18
+ },
19
+ {
20
+ file: 'dist/index.umd.js',
21
+ format: 'umd',
22
+ name: 'carbon-baas-sdk',
23
+ sourcemap: true,
24
+ },
25
+ ],
26
+ plugins: [
27
+ resolve(),
28
+ commonjs(),
29
+ json(),
30
+ typescript({
31
+ tsconfig: './tsconfig.json',
32
+ }),
33
+ ],
34
+ };
@@ -0,0 +1,26 @@
1
+ import { getInstance } from './index';
2
+ import { handleError } from './util';
3
+
4
+ interface CreateAccountRequest {
5
+ customer_id: string;
6
+ account_type: string;
7
+ }
8
+
9
+ export async function createAccount(accountData: CreateAccountRequest) {
10
+ try {
11
+ const response = await getInstance().post('/v1/accounts', accountData);
12
+ return response.data;
13
+ } catch (error) {
14
+ return handleError(error);
15
+ }
16
+ }
17
+
18
+ export async function fetchAccount(accountNumber: string) {
19
+ try {
20
+ const response = await getInstance().get(`/v1/accounts/${accountNumber}`);
21
+ return response.data;
22
+ } catch (error) {
23
+ return handleError(error);
24
+ }
25
+ }
26
+
package/src/banks.ts ADDED
@@ -0,0 +1,44 @@
1
+ import { getInstance } from './index';
2
+ import { handleError } from './util';
3
+
4
+ interface ResolveAccountRequest {
5
+ account_number: string;
6
+ bank_code: string;
7
+ }
8
+
9
+ interface UptimeResponse {
10
+ status: string;
11
+ message: string;
12
+ data: Array<{
13
+ cbnBankCode: string;
14
+ nipBankCode: string;
15
+ uptime: number;
16
+ }>;
17
+ }
18
+
19
+ export async function fetchBanks() {
20
+ try {
21
+ const response = await getInstance().get('/v1/banks');
22
+ return response.data;
23
+ } catch (error) {
24
+ return handleError(error);
25
+ }
26
+ }
27
+
28
+ export async function resolveAccount(accountData: ResolveAccountRequest) {
29
+ try {
30
+ const response = await getInstance().post('/v1/banks/resolve', accountData);
31
+ return response.data;
32
+ } catch (error) {
33
+ return handleError(error);
34
+ }
35
+ }
36
+
37
+ export async function fetchBanksUptime() {
38
+ try {
39
+ const response = await getInstance().get('/v1/banks/uptime');
40
+ return response.data;
41
+ } catch (error) {
42
+ return handleError(error);
43
+ }
44
+ }
@@ -0,0 +1,47 @@
1
+ import axios from 'axios';
2
+ import { getInstance } from './index';
3
+ import { handleError } from './util';
4
+
5
+ interface CreateCustomerRequest {
6
+ first_name: string;
7
+ last_name: string;
8
+ email: string;
9
+ phone: string;
10
+ dob: string;
11
+ gender: string;
12
+ street: string;
13
+ city: string;
14
+ state: string;
15
+ country: string;
16
+ bvn: string;
17
+ nin: string;
18
+ }
19
+
20
+ export async function createCustomer(customerData: CreateCustomerRequest) {
21
+ try {
22
+ const response = await getInstance().post('/v1/customers', customerData);
23
+ return response.data;
24
+ } catch (error) {
25
+ return handleError(error);
26
+ }
27
+ }
28
+
29
+ export async function fetchCustomer(customerId: string) {
30
+ try {
31
+ const response = await getInstance().get(`/v1/customers/${customerId}`);
32
+ return response.data;
33
+ } catch (error) {
34
+ return handleError(error);
35
+ }
36
+ }
37
+
38
+ export async function fetchCustomers(page: number = 1, limit: number = 10) {
39
+ try {
40
+ const response = await getInstance().get('/v1/customers', {
41
+ params: { page, limit },
42
+ });
43
+ return response.data;
44
+ } catch (error) {
45
+ return handleError(error);
46
+ }
47
+ }
package/src/index.ts ADDED
@@ -0,0 +1,34 @@
1
+ import axios, { AxiosInstance } from 'axios';
2
+
3
+ let instance: AxiosInstance;
4
+
5
+ export function initialize(apiKey: string, mode: 'live' | 'sandbox') {
6
+ const baseUrl = mode === 'live' ? 'https://carbonapisecure.getcarbon.co/baas/api' : 'https://carbonapistagingsecure.getcarbon.co/baas/api';
7
+ const accessKey = 'baas-consumers';
8
+
9
+ if (!apiKey) {
10
+ throw new Error('API key must be provided');
11
+ }
12
+
13
+ instance = axios.create({
14
+ baseURL: baseUrl,
15
+ headers: {
16
+ 'x-carbon-key': apiKey,
17
+ 'apiKey': accessKey,
18
+ },
19
+ });
20
+ }
21
+
22
+ export function getInstance(): AxiosInstance {
23
+ if (!instance) {
24
+ throw new Error('SDK not initialized. Call initialize() first.');
25
+ }
26
+ return instance;
27
+ }
28
+
29
+ export { createAccount, fetchAccount } from './accounts';
30
+ export { verifyTransaction, fetchTransactions } from './transactions';
31
+ export { createCustomer, fetchCustomer, fetchCustomers } from './customers';
32
+ export { initiatePayout, fetchPayout } from './payouts';
33
+ export { fetchBanks, resolveAccount } from './banks';
34
+ export { fetchWebhook, fetchWebhookHistory, updateWebhook, resendWebhookEvent } from './webhook';
package/src/payouts.ts ADDED
@@ -0,0 +1,36 @@
1
+ import { getInstance } from './index';
2
+ import { handleError } from './util';
3
+
4
+ interface InitiatePayoutRequest {
5
+ amount: number;
6
+ source: {
7
+ account_number: string;
8
+ };
9
+ beneficiary: {
10
+ bank_code: string;
11
+ bank_name: string;
12
+ account_number: string;
13
+ account_name: string;
14
+ };
15
+ reference: string;
16
+ meta_data: object;
17
+ remark: string;
18
+ }
19
+
20
+ export async function initiatePayout(payoutData: InitiatePayoutRequest) {
21
+ try {
22
+ const response = await getInstance().post('/v1/payouts', payoutData);
23
+ return response.data;
24
+ } catch (error) {
25
+ return handleError(error);
26
+ }
27
+ }
28
+
29
+ export async function fetchPayout(payoutId: string) {
30
+ try {
31
+ const response = await getInstance().get(`/v1/payouts/${payoutId}`);
32
+ return response.data;
33
+ } catch (error) {
34
+ return handleError(error);
35
+ }
36
+ }
@@ -0,0 +1,22 @@
1
+ import { getInstance } from './index';
2
+ import { handleError } from './util';
3
+
4
+ export async function verifyTransaction(accountNumber: string, reference: string) {
5
+ try {
6
+ const response = await getInstance().get(`/v1/accounts/${accountNumber}/transactions/${reference}`);
7
+ return response.data;
8
+ } catch (error) {
9
+ return handleError(error);
10
+ }
11
+ }
12
+
13
+ export async function fetchTransactions(accountNumber: string, page: number = 1, limit: number = 10) {
14
+ try {
15
+ const response = await getInstance().get(`/v1/accounts/${accountNumber}/transactions`, {
16
+ params: { page, limit },
17
+ });
18
+ return response.data;
19
+ } catch (error) {
20
+ return handleError(error);
21
+ }
22
+ }
package/src/util.ts ADDED
@@ -0,0 +1,9 @@
1
+ export function handleError(error: any) {
2
+ if (error.response) {
3
+ console.error('Error response:', error.response.data);
4
+ return error.response.data;
5
+ } else {
6
+ console.error('Error message:', error.message);
7
+ throw error.message;
8
+ }
9
+ }
package/src/webhook.ts ADDED
@@ -0,0 +1,94 @@
1
+ import { getInstance } from './index';
2
+ import { handleError } from './util';
3
+
4
+ interface UpdateWebhookRequest {
5
+ url: string;
6
+ }
7
+
8
+ interface WebhookResponse {
9
+ status: string;
10
+ message: string;
11
+ data: {
12
+ url: string;
13
+ signature_secret: string | null;
14
+ status: string;
15
+ mode: string;
16
+ };
17
+ }
18
+
19
+ interface WebhookHistoryResponse {
20
+ status: string;
21
+ message: string;
22
+ data: Array<{
23
+ event_id: string;
24
+ event_type: string;
25
+ data: {
26
+ event: string;
27
+ data: {
28
+ id: string;
29
+ amount: number;
30
+ currency: string;
31
+ transactionType: string;
32
+ entryDate: string;
33
+ uniqueRef: string;
34
+ account: {
35
+ id: string;
36
+ bankAccount: {
37
+ accountName: string;
38
+ accountNumber: string;
39
+ bank: {
40
+ code: string;
41
+ name: string;
42
+ };
43
+ };
44
+ static: boolean;
45
+ currency: string;
46
+ clientId: string;
47
+ };
48
+ };
49
+ };
50
+ created_at: string;
51
+ updated_at: string;
52
+ }>;
53
+ total: number;
54
+ }
55
+
56
+ export async function fetchWebhook() {
57
+ try {
58
+ const response = await getInstance().get('/v1/webhook');
59
+ return response.data;
60
+ } catch (error) {
61
+ return handleError(error);
62
+ }
63
+ }
64
+
65
+ export async function updateWebhook(data: UpdateWebhookRequest) {
66
+ try {
67
+ const response = await getInstance().put('/v1/webhook', data);
68
+ return response.data;
69
+ } catch (error) {
70
+ return handleError(error);
71
+ }
72
+ }
73
+
74
+ export async function fetchWebhookHistory(page: number = 0, limit: number = 10) {
75
+ try {
76
+ const response = await getInstance().get('/v1/webhook/history', {
77
+ params: { page, limit },
78
+ });
79
+ return response.data;
80
+ } catch (error) {
81
+ return handleError(error);
82
+ }
83
+ }
84
+
85
+ export async function resendWebhookEvent(eventId: string) {
86
+ try {
87
+ const response = await getInstance().post('/v1/webhook/resend-webhook-event', {
88
+ event_id: eventId,
89
+ });
90
+ return response.data;
91
+ } catch (error) {
92
+ return handleError(error);
93
+ }
94
+ }
@@ -0,0 +1,88 @@
1
+ import { createCustomer, fetchCustomer } from '../src/customers';
2
+ import { beforeEach, describe, expect, it, jest } from '@jest/globals';
3
+ import axios from 'axios';
4
+
5
+ // Mock the getInstance function instead of axios directly
6
+ jest.mock('../src/index', () => ({
7
+ getInstance: () => axios,
8
+ }));
9
+
10
+ // Now mock axios
11
+ jest.mock('axios');
12
+ const mockedAxios = axios as jest.Mocked<typeof axios>;
13
+
14
+ describe('Customer API', () => {
15
+ beforeEach(() => {
16
+ // Clear all mocks before each test
17
+ jest.clearAllMocks();
18
+ });
19
+
20
+ it('should create a customer', async () => {
21
+ const customerData = {
22
+ first_name: 'John',
23
+ last_name: 'Doe',
24
+ email: 'john.doe@example.com',
25
+ phone: '+1234567890',
26
+ dob: '1990-01-01',
27
+ gender: 'male',
28
+ street: '123 Main St',
29
+ city: 'Anytown',
30
+ state: 'CA',
31
+ country: 'US',
32
+ bvn: '1234567890',
33
+ nin: '1234567890',
34
+ };
35
+
36
+ const responseData = { data: { id: '123', ...customerData } };
37
+ mockedAxios.post.mockResolvedValueOnce({ data: responseData });
38
+
39
+ const result = await createCustomer(customerData);
40
+ expect(result).toEqual(responseData);
41
+ expect(mockedAxios.post).toHaveBeenCalledWith('/v1/customers', customerData);
42
+ });
43
+
44
+ it('should fetch a customer', async () => {
45
+ const customerId = '123';
46
+ const responseData = { data: { id: customerId, first_name: 'John', last_name: 'Doe' } };
47
+ mockedAxios.get.mockResolvedValueOnce({ data: responseData });
48
+
49
+ const result = await fetchCustomer(customerId);
50
+ expect(result).toEqual(responseData);
51
+ expect(mockedAxios.get).toHaveBeenCalledWith(`/v1/customers/${customerId}`);
52
+ });
53
+
54
+ it('should handle API errors', async () => {
55
+ const customerData = {
56
+ first_name: 'John',
57
+ last_name: 'Doe',
58
+ email: 'john.doe@example.com',
59
+ phone: '+1234567890',
60
+ dob: '1990-01-01',
61
+ gender: 'male',
62
+ street: '123 Main St',
63
+ city: 'Anytown',
64
+ state: 'CA',
65
+ country: 'US',
66
+ bvn: '1234567890',
67
+ nin: '1234567890',
68
+ };
69
+
70
+ const errorResponse = {
71
+ response: {
72
+ data: {
73
+ status: 'failed',
74
+ message: 'bad request',
75
+ errors: [
76
+ { msg: 'BVN must be 11 numbers long', param: 'bvn' },
77
+ { msg: 'NIN must be 11 numbers long', param: 'nin' },
78
+ ],
79
+ },
80
+ },
81
+ };
82
+
83
+ mockedAxios.post.mockRejectedValueOnce(errorResponse);
84
+
85
+ const result = await createCustomer(customerData);
86
+ expect(result).toEqual(errorResponse.response.data);
87
+ });
88
+ });