For the complete documentation index, see llms.txt. This page is also available as Markdown.

Campaigns & Pending SP

This guide walks through the operational lifecycle of a pSP campaign: create, issue, settle, clawback, recycle. For the conceptual model — why pSP exists, how budget recycling works — see Pending SP (pSP).

Lifecycle Mental Model

SP is the stable currency. pSP is conditional escrow.

  1. You create a campaign with an SP budget.

  2. You issue pSP to users.

  3. Users that meet the campaign condition (hold N days, perform action X) get their pSP settled into SP and delivered to a destination address.

  4. For pSP that goes unfulfilled, an admin explicitly clawbacks the balance back into the campaign budget. pSP does not auto-expire — it stays in the user's balance until an admin acts on it.

Each step is gated by a specific role. The role model lets you split operations across teams or partners — see Whitelist Management → Partner A → Partner B for the canonical delegation example.

Create a Campaign

Required authority: MANAGER_ROLE or CAMPAIGN_ADMIN_ROLE on the PSPVault. CAMPAIGN_ADMIN_ROLE is auto-granted to your deployer wallet. The caller automatically becomes a per-campaign admin on the campaign they create (which lets them later configure delegated minters and per-campaign whitelists without needing additional grants).

The on-chain createCampaign call takes:

createCampaign(
  bytes32 campaignId,
  uint256 spBudget,
  address[] settlementDestinations,
  address[] transferWhitelist,
  string metadata
)
Path
Where

Studio UI

/sp/pending → New campaign

SDK

pendingSPVault.createCampaign(campaignId, spBudget, settlementDestinations, transferWhitelist, metadata)

HTTP API

POST /studio/sdk/v1/tx/psp/create-campaign

spBudget must be funded — you transfer SP into the vault before or as part of campaign creation. Use pendingSPVault.fundCampaign(campaignId, amount) (HTTP: POST /studio/sdk/v1/tx/psp/fund-campaign) to top up an existing campaign.

Issue pSP

Authority to call mint(...) comes from any of:

  • MANAGER_ROLE on the PSPVault (no per-campaign limit, no budget limit beyond the campaign's spBudget).

  • ISSUING_ADMIN_ROLE on the PSPVault — broad: the holder can mint into any active campaign on this vault, budget-limited only.

  • Campaign admin status on a specific campaign — the campaign creator gets this automatically; additional admins can be added with setCampaignAdmin.

  • A per-campaign delegated minter configuration set via setMinter(campaignId, minter, limit, active=true) — scoped to one campaign with a hard limit. See Whitelist Management → Partner A → Partner B for the canonical scoped-delegation pattern.

Path
Where

Studio UI

Campaign detail → Issue pSP

SDK

pendingSPVault.mint(campaignId, to, amount, metadata)

HTTP API

POST /studio/sdk/v1/tx/psp/mint

Issuance is the high-frequency operation in a campaign. Most partners drive it from a backend service that watches user activity and calls mint(...) server-side via the SDK or HTTP API.

Settle pSP → SP

Required role: SETTLEMENT_ADMIN_ROLE. The destination must be on the campaign's settlement whitelist (see updateSettlementWhitelist).

Path
Where

Studio UI

Campaign detail → Settle

SDK

pendingSPVault.settle(holder, receiver, amount, campaignId, metadata)

HTTP API

POST /studio/sdk/v1/tx/psp/settle

Settlement converts pSP into SP and delivers it to the receiver address. Use the same address as the holder for direct claims, or a different address for redirect (e.g., to a custodian).

Clawback Unfulfilled pSP

pSP does not auto-expire. Issued pSP stays in a user's balance indefinitely until an admin explicitly settles it (converts to SP, sends to a destination) or clawbacks it (returns the underlying SP to the campaign budget).

To clawback unfulfilled pSP — typically at the end of a campaign window or for a user that didn't meet the qualifying condition — an admin calls expire(...):

Path
Where

Studio UI

Campaign detail → Clawback / Expire

SDK

pendingSPVault.expire(holder, amount, campaignId, metadata)

HTTP API

POST /studio/sdk/v1/tx/psp/expire

The clawed-back SP returns to the campaign budget. You can then issue new pSP from the recycled budget without depositing additional collateral.

Required role: SETTLEMENT_ADMIN_ROLE.

Per-Campaign Whitelists

Each campaign has its own settlement-destination whitelist (which addresses can receive settled SP) and transfer whitelist (which addresses can hold pSP for this campaign). Both are set at createCampaign time and can be amended afterward:

Operation
SDK
HTTP API

Update settlement whitelist

pendingSPVault.updateSettlementWhitelist(campaignId, account, allowed)

POST /studio/sdk/v1/tx/psp/update-settlement-whitelist

Update transfer whitelist

pendingSPVault.updateTransferWhitelist(campaignId, account, allowed)

POST /studio/sdk/v1/tx/psp/update-transfer-whitelist

These per-campaign whitelists are independent of mint authorisation, which comes from ISSUING_ADMIN_ROLE, per-campaign admin status, or a per-campaign delegated-minter config (setMinter). See the worked example in Whitelist Management for how to scope all three.

Required Roles by Step

Step
Authority required

Create campaign

MANAGER_ROLE or CAMPAIGN_ADMIN_ROLE (creator becomes per-campaign admin automatically)

Configure per-campaign minter / settlement / transfer whitelist

MANAGER_ROLE or per-campaign admin

Set additional campaign admins

MANAGER_ROLE or campaign creator

Issue pSP

One of: MANAGER_ROLE, ISSUING_ADMIN_ROLE, per-campaign admin, or active per-campaign delegated minter

Settle pSP → SP

MANAGER_ROLE or SETTLEMENT_ADMIN_ROLE

Clawback / expire

MANAGER_ROLE or SETTLEMENT_ADMIN_ROLE

Admin transfer between users

MANAGER_ROLE or TRANSFER_ADMIN_ROLE

Common Patterns

Pattern
Condition
Issue when
Settle when

Hold-and-release

Hold ≥ X SP for N days

User completes a target action

Hold duration validated on-chain

Swap-and-claim

Complete N swaps

User performs first swap

Nth swap confirmed

Event attendance

Attend N events

Pre-event registration

Attendance check-in

Spend-and-earn

Spend ≥ $X

Purchase confirmation

Refund window passes

Last updated