Package Exports
- @myazahq/pos-sdk
- @myazahq/pos-sdk/webhook
Readme
@myazahq/pos-sdk
Production-grade crypto POS payment SDK for the Gridlog platform. Accept crypto payments in your storefront with a single method call — no webhooks required.
Installation
npm install @myazahq/pos-sdk
# yarn add @myazahq/pos-sdk
# pnpm add @myazahq/pos-sdkWorks with React, Next.js, Vue, Svelte, Vite, Nuxt, and plain JavaScript.
Next.js / Nuxt (SSR): The SDK renders a DOM modal and must only run in the browser. Wrap usage in
useEffect/onMounted— see the framework examples below.
Quick Start
import { MyazaPOS } from '@myazahq/pos-sdk';
const sdk = new MyazaPOS({
apiKey: 'YOUR_GRIDLOG_BEARER_TOKEN',
merchantId: 'YOUR_MERCHANT_ID',
});
await sdk.init();
sdk.on('payment.confirmed', ({ session }) => {
fulfillOrder(session.id);
});
await sdk.createSession({ amount: 5000, currency: 'NGN' });createSession opens the payment modal and polls for status automatically. The modal closes itself on success, failure, or cancellation.
Configuration
const sdk = new MyazaPOS({
// Required — pass your Gridlog credentials directly here,
// not via environment variables.
apiKey: 'YOUR_API_KEY',
merchantId: 'YOUR_MERCHANT_ID',
// Optional
isSandbox: false, // true → Gridlog sandbox (testing only)
defaultChain: 'ethereum',
defaultToken: 'USDT',
pollIntervalMs: 120_000, // 2 minutes (default)
maxPollDurationMs: 900_000, // 15 minutes (default)
theme: {
primaryColor: '#6366f1',
backgroundColor: '#ffffff',
textColor: '#1a1a2e',
borderRadius: 12,
logoUrl: 'https://your-site.com/logo.png',
colorScheme: 'light', // 'light' | 'dark' | 'system'
},
});For advanced config (fraud rules, plugins, multi-tenant, observability) see MAINTAINERS.md.
Sandbox vs Production
Use isSandbox: true while developing and testing. Switch to false (the default) before going live.
// Development / testing — hits the Gridlog sandbox API
const sdk = new MyazaPOS({
apiKey: 'YOUR_SANDBOX_BEARER_TOKEN',
merchantId: 'YOUR_MERCHANT_ID',
isSandbox: true,
});
// Production — default, no flag needed
const sdk = new MyazaPOS({
apiKey: 'YOUR_PRODUCTION_BEARER_TOKEN',
merchantId: 'YOUR_MERCHANT_ID',
});| Mode | API base URL | Flag |
|---|---|---|
| Production | https://secureapi.gridlog.io/api/v1 |
isSandbox: false (default) |
| Sandbox | https://sandbox.secureapi.gridlog.io/api/v1 |
isSandbox: true |
| Custom / self-hosted | Your URL | apiBaseUrl: 'https://...' |
apiBaseUrlalways takes precedence overisSandboxif both are set.
When isSandbox: true the SDK logs a console warning immediately on construction so you cannot accidentally ship sandbox credentials to production.
Key Events
// Address ready — display to customer
sdk.on('payment.created', ({ session }) => {
console.log('Send', session.token, 'to:', session.address);
});
// Payout complete — fulfil the order
sdk.on('payment.confirmed', ({ session }) => {
fulfillOrder(session.id);
});
// Timed out
sdk.on('payment.expired', ({ sessionId }) => {
notifyCustomer(sessionId);
});
// Payout failed or fraud blocked
sdk.on('payment.failed', ({ sessionId, reason }) => {
console.error(reason);
});Full event reference in MAINTAINERS.md.
Theming
The modal renders inside a Shadow DOM — your host-page styles cannot affect it. Pass a theme object to the constructor:
theme: {
primaryColor: '#10b981', // buttons, highlights
backgroundColor: '#0f172a', // modal background
textColor: '#f1f5f9', // all text
borderRadius: 16, // corner radius (px)
fontFamily: '"Geist", sans-serif',
logoUrl: 'https://your-brand.com/logo.png',
colorScheme: 'dark',
customCss: '.myaza-cancel-btn { display: none; }',
}Framework Examples
CDN (no build step)
<script src="https://cdn.jsdelivr.net/npm/@myazahq/pos-sdk/dist/index.umd.js"></script>
<script>
const sdk = new MyazaPOS.MyazaPOS({ apiKey: '...', merchantId: '...' });
sdk.init().then(() => {
document.getElementById('pay-btn').addEventListener('click', () => {
sdk.createSession({ amount: 5000, currency: 'NGN' });
});
sdk.on('payment.confirmed', ({ session }) => {
window.location.href = '/order-complete?id=' + session.id;
});
});
</script>React
import { useEffect, useRef } from 'react';
import { MyazaPOS } from '@myazahq/pos-sdk';
export function CheckoutButton({ amount }: { amount: number }) {
const sdkRef = useRef<MyazaPOS | null>(null);
useEffect(() => {
const sdk = new MyazaPOS({ apiKey: '...', merchantId: '...' });
sdk.init().then(() => { sdkRef.current = sdk; });
sdk.on('payment.confirmed', ({ session }) => fulfillOrder(session.id));
return () => { void sdk.terminate(); };
}, []);
return (
<button onClick={() => sdkRef.current?.createSession({ amount, currency: 'NGN' })}>
Pay with Crypto
</button>
);
}Next.js (App Router)
'use client';
import { useEffect, useRef } from 'react';
import { MyazaPOS } from '@myazahq/pos-sdk';
export function CryptoCheckout({ amount }: { amount: number }) {
const sdkRef = useRef<MyazaPOS | null>(null);
useEffect(() => {
const sdk = new MyazaPOS({ apiKey: '...', merchantId: '...' });
sdk.init().then(() => { sdkRef.current = sdk; });
return () => { void sdk.terminate(); };
}, []);
return (
<button onClick={() => sdkRef.current?.createSession({ amount, currency: 'NGN' })}>
Pay with Crypto
</button>
);
}For dynamic import (Pages Router or layouts):
const { MyazaPOS } = await import('@myazahq/pos-sdk');Vue 3
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import { MyazaPOS } from '@myazahq/pos-sdk';
const props = defineProps<{ amount: number }>();
let sdk: MyazaPOS | null = null;
onMounted(async () => {
sdk = new MyazaPOS({ apiKey: '...', merchantId: '...' });
await sdk.init();
sdk.on('payment.confirmed', ({ session }) => fulfillOrder(session.id));
});
onUnmounted(() => { sdk?.terminate(); });
</script>
<template>
<button @click="sdk?.createSession({ amount: props.amount, currency: 'NGN' })">
Pay with Crypto
</button>
</template>Nuxt 3
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import type { MyazaPOS } from '@myazahq/pos-sdk';
let sdk: MyazaPOS | null = null;
onMounted(async () => {
const { MyazaPOS } = await import('@myazahq/pos-sdk');
sdk = new MyazaPOS({ apiKey: '...', merchantId: '...' });
await sdk.init();
});
onUnmounted(() => { sdk?.terminate(); });
</script>Svelte / SvelteKit
<script lang="ts">
import { onMount, onDestroy } from 'svelte';
import type { MyazaPOS as MyazaPOSType } from '@myazahq/pos-sdk';
export let amount: number;
let sdk: MyazaPOSType | null = null;
onMount(async () => {
const { MyazaPOS } = await import('@myazahq/pos-sdk');
sdk = new MyazaPOS({ apiKey: '...', merchantId: '...' });
await sdk.init();
});
onDestroy(() => { sdk?.terminate(); });
</script>
<button on:click={() => sdk?.createSession({ amount, currency: 'NGN' })}>
Pay with Crypto
</button>Server-Side Verification
Always verify payment status server-side before fulfilling orders:
const res = await fetch(
`pos/sessions/${sessionId}`,
{ headers: { Authorization: `Bearer YOUR_GRIDLOG_BEARER_TOKEN` } }
);
const session = await res.json();
if (session.status === 'paid_out') {
await fulfillOrder(session.id);
}Store your Bearer token in your server's secret manager — never expose it client-side.
Maintainers
For architecture details, plugin authoring, fraud config, multi-tenant setup, CI/CD, and build instructions see MAINTAINERS.md.
Licence
MIT © Myaza