Files
aitbc/packages/js/aitbc-sdk/src/receipts.test.ts
aitbc1 074e5fbfad
Some checks failed
JavaScript SDK Tests / test-js-sdk (push) Successful in 16s
package-tests / test-python-packages (map[name:aitbc-agent-sdk path:packages/py/aitbc-agent-sdk python_version:3.13]) (push) Failing after 9s
package-tests / test-python-packages (map[name:aitbc-core path:packages/py/aitbc-core python_version:3.13]) (push) Failing after 9s
package-tests / test-python-packages (map[name:aitbc-crypto path:packages/py/aitbc-crypto python_version:3.13]) (push) Successful in 8s
package-tests / test-python-packages (map[name:aitbc-sdk path:packages/py/aitbc-sdk python_version:3.13]) (push) Successful in 13s
package-tests / test-javascript-packages (map[name:aitbc-sdk node_version:24 path:packages/js/aitbc-sdk]) (push) Successful in 10s
package-tests / cross-language-compatibility (push) Has been skipped
package-tests / package-integration-tests (push) Has been skipped
security-scanning / audit (push) Successful in 1m22s
integration-tests / test-service-integration (push) Successful in 3m22s
style: apply Prettier formatting
2026-03-28 08:47:41 +01:00

80 lines
2.1 KiB
TypeScript

import { describe, expect, it } from "vitest";
import { generateKeyPairSync, sign } from "crypto";
import { ReceiptService } from "./receipts";
import type { ReceiptSummary } from "./types";
class ThrowingClient {
async request() {
throw new Error("offline");
}
}
describe("ReceiptService signature verification", () => {
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
const publicKeyPem = publicKey
.export({ type: "spki", format: "pem" })
.toString();
const baseReceipt: ReceiptSummary = {
receiptId: "r1",
jobId: "job-123",
miner: "miner-1",
coordinator: "coord-1",
issuedAt: new Date().toISOString(),
status: "completed",
payload: {
job_id: "job-123",
provider: "miner-1",
client: "client-1",
},
};
const signPayload = (payload: Record<string, unknown>): string => {
const message = Buffer.from(JSON.stringify(payload));
return sign(null, message, privateKey).toString("base64");
};
it("validates with provided PEM keys", async () => {
const sig = signPayload(baseReceipt.payload!);
const receipt: ReceiptSummary = {
...baseReceipt,
payload: {
...baseReceipt.payload,
minerSignature: sig,
coordinatorSignature: sig,
},
};
const svc = new ReceiptService({
client: new ThrowingClient() as any,
minerPublicKeyPem: publicKeyPem,
coordinatorPublicKeyPem: publicKeyPem,
signatureAlgorithm: "ed25519",
});
const result = await svc.validateReceipt(receipt);
expect(result.valid).toBe(true);
});
it("fails with bad signature", async () => {
const receipt: ReceiptSummary = {
...baseReceipt,
payload: {
...baseReceipt.payload,
minerSignature: "bad",
coordinatorSignature: "bad",
},
};
const svc = new ReceiptService({
client: new ThrowingClient() as any,
minerPublicKeyPem: publicKeyPem,
coordinatorPublicKeyPem: publicKeyPem,
signatureAlgorithm: "ed25519",
});
const result = await svc.validateReceipt(receipt);
expect(result.valid).toBe(false);
});
});