@duabalabs/sellub-pricing
Pure-TypeScript pricing engine that powers Sellub’s commission/processor/VAT math. Same code path runs in the server, the dashboard and 3rd-party integrations so quotes match invoices.
Install
pnpm add @duabalabs/sellub-pricingModules
| Module | Exports |
|---|---|
plans | ALL_PLANS, PLAN_CATALOG, SellerPlan |
commission | resolveCommissionRate(plan, sellerOverride?) |
attribution | resolveAttributionSource(order, channel) |
fees | calculateOrderFees({ subtotal, plan, attribution, processorRate }) |
addons | ADDONS — extras like “custom domain”, “extra channel” |
currency | formatMinor(amount, currency), parseMinor(text, currency) |
education | Plan-tier helpers for educational content packs |
Everything is tree-shakeable — import only what you need.
Plan catalog
import { PLAN_CATALOG, SellerPlan } from "@duabalabs/sellub-pricing";
PLAN_CATALOG[SellerPlan.MARKETPLACE];
//=> { plan: 'MARKETPLACE', label: 'Marketplace', commissionPercent: 8, … }Resolve effective commission
import { resolveCommissionRate, SellerPlan } from "@duabalabs/sellub-pricing";
resolveCommissionRate(SellerPlan.CUSTOM_DOMAIN); // 5
resolveCommissionRate(SellerPlan.MARKETPLACE, /* override */ 6); // 6Quote checkout fees
import { calculateOrderFees } from "@duabalabs/sellub-pricing";
const quote = calculateOrderFees({
subtotalMinor: 50_000, // GHS 500
plan: "CUSTOM_DOMAIN",
attributionSource: "custom_domain",
processorRate: { percent: 1.95, capMinor: 200_00 }, // Paystack GHS card
});
quote.commissionMinor; // 2_500
quote.processorFeeMinor;// 975
quote.payoutMinor; // 46_525Attribution-aware billing
A “marketplace” plan that gets a sale from the seller’s own custom domain gets billed at custom-domain rates, not marketplace rates. The engine encodes those rules:
import { resolveAttributionSource } from "@duabalabs/sellub-pricing";
resolveAttributionSource({ channelToken: "nenaboateng" }, { plan: "CUSTOM_DOMAIN" });
//=> 'custom_domain'
resolveAttributionSource({ utm: { source: "sellub" } }, { plan: "MARKETPLACE" });
//=> 'marketplace'Format / parse minor units
import { formatMinor, parseMinor } from "@duabalabs/sellub-pricing";
formatMinor(50_00, "GHS"); // "GH₵ 50.00"
parseMinor("GH₵ 50", "GHS"); // 50_00Why this lives in npm (not the server)
The same math has three callers:
- The Sellub Vendure server (
sellub-pricing-plugin) — persists the breakdown. - The Sellub dashboard — quotes payouts before order placement.
- Your integration — quotes “you’ll be charged X commission” in your UI.
By shipping it on npm, all three stay in lock-step. Bumping this package is the single source of truth for a rate change.
Related
sellub-pricing-plugin— the server plugin that consumes this package and persists the resultingOrderFeeBreakdown.sellub-types—Cents/Moneytypes used here.