Skip to content

Commit 31a7ea4

Browse files
authored
feat(1719): mirror node callcontract response validation (#1753)
Signed-off-by: rozekmichal <michal.rozek@blockydevs.com>
1 parent 16ebc17 commit 31a7ea4

File tree

4 files changed

+52
-8
lines changed

4 files changed

+52
-8
lines changed

src/core/services/contract-verifier/contract-verifier-service.ts

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@ import type { ContractVerifierService } from '@/core/services/contract-verifier/
33
import type {
44
ContractVerificationParams,
55
ContractVerificationResult,
6-
SmartContractVerifyApiErrorResponse,
7-
SmartContractVerifyApiOkResponse,
86
} from '@/core/services/contract-verifier/types';
97

108
import fs from 'fs/promises';
119
import path from 'path';
1210

11+
import {
12+
SmartContractVerifyApiErrorResponseSchema,
13+
SmartContractVerifyApiOkResponseSchema,
14+
} from '@/core/services/contract-verifier/schema';
15+
import { parseWithSchema } from '@/core/shared/validation/parse-with-schema.zod';
1316
import { NetworkChainMap } from '@/core/types/shared.types';
1417
import { scanSolidityFiles } from '@/core/utils/solidity-file-importer';
1518

@@ -57,10 +60,12 @@ export class ContractVerifierServiceImpl implements ContractVerifierService {
5760
if (!response.ok) {
5861
let errorMessage: string;
5962
try {
60-
const errorData =
61-
(await response.json()) as SmartContractVerifyApiErrorResponse;
62-
errorMessage =
63-
errorData.error ?? `${response.status} ${response.statusText}`;
63+
const parsed = SmartContractVerifyApiErrorResponseSchema.safeParse(
64+
await response.json(),
65+
);
66+
errorMessage = parsed.success
67+
? (parsed.data.error ?? `${response.status} ${response.statusText}`)
68+
: `${response.status} ${response.statusText}`;
6469
} catch {
6570
errorMessage = `${response.status} ${response.statusText}`;
6671
}
@@ -71,7 +76,11 @@ export class ContractVerifierServiceImpl implements ContractVerifierService {
7176
};
7277
}
7378

74-
const data = (await response.json()) as SmartContractVerifyApiOkResponse;
79+
const data = parseWithSchema(
80+
SmartContractVerifyApiOkResponseSchema,
81+
await response.json(),
82+
'Hashscan verify API POST /verify',
83+
);
7584

7685
return {
7786
success: true,
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import type {
2+
SmartContractVerifyApiErrorResponse,
3+
SmartContractVerifyApiOkResponse,
4+
} from './types';
5+
6+
import { z } from 'zod';
7+
8+
const verifyResultItemSchema = z.object({
9+
address: z.string(),
10+
chainId: z.string(),
11+
status: z.string(),
12+
message: z.string(),
13+
libraryMap: z.record(z.string(), z.unknown()),
14+
});
15+
16+
export const SmartContractVerifyApiOkResponseSchema: z.ZodType<SmartContractVerifyApiOkResponse> =
17+
z.object({
18+
result: z.array(verifyResultItemSchema).min(1),
19+
});
20+
21+
export const SmartContractVerifyApiErrorResponseSchema: z.ZodType<SmartContractVerifyApiErrorResponse> =
22+
z.object({
23+
error: z.string(),
24+
});

src/core/services/mirrornode/hedera-mirrornode-service.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import { handleMirrorNodeErrorResponse } from '@/core/utils/handle-mirror-node-e
3636

3737
import {
3838
AccountAPIResponseSchema,
39+
ContractCallResponseSchema,
3940
ContractInfoSchema,
4041
ExchangeRateResponseSchema,
4142
GetAccountsAPIResponseSchema,
@@ -602,7 +603,11 @@ export class HederaMirrornodeServiceDefaultImpl implements HederaMirrornodeServi
602603
);
603604
}
604605

605-
return (await response.json()) as ContractCallResponse;
606+
return parseWithSchema(
607+
ContractCallResponseSchema,
608+
await response.json(),
609+
'Mirror Node POST /contracts/call',
610+
);
606611
} catch (error) {
607612
if (error instanceof CliError) throw error;
608613
throw new NetworkError('Failed to call contract via mirror node', {

src/core/services/mirrornode/schemas.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import {
77
type AccountListItemAPIResponse,
88
type AccountListItemBalance,
99
type AccountListItemTokenBalance,
10+
type ContractCallResponse,
1011
type ContractInfo,
1112
type ExchangeRateResponse,
1213
type GetAccountsAPIResponse,
@@ -232,6 +233,11 @@ export const ContractInfoSchema: z.ZodType<ContractInfo> = z.object({
232233
stake_period_start: nullableStringKey,
233234
});
234235

236+
export const ContractCallResponseSchema: z.ZodType<ContractCallResponse> =
237+
z.object({
238+
result: z.string(),
239+
});
240+
235241
const exchangeRateBandSchema = z.object({
236242
cent_equivalent: z.number(),
237243
expiration_time: z.number(),

0 commit comments

Comments
 (0)