UNPKG

@moneygraph/sdk

Version:

AI-native SDK for global payouts powered by StratosPay

264 lines (224 loc) 8.29 kB
/** * MoneyGraph SDK - Supabase Edge Function Recipe * * Use this as a backend proxy to avoid CORS issues when calling * the MoneyGraph SDK from browser applications. * * Deployment: * 1. Create a new Edge Function: supabase functions new moneygraph * 2. Copy this file to supabase/functions/moneygraph/index.ts * 3. Set secret: supabase secrets set MONEYGRAPH_API_KEY=sk_test_... * 4. Deploy: supabase functions deploy moneygraph * * Frontend usage: * ```typescript * const response = await fetch('/functions/v1/moneygraph', { * method: 'POST', * headers: { 'Content-Type': 'application/json' }, * body: JSON.stringify({ * action: 'payout.send', * params: { customerId: '123', from: 'USD', to: 'NGN', amount: 100, recipient: {...} } * }), * }); * ``` */ // @ts-ignore - Deno types import { serve } from 'https://deno.land/std@0.168.0/http/server.ts'; // Import types from npm (Deno can use npm: prefix) // Note: In production, you'd bundle the SDK or use a CDN version const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Headers': 'authorization, x-client-info, apikey, content-type', }; interface RequestBody { action: string; params: Record<string, unknown>; } // Simplified MoneyGraph client for Edge Function class MoneyGraphClient { private apiKey: string; private baseUrl = 'https://stratospay.com/api/v1'; constructor(apiKey: string) { this.apiKey = apiKey; } async request<T>(method: string, endpoint: string, body?: Record<string, unknown>): Promise<T> { const response = await fetch(`${this.baseUrl}${endpoint}`, { method, headers: { 'Authorization': `Bearer ${this.apiKey}`, 'Content-Type': 'application/json', 'Accept': 'application/json', }, body: body ? JSON.stringify(body) : undefined, }); const data = await response.json(); if (!response.ok || data.status === 'failed') { throw new Error(data.message || `Request failed: ${response.status}`); } return data.data; } } serve(async (req: Request) => { // Handle CORS preflight if (req.method === 'OPTIONS') { return new Response('ok', { headers: corsHeaders }); } try { // @ts-ignore - Deno.env const apiKey = Deno.env.get('MONEYGRAPH_API_KEY'); if (!apiKey) { throw new Error('MONEYGRAPH_API_KEY not configured'); } const client = new MoneyGraphClient(apiKey); const { action, params } = await req.json() as RequestBody; let result: unknown; switch (action) { // Customer operations case 'customer.create': result = await client.request('POST', '/customer/create', params); break; case 'customer.get': result = await client.request('GET', `/customer/users/${params.customerId}`); break; case 'customer.update': result = await client.request('POST', `/customer/update/${params.customerId}`, params.data as Record<string, unknown>); break; case 'customer.list': result = await client.request('GET', '/customer/users'); break; // KYC operations case 'kyc.submit': result = await client.request('POST', `/customer/submit_kyc/${params.customerId}`); break; case 'kyc.canPayout': { const customer = await client.request<{ kyc_status: string }>('GET', `/customer/users/${params.customerId}`); result = { allowed: customer.kyc_status === 'APPROVED', status: customer.kyc_status, }; break; } // Director operations case 'director.list': result = await client.request('GET', `/customer/director/all/${params.customerId}`); break; case 'director.create': result = await client.request('POST', `/customer/director/create/${params.customerId}`, params.data as Record<string, unknown>); break; case 'director.update': result = await client.request('POST', `/customer/director/update/${params.customerId}/${params.directorId}`, params.data as Record<string, unknown>); break; case 'director.delete': result = await client.request('DELETE', `/customer/director/delete/${params.customerId}/${params.directorId}`); break; // Wallet & Transaction operations case 'wallet.list': result = await client.request('GET', `/customer/wallets/${params.customerId}`); break; case 'transaction.list': result = await client.request('GET', `/customer/transactions/${params.customerId}`); break; case 'transaction.get': result = await client.request('GET', `/customer/transactions/${params.customerId}/${params.transactionId}`); break; // Quote operations (these would need real endpoints - using mock for now) case 'quote.get': // In production, call actual quote endpoint result = { id: `quote_${Date.now()}`, from_currency: params.from, to_currency: params.to, from_amount: params.amount, to_amount: (params.amount as number) * 1550, // Mock rate rate: 1550, fee: 2, expires_at: new Date(Date.now() + 120000).toISOString(), }; break; case 'quote.confirm': result = { id: crypto.randomUUID(), quote_id: params.quoteId, status: 'confirmed', confirmed_at: new Date().toISOString(), }; break; // Payout operations case 'payout.send': { // First check KYC const customer = await client.request<{ kyc_status: string }>('GET', `/customer/users/${params.customerId}`); if (customer.kyc_status !== 'APPROVED') { throw new Error(`KYC not approved: ${customer.kyc_status}`); } // In production, call actual payout endpoint result = { id: `payout_${Date.now()}`, status: 'pending', created_at: new Date().toISOString(), }; break; } // Reference data case 'reference.countries': result = await client.request('GET', '/countries'); break; case 'reference.currencies': result = await client.request('GET', `/currencies/${params.countryIso2}`); break; case 'reference.sourceOfFunds': result = await client.request('GET', '/source_of_funds'); break; case 'reference.mcc': result = await client.request('GET', '/mcc'); break; case 'reference.businessTypes': result = await client.request('GET', '/business_registration_type'); break; default: throw new Error(`Unknown action: ${action}`); } return new Response(JSON.stringify({ success: true, data: result }), { headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } catch (error) { const message = error instanceof Error ? error.message : 'Unknown error'; return new Response(JSON.stringify({ success: false, error: message }), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' }, }); } }); /* * Frontend Client Example: * * class MoneyGraphProxy { * private baseUrl: string; * * constructor(supabaseUrl: string) { * this.baseUrl = `${supabaseUrl}/functions/v1/moneygraph`; * } * * private async call<T>(action: string, params: Record<string, unknown> = {}): Promise<T> { * const response = await fetch(this.baseUrl, { * method: 'POST', * headers: { 'Content-Type': 'application/json' }, * body: JSON.stringify({ action, params }), * }); * const { success, data, error } = await response.json(); * if (!success) throw new Error(error); * return data; * } * * async createCustomer(params: CreateCustomerParams) { * return this.call('customer.create', params); * } * * async getQuote(from: string, to: string, amount: number) { * return this.call('quote.get', { from, to, amount }); * } * * async sendPayout(customerId: string, quoteId: string, recipient: object) { * return this.call('payout.send', { customerId, quoteId, recipient }); * } * } */