> ## Documentation Index
> Fetch the complete documentation index at: https://vowena-dependabot-github-actions-actions-checkout-7.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# VowenaClient Reference

> Complete API reference for VowenaClient. Every write method, read method, and submit function with signatures, parameters, and TypeScript examples.

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.

```typescript theme={null}
import { VowenaClient, NETWORKS } from "@vowena/sdk";

const client = new VowenaClient({
  contractId: NETWORKS.testnet.contractId,
  rpcUrl: NETWORKS.testnet.rpcUrl,
  networkPassphrase: NETWORKS.testnet.networkPassphrase,
});
```

Switch `testnet` → `mainnet` on `NETWORKS` when Vowena deploys to Stellar mainnet.

***

<Tabs>
  <Tab title="Write Methods">
    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.

    ```typescript theme={null}
    const xdr = await client.buildCreateProject({
      merchant: "GMERCHANT...ADDR",
      name: "Acme SaaS",
      description: "Recurring billing for Acme's hosted product.",
    });
    ```

    | Parameter     | Type     | Required | Description                               |
    | ------------- | -------- | -------- | ----------------------------------------- |
    | `merchant`    | `string` | Yes      | Stellar address of the merchant           |
    | `name`        | `string` | Yes      | Human-readable project name               |
    | `description` | `string` | No       | Longer description shown in the dashboard |

    **Returns:** `Promise<string>` — assembled XDR.

    ***

    ## buildCreatePlan

    Creates a new subscription plan inside an existing project.

    ```typescript theme={null}
    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,
    });
    ```

    | Parameter      | Type     | Required | Description                                                     |
    | -------------- | -------- | -------- | --------------------------------------------------------------- |
    | `merchant`     | `string` | Yes      | Stellar address of the merchant receiving payments              |
    | `token`        | `string` | Yes      | SEP-41 token contract address (e.g. USDC)                       |
    | `amount`       | `bigint` | Yes      | Amount per billing period in stroops                            |
    | `period`       | `number` | Yes      | Billing period duration in seconds                              |
    | `priceCeiling` | `bigint` | Yes      | Maximum amount the plan can ever charge per period              |
    | `name`         | `string` | Yes      | Display name for the plan                                       |
    | `projectId`    | `number` | Yes      | Parent project ID                                               |
    | `trialPeriods` | `number` | No       | Number of free billing periods (default: 0)                     |
    | `maxPeriods`   | `number` | No       | Maximum billing periods, 0 = unlimited (default: 0)             |
    | `gracePeriod`  | `number` | No       | Grace 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.

    ```typescript theme={null}
    // 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,
      },
    );
    ```

    | Parameter               | Type     | Required | Description                                                               |
    | ----------------------- | -------- | -------- | ------------------------------------------------------------------------- |
    | `subscriber`            | `string` | Yes      | Stellar address of the subscriber                                         |
    | `planId`                | `number` | Yes      | Plan to subscribe to                                                      |
    | `opts.expirationLedger` | `number` | No       | Absolute ledger the allowance expires at. Defaults to current + 2,900,000 |
    | `opts.allowancePeriods` | `number` | No       | Number of periods the allowance should cover. Default 120                 |

    <Tip>
      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](/api-reference/subscribe)
      for the full explanation.
    </Tip>

    **Returns:** `Promise<string>` — assembled XDR.

    ***

    ## buildCharge

    Charges a subscription for the current billing period. Permissionless — anyone can call.

    ```typescript theme={null}
    const xdr = await client.buildCharge("GKEEPER...ADDR", 101);
    ```

    | Parameter       | Type     | Required | Description                  |
    | --------------- | -------- | -------- | ---------------------------- |
    | `callerAddress` | `string` | Yes      | Address that pays the tx fee |
    | `subId`         | `number` | Yes      | Subscription ID to charge    |

    ***

    ## buildCancel

    Cancels a subscription. Either the subscriber or the merchant can call.

    ```typescript theme={null}
    const xdr = await client.buildCancel("GSUBSCRIBER...ADDR", 101);
    ```

    ***

    ## buildRefund

    Issues a refund from the merchant to the subscriber.

    ```typescript theme={null}
    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.

    ```typescript theme={null}
    const xdr = await client.buildUpdatePlanAmount(
      "GMERCHANT...ADDR",
      42,
      toStroops("12.99"),
    );
    ```

    <Warning>
      The new amount cannot exceed `priceCeiling`. This protects subscribers from
      unexpected price increases beyond what they originally authorized.
    </Warning>

    ***

    ## buildRequestMigration

    Flags every active subscription on `oldPlanId` as "migration pending" to `newPlanId`. Subscribers must accept individually.

    ```typescript theme={null}
    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.

    ```typescript theme={null}
    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.

    ```typescript theme={null}
    const xdr = await client.buildRejectMigration("GSUBSCRIBER...ADDR", 101);
    ```

    ***

    ## buildReactivate

    Subscriber reactivates a paused subscription. Re-signs a new allowance and attempts an immediate charge.

    ```typescript theme={null}
    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.

    ```typescript theme={null}
    const xdr = await client.buildExtendTtl("GKEEPER...ADDR", 42, 101);
    ```
  </Tab>

  <Tab title="Read Methods">
    Read methods query on-chain state by simulating a contract call. They require a `callerAddress` (any valid Stellar address) for simulation context but don't create a transaction.

    ## getProject

    Fetches a project by ID.

    ```typescript theme={null}
    const project = await client.getProject(1, "GREAD...ADDR");
    console.log(project.name); // "Acme SaaS"
    ```

    Returns:

    ```typescript theme={null}
    interface Project {
      id: number;
      merchant: string;
      name: string;
      description: string;
      createdAt: number;
    }
    ```

    ***

    ## getMerchantProjects

    All project IDs owned by a merchant.

    ```typescript theme={null}
    const ids = await client.getMerchantProjects(
      "GMERCHANT...ADDR",
      "GREAD...ADDR",
    );
    ```

    ***

    ## getPlan

    Fetches a plan by ID.

    ```typescript theme={null}
    const plan = await client.getPlan(42, "GREAD...ADDR");
    console.log(plan.name, plan.amount, plan.projectId);
    ```

    Returns:

    ```typescript theme={null}
    interface Plan {
      id: number;
      merchant: string;
      token: string;
      amount: bigint;
      period: number;
      trialPeriods: number;
      maxPeriods: number;
      gracePeriod: number;
      priceCeiling: bigint;
      createdAt: number;
      active: boolean;
      name: string;
      projectId: number;
    }
    ```

    ***

    ## getSubscription

    Fetches a subscription by ID.

    ```typescript theme={null}
    const sub = await client.getSubscription(101, "GREAD...ADDR");
    console.log(sub.status, sub.periodsBilled, sub.nextBillingTime);
    ```

    Returns:

    ```typescript theme={null}
    interface Subscription {
      id: number;
      planId: number;
      subscriber: string;
      status: SubscriptionStatus;
      createdAt: number;
      periodsBilled: number;
      nextBillingTime: number;
      failedAt: number;
      migrationTarget: number;
      cancelledAt: number;
    }

    type SubscriptionStatus = "Active" | "Paused" | "Cancelled" | "Expired";
    ```

    ***

    ## getMerchantPlans

    All plan IDs owned by a merchant.

    ```typescript theme={null}
    const ids = await client.getMerchantPlans(
      "GMERCHANT...ADDR",
      "GREAD...ADDR",
    );
    ```

    ***

    ## getSubscriberSubscriptions

    All subscription IDs tied to a subscriber.

    ```typescript theme={null}
    const ids = await client.getSubscriberSubscriptions(
      "GSUBSCRIBER...ADDR",
      "GREAD...ADDR",
    );
    ```

    ***

    ## getPlanSubscribers

    All subscription IDs active on a plan.

    ```typescript theme={null}
    const ids = await client.getPlanSubscribers(42, "GREAD...ADDR");
    ```
  </Tab>

  <Tab title="Submit">
    ## submitTransaction

    Submits a signed XDR transaction to the Stellar network and waits for confirmation.

    ```typescript theme={null}
    const xdr = await client.buildSubscribe("GSUB...ADDR", 42);
    const signedXdr = await wallet.signTransaction(xdr);
    const result = await client.submitTransaction(signedXdr);

    console.log(result.hash);        // Transaction hash
    console.log(result.success);     // true if successful
    console.log(result.returnValue); // Contract return value (if any)
    ```

    Returns:

    ```typescript theme={null}
    interface TransactionResult {
      hash: string;
      success: boolean;
      returnValue?: unknown;
    }
    ```

    <Tip>
      Flow: **build** (VowenaClient) → **sign** (your wallet) → **submit**
      (VowenaClient). The SDK never touches private keys.
    </Tip>
  </Tab>
</Tabs>
