Skip to content

About

COMEBACKHERE Protocol - Tooling, scripts, ABIs and deployment

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Latest commit

 

History

771 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Project

Repository layout

Canonical source trees:

  • packages/contracts/ — smart contracts
  • packages/backend/ — backend services
  • packages/frontend/ — web frontend

Legacy tree migration (issue #951)

The top-level contracts/, backend/, and frontend/ directories are legacy trees scheduled for removal. All open pull requests that still modify these legacy paths must be migrated to the canonical packages/* paths before the legacy trees are deleted.

Migration checklist for open PRs:

  1. Identify every open PR whose diff touches contracts/, backend/, or frontend/.
  2. Rebase the PR onto the current default branch and port each changed file to its canonical replacement under packages/contracts/, packages/backend/, or packages/frontend/ (preserving the relative path within the tree).
  3. Drop any changes that only touch the legacy trees and have no canonical counterpart; note them in the PR description instead.
  4. Confirm the PR diff no longer references the legacy trees, then merge.

Acceptance: no open PR targets a tree scheduled for removal.

Typed API Client

The backend publishes an OpenAPI schema at docs/openapi.yaml. A typed client is generated from that schema so request and response types stay synchronized with the published API.

Generate the client

npm run generate:client

This regenerates the client into packages/api-client/ from docs/openapi.yaml. Do not edit generated files by hand — change the spec and regenerate.

CI staleness check

CI runs npm run generate:client and fails if the regenerated output differs from what is committed. If the check fails locally, regenerate and commit the result:

npm run generate:client
git add packages/api-client
git commit -m "chore: regenerate API client"

Consumer example

import { createClient } from "@comebackhere/api-client"

const client = createClient({
  baseUrl: "http://localhost:3000",
  apiKey: process.env.MERCHANT_API_KEY,
})

// Request and response types are derived from the OpenAPI schema.
const invoice = await client.createInvoice({
  token: "USDC",
  amount: 1000000,
  due_date: 1720000000,
})

console.log(invoice.invoice_id)

Full request/response shapes: docs/api-reference.md


Quickstart for Merchants

Handsoff notes

1. Create an invoice

curl -X POST http://localhost:3000/invoices \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $MERCHANT_API_KEY" \
  -d '{
    "token": "USDC",
    "amount": 1000000,
    "due_date": 1720000000
  }'

The response includes invoice_id — share this with your payer.

Full request/response shapes: docs/api-reference.md

2. Set up webhooks

Configure WEBHOOK_URL and WEBHOOK_SIGNING_SECRET in your environment so the backend can notify your system when payments land.

All outbound webhook POSTs are signed with HMAC-SHA256 over the exact raw body bytes. Verify the X-COMEBACKHERE-Signature header before processing:

import { createHmac, timingSafeEqual } from "crypto"

function verifyWebhook(rawBody: string, signature: string, secret: string): boolean {
  const expected = createHmac("sha256", secret).update(rawBody, "utf8").digest("hex")
  const expectedBuf = Buffer.from(expected, "hex")
  const actualBuf = Buffer.from(signature, "hex")

  // timingSafeEqual throws on a length mismatch, so reject short or
  // malformed signatures before comparing.
  if (expectedBuf.length !== actualBuf.length) return false
  return timingSafeEqual(expectedBuf, actualBuf)
}

The body-only digest is temporarily available as X-COMEBACKHERE-Legacy-Signature for one release while receivers migrate.

Webhook events and configuration: docs/api-reference.md

3. Minimal payment flow

Merchant            Backend              Payer
  |                   |                    |
  |-- create_invoice ->|                    |
  |                   |                    |
  |  (share invoice_id with payer)         |
  |                   |                    |
  |                   |<-- pay off-chain ---|
  |                   |                    |
  |<-- webhook POST --|                    |
  |  (settlement_executed)                 |

For the full end-to-end testnet walkthrough (funding accounts, deploying contracts, paying with USDC, and executing a settlement), see docs/TESTNET_ONBOARDING.md.

Rate limits apply to all API endpoints. See docs/rate-limits.md.


Seeded Local Testnet Merchant Walkthrough

This walkthrough seeds a repeatable merchant scenario (merchant, invoice, and settlement) against a local testnet so a clean environment can verify both the on-chain and backend state end to end.

Prerequisites

  • Docker and Docker Compose
  • Node.js 20+ and npm
  • A clean checkout (no prior local state)

1. Start a clean stack

# Tear down any previous state so the walkthrough is repeatable.
docker compose down -v

# Bring up the local testnet, backend, and dependencies.
docker compose up -d

Wait for the backend health check to pass:

curl -fsS http://localhost:3000/health

2. Seed the merchant scenario

The seed script provisions a deterministic merchant, funds its account, and creates a known invoice. It is idempotent — re-running it resets the scenario to the same known state.

npm run seed:testnet

This writes the seeded identifiers to .env.testnet (merchant API key, MERCHANT_ID, INVOICE_ID, and contract IDs). Source it for the steps below:

set -a && . ./.env.testnet && set +a

3. Create and pay the invoice

# Create the invoice (or reuse the seeded INVOICE_ID).
curl -X POST http://localhost:3000/invoices \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $MERCHANT_API_KEY" \
  -d '{"token":"USDC","amount":1000000,"due_date":1720000000}'

# Pay the invoice from the seeded payer account.
curl -X POST http://localhost:3000/invoices/$INVOICE_ID/pay \
  -H "Authorization: Bearer $MERCHANT_API_KEY"

4. Observe settlement

curl -fsS http://localhost:3000/invoices/$INVOICE_ID \
  -H "Authorization: Bearer $MERCHANT_API_KEY"

Expect status: "settled" and a populated settlement_tx_hash.

5. Verify expected state

Backend state (API/DB):

# Invoice is settled and linked to the seeded merchant.
curl -fsS http://localhost:3000/invoices/$INVOICE_ID \
  -H "Authorization: Bearer $MERCHANT_API_KEY" | jq '.status, .merchant_id'

# Confirm the settlement record exists in MongoDB.
docker compose exec mongo mongosh --quiet --eval \
  'db.settlements.findOne({invoice_id: "'"$INVOICE_ID"'"})'

On-chain state (contract/ledger):

# Confirm the invoice is marked paid on the invoice contract.
stellar contract invoke \
  --id "$INVOICE_CONTRACT_ID" \
  --network local \
  -- get_invoice --invoice_id "$INVOICE_ID"

# Confirm the treasury released funds to the merchant.
stellar contract invoke \
  --id "$TREASURY_CONTRACT_ID" \
  --network local \
  -- balance --account "$MERCHANT_ID"

A successful walkthrough shows the invoice paid on-chain, the merchant treasury balance increased by the invoice amount, and a matching settlement record in the backend.


Architecture

The diagram below illustrates the primary payment flow through the COMEBACKHERE Protocol.

sequenceDiagram
    participant Payer
    participant Merchant as Merchant Backend
    participant Invoice as Invoice Contract
    participant Treasury
    participant Compliance

    Payer->>Merchant: Initiate payment
    Merchant->>Invoice: create_invoice(amount, token)
    activate Invoice
    Invoice->>Treasury: deposit(amount)
    activate Treasury
    Treasury->>Payer: request authorization
    Payer->>Treasury: authorize & transfer
    Treasury->>Treasury: escrow tokens
    Treasury-->>Invoice: deposit confirmed
    deactivate Treasury
    Invoice->>Compliance: verify_payer()
    activate Compliance
    Compliance-->>Invoice: compliance status
    deactivate Compliance
    Invoice-->>Merchant: invoice_id
    deactivate Invoice

    Merchant->>Payer: payment link
    Payer->>Invoice: confirm_payment()
    activate Invoice
    Invoice->>Treasury: release(invoice_id)
    activate Treasury
    Treasury->>Treasury: transfer to merchant
    Treasury-->>Invoice: transfer confirmed
    deactivate Treasury
    Invoice-->>Merchant: payment confirmed
    deactivate Invoice

    Merchant->>Payer: receipt
Loading

Repository Structure

.
├── abis/          # Contract ABI files consumed by the backend
├── docs/          # Developer guides and deployment documentation
├── scripts/       # Deployment, verification, and utility scripts
└── tests/         # Workspace-level integration tests
Directory Description
abis/ Generated contract ABIs used by comebackhere-backend
scripts/ Deployment, verification, and ABI generation scripts
docs/ Technical documentation and deployment guides
tests/ Integration and workspace-level test suites

Local Development

Prerequisites

Before getting started, ensure you have:

  • Docker
  • Docker Compose

Required Environment Variables Checklist

Before starting the stack, ensure your local .env (or service-specific .env files) defines these required values:

Backend (comebackhere-backend or Docker backend)

Variable Required Default Description
SOROBAN_RPC_URL Yes http://localhost:8000/soroban/rpc Soroban RPC endpoint
INVOICE_CONTRACT_ID Yes* — Deployed invoice contract address (required when calling invoice routes)
TREASURY_CONTRACT_ID Yes* — Deployed treasury contract address (required when calling treasury routes)
USDC_CONTRACT_ID Yes* — USDC token contract address
SIGNER_SECRET_KEY Yes — Stellar secret key used for signing transactions
MONGODB_URI No mongodb://localhost:27017 MongoDB connection URI for indexer state
REDIS_URL No redis://localhost:6379 Redis connection URL for rate limiting & event channels
PORT No 3000 (host) / 3001 (Docker) HTTP server listen port

* Required at runtime when invoking the respective contract-backed endpoints.

Frontend (comebackhere-frontend or Docker frontend)

Variable Required Default Description
VITE_API_URL Yes http://localhost:3000 Backend API base URL
VITE_SOROBAN_RPC Yes http://localhost:8000/soroban/rpc Soroban RPC endpoint for wallet interactions
VITE_HORIZON_URL No http://localhost:8000 Horizon endpoint for account queries

Handsoff notes

  • #982: Add merchant API-key management to the frontend
  • #954: Version contract storage schemas and test migrations

About

COMEBACKHERE Protocol - Tooling, scripts, ABIs and deployment

Resources

Contributing

Security policy

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages