npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@moneygraph/sdk

v2.0.4

Published

AI-native SDK for global payouts powered by StratosPay

Readme

@moneygraph/sdk

AI-native SDK for global payouts powered by StratosPay. Send money to 107+ countries with automatic FX, KYC enforcement, and developer-friendly APIs.

Features

  • 🌍 Global Payouts - Send to 107+ countries via local rails
  • 💳 Accept Payments - Cards, embedded widget, popup checkout
  • 💱 Quote & Confirm FX - Lock rates for 2 minutes before executing
  • 🔐 KYC Enforcement - Automatic verification before payouts
  • 🧪 Sandbox Mode - Full mock data for rapid development
  • 📦 Zero Dependencies - Uses native fetch API
  • 🤖 AI-Native - Optimized for Cursor, Lovable, Claude.ai, and AI coding assistants

Installation

npm install @moneygraph/sdk
# or
yarn add @moneygraph/sdk
# or
pnpm add @moneygraph/sdk

Quick Start

import { MoneyGraph } from '@moneygraph/sdk';

// Initialize with your API key
// sk_test_* = sandbox mode (mock data)
// sk_live_* = live mode (real transactions)
const mg = new MoneyGraph({ apiKey: 'sk_test_your_key' });

// Check mode
console.log(mg.mode); // 'sandbox' or 'live'

Complete Payout Flow

1. Create a Customer

// Personal account
const customer = await mg.onboard.createCustomer({
  account_type: 'personal',
  first_name: 'John',
  last_name: 'Doe',
  email: '[email protected]',
  phone: '2025551234',
  phone_iso2: 'US',
  country: 'US',
});

// Business account
const business = await mg.onboard.createCustomer({
  account_type: 'business',
  first_name: 'Jane',
  last_name: 'Smith',
  email: '[email protected]',
  phone: '2025555678',
  phone_iso2: 'US',
  country: 'US',
  business_details: {
    business_name: 'Acme Corp',
    address: {
      country: 'US',
      state: 'CA',
      city: 'San Francisco',
      street: '123 Main St',
      postal_code: '94105',
    },
  },
});

2. Complete KYC

// Update with KYC information
await mg.onboard.updateCustomer(customer.id, {
  birthday: '15-06-1990', // DD-MM-YYYY format
  gender: 'male',
  id_type: 'PASSPORT',
  id_number: 'P123456789',
  source_of_fund_id: '22bc46b1-6a5a-493b-96cd-61b986ab698d',
  state: 'CA',
  city: 'San Francisco',
  street: '123 Main Street',
  postal_code: '94105',
});

// Upload documents
await mg.onboard.uploadDocument(customer.id, 'document', documentFile, 'passport.jpg');
await mg.onboard.uploadDocument(customer.id, 'selfie', selfieFile, 'selfie.jpg');

// Submit for review
await mg.onboard.submitKyc(customer.id);

// Check KYC status
const status = await mg.onboard.canPayout(customer.id);
console.log(status); // { allowed: true, status: 'APPROVED' }

3. Get FX Quote

// Get a quote (valid for 2 minutes)
const quote = await mg.liquidity.getQuote({
  from: 'USD',
  to: 'NGN',
  amount: 100,
});

console.log(quote);
// {
//   id: 'quote_123...',
//   from_currency: 'USD',
//   to_currency: 'NGN',
//   from_amount: 100,
//   to_amount: 151500,
//   rate: 1550,
//   fee: 2,
//   expires_at: '2025-01-15T10:02:00Z'
// }

// Check time remaining
const seconds = mg.liquidity.getQuoteTimeRemaining(quote);
console.log(`Quote expires in ${seconds} seconds`);

4. Confirm Quote & Send Payout

// Confirm the quote (lock the rate)
const confirmation = await mg.liquidity.confirmQuote(quote.id);

// Send the payout
const payout = await mg.payouts.send({
  quote_id: quote.id,
  customer_id: customer.id,
  recipient: {
    name: 'Jane Doe',
    bank_code: '058',           // GTBank
    account_number: '0123456789',
    account_name: 'Jane Doe',
  },
  reference: 'INV-2025-001',
  narration: 'Invoice payment',
});

// Or use the convenience method
const payout = await mg.sendPayout({
  customerId: customer.id,
  from: 'USD',
  to: 'NGN',
  amount: 100,
  recipient: {
    name: 'Jane Doe',
    bank_code: '058',
    account_number: '0123456789',
  },
});

5. Track Payout Status

const status = await mg.payouts.getStatus(payout.id);
console.log(status.status); // 'pending' -> 'processing' -> 'completed'

Business Directors (for Business Accounts)

// Add a director
const director = await mg.onboard.createDirector(business.id, {
  first_name: 'Michael',
  last_name: 'Johnson',
  email: '[email protected]',
  phone: '2025551234',
  phone_iso2: 'US',
  country: 'US',
  state: 'CA',
  city: 'San Francisco',
  street: '123 Main St',
  postal_code: '94105',
  birthday: '15-08-1978',
  ownership: 25,
  position: 'Chief Financial Officer',
});

// List all directors
const directors = await mg.onboard.listDirectors(business.id);

// Update a director
await mg.onboard.updateDirector(business.id, director.id, {
  ownership: 30,
});

// Delete a director
await mg.onboard.deleteDirector(business.id, director.id);

Reference Data

// Get supported countries
const countries = await mg.reference.getAllCountries();

// Get currencies for a country
const currencies = await mg.reference.getCurrencies('NG');

// Get source of funds options
const sources = await mg.reference.getSourceOfFunds();

// Get MCC codes
const mccs = await mg.reference.getMccCodes();

// Get business registration types
const types = await mg.reference.getBusinessRegistrationTypes();

