Installation

npm install @crossprotocolorg/sdk

CrossProvider

import { CrossProvider } from "@crossprotocolorg/sdk";

const cross = new CrossProvider(config: CrossProviderConfig);

CrossProviderConfig

Option Type Required Description
wallet Keypair \| Signer Yes Provider’s Robinhood Chain wallet
apiKey string Yes Cross API key from the Dashboard
network "mainnet" \| "devnet" Yes Robinhood Chain network
rpcUrl string No Custom Robinhood Chain RPC endpoint
facilitatorUrl string No Custom Facilitator URL
webhookSecret string No Secret for verifying incoming webhook signatures

Methods

cross.createPlan()

Creates a Plan account on the Cross Plan Registry. Immutable after creation.

const plan = await cross.createPlan(options: CreatePlanOptions): Promise<Plan>

CreatePlanOptions

Option Type Required Description
name string Yes Display name for the plan
amount number Yes Price per billing cycle, in token base units
interval BillingInterval Yes "MONTHLY" \| "WEEKLY" \| "DAILY" \| "PER_REQUEST"
token string No Token mint (default: USDC)
trialPeriodDays number No Free trial length in days
meteredOverage MeteredOverage No Usage-based overage billing config
const plan = await cross.createPlan({
  name: "API Pro",
  amount: 49_000_000,   // 49 USDC
  interval: "MONTHLY",
  trialPeriodDays: 7,
  meteredOverage: {
    unit: "1000 tokens",
    price: 2_000, // 0.002 USDC per 1k tokens
  },
});

console.log(plan.id); // PublicKey; persist this as your plan address

cross.deprecatePlan()

Marks a plan as deprecated so no new subscriptions can be created. Existing subscriptions continue.

await cross.deprecatePlan(options: { planId: string }): Promise<void>

cross.paymentGate()

Express/Node.js middleware that gates routes behind payment. Returns a 402 response to unauthenticated requests and passes through requests with valid payment proofs or active subscriptions.

app.use("/api/v1", cross.paymentGate(options: PaymentGateOptions))

PaymentGateOptions

Option Type Required Description
pricing PricingRule[] Yes Payment options to offer
onSuccess function No Callback after successful verification. Receives (req, paymentInfo).
onFailure function No Callback for failed verifications

PricingRule is one of:

{ type: "subscription"; plan: string }
{ type: "one-time"; amount: number; token?: string }
app.use("/api/v1", cross.paymentGate({
  pricing: [
    { type: "subscription", plan: plan.id },
    { type: "one-time", amount: 500_000 },
  ],
  onSuccess: (req, info) => {
    req.paymentInfo = info; // attach to request for downstream handlers
  },
}));

The middleware adds a req.payment object to authenticated requests with the payment details (subscription ID, wallet address, payment proof, etc.).


cross.verifySubscription()

Verifies that a wallet has an active subscription to a plan.

const valid = await cross.verifySubscription(options: {
  subscriber: string;
  plan: string;
}): Promise<boolean>
const isActive = await cross.verifySubscription({
  subscriber: req.headers["x-wallet-address"],
  plan: plan.id,
});

cross.verifyPaymentProof()

Verifies a payment proof from the X-PAYMENT header.

const result = await cross.verifyPaymentProof(
  proof: string
): Promise<PaymentProofResult>

PaymentProofResult

Field Type Description
valid boolean Whether the proof is valid
txSignature string On-chain transaction signature
amount number Amount paid, in base units
payer string Payer wallet address
memo string Memo from the original payment request

cross.buildPaymentRequired()

Constructs a properly formatted 402 Payment Required response body.

const body = cross.buildPaymentRequired(options: {
  pricing: PricingRule[];
  memo?: string;
}): PaymentRequiredResponse

Useful if you are not using the paymentGate middleware:

app.get("/api/v1/data", async (req, res) => {
  const proof = req.headers["x-payment"];

  if (!proof) {
    return res.status(402).json(cross.buildPaymentRequired({
      pricing: [{ type: "subscription", plan: plan.id }],
    }));
  }

  const result = await cross.verifyPaymentProof(proof);
  if (!result.valid) {
    return res.status(402).json(cross.buildPaymentRequired({
      pricing: [{ type: "subscription", plan: plan.id }],
    }));
  }

  res.json({ data: "..." });
});

cross.collectAll()

Triggers collection for all active subscribers on a plan. Typically called from a cron job or scheduled task.

const result = await cross.collectAll(options: {
  plan: string;
  dryRun?: boolean;
}): Promise<CollectResult>

CollectResult

Field Type Description
collected number Number of successful collections
failed number Number of failed collections
totalAmount number Total USDC collected, in base units
failures CollectFailure[] Details on each failure

cross.collect()

Triggers collection for a single subscription.

await cross.collect(options: { subscriptionId: string }): Promise<CollectResult>

cross.listSubscribers()

Returns all subscribers to a plan.

const subscribers = await cross.listSubscribers(options: {
  plan: string;
  status?: SubscriptionStatus;
}): Promise<Subscription[]>

cross.deductAllowance()

Draws down against a subscriber’s allowance. Used for metered billing.

const result = await cross.deductAllowance(options: {
  allowanceId: string;
  amount: number;
  memo?: string;
}): Promise<{ remaining: number; txSignature: string }>

cross.parseWebhookPayload()

Parses and verifies an incoming webhook payload. See Webhooks.

const event = cross.parseWebhookPayload(options: {
  payload: string;
  signature: string;
}): WebhookEvent