@kaspacom/mpp-provider-runtime
v0.1.3
Published
Runnable provider settlement worker runtime for Kaspa MPP API payment channels.
Readme
@kaspacom/mpp-provider-runtime
Runnable settlement-worker wiring for Kaspa MPP provider servers.
This package is intentionally small: it connects the existing provider,
Postgres storage, and Kaspa settlement redeemer packages into an operator
process. HTTP route guarding still belongs in the provider application through
@kaspacom/mpp-provider.
The runtime can be used in two ways:
- imported and started inside an existing API server for simple same-server provider onboarding;
- run as
mpp-provider-settlement-workerin a sidecar/cron/second process for production key isolation.
Both modes use the same provider Postgres database.
Same-Server Mode
An existing API server can start the settlement loop directly:
import {
loadProviderRuntimeConfigFromEnv,
runProviderSettlementRuntime,
} from "@kaspacom/mpp-provider-runtime";
void runProviderSettlementRuntime(loadProviderRuntimeConfigFromEnv()).catch((error) => {
console.error(error);
process.exitCode = 1;
});This avoids a separate deployment, but the API process now has access to
MPP_PROVIDER_PRIVATE_KEY. Use the CLI/sidecar mode when the provider wants to
keep the signing key out of the HTTP process.
CLI
npx mpp-provider-settlement-worker --onceInspect read-only operator state without loading a provider key or Kaspa WASM:
MPP_DATABASE_URL=postgres://... \
npx mpp-provider-settlement-worker --inspect | jqList selected-route policies without loading a settlement key:
MPP_DATABASE_URL=postgres://... \
MPP_ROUTE_NETWORK_ID=testnet-10 \
MPP_ROUTE_ENABLED=true \
npx mpp-provider-settlement-worker --routes | jqInsert or update one route policy:
MPP_DATABASE_URL=postgres://... \
MPP_ROUTE_POLICY_ID=expensive-report \
MPP_ROUTE_ENABLED=true \
MPP_ROUTE_NETWORK_ID=testnet-10 \
MPP_ROUTE_METHOD=GET \
MPP_ROUTE_PATH=/api/expensive-report \
MPP_ROUTE_PRICING_ID=api.expensive-report.v1 \
MPP_ROUTE_AMOUNT_SOMPI=300000 \
MPP_ROUTE_PROVIDER_PUBKEY=<provider-pubkey> \
npx mpp-provider-settlement-worker --upsert-route-policyRequired environment:
MPP_DATABASE_URL=postgres://...
MPP_PROVIDER_PRIVATE_KEY=...
MPP_KASPA_WRPC_URL=wss://tn10-node.kaspa.com
MPP_NETWORK_ID=testnet-10Policy environment:
MPP_SETTLEMENT_INTERVAL_MS=60000
MPP_SETTLEMENT_MAX_ITERATIONS=1
MPP_SETTLEMENT_MIN_UNSETTLED_SOMPI=50000000
MPP_SETTLEMENT_MAX_VOUCHER_AGE_MS=300000
MPP_SETTLEMENT_REFUND_SAFETY_MARGIN_MS=600000
MPP_SETTLEMENT_FAIL_ON_REJECTED=true
MPP_SETTLEMENT_MIGRATE=true
MPP_INSPECT_LIMIT=50
MPP_ROUTE_POLICY_ID=expensive-report
MPP_ROUTE_NETWORK_ID=testnet-10
MPP_ROUTE_METHOD=GET
MPP_ROUTE_PATH=/api/expensive-report
MPP_ROUTE_PRICING_ID=api.expensive-report.v1
MPP_ROUTE_AMOUNT_SOMPI=300000
MPP_ROUTE_PROVIDER_PUBKEY=<provider-pubkey>
MPP_ROUTE_ENABLED=true
MPP_ROUTE_LABEL="GET /api/expensive-report"
MPP_ROUTE_ROLLOUT_STATE=enabled
MPP_ROUTE_REFUND_SAFETY_MARGIN_MS=3600000
MPP_ROUTE_METADATA_JSON='{"owner":"api-team"}'The worker runs migrations by default, selects settlement candidates from Postgres, signs the stored payer settlement artifact with the provider key, and submits the transaction through the configured Kaspa wRPC endpoint.
After a submit or rejection, the runtime updates Postgres settlement state so a
later interval does not keep retrying the same artifact. Submitted channels move
to settlement_pending; rejected channels move to settlement_rejected.
--inspect prints channels, route policy rows, settlement authorization rows,
and current settlement candidates. --routes is a narrower route-policy view,
and --upsert-route-policy lets operators enable or disable one selected paid
route without editing application code.
The runtime loads its bundled TOC Kaspa WASM module by default. Providers only
need MPP_KASPA_RUNTIME_MODULE when they want to override that default with a
different network-specific or vendored Kaspa WASM build. A custom module must export an
already initialized runtime object containing PrivateKey, ScriptBuilder,
SighashType, Transaction, createInputSignature, and optionally
RpcClient/Encoding.
The bundled runtime is kaspa-wasm 1.1.1-toc.1 from rusty-kaspa, included
under vendor/kaspa-wasm-toc/ with its ISC license and package metadata.
Example wrapper:
import { readFileSync } from "node:fs";
import kaspa from "./kaspa/kaspa.js";
await kaspa.default({ module_or_path: readFileSync("./kaspa/kaspa_bg.wasm") });
export default kaspa;Logs are compact JSON and do not include private keys or payment credentials.
