From 722bdf47b0bc73feedb9f4fcb22606dd3828eb5e Mon Sep 17 00:00:00 2001 From: Jeremie Date: Fri, 17 Apr 2026 23:51:46 +0200 Subject: [PATCH 1/2] fix: Allow calculateAtomId to accept string | Hex instead of just Hex MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ## Problem The calculateAtomId function currently has a type signature that only accepts Hex, but the runtime behavior and documentation suggest it should accept strings as well. This creates a developer experience issue where: 1. Documentation shows: calculateAtomId("completed") 2. TypeScript errors: Argument of type 'string' is not assignable to parameter of type 'Hex' 3. Developers must manually convert: calculateAtomId(stringToHex("completed")) ## Evidence - Documentation examples use strings directly: https://docs.intuition.systems/docs/intuition-sdk/atoms-guide#calculateatomid - Developer report of DX issue: https://discord.com/channels/909531430881746974/1416097676772249753/1494751047909118155 - Demonstration repository: https://github.com/jeremie-olivier/intuition-calculateAtomId-demo ## Solution Update type signature from: ```typescript function calculateAtomId(atomData: Hex): string ``` To: ```typescript function calculateAtomId(atomData: string | Hex): string ``` Implementation uses explicit conversion to ensure type safety: - If string input → convert with stringToHex() - If hex input → use directly ## Changes - packages/sdk/src/utils/calculate-atom-id.ts: Updated type signature and implementation - packages/protocol/tests/helpers/calculate.ts: Updated for consistency ## Benefits - ✅ Types match documentation examples - ✅ Better developer experience (no forced stringToHex calls) - ✅ Backward compatible (existing hex usage still works) - ✅ Type safe (explicit conversion rather than assertions) - ✅ Performance optimized (only converts when needed) --- packages/protocol/tests/helpers/calculate.ts | 9 ++++++--- packages/sdk/src/utils/calculate-atom-id.ts | 11 +++++++---- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/packages/protocol/tests/helpers/calculate.ts b/packages/protocol/tests/helpers/calculate.ts index 0442c322d..2cf66368f 100644 --- a/packages/protocol/tests/helpers/calculate.ts +++ b/packages/protocol/tests/helpers/calculate.ts @@ -1,10 +1,13 @@ import type { Hex } from 'viem' -import { encodePacked, keccak256, toHex } from 'viem' +import { encodePacked, keccak256, stringToHex, toHex } from 'viem' -export function calculateAtomId(atomData: Hex) { +export function calculateAtomId(atomData: string | Hex) { const salt = keccak256(toHex('ATOM_SALT')) + // Convert to hex if it's a string, ensuring safe input to keccak256 + const hexData = + typeof atomData === 'string' ? stringToHex(atomData) : atomData return keccak256( - encodePacked(['bytes32', 'bytes'], [salt, keccak256(atomData)]), + encodePacked(['bytes32', 'bytes'], [salt, keccak256(hexData)]), ) } diff --git a/packages/sdk/src/utils/calculate-atom-id.ts b/packages/sdk/src/utils/calculate-atom-id.ts index 82ef46161..7f7e72201 100644 --- a/packages/sdk/src/utils/calculate-atom-id.ts +++ b/packages/sdk/src/utils/calculate-atom-id.ts @@ -1,14 +1,17 @@ import type { Hex } from 'viem' -import { encodePacked, keccak256, toHex } from 'viem' +import { encodePacked, keccak256, stringToHex, toHex } from 'viem' /** * Computes an atom ID by hashing the atom data with the ATOM_SALT. - * @param atomData Raw atom data as hex. + * @param atomData Raw atom data as string or hex. * @returns Keccak256 hash representing the atom ID. */ -export function calculateAtomId(atomData: Hex) { +export function calculateAtomId(atomData: string | Hex) { const salt = keccak256(toHex('ATOM_SALT')) + // Convert to hex if it's a string, ensuring safe input to keccak256 + const hexData = + typeof atomData === 'string' ? stringToHex(atomData) : atomData return keccak256( - encodePacked(['bytes32', 'bytes'], [salt, keccak256(atomData)]), + encodePacked(['bytes32', 'bytes'], [salt, keccak256(hexData)]), ) } From 3456c29a08d775e76d26ae1e008b5e211b07004a Mon Sep 17 00:00:00 2001 From: Jeremie Date: Sat, 18 Apr 2026 00:04:08 +0200 Subject: [PATCH 2/2] fix: Use isHex() instead of typeof to properly distinguish hex vs string MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Address critical bug identified in code review where typeof check was always true for both strings and Hex values, causing double-encoding of hex inputs. ## Problem Fixed - typeof atomData === 'string' was always true since Hex is `0x${string}` (still a JS string) - This caused stringToHex() to always run, double-encoding hex inputs - Result: calculateAtomId("0xdeadbeef") produced wrong hash vs old implementation ## Solution - Use viem's isHex() utility to properly detect hex-encoded values - isHex(atomData) ? atomData : stringToHex(atomData) - Preserves backward compatibility for existing hex users - Only converts plain strings to hex when needed ## Benefits - ✅ Correct runtime behavior for both input types - ✅ Maintains backward compatibility - ✅ Uses proper viem utilities instead of fragile typeof checks - ✅ Same atom IDs as before for existing hex inputs --- packages/protocol/tests/helpers/calculate.ts | 7 +++---- packages/sdk/src/utils/calculate-atom-id.ts | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/protocol/tests/helpers/calculate.ts b/packages/protocol/tests/helpers/calculate.ts index 2cf66368f..2f7f6dd6b 100644 --- a/packages/protocol/tests/helpers/calculate.ts +++ b/packages/protocol/tests/helpers/calculate.ts @@ -1,11 +1,10 @@ import type { Hex } from 'viem' -import { encodePacked, keccak256, stringToHex, toHex } from 'viem' +import { encodePacked, isHex, keccak256, stringToHex, toHex } from 'viem' export function calculateAtomId(atomData: string | Hex) { const salt = keccak256(toHex('ATOM_SALT')) - // Convert to hex if it's a string, ensuring safe input to keccak256 - const hexData = - typeof atomData === 'string' ? stringToHex(atomData) : atomData + // Convert to hex if it's not already hex-encoded, ensuring safe input to keccak256 + const hexData = isHex(atomData) ? atomData : stringToHex(atomData) return keccak256( encodePacked(['bytes32', 'bytes'], [salt, keccak256(hexData)]), ) diff --git a/packages/sdk/src/utils/calculate-atom-id.ts b/packages/sdk/src/utils/calculate-atom-id.ts index 7f7e72201..5a63857cc 100644 --- a/packages/sdk/src/utils/calculate-atom-id.ts +++ b/packages/sdk/src/utils/calculate-atom-id.ts @@ -1,5 +1,5 @@ import type { Hex } from 'viem' -import { encodePacked, keccak256, stringToHex, toHex } from 'viem' +import { encodePacked, isHex, keccak256, stringToHex, toHex } from 'viem' /** * Computes an atom ID by hashing the atom data with the ATOM_SALT. @@ -8,9 +8,8 @@ import { encodePacked, keccak256, stringToHex, toHex } from 'viem' */ export function calculateAtomId(atomData: string | Hex) { const salt = keccak256(toHex('ATOM_SALT')) - // Convert to hex if it's a string, ensuring safe input to keccak256 - const hexData = - typeof atomData === 'string' ? stringToHex(atomData) : atomData + // Convert to hex if it's not already hex-encoded, ensuring safe input to keccak256 + const hexData = isHex(atomData) ? atomData : stringToHex(atomData) return keccak256( encodePacked(['bytes32', 'bytes'], [salt, keccak256(hexData)]), )