@verixo/sdk 0.2.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +57 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +97 -1
- package/dist/index.d.ts +97 -1
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -254,6 +254,34 @@ var Numbers = class {
|
|
|
254
254
|
}
|
|
255
255
|
};
|
|
256
256
|
|
|
257
|
+
// src/resources/payment.ts
|
|
258
|
+
var Payment = class {
|
|
259
|
+
constructor(http) {
|
|
260
|
+
this.http = http;
|
|
261
|
+
}
|
|
262
|
+
http;
|
|
263
|
+
/**
|
|
264
|
+
* Initiate a wallet top-up payment. The response varies by provider:
|
|
265
|
+
* - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`
|
|
266
|
+
* - Stripe → use `clientSecret` with the Stripe.js embedded element
|
|
267
|
+
* - OPay USSD → display `ussdCode`
|
|
268
|
+
* - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`
|
|
269
|
+
*
|
|
270
|
+
* @example
|
|
271
|
+
* const result = await vc.payment.initiate({
|
|
272
|
+
* creditPackId: 'pack_100',
|
|
273
|
+
* usdAmount: 10,
|
|
274
|
+
* creditsToAdd: 100,
|
|
275
|
+
* currency: 'NGN',
|
|
276
|
+
* customerEmail: 'user@example.com',
|
|
277
|
+
* });
|
|
278
|
+
* if (result.checkoutUrl) window.location.href = result.checkoutUrl;
|
|
279
|
+
*/
|
|
280
|
+
initiate(params) {
|
|
281
|
+
return this.http.post("/api/v1/payment/initiate", params);
|
|
282
|
+
}
|
|
283
|
+
};
|
|
284
|
+
|
|
257
285
|
// src/resources/sessions.ts
|
|
258
286
|
var Sessions = class {
|
|
259
287
|
constructor(http) {
|
|
@@ -280,6 +308,31 @@ var Sessions = class {
|
|
|
280
308
|
}
|
|
281
309
|
};
|
|
282
310
|
|
|
311
|
+
// src/resources/wallet.ts
|
|
312
|
+
var Wallet = class {
|
|
313
|
+
constructor(http) {
|
|
314
|
+
this.http = http;
|
|
315
|
+
}
|
|
316
|
+
http;
|
|
317
|
+
/** Get the authenticated user's current wallet balance and today's auto-refund count. */
|
|
318
|
+
balance() {
|
|
319
|
+
return this.http.get("/api/v1/wallet/balance");
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* List wallet transactions (credits, debits, refunds) for the authenticated user.
|
|
323
|
+
*
|
|
324
|
+
* @example
|
|
325
|
+
* const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })
|
|
326
|
+
*/
|
|
327
|
+
transactions(params = {}) {
|
|
328
|
+
const q = new URLSearchParams();
|
|
329
|
+
if (params.page != null) q.set("page", String(params.page));
|
|
330
|
+
if (params.size != null) q.set("size", String(params.size));
|
|
331
|
+
const qs = q.toString();
|
|
332
|
+
return this.http.get(`/api/v1/wallet/transactions${qs ? `?${qs}` : ""}`);
|
|
333
|
+
}
|
|
334
|
+
};
|
|
335
|
+
|
|
283
336
|
// src/subscribe.ts
|
|
284
337
|
var import_stompjs = require("@stomp/stompjs");
|
|
285
338
|
function subscribe(http, sessionToken, onOtp) {
|
|
@@ -315,6 +368,8 @@ var Verixo = class {
|
|
|
315
368
|
analytics;
|
|
316
369
|
esim;
|
|
317
370
|
callPlans;
|
|
371
|
+
payment;
|
|
372
|
+
wallet;
|
|
318
373
|
http;
|
|
319
374
|
constructor(apiKey, options = {}) {
|
|
320
375
|
this.http = new HttpClient(apiKey, options);
|
|
@@ -323,6 +378,8 @@ var Verixo = class {
|
|
|
323
378
|
this.analytics = new Analytics(this.http);
|
|
324
379
|
this.esim = new ESim(this.http);
|
|
325
380
|
this.callPlans = new CallPlans(this.http);
|
|
381
|
+
this.payment = new Payment(this.http);
|
|
382
|
+
this.wallet = new Wallet(this.http);
|
|
326
383
|
}
|
|
327
384
|
/**
|
|
328
385
|
* Get pushed the OTP for a session in real time, instead of polling
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/resources/analytics.ts","../src/resources/call_plans.ts","../src/resources/esim.ts","../src/resources/numbers.ts","../src/resources/sessions.ts","../src/subscribe.ts"],"sourcesContent":["import { HttpClient } from \"./client.js\";\nimport { Analytics } from \"./resources/analytics.js\";\nimport { CallPlans } from \"./resources/call_plans.js\";\nimport { ESim } from \"./resources/esim.js\";\nimport { Numbers } from \"./resources/numbers.js\";\nimport { Sessions } from \"./resources/sessions.js\";\nimport { subscribe } from \"./subscribe.js\";\nimport type { OtpPush, VerixoOptions } from \"./types.js\";\n\nexport { VerixoError } from \"./errors.js\";\nexport type {\n CallPlan,\n CallPlanSubscription,\n DeliveryRate,\n ESimPackage,\n ESimProfile,\n ESimPurchaseParams,\n ESimUsage,\n OtpPush,\n PurchaseBundleParams,\n PurchaseNumberParams,\n PurchaseResult,\n SearchNumbersParams,\n SearchNumbersResult,\n SessionState,\n SessionStatus,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n VerixoOptions,\n VirtualNumber,\n} from \"./types.js\";\n\nexport default class Verixo {\n readonly numbers: Numbers;\n readonly sessions: Sessions;\n readonly analytics: Analytics;\n readonly esim: ESim;\n readonly callPlans: CallPlans;\n private readonly http: HttpClient;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n this.http = new HttpClient(apiKey, options);\n this.numbers = new Numbers(this.http);\n this.sessions = new Sessions(this.http);\n this.analytics = new Analytics(this.http);\n this.esim = new ESim(this.http);\n this.callPlans = new CallPlans(this.http);\n }\n\n /**\n * Get pushed the OTP for a session in real time, instead of polling\n * `sessions.get()`. Returns an unsubscribe function.\n *\n * @example\n * const session = await vc.numbers.purchase({ serviceSlug: 'whatsapp', countryCode: 'NG' })\n * vc.subscribe(session.sessionToken, ({ otp, latencyMs }) => {\n * console.log(`OTP: ${otp} in ${latencyMs}ms`)\n * })\n */\n subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n return subscribe(this.http, sessionToken, onOtp);\n }\n}\n","export interface VerixoErrorOptions {\n status: number;\n code?: string;\n detail?: string;\n raw?: unknown;\n}\n\n/**\n * Thrown for any non-2xx response from the Verixo API. `status` is always\n * present; `code`/`detail` are populated when the gateway returns a JSON\n * error body (most do) -- a small number of paths (e.g. an invalid API key\n * rejected before reaching a controller) return an empty body, in which case\n * only `status` and a generic `message` are available.\n */\nexport class VerixoError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly detail?: string;\n readonly raw?: unknown;\n\n constructor(message: string, options: VerixoErrorOptions) {\n super(message);\n this.name = \"VerixoError\";\n this.status = options.status;\n this.code = options.code;\n this.detail = options.detail;\n this.raw = options.raw;\n }\n}\n\nconst STATUS_FALLBACKS: Record<number, string> = {\n 401: \"Missing or invalid API key.\",\n 402: \"Insufficient wallet balance.\",\n 403: \"You don't have access to this resource.\",\n 404: \"Not found.\",\n 408: \"Request timed out.\",\n 422: \"The request did not meet a required condition (e.g. minScore).\",\n 429: \"Rate limit exceeded.\",\n};\n\nexport async function errorFromResponse(res: Response): Promise<VerixoError> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = undefined;\n }\n\n const obj = (body && typeof body === \"object\" ? body : {}) as Record<string, unknown>;\n const detail = (obj.detail ?? obj.error ?? obj.message) as string | undefined;\n const code = (obj.grpcCode ?? obj.code) as string | undefined;\n const message = detail ?? STATUS_FALLBACKS[res.status] ?? `Request failed with status ${res.status}`;\n\n return new VerixoError(message, { status: res.status, code, detail, raw: body });\n}\n","import { errorFromResponse } from \"./errors.js\";\nimport type { VerixoOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.verifiedcore.com\";\n\nexport class HttpClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n if (!apiKey) {\n throw new Error(\"Verixo: an API key (or JWT) is required, e.g. new Verixo('vc_test_...')\");\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n // The gateway classifies the credential by sniffing the raw Authorization header for a\n // vc_test_/vc_live_ prefix -- a \"Bearer \" prefix on an API key would make it misclassify\n // the request as a (malformed) JWT and reject it, so API keys go out unprefixed.\n const isApiKey = this.apiKey.startsWith(\"vc_test_\") || this.apiKey.startsWith(\"vc_live_\");\n const authorization = isApiKey ? this.apiKey : `Bearer ${this.apiKey}`;\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authorization,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n });\n\n if (!res.ok) {\n throw await errorFromResponse(res);\n }\n\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, { method: \"POST\", body: body ? JSON.stringify(body) : undefined });\n }\n\n /** ws:// or wss:// origin derived from baseUrl, for the OTP push subscription. */\n get wsOrigin(): string {\n return this.baseUrl.replace(/^http/, \"ws\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { DeliveryRate } from \"../types.js\";\n\nexport class Analytics {\n constructor(private readonly http: HttpClient) {}\n\n /** Public delivery-rate stats by country for a service. No auth required by the API itself. */\n rates(serviceSlug = \"whatsapp\"): Promise<{ rates: DeliveryRate[]; updatedAt: string }> {\n return this.http.get(`/api/v1/analytics/rates?serviceSlug=${encodeURIComponent(serviceSlug)}`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type {\n CallPlan,\n CallPlanSubscription,\n PurchaseBundleParams,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n} from \"../types.js\";\n\nexport class CallPlans {\n constructor(private readonly http: HttpClient) {}\n\n // ─── Call Plans ─────────────────────────────────────────────────────────────\n\n /**\n * List all available call plan tiers with pricing.\n * No authentication required — safe to call before purchase.\n *\n * Premium plans cap high-cost destinations (NG/GH/KE) to a disclosed minute\n * bucket rather than silently throttling. See `highCostMinutes` on each plan.\n */\n list(): Promise<CallPlan[]> {\n return this.http.get<CallPlan[]>(\"/api/v1/call-plans\");\n }\n\n /**\n * Subscribe to a call plan. Debits your wallet.\n *\n * @example\n * await vc.callPlans.subscribe({ tier: 'STANDARD', paymentProvider: 'STRIPE' })\n */\n subscribe(params: SubscribeCallPlanParams): Promise<CallPlanSubscription> {\n return this.http.post<CallPlanSubscription>(\"/api/v1/call-plans/subscribe\", {\n tier: params.tier,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** Get the authenticated user's active call plan subscription, or null if none. */\n async current(): Promise<CallPlanSubscription | null> {\n try {\n return await this.http.get<CallPlanSubscription>(\"/api/v1/call-plans/my\");\n } catch (err: any) {\n if (err?.status === 204 || err?.status === 404) return null;\n throw err;\n }\n }\n\n /** List all call plan subscription history for the authenticated user. */\n history(): Promise<CallPlanSubscription[]> {\n return this.http.get<CallPlanSubscription[]>(\"/api/v1/call-plans/history\");\n }\n\n /** Cancel the active call plan subscription immediately. */\n cancel(): Promise<void> {\n return this.http.request<void>(\"/api/v1/call-plans/my\", { method: \"DELETE\" });\n }\n\n // ─── Special / Bundle Packages ───────────────────────────────────────────────\n\n /**\n * List all available bundle packages (STARTER, BUSINESS, DEVELOPER, etc.).\n * No authentication required.\n */\n listBundles(): Promise<SpecialPackage[]> {\n return this.http.get<SpecialPackage[]>(\"/api/v1/special-packages\");\n }\n\n /**\n * Purchase a bundle package. Each bundle fans out async provisioning events\n * (SMS credits, call plan, eSIM, virtual number, API access) via Kafka.\n * Poll `myBundles()` to track provisioning completion.\n *\n * @example\n * const order = await vc.callPlans.purchaseBundle({ packageType: 'STARTER_BUNDLE' })\n * console.log(order.status) // \"PROCESSING\"\n */\n purchaseBundle(params: PurchaseBundleParams): Promise<SpecialPackageOrder> {\n return this.http.post<SpecialPackageOrder>(\"/api/v1/special-packages/purchase\", {\n packageType: params.packageType,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** List all bundle purchases for the authenticated user. */\n myBundles(): Promise<SpecialPackageOrder[]> {\n return this.http.get<SpecialPackageOrder[]>(\"/api/v1/special-packages/my\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { ESimPackage, ESimProfile, ESimPurchaseParams, ESimUsage } from \"../types.js\";\n\nexport class ESim {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List available eSIM packages for a country via Airalo.\n * No authentication required.\n */\n listPackages(countryCode: string, days = 30): Promise<ESimPackage[]> {\n return this.http.get<ESimPackage[]>(\n `/api/v1/esim/packages?countryCode=${encodeURIComponent(countryCode)}&days=${days}`,\n );\n }\n\n /**\n * Purchase an eSIM. The gateway debits your wallet and returns\n * activation info including the QR code URL and LPA activation code\n * suitable for qr_flutter / Apple's one-tap install URL.\n *\n * @example\n * const profile = await vc.esim.purchase({ packageId: 'airalo-ng-1gb', countryCode: 'NG', priceUsd: 9.99 })\n * console.log(profile.activationCode) // \"LPA:1$smdp$matching_id\"\n */\n purchase(params: ESimPurchaseParams): Promise<ESimProfile> {\n return this.http.post<ESimProfile>(\"/api/v1/esim/purchase\", params);\n }\n\n /** List all eSIM profiles provisioned for the authenticated user. */\n list(): Promise<ESimProfile[]> {\n return this.http.get<ESimProfile[]>(\"/api/v1/esim/my\");\n }\n\n /** Check current data balance for a provisioned eSIM by its ICCID. */\n usage(iccid: string): Promise<ESimUsage> {\n return this.http.get<ESimUsage>(`/api/v1/esim/${encodeURIComponent(iccid)}/usage`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { PurchaseNumberParams, PurchaseResult, SearchNumbersParams, SearchNumbersResult } from \"../types.js\";\n\nexport class Numbers {\n constructor(private readonly http: HttpClient) {}\n\n /** Browse available numbers ranked by Health Score (TM). No purchase is made. */\n search(params: SearchNumbersParams): Promise<SearchNumbersResult> {\n const q = new URLSearchParams({ serviceSlug: params.serviceSlug });\n if (params.countryCode) q.set(\"countryCode\", params.countryCode);\n if (params.minScore != null) q.set(\"minScore\", String(params.minScore));\n if (params.limit != null) q.set(\"limit\", String(params.limit));\n return this.http.get<SearchNumbersResult>(`/api/v1/numbers/search?${q}`);\n }\n\n /**\n * Buy a number for a service + country. The server picks the best available\n * candidate by Health Score automatically -- there's no numberId parameter,\n * since by the time you'd pass one back the number may already be gone.\n */\n purchase(params: PurchaseNumberParams): Promise<PurchaseResult> {\n return this.http.post<PurchaseResult>(\"/api/v1/numbers/purchase\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { SessionStatus } from \"../types.js\";\n\nexport class Sessions {\n constructor(private readonly http: HttpClient) {}\n\n /** Poll a session's current delivery status. */\n get(sessionToken: string): Promise<SessionStatus> {\n return this.http.get<SessionStatus>(`/api/v1/numbers/session/${encodeURIComponent(sessionToken)}`);\n }\n\n /**\n * Poll until the session reaches a terminal state (DELIVERED, REFUNDED, EXPIRED, FAILED)\n * or the timeout elapses. Prefer `vc.subscribe()` for real-time push -- this is a fallback\n * for environments where a persistent WebSocket isn't practical (e.g. serverless functions).\n */\n async waitForOtp(sessionToken: string, timeoutMs = 90_000, intervalMs = 2_000): Promise<SessionStatus> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const session = await this.get(sessionToken);\n if (session.status !== \"PENDING\") return session;\n if (Date.now() >= deadline) return session;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import { Client } from \"@stomp/stompjs\";\nimport type { HttpClient } from \"./client.js\";\nimport type { OtpPush } from \"./types.js\";\n\n/**\n * Subscribes to real-time OTP push for a session over the gateway's WebSocket\n * proxy (wss://.../ws -> delivery-service's STOMP broker, topic\n * /topic/otp/{sessionToken}). Requires a global WebSocket implementation --\n * present natively in browsers and Node 22+; on older Node, pass a `ws`\n * instance via globalThis.WebSocket before calling subscribe().\n *\n * Returns an unsubscribe function. The callback fires at most once per\n * session (a session only ever delivers one OTP).\n */\nexport function subscribe(http: HttpClient, sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\n \"Verixo.subscribe() requires a global WebSocket implementation. \" +\n \"This is built into browsers and Node 22+; on older Node, polyfill \" +\n \"globalThis.WebSocket (e.g. with the 'ws' package) before calling subscribe().\"\n );\n }\n\n const subscribedAt = Date.now();\n const client = new Client({\n brokerURL: `${http.wsOrigin}/ws`,\n reconnectDelay: 5_000,\n onConnect: () => {\n client.subscribe(`/topic/otp/${sessionToken}`, (message) => {\n try {\n const payload = JSON.parse(message.body) as Omit<OtpPush, \"latencyMs\">;\n onOtp({ ...payload, latencyMs: Date.now() - subscribedAt });\n } catch {\n // Ignore malformed frames rather than crashing the caller's process.\n }\n });\n },\n });\n\n client.activate();\n return () => {\n void client.deactivate();\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts","../src/resources/analytics.ts","../src/resources/call_plans.ts","../src/resources/esim.ts","../src/resources/numbers.ts","../src/resources/payment.ts","../src/resources/sessions.ts","../src/resources/wallet.ts","../src/subscribe.ts"],"sourcesContent":["import { HttpClient } from \"./client.js\";\nimport { Analytics } from \"./resources/analytics.js\";\nimport { CallPlans } from \"./resources/call_plans.js\";\nimport { ESim } from \"./resources/esim.js\";\nimport { Numbers } from \"./resources/numbers.js\";\nimport { Payment } from \"./resources/payment.js\";\nimport { Sessions } from \"./resources/sessions.js\";\nimport { Wallet } from \"./resources/wallet.js\";\nimport { subscribe } from \"./subscribe.js\";\nimport type { OtpPush, VerixoOptions } from \"./types.js\";\n\nexport { VerixoError } from \"./errors.js\";\nexport type {\n CallPlan,\n CallPlanSubscription,\n DeliveryRate,\n ESimPackage,\n ESimProfile,\n ESimPurchaseParams,\n ESimUsage,\n InitiatePaymentParams,\n OtpPush,\n PaymentInitResult,\n PurchaseBundleParams,\n PurchaseNumberParams,\n PurchaseResult,\n SearchNumbersParams,\n SearchNumbersResult,\n SessionState,\n SessionStatus,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n VerixoOptions,\n VirtualNumber,\n WalletBalance,\n WalletTransaction,\n WalletTransactionsResult,\n} from \"./types.js\";\n\nexport default class Verixo {\n readonly numbers: Numbers;\n readonly sessions: Sessions;\n readonly analytics: Analytics;\n readonly esim: ESim;\n readonly callPlans: CallPlans;\n readonly payment: Payment;\n readonly wallet: Wallet;\n private readonly http: HttpClient;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n this.http = new HttpClient(apiKey, options);\n this.numbers = new Numbers(this.http);\n this.sessions = new Sessions(this.http);\n this.analytics = new Analytics(this.http);\n this.esim = new ESim(this.http);\n this.callPlans = new CallPlans(this.http);\n this.payment = new Payment(this.http);\n this.wallet = new Wallet(this.http);\n }\n\n /**\n * Get pushed the OTP for a session in real time, instead of polling\n * `sessions.get()`. Returns an unsubscribe function.\n *\n * @example\n * const session = await vc.numbers.purchase({ serviceSlug: 'whatsapp', countryCode: 'NG' })\n * vc.subscribe(session.sessionToken, ({ otp, latencyMs }) => {\n * console.log(`OTP: ${otp} in ${latencyMs}ms`)\n * })\n */\n subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n return subscribe(this.http, sessionToken, onOtp);\n }\n}\n","export interface VerixoErrorOptions {\n status: number;\n code?: string;\n detail?: string;\n raw?: unknown;\n}\n\n/**\n * Thrown for any non-2xx response from the Verixo API. `status` is always\n * present; `code`/`detail` are populated when the gateway returns a JSON\n * error body (most do) -- a small number of paths (e.g. an invalid API key\n * rejected before reaching a controller) return an empty body, in which case\n * only `status` and a generic `message` are available.\n */\nexport class VerixoError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly detail?: string;\n readonly raw?: unknown;\n\n constructor(message: string, options: VerixoErrorOptions) {\n super(message);\n this.name = \"VerixoError\";\n this.status = options.status;\n this.code = options.code;\n this.detail = options.detail;\n this.raw = options.raw;\n }\n}\n\nconst STATUS_FALLBACKS: Record<number, string> = {\n 401: \"Missing or invalid API key.\",\n 402: \"Insufficient wallet balance.\",\n 403: \"You don't have access to this resource.\",\n 404: \"Not found.\",\n 408: \"Request timed out.\",\n 422: \"The request did not meet a required condition (e.g. minScore).\",\n 429: \"Rate limit exceeded.\",\n};\n\nexport async function errorFromResponse(res: Response): Promise<VerixoError> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = undefined;\n }\n\n const obj = (body && typeof body === \"object\" ? body : {}) as Record<string, unknown>;\n const detail = (obj.detail ?? obj.error ?? obj.message) as string | undefined;\n const code = (obj.grpcCode ?? obj.code) as string | undefined;\n const message = detail ?? STATUS_FALLBACKS[res.status] ?? `Request failed with status ${res.status}`;\n\n return new VerixoError(message, { status: res.status, code, detail, raw: body });\n}\n","import { errorFromResponse } from \"./errors.js\";\nimport type { VerixoOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.verifiedcore.com\";\n\nexport class HttpClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n if (!apiKey) {\n throw new Error(\"Verixo: an API key (or JWT) is required, e.g. new Verixo('vc_test_...')\");\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n // The gateway classifies the credential by sniffing the raw Authorization header for a\n // vc_test_/vc_live_ prefix -- a \"Bearer \" prefix on an API key would make it misclassify\n // the request as a (malformed) JWT and reject it, so API keys go out unprefixed.\n const isApiKey = this.apiKey.startsWith(\"vc_test_\") || this.apiKey.startsWith(\"vc_live_\");\n const authorization = isApiKey ? this.apiKey : `Bearer ${this.apiKey}`;\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authorization,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n });\n\n if (!res.ok) {\n throw await errorFromResponse(res);\n }\n\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, { method: \"POST\", body: body ? JSON.stringify(body) : undefined });\n }\n\n /** ws:// or wss:// origin derived from baseUrl, for the OTP push subscription. */\n get wsOrigin(): string {\n return this.baseUrl.replace(/^http/, \"ws\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { DeliveryRate } from \"../types.js\";\n\nexport class Analytics {\n constructor(private readonly http: HttpClient) {}\n\n /** Public delivery-rate stats by country for a service. No auth required by the API itself. */\n rates(serviceSlug = \"whatsapp\"): Promise<{ rates: DeliveryRate[]; updatedAt: string }> {\n return this.http.get(`/api/v1/analytics/rates?serviceSlug=${encodeURIComponent(serviceSlug)}`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type {\n CallPlan,\n CallPlanSubscription,\n PurchaseBundleParams,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n} from \"../types.js\";\n\nexport class CallPlans {\n constructor(private readonly http: HttpClient) {}\n\n // ─── Call Plans ─────────────────────────────────────────────────────────────\n\n /**\n * List all available call plan tiers with pricing.\n * No authentication required — safe to call before purchase.\n *\n * Premium plans cap high-cost destinations (NG/GH/KE) to a disclosed minute\n * bucket rather than silently throttling. See `highCostMinutes` on each plan.\n */\n list(): Promise<CallPlan[]> {\n return this.http.get<CallPlan[]>(\"/api/v1/call-plans\");\n }\n\n /**\n * Subscribe to a call plan. Debits your wallet.\n *\n * @example\n * await vc.callPlans.subscribe({ tier: 'STANDARD', paymentProvider: 'STRIPE' })\n */\n subscribe(params: SubscribeCallPlanParams): Promise<CallPlanSubscription> {\n return this.http.post<CallPlanSubscription>(\"/api/v1/call-plans/subscribe\", {\n tier: params.tier,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** Get the authenticated user's active call plan subscription, or null if none. */\n async current(): Promise<CallPlanSubscription | null> {\n try {\n return await this.http.get<CallPlanSubscription>(\"/api/v1/call-plans/my\");\n } catch (err: any) {\n if (err?.status === 204 || err?.status === 404) return null;\n throw err;\n }\n }\n\n /** List all call plan subscription history for the authenticated user. */\n history(): Promise<CallPlanSubscription[]> {\n return this.http.get<CallPlanSubscription[]>(\"/api/v1/call-plans/history\");\n }\n\n /** Cancel the active call plan subscription immediately. */\n cancel(): Promise<void> {\n return this.http.request<void>(\"/api/v1/call-plans/my\", { method: \"DELETE\" });\n }\n\n // ─── Special / Bundle Packages ───────────────────────────────────────────────\n\n /**\n * List all available bundle packages (STARTER, BUSINESS, DEVELOPER, etc.).\n * No authentication required.\n */\n listBundles(): Promise<SpecialPackage[]> {\n return this.http.get<SpecialPackage[]>(\"/api/v1/special-packages\");\n }\n\n /**\n * Purchase a bundle package. Each bundle fans out async provisioning events\n * (SMS credits, call plan, eSIM, virtual number, API access) via Kafka.\n * Poll `myBundles()` to track provisioning completion.\n *\n * @example\n * const order = await vc.callPlans.purchaseBundle({ packageType: 'STARTER_BUNDLE' })\n * console.log(order.status) // \"PROCESSING\"\n */\n purchaseBundle(params: PurchaseBundleParams): Promise<SpecialPackageOrder> {\n return this.http.post<SpecialPackageOrder>(\"/api/v1/special-packages/purchase\", {\n packageType: params.packageType,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** List all bundle purchases for the authenticated user. */\n myBundles(): Promise<SpecialPackageOrder[]> {\n return this.http.get<SpecialPackageOrder[]>(\"/api/v1/special-packages/my\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { ESimPackage, ESimProfile, ESimPurchaseParams, ESimUsage } from \"../types.js\";\n\nexport class ESim {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List available eSIM packages for a country via Airalo.\n * No authentication required.\n */\n listPackages(countryCode: string, days = 30): Promise<ESimPackage[]> {\n return this.http.get<ESimPackage[]>(\n `/api/v1/esim/packages?countryCode=${encodeURIComponent(countryCode)}&days=${days}`,\n );\n }\n\n /**\n * Purchase an eSIM. The gateway debits your wallet and returns\n * activation info including the QR code URL and LPA activation code\n * suitable for qr_flutter / Apple's one-tap install URL.\n *\n * @example\n * const profile = await vc.esim.purchase({ packageId: 'airalo-ng-1gb', countryCode: 'NG', priceUsd: 9.99 })\n * console.log(profile.activationCode) // \"LPA:1$smdp$matching_id\"\n */\n purchase(params: ESimPurchaseParams): Promise<ESimProfile> {\n return this.http.post<ESimProfile>(\"/api/v1/esim/purchase\", params);\n }\n\n /** List all eSIM profiles provisioned for the authenticated user. */\n list(): Promise<ESimProfile[]> {\n return this.http.get<ESimProfile[]>(\"/api/v1/esim/my\");\n }\n\n /** Check current data balance for a provisioned eSIM by its ICCID. */\n usage(iccid: string): Promise<ESimUsage> {\n return this.http.get<ESimUsage>(`/api/v1/esim/${encodeURIComponent(iccid)}/usage`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { PurchaseNumberParams, PurchaseResult, SearchNumbersParams, SearchNumbersResult } from \"../types.js\";\n\nexport class Numbers {\n constructor(private readonly http: HttpClient) {}\n\n /** Browse available numbers ranked by Health Score (TM). No purchase is made. */\n search(params: SearchNumbersParams): Promise<SearchNumbersResult> {\n const q = new URLSearchParams({ serviceSlug: params.serviceSlug });\n if (params.countryCode) q.set(\"countryCode\", params.countryCode);\n if (params.minScore != null) q.set(\"minScore\", String(params.minScore));\n if (params.limit != null) q.set(\"limit\", String(params.limit));\n return this.http.get<SearchNumbersResult>(`/api/v1/numbers/search?${q}`);\n }\n\n /**\n * Buy a number for a service + country. The server picks the best available\n * candidate by Health Score automatically -- there's no numberId parameter,\n * since by the time you'd pass one back the number may already be gone.\n */\n purchase(params: PurchaseNumberParams): Promise<PurchaseResult> {\n return this.http.post<PurchaseResult>(\"/api/v1/numbers/purchase\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { InitiatePaymentParams, PaymentInitResult } from \"../types.js\";\n\nexport class Payment {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Initiate a wallet top-up payment. The response varies by provider:\n * - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`\n * - Stripe → use `clientSecret` with the Stripe.js embedded element\n * - OPay USSD → display `ussdCode`\n * - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`\n *\n * @example\n * const result = await vc.payment.initiate({\n * creditPackId: 'pack_100',\n * usdAmount: 10,\n * creditsToAdd: 100,\n * currency: 'NGN',\n * customerEmail: 'user@example.com',\n * });\n * if (result.checkoutUrl) window.location.href = result.checkoutUrl;\n */\n initiate(params: InitiatePaymentParams): Promise<PaymentInitResult> {\n return this.http.post<PaymentInitResult>(\"/api/v1/payment/initiate\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { SessionStatus } from \"../types.js\";\n\nexport class Sessions {\n constructor(private readonly http: HttpClient) {}\n\n /** Poll a session's current delivery status. */\n get(sessionToken: string): Promise<SessionStatus> {\n return this.http.get<SessionStatus>(`/api/v1/numbers/session/${encodeURIComponent(sessionToken)}`);\n }\n\n /**\n * Poll until the session reaches a terminal state (DELIVERED, REFUNDED, EXPIRED, FAILED)\n * or the timeout elapses. Prefer `vc.subscribe()` for real-time push -- this is a fallback\n * for environments where a persistent WebSocket isn't practical (e.g. serverless functions).\n */\n async waitForOtp(sessionToken: string, timeoutMs = 90_000, intervalMs = 2_000): Promise<SessionStatus> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const session = await this.get(sessionToken);\n if (session.status !== \"PENDING\") return session;\n if (Date.now() >= deadline) return session;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { WalletBalance, WalletTransaction, WalletTransactionsResult } from \"../types.js\";\n\nexport class Wallet {\n constructor(private readonly http: HttpClient) {}\n\n /** Get the authenticated user's current wallet balance and today's auto-refund count. */\n balance(): Promise<WalletBalance> {\n return this.http.get<WalletBalance>(\"/api/v1/wallet/balance\");\n }\n\n /**\n * List wallet transactions (credits, debits, refunds) for the authenticated user.\n *\n * @example\n * const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })\n */\n transactions(params: { page?: number; size?: number } = {}): Promise<WalletTransactionsResult> {\n const q = new URLSearchParams();\n if (params.page != null) q.set(\"page\", String(params.page));\n if (params.size != null) q.set(\"size\", String(params.size));\n const qs = q.toString();\n return this.http.get<WalletTransactionsResult>(`/api/v1/wallet/transactions${qs ? `?${qs}` : \"\"}`);\n }\n}\n","import { Client } from \"@stomp/stompjs\";\nimport type { HttpClient } from \"./client.js\";\nimport type { OtpPush } from \"./types.js\";\n\n/**\n * Subscribes to real-time OTP push for a session over the gateway's WebSocket\n * proxy (wss://.../ws -> delivery-service's STOMP broker, topic\n * /topic/otp/{sessionToken}). Requires a global WebSocket implementation --\n * present natively in browsers and Node 22+; on older Node, pass a `ws`\n * instance via globalThis.WebSocket before calling subscribe().\n *\n * Returns an unsubscribe function. The callback fires at most once per\n * session (a session only ever delivers one OTP).\n */\nexport function subscribe(http: HttpClient, sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\n \"Verixo.subscribe() requires a global WebSocket implementation. \" +\n \"This is built into browsers and Node 22+; on older Node, polyfill \" +\n \"globalThis.WebSocket (e.g. with the 'ws' package) before calling subscribe().\"\n );\n }\n\n const subscribedAt = Date.now();\n const client = new Client({\n brokerURL: `${http.wsOrigin}/ws`,\n reconnectDelay: 5_000,\n onConnect: () => {\n client.subscribe(`/topic/otp/${sessionToken}`, (message) => {\n try {\n const payload = JSON.parse(message.body) as Omit<OtpPush, \"latencyMs\">;\n onOtp({ ...payload, latencyMs: Date.now() - subscribedAt });\n } catch {\n // Ignore malformed frames rather than crashing the caller's process.\n }\n });\n },\n });\n\n client.activate();\n return () => {\n void client.deactivate();\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -86,6 +86,60 @@ interface OtpPush {
|
|
|
86
86
|
/** Milliseconds between calling subscribe() and this push arriving -- not from the server. */
|
|
87
87
|
latencyMs: number;
|
|
88
88
|
}
|
|
89
|
+
interface InitiatePaymentParams {
|
|
90
|
+
creditPackId: string;
|
|
91
|
+
usdAmount: number;
|
|
92
|
+
creditsToAdd: number;
|
|
93
|
+
bonusCredits?: number;
|
|
94
|
+
/** ISO currency code: NGN, GHS, KES, ZAR, USD, EUR … */
|
|
95
|
+
currency: string;
|
|
96
|
+
customerEmail: string;
|
|
97
|
+
customerName?: string;
|
|
98
|
+
customerPhone?: string;
|
|
99
|
+
/** Optional override — OPAY | FLUTTERWAVE | PAYSTACK | STRIPE */
|
|
100
|
+
preferredProvider?: string;
|
|
101
|
+
/** URL to redirect to after payment completes */
|
|
102
|
+
callbackUrl?: string;
|
|
103
|
+
}
|
|
104
|
+
interface PaymentInitResult {
|
|
105
|
+
success: boolean;
|
|
106
|
+
provider: string;
|
|
107
|
+
transactionId: string;
|
|
108
|
+
/** Redirect URL for OPay / Flutterwave / Paystack checkout flows */
|
|
109
|
+
checkoutUrl: string;
|
|
110
|
+
/** Client secret for Stripe embedded payment element */
|
|
111
|
+
clientSecret: string;
|
|
112
|
+
reference: string;
|
|
113
|
+
currency: string;
|
|
114
|
+
localAmount: number;
|
|
115
|
+
paymentMethods: string[];
|
|
116
|
+
errorMessage: string;
|
|
117
|
+
/** USSD short code (OPay USSD flow) */
|
|
118
|
+
ussdCode: string;
|
|
119
|
+
bankCode: string;
|
|
120
|
+
/** NGN virtual account number (Paystack DVA flow) */
|
|
121
|
+
virtualAccountNumber: string;
|
|
122
|
+
virtualAccountBank: string;
|
|
123
|
+
}
|
|
124
|
+
interface WalletBalance {
|
|
125
|
+
balanceUsd: number;
|
|
126
|
+
refundsToday: number;
|
|
127
|
+
}
|
|
128
|
+
interface WalletTransaction {
|
|
129
|
+
id: string;
|
|
130
|
+
type: string;
|
|
131
|
+
amountUsd: number;
|
|
132
|
+
description: string;
|
|
133
|
+
referenceId: string;
|
|
134
|
+
balanceAfterUsd: number;
|
|
135
|
+
createdAt: string;
|
|
136
|
+
}
|
|
137
|
+
interface WalletTransactionsResult {
|
|
138
|
+
transactions: WalletTransaction[];
|
|
139
|
+
total: number;
|
|
140
|
+
page: number;
|
|
141
|
+
size: number;
|
|
142
|
+
}
|
|
89
143
|
interface ESimPackage {
|
|
90
144
|
packageId: string;
|
|
91
145
|
name: string;
|
|
@@ -282,6 +336,29 @@ declare class Numbers {
|
|
|
282
336
|
purchase(params: PurchaseNumberParams): Promise<PurchaseResult>;
|
|
283
337
|
}
|
|
284
338
|
|
|
339
|
+
declare class Payment {
|
|
340
|
+
private readonly http;
|
|
341
|
+
constructor(http: HttpClient);
|
|
342
|
+
/**
|
|
343
|
+
* Initiate a wallet top-up payment. The response varies by provider:
|
|
344
|
+
* - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`
|
|
345
|
+
* - Stripe → use `clientSecret` with the Stripe.js embedded element
|
|
346
|
+
* - OPay USSD → display `ussdCode`
|
|
347
|
+
* - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* const result = await vc.payment.initiate({
|
|
351
|
+
* creditPackId: 'pack_100',
|
|
352
|
+
* usdAmount: 10,
|
|
353
|
+
* creditsToAdd: 100,
|
|
354
|
+
* currency: 'NGN',
|
|
355
|
+
* customerEmail: 'user@example.com',
|
|
356
|
+
* });
|
|
357
|
+
* if (result.checkoutUrl) window.location.href = result.checkoutUrl;
|
|
358
|
+
*/
|
|
359
|
+
initiate(params: InitiatePaymentParams): Promise<PaymentInitResult>;
|
|
360
|
+
}
|
|
361
|
+
|
|
285
362
|
declare class Sessions {
|
|
286
363
|
private readonly http;
|
|
287
364
|
constructor(http: HttpClient);
|
|
@@ -295,6 +372,23 @@ declare class Sessions {
|
|
|
295
372
|
waitForOtp(sessionToken: string, timeoutMs?: number, intervalMs?: number): Promise<SessionStatus>;
|
|
296
373
|
}
|
|
297
374
|
|
|
375
|
+
declare class Wallet {
|
|
376
|
+
private readonly http;
|
|
377
|
+
constructor(http: HttpClient);
|
|
378
|
+
/** Get the authenticated user's current wallet balance and today's auto-refund count. */
|
|
379
|
+
balance(): Promise<WalletBalance>;
|
|
380
|
+
/**
|
|
381
|
+
* List wallet transactions (credits, debits, refunds) for the authenticated user.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })
|
|
385
|
+
*/
|
|
386
|
+
transactions(params?: {
|
|
387
|
+
page?: number;
|
|
388
|
+
size?: number;
|
|
389
|
+
}): Promise<WalletTransactionsResult>;
|
|
390
|
+
}
|
|
391
|
+
|
|
298
392
|
interface VerixoErrorOptions {
|
|
299
393
|
status: number;
|
|
300
394
|
code?: string;
|
|
@@ -322,6 +416,8 @@ declare class Verixo {
|
|
|
322
416
|
readonly analytics: Analytics;
|
|
323
417
|
readonly esim: ESim;
|
|
324
418
|
readonly callPlans: CallPlans;
|
|
419
|
+
readonly payment: Payment;
|
|
420
|
+
readonly wallet: Wallet;
|
|
325
421
|
private readonly http;
|
|
326
422
|
constructor(apiKey: string, options?: VerixoOptions);
|
|
327
423
|
/**
|
|
@@ -337,4 +433,4 @@ declare class Verixo {
|
|
|
337
433
|
subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void;
|
|
338
434
|
}
|
|
339
435
|
|
|
340
|
-
export { type CallPlan, type CallPlanSubscription, type DeliveryRate, type ESimPackage, type ESimProfile, type ESimPurchaseParams, type ESimUsage, type OtpPush, type PurchaseBundleParams, type PurchaseNumberParams, type PurchaseResult, type SearchNumbersParams, type SearchNumbersResult, type SessionState, type SessionStatus, type SpecialPackage, type SpecialPackageOrder, type SubscribeCallPlanParams, VerixoError, type VerixoOptions, type VirtualNumber, Verixo as default };
|
|
436
|
+
export { type CallPlan, type CallPlanSubscription, type DeliveryRate, type ESimPackage, type ESimProfile, type ESimPurchaseParams, type ESimUsage, type InitiatePaymentParams, type OtpPush, type PaymentInitResult, type PurchaseBundleParams, type PurchaseNumberParams, type PurchaseResult, type SearchNumbersParams, type SearchNumbersResult, type SessionState, type SessionStatus, type SpecialPackage, type SpecialPackageOrder, type SubscribeCallPlanParams, VerixoError, type VerixoOptions, type VirtualNumber, type WalletBalance, type WalletTransaction, type WalletTransactionsResult, Verixo as default };
|
package/dist/index.d.ts
CHANGED
|
@@ -86,6 +86,60 @@ interface OtpPush {
|
|
|
86
86
|
/** Milliseconds between calling subscribe() and this push arriving -- not from the server. */
|
|
87
87
|
latencyMs: number;
|
|
88
88
|
}
|
|
89
|
+
interface InitiatePaymentParams {
|
|
90
|
+
creditPackId: string;
|
|
91
|
+
usdAmount: number;
|
|
92
|
+
creditsToAdd: number;
|
|
93
|
+
bonusCredits?: number;
|
|
94
|
+
/** ISO currency code: NGN, GHS, KES, ZAR, USD, EUR … */
|
|
95
|
+
currency: string;
|
|
96
|
+
customerEmail: string;
|
|
97
|
+
customerName?: string;
|
|
98
|
+
customerPhone?: string;
|
|
99
|
+
/** Optional override — OPAY | FLUTTERWAVE | PAYSTACK | STRIPE */
|
|
100
|
+
preferredProvider?: string;
|
|
101
|
+
/** URL to redirect to after payment completes */
|
|
102
|
+
callbackUrl?: string;
|
|
103
|
+
}
|
|
104
|
+
interface PaymentInitResult {
|
|
105
|
+
success: boolean;
|
|
106
|
+
provider: string;
|
|
107
|
+
transactionId: string;
|
|
108
|
+
/** Redirect URL for OPay / Flutterwave / Paystack checkout flows */
|
|
109
|
+
checkoutUrl: string;
|
|
110
|
+
/** Client secret for Stripe embedded payment element */
|
|
111
|
+
clientSecret: string;
|
|
112
|
+
reference: string;
|
|
113
|
+
currency: string;
|
|
114
|
+
localAmount: number;
|
|
115
|
+
paymentMethods: string[];
|
|
116
|
+
errorMessage: string;
|
|
117
|
+
/** USSD short code (OPay USSD flow) */
|
|
118
|
+
ussdCode: string;
|
|
119
|
+
bankCode: string;
|
|
120
|
+
/** NGN virtual account number (Paystack DVA flow) */
|
|
121
|
+
virtualAccountNumber: string;
|
|
122
|
+
virtualAccountBank: string;
|
|
123
|
+
}
|
|
124
|
+
interface WalletBalance {
|
|
125
|
+
balanceUsd: number;
|
|
126
|
+
refundsToday: number;
|
|
127
|
+
}
|
|
128
|
+
interface WalletTransaction {
|
|
129
|
+
id: string;
|
|
130
|
+
type: string;
|
|
131
|
+
amountUsd: number;
|
|
132
|
+
description: string;
|
|
133
|
+
referenceId: string;
|
|
134
|
+
balanceAfterUsd: number;
|
|
135
|
+
createdAt: string;
|
|
136
|
+
}
|
|
137
|
+
interface WalletTransactionsResult {
|
|
138
|
+
transactions: WalletTransaction[];
|
|
139
|
+
total: number;
|
|
140
|
+
page: number;
|
|
141
|
+
size: number;
|
|
142
|
+
}
|
|
89
143
|
interface ESimPackage {
|
|
90
144
|
packageId: string;
|
|
91
145
|
name: string;
|
|
@@ -282,6 +336,29 @@ declare class Numbers {
|
|
|
282
336
|
purchase(params: PurchaseNumberParams): Promise<PurchaseResult>;
|
|
283
337
|
}
|
|
284
338
|
|
|
339
|
+
declare class Payment {
|
|
340
|
+
private readonly http;
|
|
341
|
+
constructor(http: HttpClient);
|
|
342
|
+
/**
|
|
343
|
+
* Initiate a wallet top-up payment. The response varies by provider:
|
|
344
|
+
* - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`
|
|
345
|
+
* - Stripe → use `clientSecret` with the Stripe.js embedded element
|
|
346
|
+
* - OPay USSD → display `ussdCode`
|
|
347
|
+
* - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`
|
|
348
|
+
*
|
|
349
|
+
* @example
|
|
350
|
+
* const result = await vc.payment.initiate({
|
|
351
|
+
* creditPackId: 'pack_100',
|
|
352
|
+
* usdAmount: 10,
|
|
353
|
+
* creditsToAdd: 100,
|
|
354
|
+
* currency: 'NGN',
|
|
355
|
+
* customerEmail: 'user@example.com',
|
|
356
|
+
* });
|
|
357
|
+
* if (result.checkoutUrl) window.location.href = result.checkoutUrl;
|
|
358
|
+
*/
|
|
359
|
+
initiate(params: InitiatePaymentParams): Promise<PaymentInitResult>;
|
|
360
|
+
}
|
|
361
|
+
|
|
285
362
|
declare class Sessions {
|
|
286
363
|
private readonly http;
|
|
287
364
|
constructor(http: HttpClient);
|
|
@@ -295,6 +372,23 @@ declare class Sessions {
|
|
|
295
372
|
waitForOtp(sessionToken: string, timeoutMs?: number, intervalMs?: number): Promise<SessionStatus>;
|
|
296
373
|
}
|
|
297
374
|
|
|
375
|
+
declare class Wallet {
|
|
376
|
+
private readonly http;
|
|
377
|
+
constructor(http: HttpClient);
|
|
378
|
+
/** Get the authenticated user's current wallet balance and today's auto-refund count. */
|
|
379
|
+
balance(): Promise<WalletBalance>;
|
|
380
|
+
/**
|
|
381
|
+
* List wallet transactions (credits, debits, refunds) for the authenticated user.
|
|
382
|
+
*
|
|
383
|
+
* @example
|
|
384
|
+
* const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })
|
|
385
|
+
*/
|
|
386
|
+
transactions(params?: {
|
|
387
|
+
page?: number;
|
|
388
|
+
size?: number;
|
|
389
|
+
}): Promise<WalletTransactionsResult>;
|
|
390
|
+
}
|
|
391
|
+
|
|
298
392
|
interface VerixoErrorOptions {
|
|
299
393
|
status: number;
|
|
300
394
|
code?: string;
|
|
@@ -322,6 +416,8 @@ declare class Verixo {
|
|
|
322
416
|
readonly analytics: Analytics;
|
|
323
417
|
readonly esim: ESim;
|
|
324
418
|
readonly callPlans: CallPlans;
|
|
419
|
+
readonly payment: Payment;
|
|
420
|
+
readonly wallet: Wallet;
|
|
325
421
|
private readonly http;
|
|
326
422
|
constructor(apiKey: string, options?: VerixoOptions);
|
|
327
423
|
/**
|
|
@@ -337,4 +433,4 @@ declare class Verixo {
|
|
|
337
433
|
subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void;
|
|
338
434
|
}
|
|
339
435
|
|
|
340
|
-
export { type CallPlan, type CallPlanSubscription, type DeliveryRate, type ESimPackage, type ESimProfile, type ESimPurchaseParams, type ESimUsage, type OtpPush, type PurchaseBundleParams, type PurchaseNumberParams, type PurchaseResult, type SearchNumbersParams, type SearchNumbersResult, type SessionState, type SessionStatus, type SpecialPackage, type SpecialPackageOrder, type SubscribeCallPlanParams, VerixoError, type VerixoOptions, type VirtualNumber, Verixo as default };
|
|
436
|
+
export { type CallPlan, type CallPlanSubscription, type DeliveryRate, type ESimPackage, type ESimProfile, type ESimPurchaseParams, type ESimUsage, type InitiatePaymentParams, type OtpPush, type PaymentInitResult, type PurchaseBundleParams, type PurchaseNumberParams, type PurchaseResult, type SearchNumbersParams, type SearchNumbersResult, type SessionState, type SessionStatus, type SpecialPackage, type SpecialPackageOrder, type SubscribeCallPlanParams, VerixoError, type VerixoOptions, type VirtualNumber, type WalletBalance, type WalletTransaction, type WalletTransactionsResult, Verixo as default };
|
package/dist/index.js
CHANGED
|
@@ -227,6 +227,34 @@ var Numbers = class {
|
|
|
227
227
|
}
|
|
228
228
|
};
|
|
229
229
|
|
|
230
|
+
// src/resources/payment.ts
|
|
231
|
+
var Payment = class {
|
|
232
|
+
constructor(http) {
|
|
233
|
+
this.http = http;
|
|
234
|
+
}
|
|
235
|
+
http;
|
|
236
|
+
/**
|
|
237
|
+
* Initiate a wallet top-up payment. The response varies by provider:
|
|
238
|
+
* - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`
|
|
239
|
+
* - Stripe → use `clientSecret` with the Stripe.js embedded element
|
|
240
|
+
* - OPay USSD → display `ussdCode`
|
|
241
|
+
* - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`
|
|
242
|
+
*
|
|
243
|
+
* @example
|
|
244
|
+
* const result = await vc.payment.initiate({
|
|
245
|
+
* creditPackId: 'pack_100',
|
|
246
|
+
* usdAmount: 10,
|
|
247
|
+
* creditsToAdd: 100,
|
|
248
|
+
* currency: 'NGN',
|
|
249
|
+
* customerEmail: 'user@example.com',
|
|
250
|
+
* });
|
|
251
|
+
* if (result.checkoutUrl) window.location.href = result.checkoutUrl;
|
|
252
|
+
*/
|
|
253
|
+
initiate(params) {
|
|
254
|
+
return this.http.post("/api/v1/payment/initiate", params);
|
|
255
|
+
}
|
|
256
|
+
};
|
|
257
|
+
|
|
230
258
|
// src/resources/sessions.ts
|
|
231
259
|
var Sessions = class {
|
|
232
260
|
constructor(http) {
|
|
@@ -253,6 +281,31 @@ var Sessions = class {
|
|
|
253
281
|
}
|
|
254
282
|
};
|
|
255
283
|
|
|
284
|
+
// src/resources/wallet.ts
|
|
285
|
+
var Wallet = class {
|
|
286
|
+
constructor(http) {
|
|
287
|
+
this.http = http;
|
|
288
|
+
}
|
|
289
|
+
http;
|
|
290
|
+
/** Get the authenticated user's current wallet balance and today's auto-refund count. */
|
|
291
|
+
balance() {
|
|
292
|
+
return this.http.get("/api/v1/wallet/balance");
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* List wallet transactions (credits, debits, refunds) for the authenticated user.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })
|
|
299
|
+
*/
|
|
300
|
+
transactions(params = {}) {
|
|
301
|
+
const q = new URLSearchParams();
|
|
302
|
+
if (params.page != null) q.set("page", String(params.page));
|
|
303
|
+
if (params.size != null) q.set("size", String(params.size));
|
|
304
|
+
const qs = q.toString();
|
|
305
|
+
return this.http.get(`/api/v1/wallet/transactions${qs ? `?${qs}` : ""}`);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
|
|
256
309
|
// src/subscribe.ts
|
|
257
310
|
import { Client } from "@stomp/stompjs";
|
|
258
311
|
function subscribe(http, sessionToken, onOtp) {
|
|
@@ -288,6 +341,8 @@ var Verixo = class {
|
|
|
288
341
|
analytics;
|
|
289
342
|
esim;
|
|
290
343
|
callPlans;
|
|
344
|
+
payment;
|
|
345
|
+
wallet;
|
|
291
346
|
http;
|
|
292
347
|
constructor(apiKey, options = {}) {
|
|
293
348
|
this.http = new HttpClient(apiKey, options);
|
|
@@ -296,6 +351,8 @@ var Verixo = class {
|
|
|
296
351
|
this.analytics = new Analytics(this.http);
|
|
297
352
|
this.esim = new ESim(this.http);
|
|
298
353
|
this.callPlans = new CallPlans(this.http);
|
|
354
|
+
this.payment = new Payment(this.http);
|
|
355
|
+
this.wallet = new Wallet(this.http);
|
|
299
356
|
}
|
|
300
357
|
/**
|
|
301
358
|
* Get pushed the OTP for a session in real time, instead of polling
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/resources/analytics.ts","../src/resources/call_plans.ts","../src/resources/esim.ts","../src/resources/numbers.ts","../src/resources/sessions.ts","../src/subscribe.ts","../src/index.ts"],"sourcesContent":["export interface VerixoErrorOptions {\n status: number;\n code?: string;\n detail?: string;\n raw?: unknown;\n}\n\n/**\n * Thrown for any non-2xx response from the Verixo API. `status` is always\n * present; `code`/`detail` are populated when the gateway returns a JSON\n * error body (most do) -- a small number of paths (e.g. an invalid API key\n * rejected before reaching a controller) return an empty body, in which case\n * only `status` and a generic `message` are available.\n */\nexport class VerixoError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly detail?: string;\n readonly raw?: unknown;\n\n constructor(message: string, options: VerixoErrorOptions) {\n super(message);\n this.name = \"VerixoError\";\n this.status = options.status;\n this.code = options.code;\n this.detail = options.detail;\n this.raw = options.raw;\n }\n}\n\nconst STATUS_FALLBACKS: Record<number, string> = {\n 401: \"Missing or invalid API key.\",\n 402: \"Insufficient wallet balance.\",\n 403: \"You don't have access to this resource.\",\n 404: \"Not found.\",\n 408: \"Request timed out.\",\n 422: \"The request did not meet a required condition (e.g. minScore).\",\n 429: \"Rate limit exceeded.\",\n};\n\nexport async function errorFromResponse(res: Response): Promise<VerixoError> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = undefined;\n }\n\n const obj = (body && typeof body === \"object\" ? body : {}) as Record<string, unknown>;\n const detail = (obj.detail ?? obj.error ?? obj.message) as string | undefined;\n const code = (obj.grpcCode ?? obj.code) as string | undefined;\n const message = detail ?? STATUS_FALLBACKS[res.status] ?? `Request failed with status ${res.status}`;\n\n return new VerixoError(message, { status: res.status, code, detail, raw: body });\n}\n","import { errorFromResponse } from \"./errors.js\";\nimport type { VerixoOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.verifiedcore.com\";\n\nexport class HttpClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n if (!apiKey) {\n throw new Error(\"Verixo: an API key (or JWT) is required, e.g. new Verixo('vc_test_...')\");\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n // The gateway classifies the credential by sniffing the raw Authorization header for a\n // vc_test_/vc_live_ prefix -- a \"Bearer \" prefix on an API key would make it misclassify\n // the request as a (malformed) JWT and reject it, so API keys go out unprefixed.\n const isApiKey = this.apiKey.startsWith(\"vc_test_\") || this.apiKey.startsWith(\"vc_live_\");\n const authorization = isApiKey ? this.apiKey : `Bearer ${this.apiKey}`;\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authorization,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n });\n\n if (!res.ok) {\n throw await errorFromResponse(res);\n }\n\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, { method: \"POST\", body: body ? JSON.stringify(body) : undefined });\n }\n\n /** ws:// or wss:// origin derived from baseUrl, for the OTP push subscription. */\n get wsOrigin(): string {\n return this.baseUrl.replace(/^http/, \"ws\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { DeliveryRate } from \"../types.js\";\n\nexport class Analytics {\n constructor(private readonly http: HttpClient) {}\n\n /** Public delivery-rate stats by country for a service. No auth required by the API itself. */\n rates(serviceSlug = \"whatsapp\"): Promise<{ rates: DeliveryRate[]; updatedAt: string }> {\n return this.http.get(`/api/v1/analytics/rates?serviceSlug=${encodeURIComponent(serviceSlug)}`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type {\n CallPlan,\n CallPlanSubscription,\n PurchaseBundleParams,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n} from \"../types.js\";\n\nexport class CallPlans {\n constructor(private readonly http: HttpClient) {}\n\n // ─── Call Plans ─────────────────────────────────────────────────────────────\n\n /**\n * List all available call plan tiers with pricing.\n * No authentication required — safe to call before purchase.\n *\n * Premium plans cap high-cost destinations (NG/GH/KE) to a disclosed minute\n * bucket rather than silently throttling. See `highCostMinutes` on each plan.\n */\n list(): Promise<CallPlan[]> {\n return this.http.get<CallPlan[]>(\"/api/v1/call-plans\");\n }\n\n /**\n * Subscribe to a call plan. Debits your wallet.\n *\n * @example\n * await vc.callPlans.subscribe({ tier: 'STANDARD', paymentProvider: 'STRIPE' })\n */\n subscribe(params: SubscribeCallPlanParams): Promise<CallPlanSubscription> {\n return this.http.post<CallPlanSubscription>(\"/api/v1/call-plans/subscribe\", {\n tier: params.tier,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** Get the authenticated user's active call plan subscription, or null if none. */\n async current(): Promise<CallPlanSubscription | null> {\n try {\n return await this.http.get<CallPlanSubscription>(\"/api/v1/call-plans/my\");\n } catch (err: any) {\n if (err?.status === 204 || err?.status === 404) return null;\n throw err;\n }\n }\n\n /** List all call plan subscription history for the authenticated user. */\n history(): Promise<CallPlanSubscription[]> {\n return this.http.get<CallPlanSubscription[]>(\"/api/v1/call-plans/history\");\n }\n\n /** Cancel the active call plan subscription immediately. */\n cancel(): Promise<void> {\n return this.http.request<void>(\"/api/v1/call-plans/my\", { method: \"DELETE\" });\n }\n\n // ─── Special / Bundle Packages ───────────────────────────────────────────────\n\n /**\n * List all available bundle packages (STARTER, BUSINESS, DEVELOPER, etc.).\n * No authentication required.\n */\n listBundles(): Promise<SpecialPackage[]> {\n return this.http.get<SpecialPackage[]>(\"/api/v1/special-packages\");\n }\n\n /**\n * Purchase a bundle package. Each bundle fans out async provisioning events\n * (SMS credits, call plan, eSIM, virtual number, API access) via Kafka.\n * Poll `myBundles()` to track provisioning completion.\n *\n * @example\n * const order = await vc.callPlans.purchaseBundle({ packageType: 'STARTER_BUNDLE' })\n * console.log(order.status) // \"PROCESSING\"\n */\n purchaseBundle(params: PurchaseBundleParams): Promise<SpecialPackageOrder> {\n return this.http.post<SpecialPackageOrder>(\"/api/v1/special-packages/purchase\", {\n packageType: params.packageType,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** List all bundle purchases for the authenticated user. */\n myBundles(): Promise<SpecialPackageOrder[]> {\n return this.http.get<SpecialPackageOrder[]>(\"/api/v1/special-packages/my\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { ESimPackage, ESimProfile, ESimPurchaseParams, ESimUsage } from \"../types.js\";\n\nexport class ESim {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List available eSIM packages for a country via Airalo.\n * No authentication required.\n */\n listPackages(countryCode: string, days = 30): Promise<ESimPackage[]> {\n return this.http.get<ESimPackage[]>(\n `/api/v1/esim/packages?countryCode=${encodeURIComponent(countryCode)}&days=${days}`,\n );\n }\n\n /**\n * Purchase an eSIM. The gateway debits your wallet and returns\n * activation info including the QR code URL and LPA activation code\n * suitable for qr_flutter / Apple's one-tap install URL.\n *\n * @example\n * const profile = await vc.esim.purchase({ packageId: 'airalo-ng-1gb', countryCode: 'NG', priceUsd: 9.99 })\n * console.log(profile.activationCode) // \"LPA:1$smdp$matching_id\"\n */\n purchase(params: ESimPurchaseParams): Promise<ESimProfile> {\n return this.http.post<ESimProfile>(\"/api/v1/esim/purchase\", params);\n }\n\n /** List all eSIM profiles provisioned for the authenticated user. */\n list(): Promise<ESimProfile[]> {\n return this.http.get<ESimProfile[]>(\"/api/v1/esim/my\");\n }\n\n /** Check current data balance for a provisioned eSIM by its ICCID. */\n usage(iccid: string): Promise<ESimUsage> {\n return this.http.get<ESimUsage>(`/api/v1/esim/${encodeURIComponent(iccid)}/usage`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { PurchaseNumberParams, PurchaseResult, SearchNumbersParams, SearchNumbersResult } from \"../types.js\";\n\nexport class Numbers {\n constructor(private readonly http: HttpClient) {}\n\n /** Browse available numbers ranked by Health Score (TM). No purchase is made. */\n search(params: SearchNumbersParams): Promise<SearchNumbersResult> {\n const q = new URLSearchParams({ serviceSlug: params.serviceSlug });\n if (params.countryCode) q.set(\"countryCode\", params.countryCode);\n if (params.minScore != null) q.set(\"minScore\", String(params.minScore));\n if (params.limit != null) q.set(\"limit\", String(params.limit));\n return this.http.get<SearchNumbersResult>(`/api/v1/numbers/search?${q}`);\n }\n\n /**\n * Buy a number for a service + country. The server picks the best available\n * candidate by Health Score automatically -- there's no numberId parameter,\n * since by the time you'd pass one back the number may already be gone.\n */\n purchase(params: PurchaseNumberParams): Promise<PurchaseResult> {\n return this.http.post<PurchaseResult>(\"/api/v1/numbers/purchase\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { SessionStatus } from \"../types.js\";\n\nexport class Sessions {\n constructor(private readonly http: HttpClient) {}\n\n /** Poll a session's current delivery status. */\n get(sessionToken: string): Promise<SessionStatus> {\n return this.http.get<SessionStatus>(`/api/v1/numbers/session/${encodeURIComponent(sessionToken)}`);\n }\n\n /**\n * Poll until the session reaches a terminal state (DELIVERED, REFUNDED, EXPIRED, FAILED)\n * or the timeout elapses. Prefer `vc.subscribe()` for real-time push -- this is a fallback\n * for environments where a persistent WebSocket isn't practical (e.g. serverless functions).\n */\n async waitForOtp(sessionToken: string, timeoutMs = 90_000, intervalMs = 2_000): Promise<SessionStatus> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const session = await this.get(sessionToken);\n if (session.status !== \"PENDING\") return session;\n if (Date.now() >= deadline) return session;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import { Client } from \"@stomp/stompjs\";\nimport type { HttpClient } from \"./client.js\";\nimport type { OtpPush } from \"./types.js\";\n\n/**\n * Subscribes to real-time OTP push for a session over the gateway's WebSocket\n * proxy (wss://.../ws -> delivery-service's STOMP broker, topic\n * /topic/otp/{sessionToken}). Requires a global WebSocket implementation --\n * present natively in browsers and Node 22+; on older Node, pass a `ws`\n * instance via globalThis.WebSocket before calling subscribe().\n *\n * Returns an unsubscribe function. The callback fires at most once per\n * session (a session only ever delivers one OTP).\n */\nexport function subscribe(http: HttpClient, sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\n \"Verixo.subscribe() requires a global WebSocket implementation. \" +\n \"This is built into browsers and Node 22+; on older Node, polyfill \" +\n \"globalThis.WebSocket (e.g. with the 'ws' package) before calling subscribe().\"\n );\n }\n\n const subscribedAt = Date.now();\n const client = new Client({\n brokerURL: `${http.wsOrigin}/ws`,\n reconnectDelay: 5_000,\n onConnect: () => {\n client.subscribe(`/topic/otp/${sessionToken}`, (message) => {\n try {\n const payload = JSON.parse(message.body) as Omit<OtpPush, \"latencyMs\">;\n onOtp({ ...payload, latencyMs: Date.now() - subscribedAt });\n } catch {\n // Ignore malformed frames rather than crashing the caller's process.\n }\n });\n },\n });\n\n client.activate();\n return () => {\n void client.deactivate();\n };\n}\n","import { HttpClient } from \"./client.js\";\nimport { Analytics } from \"./resources/analytics.js\";\nimport { CallPlans } from \"./resources/call_plans.js\";\nimport { ESim } from \"./resources/esim.js\";\nimport { Numbers } from \"./resources/numbers.js\";\nimport { Sessions } from \"./resources/sessions.js\";\nimport { subscribe } from \"./subscribe.js\";\nimport type { OtpPush, VerixoOptions } from \"./types.js\";\n\nexport { VerixoError } from \"./errors.js\";\nexport type {\n CallPlan,\n CallPlanSubscription,\n DeliveryRate,\n ESimPackage,\n ESimProfile,\n ESimPurchaseParams,\n ESimUsage,\n OtpPush,\n PurchaseBundleParams,\n PurchaseNumberParams,\n PurchaseResult,\n SearchNumbersParams,\n SearchNumbersResult,\n SessionState,\n SessionStatus,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n VerixoOptions,\n VirtualNumber,\n} from \"./types.js\";\n\nexport default class Verixo {\n readonly numbers: Numbers;\n readonly sessions: Sessions;\n readonly analytics: Analytics;\n readonly esim: ESim;\n readonly callPlans: CallPlans;\n private readonly http: HttpClient;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n this.http = new HttpClient(apiKey, options);\n this.numbers = new Numbers(this.http);\n this.sessions = new Sessions(this.http);\n this.analytics = new Analytics(this.http);\n this.esim = new ESim(this.http);\n this.callPlans = new CallPlans(this.http);\n }\n\n /**\n * Get pushed the OTP for a session in real time, instead of polling\n * `sessions.get()`. Returns an unsubscribe function.\n *\n * @example\n * const session = await vc.numbers.purchase({ serviceSlug: 'whatsapp', countryCode: 'NG' })\n * vc.subscribe(session.sessionToken, ({ otp, latencyMs }) => {\n * console.log(`OTP: ${otp} in ${latencyMs}ms`)\n * })\n */\n subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n return subscribe(this.http, sessionToken, onOtp);\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/errors.ts","../src/client.ts","../src/resources/analytics.ts","../src/resources/call_plans.ts","../src/resources/esim.ts","../src/resources/numbers.ts","../src/resources/payment.ts","../src/resources/sessions.ts","../src/resources/wallet.ts","../src/subscribe.ts","../src/index.ts"],"sourcesContent":["export interface VerixoErrorOptions {\n status: number;\n code?: string;\n detail?: string;\n raw?: unknown;\n}\n\n/**\n * Thrown for any non-2xx response from the Verixo API. `status` is always\n * present; `code`/`detail` are populated when the gateway returns a JSON\n * error body (most do) -- a small number of paths (e.g. an invalid API key\n * rejected before reaching a controller) return an empty body, in which case\n * only `status` and a generic `message` are available.\n */\nexport class VerixoError extends Error {\n readonly status: number;\n readonly code?: string;\n readonly detail?: string;\n readonly raw?: unknown;\n\n constructor(message: string, options: VerixoErrorOptions) {\n super(message);\n this.name = \"VerixoError\";\n this.status = options.status;\n this.code = options.code;\n this.detail = options.detail;\n this.raw = options.raw;\n }\n}\n\nconst STATUS_FALLBACKS: Record<number, string> = {\n 401: \"Missing or invalid API key.\",\n 402: \"Insufficient wallet balance.\",\n 403: \"You don't have access to this resource.\",\n 404: \"Not found.\",\n 408: \"Request timed out.\",\n 422: \"The request did not meet a required condition (e.g. minScore).\",\n 429: \"Rate limit exceeded.\",\n};\n\nexport async function errorFromResponse(res: Response): Promise<VerixoError> {\n let body: unknown;\n try {\n body = await res.json();\n } catch {\n body = undefined;\n }\n\n const obj = (body && typeof body === \"object\" ? body : {}) as Record<string, unknown>;\n const detail = (obj.detail ?? obj.error ?? obj.message) as string | undefined;\n const code = (obj.grpcCode ?? obj.code) as string | undefined;\n const message = detail ?? STATUS_FALLBACKS[res.status] ?? `Request failed with status ${res.status}`;\n\n return new VerixoError(message, { status: res.status, code, detail, raw: body });\n}\n","import { errorFromResponse } from \"./errors.js\";\nimport type { VerixoOptions } from \"./types.js\";\n\nconst DEFAULT_BASE_URL = \"https://api.verifiedcore.com\";\n\nexport class HttpClient {\n readonly apiKey: string;\n readonly baseUrl: string;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n if (!apiKey) {\n throw new Error(\"Verixo: an API key (or JWT) is required, e.g. new Verixo('vc_test_...')\");\n }\n this.apiKey = apiKey;\n this.baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\\/$/, \"\");\n }\n\n async request<T>(path: string, init: RequestInit = {}): Promise<T> {\n // The gateway classifies the credential by sniffing the raw Authorization header for a\n // vc_test_/vc_live_ prefix -- a \"Bearer \" prefix on an API key would make it misclassify\n // the request as a (malformed) JWT and reject it, so API keys go out unprefixed.\n const isApiKey = this.apiKey.startsWith(\"vc_test_\") || this.apiKey.startsWith(\"vc_live_\");\n const authorization = isApiKey ? this.apiKey : `Bearer ${this.apiKey}`;\n\n const res = await fetch(`${this.baseUrl}${path}`, {\n ...init,\n headers: {\n Authorization: authorization,\n ...(init.body ? { \"Content-Type\": \"application/json\" } : {}),\n ...init.headers,\n },\n });\n\n if (!res.ok) {\n throw await errorFromResponse(res);\n }\n\n if (res.status === 204) return undefined as T;\n return (await res.json()) as T;\n }\n\n get<T>(path: string): Promise<T> {\n return this.request<T>(path, { method: \"GET\" });\n }\n\n post<T>(path: string, body?: unknown): Promise<T> {\n return this.request<T>(path, { method: \"POST\", body: body ? JSON.stringify(body) : undefined });\n }\n\n /** ws:// or wss:// origin derived from baseUrl, for the OTP push subscription. */\n get wsOrigin(): string {\n return this.baseUrl.replace(/^http/, \"ws\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { DeliveryRate } from \"../types.js\";\n\nexport class Analytics {\n constructor(private readonly http: HttpClient) {}\n\n /** Public delivery-rate stats by country for a service. No auth required by the API itself. */\n rates(serviceSlug = \"whatsapp\"): Promise<{ rates: DeliveryRate[]; updatedAt: string }> {\n return this.http.get(`/api/v1/analytics/rates?serviceSlug=${encodeURIComponent(serviceSlug)}`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type {\n CallPlan,\n CallPlanSubscription,\n PurchaseBundleParams,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n} from \"../types.js\";\n\nexport class CallPlans {\n constructor(private readonly http: HttpClient) {}\n\n // ─── Call Plans ─────────────────────────────────────────────────────────────\n\n /**\n * List all available call plan tiers with pricing.\n * No authentication required — safe to call before purchase.\n *\n * Premium plans cap high-cost destinations (NG/GH/KE) to a disclosed minute\n * bucket rather than silently throttling. See `highCostMinutes` on each plan.\n */\n list(): Promise<CallPlan[]> {\n return this.http.get<CallPlan[]>(\"/api/v1/call-plans\");\n }\n\n /**\n * Subscribe to a call plan. Debits your wallet.\n *\n * @example\n * await vc.callPlans.subscribe({ tier: 'STANDARD', paymentProvider: 'STRIPE' })\n */\n subscribe(params: SubscribeCallPlanParams): Promise<CallPlanSubscription> {\n return this.http.post<CallPlanSubscription>(\"/api/v1/call-plans/subscribe\", {\n tier: params.tier,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** Get the authenticated user's active call plan subscription, or null if none. */\n async current(): Promise<CallPlanSubscription | null> {\n try {\n return await this.http.get<CallPlanSubscription>(\"/api/v1/call-plans/my\");\n } catch (err: any) {\n if (err?.status === 204 || err?.status === 404) return null;\n throw err;\n }\n }\n\n /** List all call plan subscription history for the authenticated user. */\n history(): Promise<CallPlanSubscription[]> {\n return this.http.get<CallPlanSubscription[]>(\"/api/v1/call-plans/history\");\n }\n\n /** Cancel the active call plan subscription immediately. */\n cancel(): Promise<void> {\n return this.http.request<void>(\"/api/v1/call-plans/my\", { method: \"DELETE\" });\n }\n\n // ─── Special / Bundle Packages ───────────────────────────────────────────────\n\n /**\n * List all available bundle packages (STARTER, BUSINESS, DEVELOPER, etc.).\n * No authentication required.\n */\n listBundles(): Promise<SpecialPackage[]> {\n return this.http.get<SpecialPackage[]>(\"/api/v1/special-packages\");\n }\n\n /**\n * Purchase a bundle package. Each bundle fans out async provisioning events\n * (SMS credits, call plan, eSIM, virtual number, API access) via Kafka.\n * Poll `myBundles()` to track provisioning completion.\n *\n * @example\n * const order = await vc.callPlans.purchaseBundle({ packageType: 'STARTER_BUNDLE' })\n * console.log(order.status) // \"PROCESSING\"\n */\n purchaseBundle(params: PurchaseBundleParams): Promise<SpecialPackageOrder> {\n return this.http.post<SpecialPackageOrder>(\"/api/v1/special-packages/purchase\", {\n packageType: params.packageType,\n paymentProvider: params.paymentProvider ?? \"STRIPE\",\n paymentReference: params.paymentReference ?? \"\",\n });\n }\n\n /** List all bundle purchases for the authenticated user. */\n myBundles(): Promise<SpecialPackageOrder[]> {\n return this.http.get<SpecialPackageOrder[]>(\"/api/v1/special-packages/my\");\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { ESimPackage, ESimProfile, ESimPurchaseParams, ESimUsage } from \"../types.js\";\n\nexport class ESim {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * List available eSIM packages for a country via Airalo.\n * No authentication required.\n */\n listPackages(countryCode: string, days = 30): Promise<ESimPackage[]> {\n return this.http.get<ESimPackage[]>(\n `/api/v1/esim/packages?countryCode=${encodeURIComponent(countryCode)}&days=${days}`,\n );\n }\n\n /**\n * Purchase an eSIM. The gateway debits your wallet and returns\n * activation info including the QR code URL and LPA activation code\n * suitable for qr_flutter / Apple's one-tap install URL.\n *\n * @example\n * const profile = await vc.esim.purchase({ packageId: 'airalo-ng-1gb', countryCode: 'NG', priceUsd: 9.99 })\n * console.log(profile.activationCode) // \"LPA:1$smdp$matching_id\"\n */\n purchase(params: ESimPurchaseParams): Promise<ESimProfile> {\n return this.http.post<ESimProfile>(\"/api/v1/esim/purchase\", params);\n }\n\n /** List all eSIM profiles provisioned for the authenticated user. */\n list(): Promise<ESimProfile[]> {\n return this.http.get<ESimProfile[]>(\"/api/v1/esim/my\");\n }\n\n /** Check current data balance for a provisioned eSIM by its ICCID. */\n usage(iccid: string): Promise<ESimUsage> {\n return this.http.get<ESimUsage>(`/api/v1/esim/${encodeURIComponent(iccid)}/usage`);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { PurchaseNumberParams, PurchaseResult, SearchNumbersParams, SearchNumbersResult } from \"../types.js\";\n\nexport class Numbers {\n constructor(private readonly http: HttpClient) {}\n\n /** Browse available numbers ranked by Health Score (TM). No purchase is made. */\n search(params: SearchNumbersParams): Promise<SearchNumbersResult> {\n const q = new URLSearchParams({ serviceSlug: params.serviceSlug });\n if (params.countryCode) q.set(\"countryCode\", params.countryCode);\n if (params.minScore != null) q.set(\"minScore\", String(params.minScore));\n if (params.limit != null) q.set(\"limit\", String(params.limit));\n return this.http.get<SearchNumbersResult>(`/api/v1/numbers/search?${q}`);\n }\n\n /**\n * Buy a number for a service + country. The server picks the best available\n * candidate by Health Score automatically -- there's no numberId parameter,\n * since by the time you'd pass one back the number may already be gone.\n */\n purchase(params: PurchaseNumberParams): Promise<PurchaseResult> {\n return this.http.post<PurchaseResult>(\"/api/v1/numbers/purchase\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { InitiatePaymentParams, PaymentInitResult } from \"../types.js\";\n\nexport class Payment {\n constructor(private readonly http: HttpClient) {}\n\n /**\n * Initiate a wallet top-up payment. The response varies by provider:\n * - OPay / Flutterwave / Paystack → redirect to `checkoutUrl`\n * - Stripe → use `clientSecret` with the Stripe.js embedded element\n * - OPay USSD → display `ussdCode`\n * - Paystack DVA → show `virtualAccountNumber` / `virtualAccountBank`\n *\n * @example\n * const result = await vc.payment.initiate({\n * creditPackId: 'pack_100',\n * usdAmount: 10,\n * creditsToAdd: 100,\n * currency: 'NGN',\n * customerEmail: 'user@example.com',\n * });\n * if (result.checkoutUrl) window.location.href = result.checkoutUrl;\n */\n initiate(params: InitiatePaymentParams): Promise<PaymentInitResult> {\n return this.http.post<PaymentInitResult>(\"/api/v1/payment/initiate\", params);\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { SessionStatus } from \"../types.js\";\n\nexport class Sessions {\n constructor(private readonly http: HttpClient) {}\n\n /** Poll a session's current delivery status. */\n get(sessionToken: string): Promise<SessionStatus> {\n return this.http.get<SessionStatus>(`/api/v1/numbers/session/${encodeURIComponent(sessionToken)}`);\n }\n\n /**\n * Poll until the session reaches a terminal state (DELIVERED, REFUNDED, EXPIRED, FAILED)\n * or the timeout elapses. Prefer `vc.subscribe()` for real-time push -- this is a fallback\n * for environments where a persistent WebSocket isn't practical (e.g. serverless functions).\n */\n async waitForOtp(sessionToken: string, timeoutMs = 90_000, intervalMs = 2_000): Promise<SessionStatus> {\n const deadline = Date.now() + timeoutMs;\n for (;;) {\n const session = await this.get(sessionToken);\n if (session.status !== \"PENDING\") return session;\n if (Date.now() >= deadline) return session;\n await new Promise((resolve) => setTimeout(resolve, intervalMs));\n }\n }\n}\n","import type { HttpClient } from \"../client.js\";\nimport type { WalletBalance, WalletTransaction, WalletTransactionsResult } from \"../types.js\";\n\nexport class Wallet {\n constructor(private readonly http: HttpClient) {}\n\n /** Get the authenticated user's current wallet balance and today's auto-refund count. */\n balance(): Promise<WalletBalance> {\n return this.http.get<WalletBalance>(\"/api/v1/wallet/balance\");\n }\n\n /**\n * List wallet transactions (credits, debits, refunds) for the authenticated user.\n *\n * @example\n * const { transactions, total } = await vc.wallet.transactions({ page: 0, size: 20 })\n */\n transactions(params: { page?: number; size?: number } = {}): Promise<WalletTransactionsResult> {\n const q = new URLSearchParams();\n if (params.page != null) q.set(\"page\", String(params.page));\n if (params.size != null) q.set(\"size\", String(params.size));\n const qs = q.toString();\n return this.http.get<WalletTransactionsResult>(`/api/v1/wallet/transactions${qs ? `?${qs}` : \"\"}`);\n }\n}\n","import { Client } from \"@stomp/stompjs\";\nimport type { HttpClient } from \"./client.js\";\nimport type { OtpPush } from \"./types.js\";\n\n/**\n * Subscribes to real-time OTP push for a session over the gateway's WebSocket\n * proxy (wss://.../ws -> delivery-service's STOMP broker, topic\n * /topic/otp/{sessionToken}). Requires a global WebSocket implementation --\n * present natively in browsers and Node 22+; on older Node, pass a `ws`\n * instance via globalThis.WebSocket before calling subscribe().\n *\n * Returns an unsubscribe function. The callback fires at most once per\n * session (a session only ever delivers one OTP).\n */\nexport function subscribe(http: HttpClient, sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n if (typeof WebSocket === \"undefined\") {\n throw new Error(\n \"Verixo.subscribe() requires a global WebSocket implementation. \" +\n \"This is built into browsers and Node 22+; on older Node, polyfill \" +\n \"globalThis.WebSocket (e.g. with the 'ws' package) before calling subscribe().\"\n );\n }\n\n const subscribedAt = Date.now();\n const client = new Client({\n brokerURL: `${http.wsOrigin}/ws`,\n reconnectDelay: 5_000,\n onConnect: () => {\n client.subscribe(`/topic/otp/${sessionToken}`, (message) => {\n try {\n const payload = JSON.parse(message.body) as Omit<OtpPush, \"latencyMs\">;\n onOtp({ ...payload, latencyMs: Date.now() - subscribedAt });\n } catch {\n // Ignore malformed frames rather than crashing the caller's process.\n }\n });\n },\n });\n\n client.activate();\n return () => {\n void client.deactivate();\n };\n}\n","import { HttpClient } from \"./client.js\";\nimport { Analytics } from \"./resources/analytics.js\";\nimport { CallPlans } from \"./resources/call_plans.js\";\nimport { ESim } from \"./resources/esim.js\";\nimport { Numbers } from \"./resources/numbers.js\";\nimport { Payment } from \"./resources/payment.js\";\nimport { Sessions } from \"./resources/sessions.js\";\nimport { Wallet } from \"./resources/wallet.js\";\nimport { subscribe } from \"./subscribe.js\";\nimport type { OtpPush, VerixoOptions } from \"./types.js\";\n\nexport { VerixoError } from \"./errors.js\";\nexport type {\n CallPlan,\n CallPlanSubscription,\n DeliveryRate,\n ESimPackage,\n ESimProfile,\n ESimPurchaseParams,\n ESimUsage,\n InitiatePaymentParams,\n OtpPush,\n PaymentInitResult,\n PurchaseBundleParams,\n PurchaseNumberParams,\n PurchaseResult,\n SearchNumbersParams,\n SearchNumbersResult,\n SessionState,\n SessionStatus,\n SpecialPackage,\n SpecialPackageOrder,\n SubscribeCallPlanParams,\n VerixoOptions,\n VirtualNumber,\n WalletBalance,\n WalletTransaction,\n WalletTransactionsResult,\n} from \"./types.js\";\n\nexport default class Verixo {\n readonly numbers: Numbers;\n readonly sessions: Sessions;\n readonly analytics: Analytics;\n readonly esim: ESim;\n readonly callPlans: CallPlans;\n readonly payment: Payment;\n readonly wallet: Wallet;\n private readonly http: HttpClient;\n\n constructor(apiKey: string, options: VerixoOptions = {}) {\n this.http = new HttpClient(apiKey, options);\n this.numbers = new Numbers(this.http);\n this.sessions = new Sessions(this.http);\n this.analytics = new Analytics(this.http);\n this.esim = new ESim(this.http);\n this.callPlans = new CallPlans(this.http);\n this.payment = new Payment(this.http);\n this.wallet = new Wallet(this.http);\n }\n\n /**\n * Get pushed the OTP for a session in real time, instead of polling\n * `sessions.get()`. Returns an unsubscribe function.\n *\n * @example\n * const session = await vc.numbers.purchase({ serviceSlug: 'whatsapp', countryCode: 'NG' })\n * vc.subscribe(session.sessionToken, ({ otp, latencyMs }) => {\n * console.log(`OTP: ${otp} in ${latencyMs}ms`)\n * })\n */\n subscribe(sessionToken: string, onOtp: (push: OtpPush) => void): () => void {\n return subscribe(this.http, sessionToken, onOtp);\n }\n}\n"],"mappings":"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","names":[]}
|