Some checks failed
Code Quality / SonarQube Analysis (pull_request) Failing after 20s
Code Quality / Code Quality Checks (pull_request) Failing after 8s
Security Scan / Dependency Vulnerability Scan (pull_request) Failing after 3s
Security Scan / OWASP ZAP Scan (pull_request) Failing after 4s
- services/notaryChain.ts: new ethers-v6 adapter speaking to the
deployed NotaryRegistry.sol via CHAIN_138_RPC_URL +
NOTARY_REGISTRY_ADDRESS + ORCHESTRATOR_PRIVATE_KEY. Exposes
anchorPlan(plan) -> { mode, txHash, planHash, blockNumber } and
finalizeAnchor(planId, success) -> { mode, txHash, receiptHash }
with deterministic mock fallback when envs are absent.
- services/notary.ts: refactored to delegate to notaryChain; preserves
the prior signature and returns extra on-chain fields (mode, txHash,
blockNumber, contractAddress) when the anchor lands.
- config/env.ts: add CHAIN_138_RPC_URL, CHAIN_138_CHAIN_ID,
NOTARY_REGISTRY_ADDRESS, ORCHESTRATOR_PRIVATE_KEY (all optional,
validated via regex where applicable).
- package.json: add ethers@^6.11.0 dependency.
- tests/unit/notaryChain.test.ts: 6 tests covering deterministic
hashing helpers and the mock fallback path.
tsc clean. 51 tests pass (45 pre-existing + 6 new).
63 lines
2.0 KiB
TypeScript
63 lines
2.0 KiB
TypeScript
import { describe, it, expect, beforeEach } from "@jest/globals";
|
|
import {
|
|
__resetForTests,
|
|
anchorPlan,
|
|
computePlanHash,
|
|
finalizeAnchor,
|
|
planIdToBytes32,
|
|
} from "../../src/services/notaryChain";
|
|
import type { Plan } from "../../src/types/plan";
|
|
|
|
const FIXTURE_PLAN: Plan = {
|
|
plan_id: "11111111-2222-3333-4444-555555555555",
|
|
creator: "0xabc",
|
|
steps: [{ type: "pay", amount: 100, asset: "USD" }],
|
|
};
|
|
|
|
describe("NotaryChain adapter", () => {
|
|
beforeEach(() => __resetForTests());
|
|
|
|
describe("helpers", () => {
|
|
it("planIdToBytes32 is deterministic and 32 bytes", () => {
|
|
const a = planIdToBytes32("p-1");
|
|
const b = planIdToBytes32("p-1");
|
|
expect(a).toBe(b);
|
|
expect(a).toMatch(/^0x[0-9a-f]{64}$/);
|
|
});
|
|
|
|
it("planIdToBytes32 collision-resistant across different ids", () => {
|
|
expect(planIdToBytes32("a")).not.toBe(planIdToBytes32("b"));
|
|
});
|
|
|
|
it("computePlanHash is deterministic and sha256", () => {
|
|
const h1 = computePlanHash(FIXTURE_PLAN);
|
|
const h2 = computePlanHash(FIXTURE_PLAN);
|
|
expect(h1).toBe(h2);
|
|
expect(h1).toMatch(/^0x[0-9a-f]{64}$/);
|
|
});
|
|
});
|
|
|
|
describe("mock fallback (envs unset)", () => {
|
|
it("anchorPlan returns mode=mock with planHash when unconfigured", async () => {
|
|
const result = await anchorPlan(FIXTURE_PLAN, {});
|
|
expect(result.mode).toBe("mock");
|
|
expect(result.planHash).toMatch(/^0x[0-9a-f]{64}$/);
|
|
expect(result.txHash).toBeUndefined();
|
|
});
|
|
|
|
it("finalizeAnchor returns mode=mock when unconfigured", async () => {
|
|
const result = await finalizeAnchor(FIXTURE_PLAN.plan_id!, true, {});
|
|
expect(result.mode).toBe("mock");
|
|
expect(result.txHash).toBeUndefined();
|
|
});
|
|
|
|
it("anchorPlan stays on the mock path when only some envs are set", async () => {
|
|
const result = await anchorPlan(FIXTURE_PLAN, {
|
|
rpcUrl: "https://rpc.d-bis.org",
|
|
// contractAddress + privateKey missing
|
|
});
|
|
expect(result.mode).toBe("mock");
|
|
});
|
|
});
|
|
});
|