Load evo-sdk from CDN to reduce bundle size - #230
Conversation
- Add cdn-loader.ts to dynamically import evo-sdk from jsdelivr CDN - Update evo-sdk-service.ts to use CDN loader instead of bundled SDK - Update signer-service.ts, document-builder-service.ts, tip-service.ts to load SDK classes from CDN - Add modulepreload hint in layout.tsx for faster SDK loading - Update CSP in next.config.js to allow scripts from cdn.jsdelivr.net - Define local types for DocumentWhereClause/DocumentOrderByClause - Export WasmIdentityPublicKey type from signer-service.ts The SDK (~7.6MB) is now loaded from CDN instead of being bundled, which improves initial load times by leveraging CDN caching and reducing the main bundle size. https://claude.ai/code/session_015si4GM8oRDKC3bZfc1fBa5
|
Codex usage limits have been reached for code reviews. Please check with the admins of this repo to increase the limits by adding credits. |
|
🕓 Ready for review — 58 ahead in queue (commit 3e22c22) |
thepastaclaw
left a comment
There was a problem hiding this comment.
Preliminary review — Codex only
The CDN refactor introduces a runtime supply-chain boundary into private-key signing: code fetched from jsDelivr receives users' WIF keys without being authenticated against the lockfile or build artifact. The global module preload also fetches the 8,030,052-byte SDK on every exported route, defeating the intended on-demand transfer savings.
Validated blockers were found in the Codex precheck. Sonnet is deferred until a fresh Codex revalidation clears the blocker gate.
Review provenance
- Codex reviewers:
gpt-5.6-sol— general (failed),gpt-5.6-sol— general (failed),gpt-5.6-sol— general (failed),gpt-5.6-sol— general (failed),gpt-5.6-sol— general (completed) - Verifier:
gpt-5.6-sol— verifier - Sonnet: not run (deferred by blocker gate)
🔴 1 blocking | 🟡 1 suggestion(s)
🤖 Prompt for all review comments with AI agents
These findings are from an automated code review. Verify each finding against the current code and only fix it if needed.
In `lib/services/cdn-loader.ts`:
- [BLOCKING] lib/services/cdn-loader.ts:159: Do not execute CDN code in private-key signing flows
This dynamic import executes the response served by jsDelivr without verifying it against the dependency lockfile or another cryptographic integrity value. The imported `IdentitySigner` is passed users' WIF private keys by `signer-service.ts`, and the same remote module participates in identity updates and credit transfers. A compromised or incorrectly served response could therefore read and exfiltrate private keys or alter signed transitions. Pinning the package version prevents ordinary version drift but does not remove the new runtime trust in the CDN; bundle the lockfile-pinned dependency or serve an integrity-controlled first-party artifact instead.
In `app/layout.tsx`:
- [SUGGESTION] app/layout.tsx:32-38: Avoid preloading the SDK on every page
Placing this `modulepreload` in the root layout makes every initial route fetch and prepare the SDK, whether or not the user invokes a Platform-dependent workflow. The referenced module is 8,030,052 bytes, and the current static export contains this preload in all 36 generated HTML files. This negates the refactor's on-demand transfer benefit; remove the global hint or initiate preloading only when the user approaches a workflow that requires the SDK.
|
|
||
| // Dynamic import from CDN | ||
| // Note: This works because the SDK is published as an ES module | ||
| const sdkModule = await import(/* webpackIgnore: true */ EVO_SDK_URL); |
There was a problem hiding this comment.
🔴 Blocking: Do not execute CDN code in private-key signing flows
This dynamic import executes the response served by jsDelivr without verifying it against the dependency lockfile or another cryptographic integrity value. The imported IdentitySigner is passed users' WIF private keys by signer-service.ts, and the same remote module participates in identity updates and credit transfers. A compromised or incorrectly served response could therefore read and exfiltrate private keys or alter signed transitions. Pinning the package version prevents ordinary version drift but does not remove the new runtime trust in the CDN; bundle the lockfile-pinned dependency or serve an integrity-controlled first-party artifact instead.
| const sdkModule = await import(/* webpackIgnore: true */ EVO_SDK_URL); | |
| const sdkModule = await import('@dashevo/evo-sdk'); |
source: ['codex']
| <head> | ||
| {/* Preload the evo-sdk from CDN for faster initial load */} | ||
| <link | ||
| rel="modulepreload" | ||
| href={EVO_SDK_CDN_URL} | ||
| crossOrigin="anonymous" | ||
| /> |
There was a problem hiding this comment.
🟡 Suggestion: Avoid preloading the SDK on every page
Placing this modulepreload in the root layout makes every initial route fetch and prepare the SDK, whether or not the user invokes a Platform-dependent workflow. The referenced module is 8,030,052 bytes, and the current static export contains this preload in all 36 generated HTML files. This negates the refactor's on-demand transfer benefit; remove the global hint or initiate preloading only when the user approaches a workflow that requires the SDK.
source: ['codex']
Summary
This PR refactors the application to load the
@dashevo/evo-sdkfrom a CDN (jsDelivr) instead of bundling it with the application. This significantly reduces the initial bundle size and improves load times by leveraging CDN caching and browser module preloading.Key Changes
New CDN Loader Service (
lib/services/cdn-loader.ts): Created a new service that dynamically imports the evo-sdk from jsDelivr CDN with proper caching and error handling. Includes comprehensive TypeScript type definitions for all SDK exports.Updated SDK Service (
lib/services/evo-sdk-service.ts): Modified to useloadEvoSdk()from the CDN loader instead of direct imports. The SDK is now loaded dynamically when first needed.Module Preloading (
app/layout.tsx): Added<link rel="modulepreload">in the document head to hint to the browser to preload the SDK module early, improving perceived performance.Service Updates: Updated all services that previously imported SDK classes directly to now call
loadEvoSdk()and destructure the needed classes:document-builder-service.ts: Load Document class from CDNsigner-service.ts: Load IdentitySigner, PrivateKey, IdentityPublicKey from CDNtip-service.ts: Load wallet module from CDNdpns-service.ts: Import WasmIdentityPublicKey type from signer-service instead of wasm-sdkType Definitions: Moved type definitions from direct SDK imports to the cdn-loader service and local type definitions where appropriate. Exported
WasmIdentityPublicKeytype from signer-service for reuse.Query Types: Moved
DocumentsQuery,DocumentWhereClause, andDocumentOrderByClausetypes tosdk-helpers.tsto avoid direct wasm-sdk imports.Build Configuration (
next.config.js):https://cdn.jsdelivr.netImplementation Details
webpackIgnore: trueto prevent webpack from trying to bundle the CDN URLensureWasmReady()callshttps://claude.ai/code/session_015si4GM8oRDKC3bZfc1fBa5