Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

---

## [0.1.39] - 2026-07-26

###    🐞 Bug Fixes

- **sdk**: Cache built-in PostHog instance across AnalyticsProvider remounts &nbsp;-&nbsp; by @akbarsaputrait [<samp>(097c2)</samp>](https://github.com/RozoAI/intent-pay/commit/097c29a4)

---

## [0.1.38] - 2026-07-26

### &nbsp;&nbsp;&nbsp;🐞 Bug Fixes
Expand Down
2 changes: 1 addition & 1 deletion packages/connectkit/bundle-analysis.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/connectkit/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@rozoai/intent-pay",
"version": "0.1.38",
"version": "0.1.39",
"private": false,
"description": "Seamless crypto payments. Onboard users from any chain, any coin into your app with one click.",
"keywords": [
Expand Down
18 changes: 18 additions & 0 deletions packages/connectkit/src/provider/AnalyticsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,16 @@ const AnalyticsContext = createContext<AnalyticsContextValue>({
capture: noop,
});

// Module-level cache for the named telemetry instance. AnalyticsProvider
// remounts whenever a host app remounts its provider tree (e.g. a
// per-route layout that wraps RozoPayProvider fresh on each client-side
// navigation) — without this, the effect below would call posthog-js's
// named-instance init() again on every remount. Re-init on an existing
// name logs "You have already initialized PostHog!" and is a no-op, but
// the console warning is still spurious noise for host apps. Reusing the
// cached instance across remounts avoids the duplicate init call entirely.
let cachedBuiltin: unknown = null;

const SDK_APP_NAME = "rozo-intent-sdk";

/** Properties stripped from built-in telemetry — host app receives them unchanged. */
Expand Down Expand Up @@ -76,6 +86,13 @@ export function AnalyticsProvider({
useEffect(() => {
if (!telemetryEnabled) return;

// Reuse the cached instance across remounts instead of calling init()
// again — see cachedBuiltin comment above.
if (cachedBuiltin) {
builtinRef.current = cachedBuiltin as PostHogFull;
return;
}

// Lazy-load posthog-js only when telemetry is on. It's a peer dep so
// we try/catch — if the host app didn't install it, built-in telemetry
// silently no-ops rather than crashing.
Expand Down Expand Up @@ -110,6 +127,7 @@ export function AnalyticsProvider({
},
"rozo-sdk-telemetry",
);
cachedBuiltin = builtin;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 (nice to have): cachedBuiltin is only assigned after the async import("posthog-js") promise resolves, so the comment's claim that this "avoids the duplicate init call entirely" is slightly overstated. If two AnalyticsProvider instances mount before this first .then() runs (e.g. a fast double-remount, or two providers in the tree), both will see cachedBuiltin == null and both call ph.init(..., "rozo-sdk-telemetry"), re-triggering the exact warning this fixes.

The real target scenario — per-route remount after initial load — happens well after init resolves, so the fix works for it. But to fully close the window you could set a "pending" sentinel synchronously before the import, or cache the promise itself:

let cachedBuiltin: unknown = null;
let builtinInitPromise: Promise<unknown> | null = null;

Minor; not blocking.

builtinRef.current = builtin;
})
.catch(() => {
Expand Down
Loading