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.buildCreatePlan
Creates a new subscription plan on-chain.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,
});
| Parameter | Type | Required | Description |
|---|
merchant | string | Yes | Stellar address of the merchant receiving payments |
token | string | Yes | 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 |
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: 2592000) |
Returns: Promise<string> - Assembled XDR transaction string.
buildSubscribe
Subscribes a user to a plan. This also sets the SEP-41 token allowance in a single transaction.const xdr = await client.buildSubscribe(
"GSUBSCRIBER...ADDR",
42
);
| Parameter | Type | Required | Description |
|---|
subscriber | string | Yes | Stellar address of the subscriber |
planId | number | Yes | ID of the plan to subscribe to |
Returns: Promise<string> - Assembled XDR transaction string.
buildCharge
Charges a subscription for the current billing period. This is permissionless - anyone can call it.const xdr = await client.buildCharge(
"GCALLER...ADDR",
101
);
| Parameter | Type | Required | Description |
|---|
callerAddress | string | Yes | Stellar address of the caller (pays the tx fee) |
subId | number | Yes | Subscription ID to charge |
Returns: Promise<string> - Assembled XDR transaction string.
buildCancel
Cancels a subscription. Can be called by either the subscriber or the merchant.const xdr = await client.buildCancel(
"GSUBSCRIBER...ADDR",
101
);
| Parameter | Type | Required | Description |
|---|
caller | string | Yes | Stellar address of the subscriber or merchant |
subId | number | Yes | Subscription ID to cancel |
Returns: Promise<string> - Assembled XDR transaction string.
buildRefund
Issues a refund from the merchant to the subscriber.const xdr = await client.buildRefund(
"GMERCHANT...ADDR",
101,
toStroops("9.99")
);
| Parameter | Type | Required | Description |
|---|
merchantAddress | string | Yes | Stellar address of the merchant issuing the refund |
subId | number | Yes | Subscription ID to refund |
amount | bigint | Yes | Refund amount in stroops |
Returns: Promise<string> - Assembled XDR transaction string.
buildUpdatePlanAmount
Updates the billing amount for an existing plan. The new amount must not exceed the plan’s price ceiling.const xdr = await client.buildUpdatePlanAmount(
"GMERCHANT...ADDR",
42,
toStroops("12.99")
);
| Parameter | Type | Required | Description |
|---|
merchantAddress | string | Yes | Stellar address of the plan’s merchant |
planId | number | Yes | Plan ID to update |
newAmount | bigint | Yes | New amount per period in stroops |
Returns: Promise<string> - Assembled XDR transaction string.The new amount cannot exceed the plan’s priceCeiling. This protects subscribers from unexpected price increases beyond what they originally authorized.
buildRequestMigration
Requests migration of all subscribers from one plan to another. Subscribers must accept individually.const xdr = await client.buildRequestMigration(
"GMERCHANT...ADDR",
42, // old plan ID
43 // new plan ID
);
| Parameter | Type | Required | Description |
|---|
merchant | string | Yes | Stellar address of the merchant |
oldPlanId | number | Yes | Plan ID to migrate from |
newPlanId | number | Yes | Plan ID to migrate to |
Returns: Promise<string> - Assembled XDR transaction string.
buildAcceptMigration
Accepts a pending migration for a subscription. Called by the subscriber.const xdr = await client.buildAcceptMigration(
"GSUBSCRIBER...ADDR",
101
);
| Parameter | Type | Required | Description |
|---|
subscriber | string | Yes | Stellar address of the subscriber |
subId | number | Yes | Subscription ID to migrate |
Returns: Promise<string> - Assembled XDR transaction string.
buildRejectMigration
Rejects a pending migration for a subscription. Called by the subscriber.const xdr = await client.buildRejectMigration(
"GSUBSCRIBER...ADDR",
101
);
| Parameter | Type | Required | Description |
|---|
subscriber | string | Yes | Stellar address of the subscriber |
subId | number | Yes | Subscription ID whose migration to reject |
Returns: Promise<string> - Assembled XDR transaction string.
buildReactivate
Reactivates a paused subscription. Called by the subscriber.const xdr = await client.buildReactivate(
"GSUBSCRIBER...ADDR",
101
);
| Parameter | Type | Required | Description |
|---|
subscriber | string | Yes | Stellar address of the subscriber |
subId | number | Yes | Subscription ID to reactivate |
Returns: Promise<string> - Assembled XDR transaction string. submitTransaction
Submits a signed XDR transaction to the Stellar network and waits for confirmation.// 1. Build the transaction
const xdr = await client.buildSubscribe("GSUB...ADDR", 42);
// 2. Sign with your wallet
const signedXdr = await wallet.signTransaction(xdr);
// 3. Submit and wait for result
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)
| Parameter | Type | Required | Description |
|---|
signedXdr | string | Yes | Signed XDR transaction string |
Returns: Promise<TransactionResult>interface TransactionResult {
hash: string; // Stellar transaction hash
success: boolean; // Whether the transaction succeeded
returnValue?: unknown; // Parsed return value from the contract
}
The typical flow is: build (VowenaClient) → sign (your wallet) → submit (VowenaClient). The SDK never touches private keys.