// Search helpers
const realEstate = await mg.reference.findSourceOfFunds('real estate');
const software = await mg.reference.findMcc('software');
const llc = await mg.reference.findBusinessType('LLC');

Sandbox Testing

Use sk_test_* API keys to enable sandbox mode with full mock data:

const mg = new MoneyGraph({ apiKey: 'sk_test_demo' });

// Create instant mock personas
const verified = await mg.onboard.createMockPersona('business_verified');
const pending = await mg.onboard.createMockPersona('pending_kyc');
const rejected = await mg.onboard.createMockPersona('rejected_kyc');

// All operations work with mock data
const quote = await mg.liquidity.getQuote({ from: 'USD', to: 'NGN', amount: 100 });

Available mock personas:

  • business_verified - Approved business with directors
  • individual_verified - Approved personal account
  • pending_kyc - Account awaiting KYC approval
  • rejected_kyc - Account with rejected KYC

Error Handling

import { MoneyGraph, MoneyGraphError } from '@moneygraph/sdk';

try {
  await mg.payouts.send({ ... });
} catch (error) {
  if (error instanceof MoneyGraphError) {
    switch (error.code) {
      case 'KYC_PENDING':
        console.log('Customer KYC is still pending');
        break;
      case 'KYC_REJECTED':
        console.log('Customer KYC was rejected');
        break;
      case 'QUOTE_EXPIRED':
        console.log('Quote has expired, get a new one');
        break;
      case 'RATE_LIMITED':
        console.log('Too many requests, slow down');
        break;
      default:
        console.log(`Error: ${error.message}`);
    }
  }
}

Error codes:

  • INVALID_API_KEY - API key is invalid
  • UNAUTHORIZED - Not authorized for this action
  • KYC_PENDING - KYC verification pending
  • KYC_REJECTED - KYC verification rejected
  • KYC_ALREADY_APPROVED - Cannot update approved KYC
  • QUOTE_EXPIRED - FX quote has expired
  • QUOTE_NOT_FOUND - Quote ID not found
  • CUSTOMER_NOT_FOUND - Customer ID not found
  • DIRECTOR_NOT_FOUND - Director ID not found
  • VALIDATION_ERROR - Invalid request parameters
  • RATE_LIMITED - Too many requests
  • SANDBOX_ONLY - Feature only available in sandbox

TypeScript Support

Full TypeScript support with strict types for all currencies:

import type {
  PayInCurrency,    // 21 options (fiat + crypto)
  PayoutCurrency,   // 107+ local rails currencies
  HoldingCurrency,  // 73 wallet currencies
  Customer,
  Quote,
  Payout,
} from '@moneygraph/sdk';

AI Integration

This SDK is optimized for AI coding assistants:

  • Cursor: Copy .cursor/rules/moneygraph.mdc to your project
  • Lovable: Paste LOVABLE_PROMPT.md into Custom Knowledge
  • Claude.ai: Use CLAUDE_AI_INSTRUCTIONS.md as Project Instructions
  • Base44: Use recipes/BASE44_GUIDE.md for app generation

Recipes

Ready-to-use implementation guides in recipes/:

| Recipe | Description | |--------|-------------| | supabase-edge-function.ts | Backend proxy for browser apps (handles CORS) | | ACCEPT_PAYMENTS.md | Card payments, widget, popup checkout for merchants | | REMITTANCE_FLOW.md | International money transfers (Sender→Recipient→Transaction) | | BASE44_GUIDE.md | Base44 AI app generator integration |

Accept Payments (Merchants)

Initialize with your public key for client-side payments:

const mg = new MoneyGraph({ 
  apiKey: 'sk_test_xxx',      // Server-side
  publicKey: 'pk_test_xxx',   // Client-side payments
});

Widget Embed

<script src="https://stratospay.com/embed.js"></script>
<div class="stratos-embed"></div>
<script>
  checkout.init({
    public_key: "pk_test_xxx",
    external_reference: "order_" + Date.now(),
    amount: 10000,  // cents
    currency: "USD",
    title: "Order Payment",
    description: "Payment for Order #12345",
    customer: {
      first_name: "John",
      last_name: "Doe",
      email: "[email protected]",
      ip_address: "127.0.0.1"
    },
    billing_address: {
      country: "US",
      city: "Los Angeles",
      address: "123 Main St",
      postal_code: "90001"
    },
    onsuccess: (data) => console.log("Success!", data),
    onerror: (data) => console.log("Error", data)
  });
</script>

Popup Checkout

<script src="https://stratospay.com/popup.js"></script>
<button onclick="checkout.init(config)">Pay Now</button>

Direct Card Charge (Server-side)

// ⚠️ Requires PCI DSS compliance!
import { TEST_CARDS } from '@moneygraph/sdk';

const result = await mg.payments.chargeCard({
  title: "Order Payment",
  description: "Order #12345",
  external_reference: `order_${Date.now()}`,
  amount: 100,
  currency: "USD",
  customer: { first_name: "John", last_name: "Doe", email: "[email protected]", ip_address: "127.0.0.1" },
  billing_address: { country: "US", city: "LA", address: "123 Main St", postal_code: "90001" },
  card: {
    card_number: TEST_CARDS.VISA_SUCCESS,
    cvv: "123",
    expire: "12/30"
  }
});

if (result.status === 'requires_action') {
  // Redirect to result.action_url for 3DS
}

Test Cards

| Card | Result | |------|--------| | 4917484589897107 | Success | | 5555555555554444 | Success | | 6011000991300009 | Blocked | | 6011111111111117 | Insufficient Funds | | 4263982640269299 | Requires 3DS |

See recipes/ACCEPT_PAYMENTS.md for complete guide.

License

MIT