UNPKG

@coinbase/cdp-sdk

Version:

SDK for interacting with the Coinbase Developer Platform Wallet API

116 lines • 4.81 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.SpendControlError = exports.SpendControlErrorCodes = void 0; exports.parseDuration = parseDuration; exports.parseAmount = parseAmount; /** * Typed string constants for every {@link SpendControlErrorCode} value. */ exports.SpendControlErrorCodes = { PER_PAYMENT_CAP: "per_payment_cap", CUMULATIVE_CAP: "cumulative_cap", ALREADY_APPLIED: "already_applied", CONFIGURATION_INVALID: "configuration_invalid", LEDGER_CAPACITY_EXCEEDED: "ledger_capacity_exceeded", NETWORK_NOT_ALLOWED: "network_not_allowed", ASSET_NOT_ALLOWED: "asset_not_allowed", PAYEE_NOT_ALLOWED: "payee_not_allowed", AMOUNT_UNPARSEABLE: "amount_unparseable", MALFORMED_REQUIREMENT: "malformed_requirement", MAX_TIMEOUT_EXCEEDED: "max_timeout_exceeded", }; /** * Thrown when a payment is blocked by the configured spend controls. */ class SpendControlError extends Error { /** - Identifies the type of violation. */ code; /** - Structured context for the error (always defined, may be empty). */ details; /** * Creates a SpendControlError with the given code and message. * * @param code - The error code identifying the violation type. * @param message - Human-readable error message. * @param details - Optional structured context for the error. */ constructor(code, message, details = {}) { super(message); this.name = "SpendControlError"; this.code = code; this.details = details; Object.setPrototypeOf(this, SpendControlError.prototype); } } exports.SpendControlError = SpendControlError; const MS_UNIT_FACTORS = { ms: 1, s: 1_000, m: 60 * 1_000, h: 60 * 60 * 1_000, d: 24 * 60 * 60 * 1_000, }; const DURATION_PATTERN = /^\s*(\d+(?:\.\d+)?)\s*(ms|s|m|h|d)\s*$/i; /** * Converts a {@link Duration} to milliseconds. * * Accepts a non-negative number (already in milliseconds) or a shorthand * string: `"500ms"`, `"30s"`, `"5m"`, `"1h"`, `"24h"`, `"7d"`. * * @param input - The duration value to parse. * @returns The duration in milliseconds. * @throws {SpendControlError} `"amount_unparseable"` if the input can't be parsed. */ function parseDuration(input) { if (typeof input === "number") { if (!Number.isFinite(input) || input < 0) { throw new SpendControlError("amount_unparseable", `Duration must be a non-negative finite number, received ${input}`, { input }); } return Math.floor(input); } const match = DURATION_PATTERN.exec(input); if (!match) { throw new SpendControlError("amount_unparseable", `Cannot parse duration ${JSON.stringify(input)}; expected e.g. "500ms", "30s", "5m", "1h", "24h", "7d"`, { input }); } const [, numericPart, unit] = match; const factor = MS_UNIT_FACTORS[unit.toLowerCase()]; return Math.floor(Number(numericPart) * factor); } const AMOUNT_SHORTHAND_PATTERN = /^([^:]+):(\d+)$/; /** * Parses an amount into `{ atomic: bigint; asset?: string }`. * * @param value - The amount value to parse (bigint, string, or Amount object). * @param asset - Optional asset identifier to scope the amount. * @returns Parsed amount with atomic bigint value and optional asset. * @throws {SpendControlError} `"amount_unparseable"` on bad input. */ function parseAmount(value, asset) { if (typeof value === "bigint") { if (value < 0n) { throw new SpendControlError("amount_unparseable", `Amount must be non-negative, got ${value}`, { input: value.toString() }); } return { atomic: value, asset }; } if (typeof value === "string") { const trimmed = value.trim(); if (trimmed === "") { throw new SpendControlError("amount_unparseable", "Amount string is empty", { input: value }); } const shorthand = AMOUNT_SHORTHAND_PATTERN.exec(trimmed); if (shorthand) { const [, parsedAsset, parsedAtomic] = shorthand; return parseAmount({ atomic: parsedAtomic, asset: parsedAsset }, asset ?? parsedAsset); } if (!/^\d+$/.test(trimmed)) { throw new SpendControlError("amount_unparseable", `Cannot parse amount ${JSON.stringify(value)}; expected a non-negative integer or an "<asset>:<atomic>" shorthand`, { input: value }); } return { atomic: BigInt(trimmed), asset }; } if (value && typeof value === "object" && "atomic" in value) { const innerAsset = asset ?? value.asset; return parseAmount(value.atomic, innerAsset); } throw new SpendControlError("amount_unparseable", `Cannot parse amount: unsupported value of type ${typeof value}`, { input: value }); } //# sourceMappingURL=types.js.map