style: apply Prettier formatting
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
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
This commit is contained in:
@@ -46,7 +46,10 @@ export class AitbcClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Coordinator API Methods
|
// Coordinator API Methods
|
||||||
async match(payload: MatchRequest, options?: RequestOptions): Promise<MatchResponse> {
|
async match(
|
||||||
|
payload: MatchRequest,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<MatchResponse> {
|
||||||
const raw = await this.request<any>("POST", "/v1/match", {
|
const raw = await this.request<any>("POST", "/v1/match", {
|
||||||
...options,
|
...options,
|
||||||
body: JSON.stringify({
|
body: JSON.stringify({
|
||||||
@@ -88,14 +91,21 @@ export class AitbcClient {
|
|||||||
return { raw };
|
return { raw };
|
||||||
}
|
}
|
||||||
|
|
||||||
async sign(request: WalletSignRequest, options?: RequestOptions): Promise<WalletSignResponse> {
|
async sign(
|
||||||
return this.request<WalletSignResponse>("POST", `/v1/wallets/${encodeURIComponent(request.walletId)}/sign`, {
|
request: WalletSignRequest,
|
||||||
...options,
|
options?: RequestOptions,
|
||||||
body: JSON.stringify({
|
): Promise<WalletSignResponse> {
|
||||||
password: request.password,
|
return this.request<WalletSignResponse>(
|
||||||
message_base64: request.messageBase64,
|
"POST",
|
||||||
}),
|
`/v1/wallets/${encodeURIComponent(request.walletId)}/sign`,
|
||||||
});
|
{
|
||||||
|
...options,
|
||||||
|
body: JSON.stringify({
|
||||||
|
password: request.password,
|
||||||
|
message_base64: request.messageBase64,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Job Management Methods
|
// Job Management Methods
|
||||||
@@ -110,11 +120,17 @@ export class AitbcClient {
|
|||||||
return this.request<Job>("GET", `/v1/jobs/${jobId}`, options);
|
return this.request<Job>("GET", `/v1/jobs/${jobId}`, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getJobStatus(jobId: string, options?: RequestOptions): Promise<JobStatus> {
|
async getJobStatus(
|
||||||
|
jobId: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<JobStatus> {
|
||||||
return this.request<JobStatus>("GET", `/v1/jobs/${jobId}/status`, options);
|
return this.request<JobStatus>("GET", `/v1/jobs/${jobId}/status`, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getJobResult(jobId: string, options?: RequestOptions): Promise<JobResult> {
|
async getJobResult(
|
||||||
|
jobId: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<JobResult> {
|
||||||
return this.request<JobResult>("GET", `/v1/jobs/${jobId}/result`, options);
|
return this.request<JobResult>("GET", `/v1/jobs/${jobId}/result`, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -122,16 +138,32 @@ export class AitbcClient {
|
|||||||
await this.request<void>("DELETE", `/v1/jobs/${jobId}`, options);
|
await this.request<void>("DELETE", `/v1/jobs/${jobId}`, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async listJobs(options?: RequestOptions): Promise<{ items: Job[]; next_offset?: string }> {
|
async listJobs(
|
||||||
return this.request<{ items: Job[]; next_offset?: string }>("GET", "/v1/jobs", options);
|
options?: RequestOptions,
|
||||||
|
): Promise<{ items: Job[]; next_offset?: string }> {
|
||||||
|
return this.request<{ items: Job[]; next_offset?: string }>(
|
||||||
|
"GET",
|
||||||
|
"/v1/jobs",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Receipt Methods
|
// Receipt Methods
|
||||||
async getJobReceipts(jobId: string, options?: RequestOptions): Promise<ReceiptListResponse> {
|
async getJobReceipts(
|
||||||
return this.request<ReceiptListResponse>("GET", `/v1/jobs/${jobId}/receipts`, options);
|
jobId: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<ReceiptListResponse> {
|
||||||
|
return this.request<ReceiptListResponse>(
|
||||||
|
"GET",
|
||||||
|
`/v1/jobs/${jobId}/receipts`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async verifyReceipt(receipt: ReceiptSummary, options?: RequestOptions): Promise<{ valid: boolean }> {
|
async verifyReceipt(
|
||||||
|
receipt: ReceiptSummary,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<{ valid: boolean }> {
|
||||||
return this.request<{ valid: boolean }>("POST", "/v1/receipts/verify", {
|
return this.request<{ valid: boolean }>("POST", "/v1/receipts/verify", {
|
||||||
...options,
|
...options,
|
||||||
body: JSON.stringify(receipt),
|
body: JSON.stringify(receipt),
|
||||||
@@ -140,47 +172,108 @@ export class AitbcClient {
|
|||||||
|
|
||||||
// Blockchain Explorer Methods
|
// Blockchain Explorer Methods
|
||||||
async getBlocks(options?: RequestOptions): Promise<BlockListResponse> {
|
async getBlocks(options?: RequestOptions): Promise<BlockListResponse> {
|
||||||
return this.request<BlockListResponse>("GET", "/v1/explorer/blocks", options);
|
return this.request<BlockListResponse>(
|
||||||
|
"GET",
|
||||||
|
"/v1/explorer/blocks",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getBlock(height: string | number, options?: RequestOptions): Promise<BlockSummary> {
|
async getBlock(
|
||||||
return this.request<BlockSummary>("GET", `/v1/explorer/blocks/${height}`, options);
|
height: string | number,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<BlockSummary> {
|
||||||
|
return this.request<BlockSummary>(
|
||||||
|
"GET",
|
||||||
|
`/v1/explorer/blocks/${height}`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTransactions(options?: RequestOptions): Promise<TransactionListResponse> {
|
async getTransactions(
|
||||||
return this.request<TransactionListResponse>("GET", "/v1/explorer/transactions", options);
|
options?: RequestOptions,
|
||||||
|
): Promise<TransactionListResponse> {
|
||||||
|
return this.request<TransactionListResponse>(
|
||||||
|
"GET",
|
||||||
|
"/v1/explorer/transactions",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getTransaction(hash: string, options?: RequestOptions): Promise<TransactionSummary> {
|
async getTransaction(
|
||||||
return this.request<TransactionSummary>("GET", `/v1/explorer/transactions/${hash}`, options);
|
hash: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<TransactionSummary> {
|
||||||
|
return this.request<TransactionSummary>(
|
||||||
|
"GET",
|
||||||
|
`/v1/explorer/transactions/${hash}`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAddresses(options?: RequestOptions): Promise<AddressListResponse> {
|
async getAddresses(options?: RequestOptions): Promise<AddressListResponse> {
|
||||||
return this.request<AddressListResponse>("GET", "/v1/explorer/addresses", options);
|
return this.request<AddressListResponse>(
|
||||||
|
"GET",
|
||||||
|
"/v1/explorer/addresses",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getAddress(address: string, options?: RequestOptions): Promise<AddressSummary> {
|
async getAddress(
|
||||||
return this.request<AddressSummary>("GET", `/v1/explorer/addresses/${address}`, options);
|
address: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<AddressSummary> {
|
||||||
|
return this.request<AddressSummary>(
|
||||||
|
"GET",
|
||||||
|
`/v1/explorer/addresses/${address}`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getReceipts(options?: RequestOptions): Promise<ReceiptListResponse> {
|
async getReceipts(options?: RequestOptions): Promise<ReceiptListResponse> {
|
||||||
return this.request<ReceiptListResponse>("GET", "/v1/explorer/receipts", options);
|
return this.request<ReceiptListResponse>(
|
||||||
|
"GET",
|
||||||
|
"/v1/explorer/receipts",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Marketplace Methods
|
// Marketplace Methods
|
||||||
async getMarketplaceStats(options?: RequestOptions): Promise<MarketplaceStats> {
|
async getMarketplaceStats(
|
||||||
return this.request<MarketplaceStats>("GET", "/v1/marketplace/stats", options);
|
options?: RequestOptions,
|
||||||
|
): Promise<MarketplaceStats> {
|
||||||
|
return this.request<MarketplaceStats>(
|
||||||
|
"GET",
|
||||||
|
"/v1/marketplace/stats",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMarketplaceOffers(options?: RequestOptions): Promise<MarketplaceOffer[]> {
|
async getMarketplaceOffers(
|
||||||
return this.request<MarketplaceOffer[]>("GET", "/v1/marketplace/offers", options);
|
options?: RequestOptions,
|
||||||
|
): Promise<MarketplaceOffer[]> {
|
||||||
|
return this.request<MarketplaceOffer[]>(
|
||||||
|
"GET",
|
||||||
|
"/v1/marketplace/offers",
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async getMarketplaceOffer(offerId: string, options?: RequestOptions): Promise<MarketplaceOffer> {
|
async getMarketplaceOffer(
|
||||||
return this.request<MarketplaceOffer>("GET", `/v1/marketplace/offers/${offerId}`, options);
|
offerId: string,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<MarketplaceOffer> {
|
||||||
|
return this.request<MarketplaceOffer>(
|
||||||
|
"GET",
|
||||||
|
`/v1/marketplace/offers/${offerId}`,
|
||||||
|
options,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
async submitMarketplaceBid(bid: MarketplaceBid, options?: RequestOptions): Promise<void> {
|
async submitMarketplaceBid(
|
||||||
|
bid: MarketplaceBid,
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<void> {
|
||||||
await this.request<void>("POST", "/v1/marketplace/bids", {
|
await this.request<void>("POST", "/v1/marketplace/bids", {
|
||||||
...options,
|
...options,
|
||||||
body: JSON.stringify(bid),
|
body: JSON.stringify(bid),
|
||||||
@@ -188,7 +281,10 @@ export class AitbcClient {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Authentication Methods
|
// Authentication Methods
|
||||||
async login(credentials: { username: string; password: string }, options?: RequestOptions): Promise<MarketplaceSession> {
|
async login(
|
||||||
|
credentials: { username: string; password: string },
|
||||||
|
options?: RequestOptions,
|
||||||
|
): Promise<MarketplaceSession> {
|
||||||
return this.request<MarketplaceSession>("POST", "/v1/users/login", {
|
return this.request<MarketplaceSession>("POST", "/v1/users/login", {
|
||||||
...options,
|
...options,
|
||||||
body: JSON.stringify(credentials),
|
body: JSON.stringify(credentials),
|
||||||
@@ -199,21 +295,33 @@ export class AitbcClient {
|
|||||||
await this.request<void>("POST", "/v1/users/logout", options);
|
await this.request<void>("POST", "/v1/users/logout", options);
|
||||||
}
|
}
|
||||||
|
|
||||||
async request<T>(method: string, path: string, options: RequestOptions = {}): Promise<T> {
|
async request<T>(
|
||||||
|
method: string,
|
||||||
|
path: string,
|
||||||
|
options: RequestOptions = {},
|
||||||
|
): Promise<T> {
|
||||||
const response = await this.rawRequest(method, path, options);
|
const response = await this.rawRequest(method, path, options);
|
||||||
const text = await response.text();
|
const text = await response.text();
|
||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
throw new Error(`AITBC request failed (${response.status}): ${text || response.statusText}`);
|
throw new Error(
|
||||||
|
`AITBC request failed (${response.status}): ${text || response.statusText}`,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return text ? (JSON.parse(text) as T) : ({} as T);
|
return text ? (JSON.parse(text) as T) : ({} as T);
|
||||||
}
|
}
|
||||||
|
|
||||||
async rawRequest(method: string, path: string, options: RequestOptions = {}): Promise<Response> {
|
async rawRequest(
|
||||||
|
method: string,
|
||||||
|
path: string,
|
||||||
|
options: RequestOptions = {},
|
||||||
|
): Promise<Response> {
|
||||||
const url = this.buildUrl(path, options.query);
|
const url = this.buildUrl(path, options.query);
|
||||||
const headers = this.buildHeaders(options.headers);
|
const headers = this.buildHeaders(options.headers);
|
||||||
|
|
||||||
const controller = new AbortController();
|
const controller = new AbortController();
|
||||||
const timeoutId = this.timeout ? setTimeout(() => controller.abort(), this.timeout) : undefined;
|
const timeoutId = this.timeout
|
||||||
|
? setTimeout(() => controller.abort(), this.timeout)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return await this.fetchImpl(url, {
|
return await this.fetchImpl(url, {
|
||||||
@@ -247,7 +355,9 @@ export class AitbcClient {
|
|||||||
headers["X-Api-Key"] = this.apiKey;
|
headers["X-Api-Key"] = this.apiKey;
|
||||||
}
|
}
|
||||||
if (this.basicAuth) {
|
if (this.basicAuth) {
|
||||||
const token = btoa(`${this.basicAuth.username}:${this.basicAuth.password}`);
|
const token = btoa(
|
||||||
|
`${this.basicAuth.username}:${this.basicAuth.password}`,
|
||||||
|
);
|
||||||
headers["Authorization"] = `Basic ${token}`;
|
headers["Authorization"] = `Basic ${token}`;
|
||||||
}
|
}
|
||||||
if (extra) {
|
if (extra) {
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ class ThrowingClient {
|
|||||||
|
|
||||||
describe("ReceiptService signature verification", () => {
|
describe("ReceiptService signature verification", () => {
|
||||||
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
const { publicKey, privateKey } = generateKeyPairSync("ed25519");
|
||||||
const publicKeyPem = publicKey.export({ type: "spki", format: "pem" }).toString();
|
const publicKeyPem = publicKey
|
||||||
|
.export({ type: "spki", format: "pem" })
|
||||||
|
.toString();
|
||||||
|
|
||||||
const baseReceipt: ReceiptSummary = {
|
const baseReceipt: ReceiptSummary = {
|
||||||
receiptId: "r1",
|
receiptId: "r1",
|
||||||
|
|||||||
@@ -1,5 +1,9 @@
|
|||||||
import { verify as verifySignature, createPublicKey } from "crypto";
|
import { verify as verifySignature, createPublicKey } from "crypto";
|
||||||
import type { ReceiptListResponse, ReceiptSummary, RequestOptions } from "./types";
|
import type {
|
||||||
|
ReceiptListResponse,
|
||||||
|
ReceiptSummary,
|
||||||
|
RequestOptions,
|
||||||
|
} from "./types";
|
||||||
import { AitbcClient } from "./client";
|
import { AitbcClient } from "./client";
|
||||||
|
|
||||||
export interface PaginatedReceipts {
|
export interface PaginatedReceipts {
|
||||||
@@ -57,19 +61,19 @@ export class ReceiptService {
|
|||||||
|
|
||||||
while (attempt <= this.maxRetries) {
|
while (attempt <= this.maxRetries) {
|
||||||
try {
|
try {
|
||||||
const data = await this.client.request<ReceiptListResponse & { next_cursor?: string }>(
|
const data = await this.client.request<
|
||||||
"GET",
|
ReceiptListResponse & { next_cursor?: string }
|
||||||
`/v1/jobs/${jobId}/receipts`,
|
>("GET", `/v1/jobs/${jobId}/receipts`, {
|
||||||
{
|
...options,
|
||||||
...options,
|
query: {
|
||||||
query: {
|
cursor,
|
||||||
cursor,
|
limit,
|
||||||
limit,
|
},
|
||||||
},
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
return {
|
return {
|
||||||
items: (data.items ?? []).filter((r) => !r.jobId || r.jobId === jobId),
|
items: (data.items ?? []).filter(
|
||||||
|
(r) => !r.jobId || r.jobId === jobId,
|
||||||
|
),
|
||||||
nextCursor: data.next_cursor ?? (data as any).nextCursor ?? null,
|
nextCursor: data.next_cursor ?? (data as any).nextCursor ?? null,
|
||||||
};
|
};
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -83,7 +87,10 @@ export class ReceiptService {
|
|||||||
throw lastError ?? new Error("Failed to fetch receipts");
|
throw lastError ?? new Error("Failed to fetch receipts");
|
||||||
}
|
}
|
||||||
|
|
||||||
async validateReceipt(receipt: ReceiptSummary, options?: ReceiptValidationOptions): Promise<ReceiptValidationResult> {
|
async validateReceipt(
|
||||||
|
receipt: ReceiptSummary,
|
||||||
|
options?: ReceiptValidationOptions,
|
||||||
|
): Promise<ReceiptValidationResult> {
|
||||||
// Placeholder for full cryptographic verification: delegate to coordinator API
|
// Placeholder for full cryptographic verification: delegate to coordinator API
|
||||||
const {
|
const {
|
||||||
minerVerifier,
|
minerVerifier,
|
||||||
@@ -94,14 +101,13 @@ export class ReceiptService {
|
|||||||
...requestOptions
|
...requestOptions
|
||||||
} = options ?? {};
|
} = options ?? {};
|
||||||
try {
|
try {
|
||||||
const data = await this.client.request<{ valid: boolean; reason?: string }>(
|
const data = await this.client.request<{
|
||||||
"POST",
|
valid: boolean;
|
||||||
"/v1/receipts/verify",
|
reason?: string;
|
||||||
{
|
}>("POST", "/v1/receipts/verify", {
|
||||||
...requestOptions,
|
...requestOptions,
|
||||||
body: JSON.stringify(this.buildVerificationPayload(receipt)),
|
body: JSON.stringify(this.buildVerificationPayload(receipt)),
|
||||||
}
|
});
|
||||||
);
|
|
||||||
return { valid: !!data.valid, reason: data.reason };
|
return { valid: !!data.valid, reason: data.reason };
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Fallback to local checks if API unavailable
|
// Fallback to local checks if API unavailable
|
||||||
@@ -111,9 +117,11 @@ export class ReceiptService {
|
|||||||
coordinatorVerifier,
|
coordinatorVerifier,
|
||||||
minerPublicKeyPem ?? this.minerPublicKeyPem,
|
minerPublicKeyPem ?? this.minerPublicKeyPem,
|
||||||
coordinatorPublicKeyPem ?? this.coordinatorPublicKeyPem,
|
coordinatorPublicKeyPem ?? this.coordinatorPublicKeyPem,
|
||||||
signatureAlgorithm ?? this.signatureAlgorithm ?? "ed25519"
|
signatureAlgorithm ?? this.signatureAlgorithm ?? "ed25519",
|
||||||
);
|
);
|
||||||
return local.valid ? local : { valid: false, reason: (err as Error).message };
|
return local.valid
|
||||||
|
? local
|
||||||
|
: { valid: false, reason: (err as Error).message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,7 +140,9 @@ export class ReceiptService {
|
|||||||
async validateLocally(
|
async validateLocally(
|
||||||
receipt: ReceiptSummary,
|
receipt: ReceiptSummary,
|
||||||
minerVerifier?: (receipt: ReceiptSummary) => Promise<boolean> | boolean,
|
minerVerifier?: (receipt: ReceiptSummary) => Promise<boolean> | boolean,
|
||||||
coordinatorVerifier?: (receipt: ReceiptSummary) => Promise<boolean> | boolean,
|
coordinatorVerifier?: (
|
||||||
|
receipt: ReceiptSummary,
|
||||||
|
) => Promise<boolean> | boolean,
|
||||||
minerPublicKeyPem?: string,
|
minerPublicKeyPem?: string,
|
||||||
coordinatorPublicKeyPem?: string,
|
coordinatorPublicKeyPem?: string,
|
||||||
signatureAlgorithm: string = "ed25519",
|
signatureAlgorithm: string = "ed25519",
|
||||||
@@ -158,22 +168,35 @@ export class ReceiptService {
|
|||||||
const ok = await minerVerifier(receipt);
|
const ok = await minerVerifier(receipt);
|
||||||
if (!ok) return { valid: false, reason: "miner signature invalid" };
|
if (!ok) return { valid: false, reason: "miner signature invalid" };
|
||||||
} else if (minerPublicKeyPem) {
|
} else if (minerPublicKeyPem) {
|
||||||
const ok = this.verifyWithCrypto(minerSig, minerPublicKeyPem, payloadForSig, signatureAlgorithm);
|
const ok = this.verifyWithCrypto(
|
||||||
|
minerSig,
|
||||||
|
minerPublicKeyPem,
|
||||||
|
payloadForSig,
|
||||||
|
signatureAlgorithm,
|
||||||
|
);
|
||||||
if (!ok) return { valid: false, reason: "miner signature invalid" };
|
if (!ok) return { valid: false, reason: "miner signature invalid" };
|
||||||
}
|
}
|
||||||
if (coordinatorVerifier) {
|
if (coordinatorVerifier) {
|
||||||
const ok = await coordinatorVerifier(receipt);
|
const ok = await coordinatorVerifier(receipt);
|
||||||
if (!ok) return { valid: false, reason: "coordinator signature invalid" };
|
if (!ok) return { valid: false, reason: "coordinator signature invalid" };
|
||||||
} else if (coordinatorPublicKeyPem) {
|
} else if (coordinatorPublicKeyPem) {
|
||||||
const ok = this.verifyWithCrypto(coordinatorSig, coordinatorPublicKeyPem, payloadForSig, signatureAlgorithm);
|
const ok = this.verifyWithCrypto(
|
||||||
|
coordinatorSig,
|
||||||
|
coordinatorPublicKeyPem,
|
||||||
|
payloadForSig,
|
||||||
|
signatureAlgorithm,
|
||||||
|
);
|
||||||
if (!ok) return { valid: false, reason: "coordinator signature invalid" };
|
if (!ok) return { valid: false, reason: "coordinator signature invalid" };
|
||||||
}
|
}
|
||||||
return { valid: true };
|
return { valid: true };
|
||||||
}
|
}
|
||||||
|
|
||||||
private sanitizePayload(payload: Record<string, unknown>): Record<string, unknown> {
|
private sanitizePayload(
|
||||||
|
payload: Record<string, unknown>,
|
||||||
|
): Record<string, unknown> {
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
const { signature, minerSignature, coordinatorSignature, ...rest } = payload ?? {};
|
const { signature, minerSignature, coordinatorSignature, ...rest } =
|
||||||
|
payload ?? {};
|
||||||
return rest;
|
return rest;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,7 +215,12 @@ export class ReceiptService {
|
|||||||
return verifySignature(null, message, key, sig);
|
return verifySignature(null, message, key, sig);
|
||||||
}
|
}
|
||||||
if (alg.toLowerCase() === "secp256k1") {
|
if (alg.toLowerCase() === "secp256k1") {
|
||||||
return verifySignature("sha256", message, { key, dsaEncoding: "ieee-p1363" }, sig);
|
return verifySignature(
|
||||||
|
"sha256",
|
||||||
|
message,
|
||||||
|
{ key, dsaEncoding: "ieee-p1363" },
|
||||||
|
sig,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (alg.toLowerCase().startsWith("rsa")) {
|
if (alg.toLowerCase().startsWith("rsa")) {
|
||||||
return verifySignature("sha256", message, key, sig);
|
return verifySignature("sha256", message, key, sig);
|
||||||
|
|||||||
Reference in New Issue
Block a user