diff --git a/packages/sdk/src/ids.test.ts b/packages/sdk/src/ids.test.ts index fa9a4ff..969988a 100644 --- a/packages/sdk/src/ids.test.ts +++ b/packages/sdk/src/ids.test.ts @@ -10,6 +10,10 @@ describe("normalizeRoundId", () => { assert.equal(normalizeRoundId("001"), 1n); assert.equal(normalizeRoundId(7), 7n); assert.equal(normalizeRoundId(7n), 7n); + assert.equal(normalizeRoundId(1), 1n); + assert.equal(normalizeRoundId(1n), 1n); + assert.equal(normalizeRoundId(Number.MAX_SAFE_INTEGER), BigInt(Number.MAX_SAFE_INTEGER)); + assert.equal(normalizeRoundId(BigInt(Number.MAX_SAFE_INTEGER) + 100n), BigInt(Number.MAX_SAFE_INTEGER) + 100n); }); it("rejects malformed values with explicit errors", () => { @@ -17,8 +21,30 @@ describe("normalizeRoundId", () => { assert.throws(() => normalizeRoundId(" "), /roundId/); assert.throws(() => normalizeRoundId("0"), /positive integer/); assert.throws(() => normalizeRoundId("-1"), /positive integer/); - assert.throws(() => normalizeRoundId("1.5"), /roundId/); - assert.throws(() => normalizeRoundId("abc"), /roundId/); + assert.throws(() => normalizeRoundId("1.5"), /positive integer/); + assert.throws(() => normalizeRoundId("abc"), /positive integer/); + assert.throws(() => normalizeRoundId("0x10"), /positive integer/); + assert.throws(() => normalizeRoundId("+5"), /positive integer/); + }); + + it("rejects zero and negative number or bigint inputs", () => { + assert.throws(() => normalizeRoundId(0), /positive integer/); + assert.throws(() => normalizeRoundId(-1), /positive integer/); + assert.throws(() => normalizeRoundId(-42), /positive integer/); + assert.throws(() => normalizeRoundId(0n), /positive integer/); + assert.throws(() => normalizeRoundId(-1n), /positive integer/); + assert.throws(() => normalizeRoundId(-42n), /positive integer/); + }); + + it("rejects unsafe, fractional, and non-finite numbers", () => { + assert.throws(() => normalizeRoundId(1.5), /positive integer/); + assert.throws(() => normalizeRoundId(0.1), /positive integer/); + assert.throws(() => normalizeRoundId(NaN), /positive integer/); + assert.throws(() => normalizeRoundId(Infinity), /positive integer/); + assert.throws(() => normalizeRoundId(-Infinity), /positive integer/); + assert.throws(() => normalizeRoundId(Number.MAX_SAFE_INTEGER + 1), /positive integer/); + assert.throws(() => normalizeRoundId(Number.MAX_SAFE_INTEGER + 2), /positive integer/); + assert.throws(() => normalizeRoundId(Number.MIN_SAFE_INTEGER), /positive integer/); }); }); diff --git a/packages/sdk/src/ids.ts b/packages/sdk/src/ids.ts index 493868b..eb1ec5b 100644 --- a/packages/sdk/src/ids.ts +++ b/packages/sdk/src/ids.ts @@ -7,11 +7,16 @@ function toTrimmedString(value: string | undefined): string | undefined { } export function normalizeRoundId(value: string | number | bigint): bigint { - if (typeof value === "bigint") return value; + if (typeof value === "bigint") { + if (value <= 0n) { + throw new Error(`roundId must be a positive integer, got ${value}`); + } + return value; + } if (typeof value === "number") { - if (!Number.isInteger(value)) { - throw new Error(`roundId must be an integer, got ${JSON.stringify(value)}`); + if (!Number.isSafeInteger(value) || value <= 0) { + throw new Error(`roundId must be a positive integer, got ${value}`); } return BigInt(value); } @@ -21,18 +26,15 @@ export function normalizeRoundId(value: string | number | bigint): bigint { throw new Error("roundId must be a non-empty decimal string"); } - try { - const parsed = BigInt(trimmed); - if (parsed < 1n) { - throw new Error(`roundId must be a positive integer, got ${JSON.stringify(trimmed)}`); - } - return parsed; - } catch (error) { - if (error instanceof Error && error.message.includes("roundId")) { - throw error; - } + if (!/^\d+$/.test(trimmed)) { + throw new Error(`roundId must be a positive integer, got ${JSON.stringify(trimmed)}`); + } + + const parsed = BigInt(trimmed); + if (parsed <= 0n) { throw new Error(`roundId must be a positive integer, got ${JSON.stringify(trimmed)}`); } + return parsed; } export function normalizeSorobanContractId(value: string): string {