run402-mcp
Version:
MCP server for Run402 — full-stack backend infrastructure for AI agents: Postgres, auth, storage, serverless functions and atomic deploys. Paid with x402/MPP. Includes $0.03 image generation.
54 lines • 2.43 kB
JavaScript
/**
* `vouchers` namespace — redeem a promo code into the organization's allowance.
*
* A promo code adds to your organization's allowance, which spends like any
* other allowance: a tier purchase settles from it with no on-chain payment.
*
* Two properties make this safe to call from anywhere in an agent's lifecycle:
*
* - **Order does not matter.** Redemption works as the very first authenticated
* call a brand-new wallet makes (the organization is provisioned on demand),
* or long after `run402 init`. There is no init-before-redeem requirement.
* - **Retrying is safe.** A repeat by the same organization returns the ORIGINAL
* result with `already_redeemed: true` and never adds twice, so a call that
* times out client-side can simply be re-issued.
*
* This namespace is deliberately thin and semantically blind: it forwards an
* opaque code string to one gateway route. It does not know what a code means,
* where it came from, or who issued it. Minting is not an agent operation —
* it needs a registered issuer key that no tenant holds.
*/
import { assertNonEmptyString } from "../validation.js";
export class Vouchers {
client;
/** Alias of {@link redeem}. */
redeemCode;
constructor(client) {
this.client = client;
this.redeemCode = this.redeem.bind(this);
}
/**
* Redeem a promo code into the authenticated wallet's organization.
*
* The code is sent verbatim — the gateway owns the grammar and is forgiving
* about it (case-insensitive, hyphens optional, and the Crockford
* confusables `O`→`0` / `I`,`L`→`1` are mapped), so a client-side format
* check would only invent ways to reject a code the server would have
* accepted.
*
* Requires wallet (SIWX) auth. Errors carry the canonical envelope:
* `VOUCHER_NOT_FOUND` (404 — unknown *or* malformed, deliberately
* indistinguishable), `VOUCHER_EXPIRED` (410), `VOUCHER_ALREADY_REDEEMED`
* (409 — a different organization got there first), `PROMO_LIMIT_REACHED`
* (403), `RATE_LIMITED` (429).
*/
async redeem(code) {
assertNonEmptyString(code, "code", "redeeming a promo code");
return this.client.request("/vouchers/v1/redemptions", {
method: "POST",
body: { code },
context: "redeeming a promo code",
});
}
}
//# sourceMappingURL=vouchers.js.map