SDK integration
The ESM SDK gives applications one consistent interface for protocol operations, resolver calls, readiness, Fiber RPC, topology analysis, route checks, and deliberate payment execution.
Packages and imports
The monorepo exposes the protocol and SDK packages with TypeScript declarations. Import only the layer your application needs.
import {
createSignedOffer,
decodeOffer,
verifyOffer
} from "@fiber-offers/protocol";
import {
createOffer,
FiberOffersClient,
FiberPaymentClient,
FiberPaymentFlowClient,
FiberRecurringPaymentScheduler,
FiberTopologyClient
} from "@fiber-offers/sdk";
| Client | Use it for |
|---|---|
FiberOffersClient | Resolver offers, readiness, invoices, addresses, resolutions, webhooks, receipts, and reconciliation. |
FiberPaymentClient | Payer-side Fiber send_payment, dry-runs, and payment status calls. |
FiberPaymentFlowClient | The composed wallet path from readiness to invoice to route confidence to explicitly opted-in payment. |
FiberTopologyClient | Merchant and payer node pair inspection plus direct-channel diagnostics. |
FiberRecurringPaymentScheduler | Payer-owned capped approvals, due-cycle execution, retries, and revocation. |
JsonFileRecurringApprovalStore | Private durable approval storage for Node payer services through @fiber-offers/sdk/node. |
Durable recurring payments
import {
FiberRecurringPaymentScheduler,
JsonFileRecurringApprovalStore
} from "@fiber-offers/sdk/node";
const scheduler = new FiberRecurringPaymentScheduler({
resolverClient: resolver,
paymentFlow,
store: new JsonFileRecurringApprovalStore(".fiber-offers/payer-approvals.json"),
autoStart: true,
retryDelayMs: 30000
});
await scheduler.approve(offerId);
The scheduler remains in the payer trust boundary. Browser wallets can use WebStorageRecurringApprovalStore; merchant resolvers never receive payer payment credentials.
Merchant offer registration
import { createOffer, FiberOffersClient } from "@fiber-offers/sdk";
const created = await createOffer({
network: "testnet",
resolver_url: "https://resolver.example",
description: "Coffee checkout",
assets: [{ asset_type: "ckb", symbol: "CKB" }],
amount_min: "1000",
amount_max: "1000"
}, { fiberRpcUrl: "http://127.0.0.1:8227" });
const resolver = new FiberOffersClient({
resolverUrl: "https://resolver.example",
apiKey: process.env.RESOLVER_API_KEY
});
const registered = await resolver.registerOffer(created.offer, {
username: "coffee"
});
Keep created.offer_private_key_pem under merchant control. The resolver verifies that the signed node_id matches its configured Fiber node before registration and invoice minting.
Wallet readiness and invoice calls
const resolver = new FiberOffersClient({
resolverUrl: "https://resolver.example"
});
const offer = await resolver.resolveFiberAddress("coffee@example.com");
const request = {
amount: "1000",
asset: { asset_type: "ckb", symbol: "CKB" }
};
const readiness = await resolver.checkPayment(offer.offer_id, request);
if (!readiness.ready) {
throw new Error(readiness.summary);
}
const invoice = await resolver.requestInvoice(offer.offer_id, request, {
idempotencyKey: "checkout-order-42"
});
Use the resolution ID returned by invoice creation when retrieving receipts, status, or reconciliation. Do not create a new idempotency key when retrying the same network request.
Operator helpers
const created = await resolver.createWebhook(offerId, {
url: "https://merchant.example/webhooks/fiber",
events: ["invoice.paid", "invoice.failed"]
});
storeSecret(created.signing_secret); // Returned only now.
const subscriptions = await resolver.getWebhooks(offerId);
await resolver.testWebhook(offerId, created.id);
await resolver.updateWebhook(offerId, created.id, { disabled: true });
const rotated = await resolver.rotateWebhookSecret(offerId, created.id);
storeSecret(rotated.signing_secret);
const events = await resolver.getWebhookEvents(offerId);
const delivery = await resolver.deliverWebhookEvents(offerId, {
retryFailed: true
});
const updated = await resolver.syncResolutions(offerId, {
includeTerminal: false
});
const csv = await resolver.getReconciliationCsv(offerId);
These operations use the resolver's protected write endpoints when an API key is configured. Treat them as merchant or operator tasks, not wallet-facing payment actions.
Topology and payer helpers
const topology = new FiberTopologyClient({
merchant: "http://127.0.0.1:8227",
payer: "http://127.0.0.1:8229"
});
const report = await topology.inspectPair();
const payer = new FiberPaymentClient({
url: "http://127.0.0.1:8229"
});
const route = await payer.checkPaymentRoute(invoice.invoice, {
maxFeeAmount: 100000,
diagnostics: report.diagnostics
});
checkPaymentRoute performs a dry-run. Use sendPayment only after application confirmation logic has explicitly approved the payment.