UNPKG

morphcredit-merchant-sdk

Version:

MorphCredit Merchant SDK for BNPL integration

588 lines (473 loc) 14.2 kB
## morphcredit-merchant-sdk Production-ready Merchant SDK for integrating MorphCredit BNPL on Morph Holesky (Chain ID 2810). ### Install ```bash npm i morphcredit-merchant-sdk # or pnpm add morphcredit-merchant-sdk ``` ### Quick start ```ts import { MorphCreditSDK } from 'morphcredit-merchant-sdk'; const sdk = new MorphCreditSDK({}, { enableLogging: true }); await sdk.connectWallet(); const address = sdk.getWalletAddress()!; const offers = await sdk.getOffers({ address, amount: 799.99 }); const result = await sdk.createAgreement(offers[0].id); console.log('tx', result.txHash, 'agreement', result.agreementId); ``` ### React button ```tsx import { MorphCreditButton } from 'morphcredit-merchant-sdk'; <MorphCreditButton amount={499.99} showOffers onSuccess={(r) => console.log(r)} onError={(e) => console.error(e)} />; ``` ### Config ```ts new MorphCreditSDK({ rpcUrl: 'https://rpc-holesky.morphl2.io', contracts: { scoreOracle: '0x...', creditRegistry: '0x...', lendingPool: '0x...', bnplFactory: '0x...' }, scoringService: 'https://your-scoring.onrender.com', networkId: 2810, }); ``` ### Events ```ts sdk.onOffersLoaded((offers) => {...}) sdk.onAgreementCreated((tx) => {...}) sdk.onWalletConnected((addr) => {...}) ``` ### Error codes - WALLET_CONNECTION_FAILED, WRONG_NETWORK, SCORE_NOT_FOUND, AGREEMENT_FAILED, INVALID_OFFER, NETWORK_ERROR, ... ### Security - Factory role check before createAgreement - Returns real agreement address from AgreementCreated event ### License MIT ### Diagram ```mermaid %%{init: { 'theme': 'dark' }}%% flowchart TD Demo[Merchant Demo] -->|uses| SDK SDK -->|score| API[Scoring Service] SDK -->|createAgreement| BF[BNPLFactory] BF --> BA[BNPLAgreement] ``` # MorphCredit Merchant SDK A TypeScript SDK for integrating MorphCredit's Buy Now, Pay Later (BNPL) functionality into merchant applications. ## Features - 🚀 **Easy Integration** - Simple React components and TypeScript API - 💳 **Wallet Connection** - Automatic MetaMask and wallet provider support - 📊 **Credit Scoring** - Real-time credit assessment and offer generation - 🔄 **Event Handling** - Comprehensive event system for payment lifecycle - 🎨 **Customizable UI** - Beautiful, responsive React components - 🔒 **Type Safe** - Full TypeScript support with comprehensive types - **Lightweight** - Optimized bundle size with tree-shaking ## Installation ```bash npm install morphcredit-merchant-sdk # or yarn add morphcredit-merchant-sdk # or pnpm add morphcredit-merchant-sdk ``` ## Quick Start ### 1. Basic React Integration ```tsx import { MorphCreditButton } from 'morphcredit-merchant-sdk'; function CheckoutPage() { const handleSuccess = (result) => { console.log('Payment successful:', result.txHash); // Redirect to success page }; const handleError = (error) => { console.error('Payment failed:', error.message); // Show error message to user }; return ( <div> <h2>Checkout</h2> <p>Total: $100.00</p> <MorphCreditButton amount={100.00} onSuccess={handleSuccess} onError={handleError} variant="primary" size="lg" > Pay with MorphCredit </MorphCreditButton> </div> ); } ``` ### 2. Programmatic SDK Usage ```typescript import { MorphCreditSDK } from 'morphcredit-merchant-sdk'; // Initialize SDK const sdk = new MorphCreditSDK({ rpcUrl: 'https://rpc-testnet.morphl2.io', networkId: 17000 }, { enableLogging: true }); // Connect wallet const address = await sdk.connectWallet(); // Get BNPL offers const offers = await sdk.getOffers({ address: address, amount: 100.00, includeFeatures: true }); console.log('Available offers:', offers); // Create agreement const result = await sdk.createAgreement(offers[0].id); console.log('Agreement created:', result.agreementId); ``` ## API Reference ### MorphCreditSDK The main SDK class for programmatic access. #### Constructor ```typescript new MorphCreditSDK(config?: Partial<SDKConfig>, options?: SDKOptions) ``` #### Configuration ```typescript interface SDKConfig { rpcUrl: string; // Morph testnet RPC endpoint contracts: { scoreOracle: string; // ScoreOracle contract address creditRegistry: string; // CreditRegistry contract address lendingPool: string; // LendingPool contract address bnplFactory: string; // BNPLFactory contract address }; scoringService: string; // Scoring API endpoint networkId: number; // Chain ID (17000 for Morph testnet) gasLimit?: number; // Default gas limit confirmations?: number; // Block confirmations to wait } ``` #### Methods ##### `connectWallet(): Promise<string>` Connects to the user's wallet and returns the wallet address. ##### `getOffers(request: OfferRequest): Promise<Offer[]>` Gets available BNPL offers for a user and amount. ```typescript interface OfferRequest { address: string; // User wallet address amount: number; // Cart total in USDC currency?: string; // Currency code (default: 'USDC') includeFeatures?: boolean; // Include offer features } ``` ##### `createAgreement(offerId: string): Promise<TxResult>` Creates a BNPL agreement from an offer. ##### `getAgreementStatus(agreementId: string): Promise<AgreementStatus>` Gets the current status of a BNPL agreement. #### Event Handling ```typescript // Listen for agreement creation sdk.onAgreementCreated((result: TxResult) => { console.log('Agreement created:', result.agreementId); }); // Listen for offers loaded sdk.onOffersLoaded((offers: Offer[]) => { console.log('Offers loaded:', offers); }); // Listen for wallet connection sdk.onWalletConnected((address: string) => { console.log('Wallet connected:', address); }); ``` ### MorphCreditButton A React component for easy BNPL integration. #### Props ```typescript interface MorphCreditButtonProps { amount: number; // Cart total in USDC userAddress?: string; // Optional, auto-detect if connected onSuccess?: (result: TxResult) => void; onError?: (error: MorphCreditError) => void; onOffersLoaded?: (offers: Offer[]) => void; onWalletConnect?: (address: string) => void; disabled?: boolean; // Disable button state className?: string; // CSS classes style?: React.CSSProperties; // Inline styles children?: React.ReactNode; // Button content variant?: 'primary' | 'secondary' | 'outline'; size?: 'sm' | 'md' | 'lg'; loading?: boolean; // Show loading state showOffers?: boolean; // Show offer selector on click } ``` #### Examples ```tsx // Basic usage <MorphCreditButton amount={100.00} /> // With custom styling <MorphCreditButton amount={100.00} variant="outline" size="lg" className="my-custom-button" style={{ marginTop: '20px' }} > Buy Now, Pay Later </MorphCreditButton> // With offer selector <MorphCreditButton amount={100.00} showOffers={true} onOffersLoaded={(offers) => console.log('Offers:', offers)} onSuccess={(result) => console.log('Success:', result)} onError={(error) => console.error('Error:', error)} /> ``` ## Types ### Core Types ```typescript interface Offer { id: string; // Unique offer identifier principal: bigint; // Total amount in wei installments: number; // Number of installments installmentAmount: bigint; // Amount per payment in wei totalCost: bigint; // Principal + fees in wei apr: number; // Annual percentage rate dueDates: number[]; // Unix timestamps for due dates merchant: string; // Merchant address status: 'available' | 'expired' | 'unavailable'; tier: 'A' | 'B' | 'C' | 'D' | 'E'; features: { noLateFees?: boolean; earlyPayoff?: boolean; autoRepay?: boolean; }; } interface TxResult { success: boolean; txHash: string; agreementId: string; blockNumber: number; gasUsed: number; gasPrice: bigint; error?: string; } interface AgreementStatus { id: string; status: 'active' | 'completed' | 'defaulted' | 'written_off'; paidInstallments: number; totalInstallments: number; nextDueDate: number; nextAmount: bigint; remainingBalance: bigint; lastPaymentDate?: number; delinquencyDays: number; } ``` ## Error Handling The SDK provides comprehensive error handling with specific error codes: ```typescript enum ErrorCodes { WALLET_NOT_CONNECTED = 'WALLET_NOT_CONNECTED', WALLET_CONNECTION_FAILED = 'WALLET_CONNECTION_FAILED', INSUFFICIENT_CREDIT = 'INSUFFICIENT_CREDIT', SCORE_NOT_FOUND = 'SCORE_NOT_FOUND', AGREEMENT_FAILED = 'AGREEMENT_FAILED', NETWORK_ERROR = 'NETWORK_ERROR', USER_REJECTED = 'USER_REJECTED', INVALID_ADDRESS = 'INVALID_ADDRESS', INVALID_AMOUNT = 'INVALID_AMOUNT', INVALID_OFFER = 'INVALID_OFFER' } ``` ### Error Handling Example ```typescript const handleError = (error: MorphCreditError) => { switch (error.code) { case ErrorCodes.WALLET_NOT_CONNECTED: showMessage('Please connect your wallet to continue'); break; case ErrorCodes.INSUFFICIENT_CREDIT: showMessage('Insufficient credit limit for this purchase'); break; case ErrorCodes.USER_REJECTED: showMessage('Transaction was cancelled'); break; default: showMessage('An unexpected error occurred. Please try again'); console.error('Unhandled error:', error); } }; ``` ## Integration Examples ### E-commerce Checkout ```tsx import { MorphCreditButton } from '@morphcredit/merchant-sdk'; import { useState } from 'react'; function ProductCheckout({ product }) { const [isProcessing, setIsProcessing] = useState(false); const handleSuccess = (result) => { setIsProcessing(false); // Redirect to success page with agreement details router.push(`/success?agreement=${result.agreementId}`); }; const handleError = (error) => { setIsProcessing(false); // Show error message to user toast.error(error.message); }; return ( <div className="checkout-container"> <div className="product-summary"> <h2>{product.name}</h2> <p className="price">${product.price}</p> </div> <div className="payment-options"> <MorphCreditButton amount={product.price} onSuccess={handleSuccess} onError={handleError} disabled={isProcessing} variant="primary" size="lg" showOffers={true} > Pay with MorphCredit </MorphCreditButton> <p className="payment-info"> Split your payment into 4 interest-free installments </p> </div> </div> ); } ``` ### Cart Checkout ```tsx import { MorphCreditButton } from '@morphcredit/merchant-sdk'; import { useCart } from './cart-context'; function CartCheckout() { const { items, total } = useCart(); const [walletAddress, setWalletAddress] = useState(null); const handleWalletConnect = (address) => { setWalletAddress(address); // Store wallet address in context or state }; const handleSuccess = (result) => { // Clear cart and redirect clearCart(); router.push(`/order-confirmation/${result.agreementId}`); }; return ( <div className="cart-checkout"> <div className="cart-summary"> <h3>Order Summary</h3> {items.map(item => ( <div key={item.id} className="cart-item"> <span>{item.name}</span> <span>${item.price}</span> </div> ))} <div className="cart-total"> <strong>Total: ${total}</strong> </div> </div> <MorphCreditButton amount={total} userAddress={walletAddress} onWalletConnect={handleWalletConnect} onSuccess={handleSuccess} onError={(error) => toast.error(error.message)} variant="primary" size="lg" showOffers={true} > Complete Purchase with MorphCredit </MorphCreditButton> </div> ); } ``` ## Styling The SDK includes default styles that can be customized: ### CSS Custom Properties ```css :root { --morphcredit-primary: #667eea; --morphcredit-secondary: #764ba2; --morphcredit-success: #28a745; --morphcredit-error: #dc3545; --morphcredit-warning: #ffc107; --morphcredit-text: #212529; --morphcredit-text-muted: #6c757d; --morphcredit-border: #dee2e6; --morphcredit-background: #f8f9fa; } ``` ### Custom Styling ```tsx // Using CSS classes <MorphCreditButton amount={100.00} className="my-custom-button" /> // Using inline styles <MorphCreditButton amount={100.00} style={{ backgroundColor: '#custom-color', borderRadius: '12px', fontSize: '18px' }} /> ``` ## Development ### Building the SDK ```bash # Install dependencies pnpm install # Build the package pnpm build # Development mode with watch pnpm dev # Run tests pnpm test # Type checking pnpm type-check ``` ### Project Structure ``` packages/merchant-sdk/ ├── src/ ├── index.ts # Main SDK exports ├── types.ts # TypeScript definitions └── button.tsx # React button component ├── dist/ # Built package ├── package.json ├── tsconfig.json ├── tsup.config.ts └── README.md ``` ## Contributing 1. Fork the repository 2. Create a feature branch 3. Make your changes 4. Add tests if applicable 5. Submit a pull request ## License MIT License - see LICENSE file for details. ## Support For support and questions: - 📧 Email: support@morphcredit.xyz - 💬 Discord: [MorphCredit Community](https://discord.gg/morphcredit) - 📖 Documentation: [docs.morphcredit.xyz](https://docs.morphcredit.xyz) - 🐛 Issues: [GitHub Issues](https://github.com/morphcredit/morphcredit/issues)