Skip to content

chore: 6960 move the Hedera SDK into @guardian/hedera - #6961

Open
Pyatakov wants to merge 10 commits into
developfrom
chore/split-hedera-sdk
Open

Pyatakov wants to merge 10 commits into
developfrom
chore/split-hedera-sdk

Conversation

@Pyatakov

@Pyatakov Pyatakov commented Sep 21, 2026 •

Copy link
Copy Markdown
Contributor

Description

Move the code that needs the Hedera SDK out of @guardian/common into a new @guardian/hedera workspace. Seven services never talk to Hedera, but they installed the 179 MB SDK because common depended on it. Their installed size drops from 340.5 MB to 133.7–229.1 MB.

  • Add the @guardian/hedera workspace with the message, VC, DID and mock code. It depends on common, not the other way around
  • Use it in guardian-service, policy-service, worker-service, analytics-service and auth-service
  • Keep Environment and the MockType enums in common, so services that only read network settings do not need the SDK
  • Make @hiero-ledger/sdk a dev dependency of common, used only for type imports
  • Build @guardian/hedera in the Dockerfiles and CI workflows of the services that use it
  • Add .github/scripts/dep-closure-check.mjs and run it in CI after the build. It fails when a built workspace imports a package that its production install does not provide

The second part reduces what services load at startup. Services run under plain Node.js, so import '@guardian/common' loads everything the root barrel exports.

  • Inside common, import each symbol from the file that declares it, not from a barrel. This also fixes an import cycle that broke mq, secret-manager and wallet when imported alone
  • Load Wallet only when DatabaseServer.deletePolicyCredentials needs it, so the cloud secret-manager SDKs do not load with the database layer
  • Export every module of common as a subpath, for example @guardian/common/mq/nats-service. The root barrel stays as it is
  • Use these subpaths in the seven services above and in their test mocks

At startup these services now use 86.6–149.6 MB of memory instead of 196.5 MB. api-gateway drops from 205.0 MB to 132.3 MB. The five services that use @guardian/hedera still import the root barrel. For them the VC and BBS code sets the memory floor, so the change would save almost nothing.

Closes #6960

@Pyatakov Pyatakov self-assigned this Sep 21, 2026
@github-actions

github-actions Bot commented Sep 21, 2026 •

Copy link
Copy Markdown

Test Results

 33 files  ±0   66 suites  ±0   3m 14s ⏱️ -1s
 35 tests ±0   35 ✅ ±0  0 💤 ±0  0 ❌ ±0 
173 runs  ±0  173 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 14cc807. ± Comparison against base commit 4d17fff.

♻️ This comment has been updated with latest results.

@Pyatakov
Pyatakov force-pushed the chore/shrink-service-dependencies branch 4 times, most recently from 036c09d to d650359 Compare September 23, 2026 15:51
Base automatically changed from chore/shrink-service-dependencies to develop September 23, 2026 16:56
@Pyatakov
Pyatakov force-pushed the chore/split-hedera-sdk branch 6 times, most recently from b0f479a to 21de473 Compare September 24, 2026 15:35
@Pyatakov Pyatakov changed the title chore: move the Hedera SDK into @guardian/hedera chore: 6960 move the Hedera SDK into @guardian/hedera Sep 24, 2026
@Pyatakov
Pyatakov force-pushed the chore/split-hedera-sdk branch 6 times, most recently from 453cc82 to f65f6d8 Compare September 28, 2026 21:10
@Pyatakov
Pyatakov force-pushed the chore/split-hedera-sdk branch from f65f6d8 to e8576f0 Compare October 6, 2026 20:23
Every service installed @hiero-ledger/sdk because @guardian/common declared it, and a per-service production install is the union of the service's own dependencies and common's. The SDK is 179 MB, and seven of the twelve services never touch Hedera.

Move the SDK-dependent code into a new @guardian/hedera workspace that depends on common rather than the other way round, so common's own graph is free of the SDK:

- split timeout out of hedera-modules/utils into decorators/timeout
- keep Environment in common and move only createClient into @guardian/hedera as HederaClientFactory
- keep the MockType and MockEntityType enums in common as mock-types and move MockService, MockHelper and the event payloads to @guardian/hedera
- relocate the SDK-free document-loader base classes and DidURL into common/src/document-loader
- give DatabaseServer.saveVirtualMessage and PolicyImportExport a structural interface instead of a Message class and a VcHelper, so neither reaches into @guardian/hedera
- declare @guardian/hedera in the five services that use it and demote the SDK to a devDependency of common

api-gateway, logger-service, queue-service, notification-service, application-events, ai-service and topic-listener-service drop from 340.5 MB to 133.7 MB installed. common's own closure drops from 339.5 MB to 132.7 MB, and importing its root barrel costs 198.8 MB RSS instead of 303.0 MB.

Add the dep-closure-check script, which scans every built dist for imports the workspace's production closure does not provide.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Services run under plain node, so `import '@guardian/common'` loads
every module the root barrel reaches. Inside common, most modules
imported their siblings through barrels too, so a module as small as
settings-container loaded the whole helpers graph to get PinoLogger,
and mq, secret-manager and wallet could not be imported on their own:
each failed with "Cannot access 'NatsService' before initialization".

Point every import inside common at the module that declares the
symbol rather than at a barrel. That breaks the NatsService cycle and
makes each module cost only what it uses. Every module in dist now
imports in isolation, apart from two standalone scripts that run at
import time.

Load Wallet on demand in DatabaseServer.deletePolicyCredentials, its
only use there. The static import pulled the secret-manager subsystem
and its cloud SDKs into every service that touches the database;
DatabaseServer alone drops from 170.7 MB to 104.3 MB resident.

Export every module under dist as a subpath, so a service can import
exactly the module a symbol is declared in, e.g.
@guardian/common/mq/nats-service. Subsystem barrels are too coarse to
be the unit: OldSecretManager costs 105 MB on its own but 148 MB
through secret-manager/index, which loads every cloud provider. The
root barrel is unchanged.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
logger-service, queue-service, notification-service,
application-events, ai-service and topic-listener-service imported
everything from the @guardian/common root barrel, which loads the
whole package at startup. Import each symbol from the module that
declares it instead.

Loading exactly what each service imports now costs 88 to 150 MB
resident instead of the 198 MB the root barrel costs.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Import each @guardian/common symbol from the module that declares it rather than from the root barrel. Loading what api-gateway imports now costs 131.8 MB resident instead of 205.0 MB.

The esmock definitions keyed on '@guardian/common' stopped applying once the code under test imported subpaths, so they are keyed on the same subpaths now. Keys for modules a target does not import were already inert and are dropped.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Moving files out of common left several imports from
@guardian/common per file, which tslint rejects.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Services that import @guardian/hedera failed to compile in CI
because no workflow built it after common.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Repointing imports to @guardian/hedera and common subpaths
left some import lines over tslint's 360-character limit.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
The demo Dockerfile for auth-service missed the hedera
workspace, so build:demo could not resolve @guardian/hedera.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Services that use @guardian/hedera do not build unless it is
built after @guardian/common.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
Run scripts/dep-closure-check.mjs in CI, so a missing dependency fails the PR, not the service image.

Signed-off-by: Alex Piatakov <alex.piatakov@hashgraph.com>
@Pyatakov
Pyatakov force-pushed the chore/split-hedera-sdk branch from e8576f0 to 14cc807 Compare October 7, 2026 18:57
@Pyatakov
Pyatakov marked this pull request as ready for review October 7, 2026 18:58
@Pyatakov
Pyatakov requested review from a team as code owners October 7, 2026 18:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant