UNPKG

@moneygraph/sdk

Version:

AI-native SDK for global payouts powered by StratosPay

537 lines (536 loc) 19.4 kB
"use strict"; /** * MoneyGraph SDK - Onboard Module * * Complete customer onboarding including: * - Customer CRUD operations * - Director management (for business accounts) * - KYC submission and document upload * - Wallet and transaction access * - Mock personas for sandbox testing */ Object.defineProperty(exports, "__esModule", { value: true }); exports.OnboardModule = void 0; const client_1 = require("../api/client"); // Mock data for sandbox personas const MOCK_PERSONAS = { business_verified: { mode: 'test', first_name: 'Jane', last_name: 'Enterprise', email: 'jane@enterprise.test', phone: '+12025550100', account_type: 'business', birthday: '15-04-1982', gender: 'female', id_type: 'DRIVERS', id_number: 'DL123456789', source_of_funds: 'Ordinary Business Activities', kyc_status: 'APPROVED', document: { document: 'https://example.com/mock-document.png', selfie: 'https://example.com/mock-selfie.png', }, address: { country: 'US', state: 'NY', city: 'New York', street: '456 Broadway', postal_code: '10013', }, business_details: { business_name: 'Enterprise Solutions LLC', website: 'https://enterprise.test', staff_size: '5-50', registration_number: 'LLC12345678', tax_number: '87-1234567', registration_date: '10-03-2010', registration_location: 'New York', registration_type: 'Private Company', mcc: 'General Services', complete_ownership: false, address: { country: 'US', state: 'NY', city: 'New York', street: '456 Broadway, Suite 500', postal_code: '10013', }, }, }, individual_verified: { mode: 'test', first_name: 'John', last_name: 'Smith', email: 'john.smith@test.com', phone: '+12025550198', account_type: 'personal', birthday: '20-06-1985', gender: 'male', id_type: 'PASSPORT', id_number: 'P123456789', source_of_funds: 'Personal Savings', kyc_status: 'APPROVED', document: { document: 'https://example.com/mock-passport.png', selfie: 'https://example.com/mock-selfie.png', }, address: { country: 'US', state: 'CA', city: 'San Francisco', street: '123 Main Street', postal_code: '94105', }, }, pending_kyc: { mode: 'test', first_name: 'Pending', last_name: 'User', email: 'pending@test.com', phone: '+12025550199', account_type: 'personal', birthday: null, gender: null, id_type: null, id_number: null, source_of_funds: null, kyc_status: 'PENDING', document: { document: null, selfie: null }, address: { country: 'US', state: null, city: null, street: null, postal_code: null, }, }, rejected_kyc: { mode: 'test', first_name: 'Rejected', last_name: 'User', email: 'rejected@test.com', phone: '+12025550200', account_type: 'personal', birthday: '01-01-1990', gender: 'male', id_type: 'PASSPORT', id_number: 'INVALID123', source_of_funds: 'Personal Savings', kyc_status: 'REJECTED', document: { document: 'https://example.com/blurry-doc.png', selfie: 'https://example.com/bad-selfie.png', }, address: { country: 'US', state: 'TX', city: 'Austin', street: '789 Oak Ave', postal_code: '78701', }, }, }; // Sandbox storage for mock data const sandboxCustomers = new Map(); const sandboxDirectors = new Map(); let mockIdCounter = 1000000; function generateMockId() { return String(mockIdCounter++).padStart(7, '0'); } class OnboardModule { constructor(client) { this.client = client; } // =========================================================================== // CUSTOMER OPERATIONS // =========================================================================== /** * Create a new customer (personal or business) */ async createCustomer(params) { if (this.client.isSandbox) { const id = generateMockId(); const customer = { id, mode: 'test', first_name: params.first_name, last_name: params.last_name, email: params.email, phone: `+${params.phone}`, account_type: params.account_type, birthday: null, gender: null, id_type: null, id_number: null, source_of_funds: null, kyc_status: 'PENDING', document: { document: null, selfie: null }, address: { country: params.country, state: null, city: null, street: null, postal_code: null, }, ...(params.account_type === 'business' && { business_details: { business_name: params.business_details.business_name, website: null, staff_size: null, registration_number: null, tax_number: null, registration_date: null, registration_location: null, registration_type: null, mcc: null, complete_ownership: false, address: params.business_details.address || { country: null, state: null, city: null, street: null, postal_code: null, }, }, }), }; sandboxCustomers.set(id, customer); sandboxDirectors.set(id, []); return customer; } return this.client.post('/customer/create', params); } /** * Get all customers (paginated) */ async listCustomers(page = 1) { if (this.client.isSandbox) { const customers = Array.from(sandboxCustomers.values()); return { data: customers.slice((page - 1) * 20, page * 20), links: { first: '?page=1', last: `?page=${Math.ceil(customers.length / 20)}`, prev: page > 1 ? `?page=${page - 1}` : null, next: page * 20 < customers.length ? `?page=${page + 1}` : null, }, meta: { current_page: page, from: (page - 1) * 20 + 1, last_page: Math.ceil(customers.length / 20), path: '/customer/users', per_page: 20, to: Math.min(page * 20, customers.length), total: customers.length, links: [], }, }; } return this.client.get('/customer/users', { page }); } /** * Get a single customer by ID */ async getCustomer(customerId) { if (this.client.isSandbox) { const customer = sandboxCustomers.get(customerId); if (!customer) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } return customer; } return this.client.get(`/customer/users/${customerId}`); } /** * Update a customer */ async updateCustomer(customerId, params) { if (this.client.isSandbox) { const customer = sandboxCustomers.get(customerId); if (!customer) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } if (customer.kyc_status === 'APPROVED') { throw new client_1.MoneyGraphError('kyc already approved', 'KYC_ALREADY_APPROVED', 403); } const updated = { ...customer, ...params, address: { ...customer.address, ...params }, business_details: customer.business_details ? { ...customer.business_details, ...params.business_details } : undefined, }; sandboxCustomers.set(customerId, updated); return updated; } return this.client.post(`/customer/update/${customerId}`, params); } /** * Create a mock persona for testing (sandbox only) * Instantly creates a customer with pre-filled data */ async createMockPersona(type) { if (!this.client.isSandbox) { throw new client_1.MoneyGraphError('Mock personas are only available in sandbox mode', 'SANDBOX_ONLY'); } const id = generateMockId(); const persona = MOCK_PERSONAS[type]; const customer = { id, ...persona, }; sandboxCustomers.set(id, customer); sandboxDirectors.set(id, []); // Add mock directors for business accounts if (type === 'business_verified') { sandboxDirectors.set(id, [ { id: crypto.randomUUID(), first_name: 'Adam', last_name: 'Director', email: 'adam@enterprise.test', phone: '+12025551234', country: 'US', state: 'NY', city: 'New York', street: '456 Broadway', postal_code: '10013', birthday: '15-08-1978', ownership: 30, position: 'Chief Financial Officer', mode: 'test', }, ]); } return customer; } // =========================================================================== // KYC OPERATIONS // =========================================================================== /** * Submit KYC for review */ async submitKyc(customerId) { if (this.client.isSandbox) { const customer = sandboxCustomers.get(customerId); if (!customer) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } // In sandbox, auto-approve after 2 seconds setTimeout(() => { const c = sandboxCustomers.get(customerId); if (c && c.kyc_status === 'PENDING') { sandboxCustomers.set(customerId, { ...c, kyc_status: 'APPROVED' }); } }, 2000); return; } await this.client.post(`/customer/submit_kyc/${customerId}`); } /** * Upload KYC document * @param documentType - 'document' or 'selfie' */ async uploadDocument(customerId, documentType, file, filename) { if (this.client.isSandbox) { const customer = sandboxCustomers.get(customerId); if (!customer) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } // Mock the document upload const updated = { ...customer, document: { ...customer.document, [documentType]: `https://mock.storage/${customerId}/${filename}`, }, }; sandboxCustomers.set(customerId, updated); return; } await this.client.uploadFile(`/customer/upload_document/${customerId}/${documentType}`, file, filename); } /** * Check if customer can make payouts (KYC approved) */ async canPayout(customerId) { const customer = await this.getCustomer(customerId); if (customer.kyc_status === 'APPROVED') { return { allowed: true, status: 'APPROVED' }; } return { allowed: false, status: customer.kyc_status, reason: customer.kyc_status === 'PENDING' ? 'KYC verification is still pending' : 'KYC verification was rejected', }; } // =========================================================================== // DIRECTOR OPERATIONS (for business customers) // =========================================================================== /** * List all directors for a business customer */ async listDirectors(customerId) { if (this.client.isSandbox) { const directors = sandboxDirectors.get(customerId) || []; return { data: directors, links: { first: '?page=1', last: '?page=1', prev: null, next: null }, meta: { current_page: 1, from: 1, last_page: 1, path: `/customer/director/all/${customerId}`, per_page: 20, to: directors.length, total: directors.length, links: [], }, }; } return this.client.get(`/customer/director/all/${customerId}`); } /** * Get a single director */ async getDirector(customerId, directorId) { if (this.client.isSandbox) { const directors = sandboxDirectors.get(customerId) || []; const director = directors.find(d => d.id === directorId); if (!director) { throw new client_1.MoneyGraphError('Director not found', 'DIRECTOR_NOT_FOUND', 404); } return director; } return this.client.get(`/customer/director/all/${customerId}/${directorId}`); } /** * Create a new director */ async createDirector(customerId, params) { if (this.client.isSandbox) { if (!sandboxCustomers.has(customerId)) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } const director = { id: crypto.randomUUID(), first_name: params.first_name, last_name: params.last_name, email: params.email, phone: `+${params.phone}`, country: params.country, state: params.state, city: params.city, street: params.street, postal_code: params.postal_code, birthday: params.birthday, ownership: params.ownership, position: params.position, mode: 'test', }; const directors = sandboxDirectors.get(customerId) || []; directors.push(director); sandboxDirectors.set(customerId, directors); return director; } return this.client.post(`/customer/director/create/${customerId}`, params); } /** * Update a director */ async updateDirector(customerId, directorId, params) { if (this.client.isSandbox) { const directors = sandboxDirectors.get(customerId) || []; const index = directors.findIndex(d => d.id === directorId); if (index === -1) { throw new client_1.MoneyGraphError('Director not found', 'DIRECTOR_NOT_FOUND', 404); } const updated = { ...directors[index], ...params }; directors[index] = updated; sandboxDirectors.set(customerId, directors); return updated; } return this.client.post(`/customer/director/update/${customerId}/${directorId}`, params); } /** * Delete a director */ async deleteDirector(customerId, directorId) { if (this.client.isSandbox) { const directors = sandboxDirectors.get(customerId) || []; const index = directors.findIndex(d => d.id === directorId); if (index === -1) { throw new client_1.MoneyGraphError('Director not found', 'DIRECTOR_NOT_FOUND', 404); } directors.splice(index, 1); sandboxDirectors.set(customerId, directors); return; } await this.client.delete(`/customer/director/delete/${customerId}/${directorId}`); } // =========================================================================== // WALLET & TRANSACTION OPERATIONS // =========================================================================== /** * Get all wallets for a customer */ async getWallets(customerId) { if (this.client.isSandbox) { if (!sandboxCustomers.has(customerId)) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } // Return mock USD wallet return [ { id: crypto.randomUUID(), currency_id: crypto.randomUUID(), amount: 0, human_readable_amount: 0, currency: 'USD', mode: 'test', }, ]; } const response = await this.client.get(`/customer/wallets/${customerId}`); return response.data; } /** * Get all transactions for a customer (paginated) */ async listTransactions(customerId, page = 1) { if (this.client.isSandbox) { if (!sandboxCustomers.has(customerId)) { throw new client_1.MoneyGraphError('User not found', 'CUSTOMER_NOT_FOUND', 404); } return { data: [], links: { first: '?page=1', last: '?page=1', prev: null, next: null }, meta: { current_page: 1, from: 0, last_page: 1, path: `/customer/transactions/${customerId}`, per_page: 20, to: 0, total: 0, links: [], }, }; } return this.client.get(`/customer/transactions/${customerId}`, { page }); } /** * Get a single transaction */ async getTransaction(customerId, transactionId) { if (this.client.isSandbox) { throw new client_1.MoneyGraphError('Transaction not found', 'NOT_FOUND', 404); } return this.client.get(`/customer/transactions/${customerId}/${transactionId}`); } } exports.OnboardModule = OnboardModule;