Are you an LLM? Read llms.txt for a summary of the docs, or llms-full.txt for the full context.
Skip to content

Savings Goals

Who it's for: Individuals saving toward a specific target — school fees, a business asset, a family event, or a down payment — who want their money to grow while it waits. Why it matters: Locking funds toward a named goal creates the discipline of a term deposit with the flexibility to bridge into a purchase the moment the goal matures.

Savings Goals let users lock cGHS for a defined period to meet a financial target — school fees, a phone, a car deposit. Funds earn yield inside the vault while locked. An optional early-exit penalty discourages premature withdrawal.

POST /goal/create

Request
{
  "userAddressId": "wallet-uuid",
  "userAddress": "0xabc...",
  "stablecoin": "0x3126627A607E730E3eCF9BbfFD67fa18Deaab846",
  "amount": "200000000",
  "lockUntil": 1757548800,
  "penaltyBps": 1000,
  "name": "School Fees 2025"
}
FieldConstraints
lockUntil> now + 30 days and < now + 3 years
penaltyBps02000 (max 20% early-exit penalty)
nameStored as bytes32 on-chain
amountInitial deposit in base units

Transaction batch: [approve(lendingDiamond, amount), createGoal(stablecoin, amount, lockUntil, penaltyBps, nameBytes32)]

Response
{ "id": "d1-uuid", "status": "pending" }

POST /goal/:goalId/topup

Add more funds to an active goal before it matures.

Request
{
  "userAddressId": "wallet-uuid",
  "userAddress": "0xabc...",
  "amount": "50000000"
}

POST /goal/:goalId/withdraw

Withdraw from a goal. Returns a preview of penalty before execution.

Response
{
  "id": "d1-uuid",
  "status": "pending",
  "preview": {
    "gross": "230000000",
    "penalty": "23000000",
    "net": "207000000",
    "isMature": false
  }
}

If isMature: true, penalty is 0 regardless of penaltyBps.


POST /goal/:goalId/buy

Use a matured savings goal as a down payment to trigger BNPL for a purchase. The goal assets fund the deposit and a lending pool covers the remainder in installments.

Request
{
  "userAddressId": "wallet-uuid",
  "userAddress": "0xabc...",
  "poolId": "1",
  "merchant": "0xmerchant...",
  "totalPrice": "500000000",
  "numInstallments": 6,
  "intervalSeconds": 2592000
}

Requires: goal must be matured (lockUntil passed), and totalPrice > goalAssets.


Read Endpoints

GET  /goal/:goalId              — goal state + current assets
GET  /goal/:goalId/preview      — { gross, penalty, net, isMature }
GET  /goal/user/:address        — all goals for a user