From 7a4633349c699ebc406be2c98dafd308866e3c01 Mon Sep 17 00:00:00 2001 From: angelTomo9 <144371630+angelTomo9@users.noreply.github.com> Date: Tue, 25 Aug 2026 06:00:55 +0200 Subject: [PATCH] feat(pricing): implement 4-tier pricing engine and migration (#1) --- migrations/add_tiered_pricing.sql | 4 +--- src/pricing/tier-engine.ts | 19 ++----------------- tests/pricing.test.ts | 29 +++++++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 20 deletions(-) create mode 100644 tests/pricing.test.ts diff --git a/migrations/add_tiered_pricing.sql b/migrations/add_tiered_pricing.sql index 39ead0c..6813836 100644 --- a/migrations/add_tiered_pricing.sql +++ b/migrations/add_tiered_pricing.sql @@ -1,6 +1,4 @@ --- Migration: Add tiered pricing support (Issue #1) --- Idempotent: safe to run multiple times - +-- Migration: Add tiered pricing support (Issue #1) ALTER TABLE IF EXISTS x402_calls ADD COLUMN IF NOT EXISTS tier TEXT DEFAULT 'standard' CHECK (tier IN ('free', 'standard', 'premium', 'priority')), ADD COLUMN IF NOT EXISTS price_per_call NUMERIC(10, 6) DEFAULT 0.01, diff --git a/src/pricing/tier-engine.ts b/src/pricing/tier-engine.ts index 45118fe..802685f 100644 --- a/src/pricing/tier-engine.ts +++ b/src/pricing/tier-engine.ts @@ -1,9 +1,4 @@ -/** - * Tiered Pricing Engine — Issue #1 - * Implements 4-tier pricing for x402 API calls - */ - -export type Tier = 'free' | 'standard' | 'premium' | 'priority'; +export type Tier = 'free' | 'standard' | 'premium' | 'priority'; export interface TierResult { tier: Tier; @@ -11,13 +6,6 @@ export interface TierResult { callsInTier: number; } -/** - * Returns the price per call based on total call count and priority flag. - * - Tier 1 (Free): calls 1–50 → $0.00 - * - Tier 2 (Standard): calls 51–500 → $0.01 - * - Tier 3 (Premium): calls 500+ → $0.03 - * - Tier 4 (Priority): priority=true → $0.10 - */ export function getTierPrice(callCount: number, priorityFlag = false): TierResult { if (priorityFlag) { return { tier: 'priority', pricePerCall: 0.10, callsInTier: 1 }; @@ -31,13 +19,10 @@ export function getTierPrice(callCount: number, priorityFlag = false): TierResul return { tier: 'premium', pricePerCall: 0.03, callsInTier: Infinity }; } -/** - * Calculates total cost for a batch of calls. - */ export function calculateBatchCost(startCount: number, numCalls: number, priority = false): number { let total = 0; for (let i = 0; i < numCalls; i++) { total += getTierPrice(startCount + i, priority).pricePerCall; } - return Math.round(total * 1e6) / 1e6; // round to 6 decimals (USDC precision) + return Math.round(total * 1e6) / 1e6; } diff --git a/tests/pricing.test.ts b/tests/pricing.test.ts new file mode 100644 index 0000000..8dfb00a --- /dev/null +++ b/tests/pricing.test.ts @@ -0,0 +1,29 @@ +import { assertEquals } from 'https://deno.land/std@0.224.0/assert/mod.ts'; +import { getTierPrice, calculateBatchCost } from '../src/pricing/tier-engine.ts'; + +Deno.test('Tier 1: free for first 50 calls', () => { + assertEquals(getTierPrice(1).tier, 'free'); + assertEquals(getTierPrice(50).tier, 'free'); + assertEquals(getTierPrice(1).pricePerCall, 0.00); +}); + +Deno.test('Tier 2: standard for calls 51-500', () => { + assertEquals(getTierPrice(51).tier, 'standard'); + assertEquals(getTierPrice(500).tier, 'standard'); + assertEquals(getTierPrice(51).pricePerCall, 0.01); +}); + +Deno.test('Tier 3: premium for calls 500+', () => { + assertEquals(getTierPrice(501).tier, 'premium'); + assertEquals(getTierPrice(501).pricePerCall, 0.03); +}); + +Deno.test('Tier 4: priority flag overrides all', () => { + assertEquals(getTierPrice(1, true).tier, 'priority'); + assertEquals(getTierPrice(1000, true).pricePerCall, 0.10); +}); + +Deno.test('Batch cost calculation', () => { + assertEquals(calculateBatchCost(1, 10), 0); + assertEquals(calculateBatchCost(51, 1), 0.01); +});