Repository navigation
0.7.0
What a Laravel service provider or a Symfony bundle needs from this library: one entry point, and four things every adapter had been writing for itself. No framework code enters the core — the bridges (ledger-direct-laravel, ledger-direct-symfony) come as separate packages on top of this. Purely additive; the only new dependency is psr/clock ^1.0.
New: LedgerDirect, the composition root (#7)
Four adapters wire five services by hand. A fifth would have done it again, and every constructor change lands once per adapter. LedgerDirect::create() takes every port once — PSR-18/17 client and factories, PSR-3 logger, the two repository and config ports, an optional PSR-16 cache, an optional PSR-20 clock — and hands out every service, built lazily and memoised: priceService(), xrplClient(), syncService(), destinationTagService(), paymentIntentService(), settlementPolicy(), syncThrottle() (null without a cache) and paymentStatus($intent).
The services stay publicly constructible. The root is the only wiring the core promises to keep stable across releases. There is no static state and no facade — a facade belongs to the platform bridge that has a container to resolve it from.
New: PSR-20 clock
PaymentIntentService and PriceService take an optional ClockInterface, defaulting to Clock\SystemClock. PaymentStatus::fromIntent(?int $now) is unchanged. Symfony's MockClock and Laravel's frozen time now reach quote expiry and rate-cache freshness; the shipped FrozenClock does the same in plain PHPUnit, and InMemoryCache shares the clock of the service under test so advancing it ages both.
New: LedgerDirectException
One marker on the four runtime failures — PriceUnavailableException, XrplRpcException, AssetNotAcceptedException, DestinationTagsExhaustedException — so one catch in a platform's exception handler covers them. Deliberately not on the InvalidArgumentExceptions the value objects throw: those are programming errors, not conditions a running shop recovers from.
New: Xrpl\Schema
The DDL template INVARIANTS.md ("Tables") promised and never had. Schema::tables() describes both tables as data — columns, types, indexes — for a Laravel migration or a Doctrine table; Schema::mysql($prefix) is ready DDL for the MySQL platforms and reproduces the PrestaShop schema apart from prefix, engine and the primary key's name (id). The network column, the unique hash, the cursor index on (destination, network, ledger_index) and the unsigned destination_tag are all pinned by test.
New: Xrpl\SyncThrottle
The status-endpoint throttle, in the core instead of once per adapter: shouldSync() / markSynced() / syncIfDue(), over the same PSR-16 cache as the rate cache, keyed by network and account — the sync is per account, so throttling per order would still let every waiting customer trigger a node request. A broken cache degrades to "always sync", never to "never sync". INVARIANTS.md "Payment status" now says an adapter uses it or an equivalent.
New: src/Testing/ ships with the package
The fixtures that lived under tests/ — InMemoryXrplTransactionRepository, FakeHttpClient, FakeConfigProvider, InMemoryCache, RecordingLogger — plus FrozenClock and XrplTransactionRepositoryContractTestCase: the repository contract as a suite an adapter extends. Newest-first ordering with a total tie-break, the cursor scoped by account and network, the random counter start that is never 0 — each once cost an adapter a mis-settled or stranded order. PHPUnit stays a dev dependency plus a suggest; the in-memory repository passing the suite is what keeps the suite honest.
What adapters do with this
Nothing is required. Optionally: replace the hand-written service wiring with LedgerDirect::create(), use syncThrottle()?->syncIfDue() in the status endpoint, generate migrations from Schema, and run the repository implementation through the contract test. PrestaShop's ServiceFactory reduces to one call; its handover's throttle step now points at the core class.
Notes
179 tests, green on PHP 8.2 / 8.3 / 8.4 plus the lowest-dependency job. Contract details in INVARIANTS.md (introduction, "Tables", "Payment status"); wiring and testing kit in README.md.