Skip to main content
The VowenaClient is the primary interface for interacting with the Vowena smart contract. Write methods return an assembled XDR string for wallet signing. Read methods query on-chain state directly through Soroban simulation.
import { VowenaClient, NETWORKS } from "@vowena/sdk";

const client = new VowenaClient({
  contractId: NETWORKS.testnet.contractId,
  rpcUrl: NETWORKS.testnet.rpcUrl,
  networkPassphrase: NETWORKS.testnet.networkPassphrase,
});
Switch testnetmainnet on NETWORKS when Vowena deploys to Stellar mainnet.
Write methods build and simulate a Soroban transaction, returning an assembled XDR string. You sign the XDR with your wallet and then call submitTransaction() to broadcast it.

buildCreateProject

Creates a Project on chain. Every plan must belong to a project, so this is the first call a merchant makes.
const xdr = await client.buildCreateProject({
  merchant: "GMERCHANT...ADDR",
  name: "Acme SaaS",
  description: "Recurring billing for Acme's hosted product.",
});
ParameterTypeRequiredDescription
merchantstringYesStellar address of the merchant
namestringYesHuman-readable project name
descriptionstringNoLonger description shown in the dashboard
Returns: Promise<string> — assembled XDR.

buildCreatePlan

Creates a new subscription plan inside an existing project.
const xdr = await client.buildCreatePlan({
  merchant: "GMERCHANT...ADDR",
  token: NETWORKS.testnet.usdcAddress,
  amount: toStroops("9.99"),
  period: 2_592_000,
  priceCeiling: toStroops("14.99"),
  trialPeriods: 1,
  maxPeriods: 0,
  gracePeriod: 259_200,
  name: "Pro",
  projectId: 1,
});
ParameterTypeRequiredDescription
merchantstringYesStellar address of the merchant receiving payments
tokenstringYesSEP-41 token contract address (e.g. USDC)
amountbigintYesAmount per billing period in stroops
periodnumberYesBilling period duration in seconds
priceCeilingbigintYesMaximum amount the plan can ever charge per period
namestringYesDisplay name for the plan
projectIdnumberYesParent project ID
trialPeriodsnumberNoNumber of free billing periods (default: 0)
maxPeriodsnumberNoMaximum billing periods, 0 = unlimited (default: 0)
gracePeriodnumberNoGrace period in seconds for failed charges (default: 2,592,000)
Returns: Promise<string> — assembled XDR.

buildSubscribe

Subscribes a user to a plan and sets the SEP-41 token allowance in a single transaction.
// Minimal — SDK picks safe defaults
const xdr = await client.buildSubscribe(
  "GSUBSCRIBER...ADDR",
  42,
);

// Explicit — caller-controlled allowance
const xdr = await client.buildSubscribe(
  "GSUBSCRIBER...ADDR",
  42,
  {
    expirationLedger: latest.sequence + 2_900_000,
    allowancePeriods: 24,
  },
);
ParameterTypeRequiredDescription
subscriberstringYesStellar address of the subscriber
planIdnumberYesPlan to subscribe to
opts.expirationLedgernumberNoAbsolute ledger the allowance expires at. Defaults to current + 2,900,000
opts.allowancePeriodsnumberNoNumber of periods the allowance should cover. Default 120
The expirationLedger and allowancePeriods are passed to the contract so the nested token.approve() auth entry is deterministic between simulation and submission. See the subscribe API reference for the full explanation.
Returns: Promise<string> — assembled XDR.

buildCharge

Charges a subscription for the current billing period. Permissionless — anyone can call.
const xdr = await client.buildCharge("GKEEPER...ADDR", 101);
ParameterTypeRequiredDescription
callerAddressstringYesAddress that pays the tx fee
subIdnumberYesSubscription ID to charge

buildCancel

Cancels a subscription. Either the subscriber or the merchant can call.
const xdr = await client.buildCancel("GSUBSCRIBER...ADDR", 101);

buildRefund

Issues a refund from the merchant to the subscriber.
const xdr = await client.buildRefund(
  "GMERCHANT...ADDR",
  101,
  toStroops("9.99"),
);

buildUpdatePlanAmount

Updates the billing amount for an existing plan. The new amount must stay within the plan’s price ceiling.
const xdr = await client.buildUpdatePlanAmount(
  "GMERCHANT...ADDR",
  42,
  toStroops("12.99"),
);
The new amount cannot exceed priceCeiling. This protects subscribers from unexpected price increases beyond what they originally authorized.

buildRequestMigration

Flags every active subscription on oldPlanId as “migration pending” to newPlanId. Subscribers must accept individually.
const xdr = await client.buildRequestMigration(
  "GMERCHANT...ADDR",
  42,  // old plan
  43,  // new plan
);

buildAcceptMigration

Subscriber accepts a pending migration. The contract cancels the old subscription, creates one on the new plan, and sets a new allowance — all in one tx.
const xdr = await client.buildAcceptMigration(
  "GSUBSCRIBER...ADDR",
  101,
  {
    expirationLedger: latest.sequence + 2_900_000,
    allowancePeriods: 24,
  },
);
The allowance options match buildSubscribe. If omitted, the SDK uses the same safe defaults.

buildRejectMigration

Subscriber rejects a pending migration. They stay on the old plan.
const xdr = await client.buildRejectMigration("GSUBSCRIBER...ADDR", 101);

buildReactivate

Subscriber reactivates a paused subscription. Re-signs a new allowance and attempts an immediate charge.
const xdr = await client.buildReactivate(
  "GSUBSCRIBER...ADDR",
  101,
  {
    expirationLedger: latest.sequence + 2_900_000,
    allowancePeriods: 24,
  },
);

buildExtendTtl

Permissionless TTL bump for a plan + subscription entry. Useful for keepers that want to keep long-lived state alive alongside their charge() calls.
const xdr = await client.buildExtendTtl("GKEEPER...ADDR", 42, 101);