diff --git a/packages/starknet-snap/src/chain/transaction-service.ts b/packages/starknet-snap/src/chain/transaction-service.ts index a6bc8828..77ac5f8d 100644 --- a/packages/starknet-snap/src/chain/transaction-service.ts +++ b/packages/starknet-snap/src/chain/transaction-service.ts @@ -3,7 +3,7 @@ import { TransactionFinalityStatus, TransactionType } from 'starknet'; import { TransactionStateManager } from '../state/transaction-state-manager'; import type { Network, Transaction, V2Transaction } from '../types/snapState'; import { TransactionDataVersion } from '../types/snapState'; -import { dayToSec, msToSec } from '../utils'; +import { dayToSec, msToSec, normalizeStarknetHex } from '../utils'; import type { IDataClient } from './data-client'; export class TransactionService { @@ -107,7 +107,6 @@ export class TransactionService { const transactionsOnState: Transaction[] = []; const transactionsToRemove: string[] = []; const transactionsOnChainSet = new Set(); - for await (const tx of this.getTransactionsOnChain( address, contractAddress, @@ -116,13 +115,13 @@ export class TransactionService { transactionsOnChain.push(tx); transactionsOnChainSet.add(tx.txnHash); } - for await (const tx of this.getTransactionsOnState( address, contractAddress, )) { + console.log(tx.txnHash); // eslint-disable-next-line no-negated-condition - if (!transactionsOnChainSet.has(tx.txnHash)) { + if (!transactionsOnChainSet.has(normalizeStarknetHex(tx.txnHash))) { transactionsOnState.push(tx); } else { transactionsToRemove.push(tx.txnHash); diff --git a/packages/starknet-snap/src/utils/formatter-utils.test.ts b/packages/starknet-snap/src/utils/formatter-utils.test.ts index cd86dea5..7aeed561 100644 --- a/packages/starknet-snap/src/utils/formatter-utils.test.ts +++ b/packages/starknet-snap/src/utils/formatter-utils.test.ts @@ -10,11 +10,59 @@ import { mapDeprecatedParams, dayToSec, msToSec, + normalizeStarknetHex, } from './formatter-utils'; import { logger } from './logger'; jest.mock('./logger'); +describe('normalizeStarkNetHex', () => { + it('pads short hex values with leading zeros to 66 characters', () => { + const input = '0x1a2b3c'; + const expected = + '0x00000000000000000000000000000000000000000000000000000000001a2b3c'; + + const result = normalizeStarknetHex(input); + + expect(result).toBe(expected); + }); + + it('returns the input unchanged if already normalized to 66 characters', () => { + const input = + '0x06e175889c70810ef42f20d27c3f04b8efd75658b05e3f673b2d383f84edc33f'; + const expected = input; + + const result = normalizeStarknetHex(input); + + expect(result).toBe(expected); + }); + + it('throws an error if the input does not start with "0x"', () => { + const input = '1a2b3c'; + + expect(() => normalizeStarknetHex(input)).toThrow( + 'Invalid input: Hex value must start with "0x"', + ); + }); + + it('throws an error if the input is longer than 64 hex characters (excluding 0x)', () => { + const input = + '0x1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef1'; + + expect(() => normalizeStarknetHex(input)).toThrow( + 'Invalid input: Hex value is longer than 64 characters', + ); + }); + + it('handles an empty string properly (throws an error)', () => { + const input = ''; + + expect(() => normalizeStarknetHex(input)).toThrow( + 'Invalid input: Hex value must start with "0x"', + ); + }); +}); + describe('mapDeprecatedParams', () => { it('maps deprecated parameters to their new equivalents', () => { const requestParams = { diff --git a/packages/starknet-snap/src/utils/formatter-utils.ts b/packages/starknet-snap/src/utils/formatter-utils.ts index 78e88e64..c2635cd4 100644 --- a/packages/starknet-snap/src/utils/formatter-utils.ts +++ b/packages/starknet-snap/src/utils/formatter-utils.ts @@ -16,6 +16,28 @@ export const hexToString = (hexStr) => { return str; }; +/** + * Normalizes a StarkNet hex string (address or transaction hash) to 66 characters, + * including the '0x' prefix. Ensures the hex value is padded with leading zeros + * to meet StarkNet's 64-character requirement (excluding the prefix). + * + * @param hexString - the input hex string to normalize. + * @returns a normalized 66-character hex string with the '0x' prefix and added leading zeros if necessary. + */ +export const normalizeStarknetHex = (hexString: string) => { + if (!hexString.startsWith('0x')) { + throw new Error('Invalid input: Hex value must start with "0x"'); + } + + const hexWithoutPrefix = hexString.slice(2); // Remove '0x' + + if (hexWithoutPrefix.length > 64) { + throw new Error('Invalid input: Hex value is longer than 64 characters'); + } + + return `0x${hexWithoutPrefix.padStart(64, '0')}`; // Pad to 64 chars + '0x' +}; + /** * Maps deprecated parameters to their new equivalents in the requestParams object * and removes the deprecated parameters afterward. diff --git a/packages/starknet-snap/src/utils/starknetUtils.ts b/packages/starknet-snap/src/utils/starknetUtils.ts index 4002d25c..f713549c 100644 --- a/packages/starknet-snap/src/utils/starknetUtils.ts +++ b/packages/starknet-snap/src/utils/starknetUtils.ts @@ -76,7 +76,7 @@ import { } from './constants'; import { DeployRequiredError, UpgradeRequiredError } from './exceptions'; import { ConsolidateFees } from './fee'; -import { hexToString } from './formatter-utils'; +import { hexToString, normalizeStarknetHex } from './formatter-utils'; import { getAddressKey } from './keyPair'; import { logger } from './logger'; import { toJson } from './serializer'; @@ -708,9 +708,7 @@ export const getAccContractAddressAndCallData = (publicKey) => { 0, ); - if (address.length < 66) { - address = address.replace('0x', `0x${'0'.repeat(66 - address.length)}`); - } + address = normalizeStarknetHex(address); return { address, callData, @@ -733,9 +731,7 @@ export const getAccContractAddressAndCallDataLegacy = (publicKey) => { callData, 0, ); - if (address.length < 66) { - address = address.replace('0x', `0x${'0'.repeat(66 - address.length)}`); - } + address = normalizeStarknetHex(address); return { address, callData,