Skip to content

Commit 63a3db2

Browse files
authored
chore: Assert integers validation for most numeric input values (#741)
1 parent 844d297 commit 63a3db2

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

59 files changed

+317
-297
lines changed

src/server/routes/admin/nonces.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ export const responseBodySchema = Type.Object({
2727
...AddressSchema,
2828
description: "Backend wallet address",
2929
},
30-
chainId: Type.Number({
30+
chainId: Type.Integer({
3131
description: "Chain ID",
3232
examples: [80002],
3333
}),

src/server/routes/backend-wallet/getAll.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { getAllWallets } from "../../../db/wallets/getAllWallets";
55
import {
@@ -8,15 +8,17 @@ import {
88
} from "../../schemas/sharedApiSchemas";
99

1010
const QuerySchema = Type.Object({
11-
page: Type.Number({
11+
page: Type.Integer({
1212
description: "The page of wallets to get.",
1313
examples: ["1"],
1414
default: "1",
15+
minimum: 1,
1516
}),
16-
limit: Type.Number({
17+
limit: Type.Integer({
1718
description: "The number of wallets to get per page.",
1819
examples: ["10"],
1920
default: "10",
21+
minimum: 1,
2022
}),
2123
});
2224

src/server/routes/backend-wallet/getNonce.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
4-
import { Address } from "thirdweb";
4+
import type { Address } from "thirdweb";
55
import { inspectNonce } from "../../../db/wallets/walletNonce";
66
import { standardResponseSchema } from "../../schemas/sharedApiSchemas";
77
import { walletWithAddressParamSchema } from "../../schemas/wallet";
@@ -11,7 +11,7 @@ const requestSchema = walletWithAddressParamSchema;
1111

1212
const responseSchema = Type.Object({
1313
result: Type.Object({
14-
nonce: Type.Number(),
14+
nonce: Type.Integer(),
1515
}),
1616
});
1717

src/server/routes/backend-wallet/getTransactionsByNonce.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { TransactionDB } from "../../../db/transactions/db";
55
import { getNonceMap } from "../../../db/wallets/nonceMap";
66
import { normalizeAddress } from "../../../utils/primitiveTypes";
7-
import { AnyTransaction } from "../../../utils/transaction/types";
7+
import type { AnyTransaction } from "../../../utils/transaction/types";
88
import { standardResponseSchema } from "../../schemas/sharedApiSchemas";
99
import {
1010
TransactionSchema,
@@ -34,7 +34,7 @@ const requestQuerySchema = Type.Object({
3434
const responseBodySchema = Type.Object({
3535
result: Type.Array(
3636
Type.Object({
37-
nonce: Type.Number(),
37+
nonce: Type.Integer(),
3838
// Returns the transaction details by default.
3939
// Falls back to the queueId if the transaction details have been pruned.
4040
transaction: Type.Union([TransactionSchema, Type.String()]),

src/server/routes/backend-wallet/signTransaction.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,8 @@ const requestBodySchema = Type.Object({
2121
gasPrice: Type.Optional(Type.String()),
2222
data: Type.Optional(Type.String()),
2323
value: Type.Optional(Type.String()),
24-
chainId: Type.Optional(Type.Number()),
25-
type: Type.Optional(Type.Number()),
24+
chainId: Type.Optional(Type.Integer()),
25+
type: Type.Optional(Type.Integer()),
2626
accessList: Type.Optional(Type.Any()),
2727
maxFeePerGas: Type.Optional(Type.String()),
2828
maxPriorityFeePerGas: Type.Optional(Type.String()),

src/server/routes/configuration/backend-wallet-balance/update.ts

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
55
import { getConfig } from "../../../../utils/cache/getConfig";
6+
import { WeiAmountStringSchema } from "../../../schemas/number";
67
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
78
import { responseBodySchema } from "./get";
89

910
const requestBodySchema = Type.Partial(
1011
Type.Object({
11-
minWalletBalance: Type.String({
12+
minWalletBalance: {
13+
...WeiAmountStringSchema,
1214
description: "Minimum wallet balance in wei",
13-
}),
15+
},
1416
}),
1517
);
1618

src/server/routes/configuration/cache/update.ts

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,12 @@ import { updateConfiguration } from "../../../../db/configuration/updateConfigur
55
import { getConfig } from "../../../../utils/cache/getConfig";
66
import { clearCacheCron } from "../../../../utils/cron/clearCacheCron";
77
import { isValidCron } from "../../../../utils/cron/isValidCron";
8+
import { createCustomError } from "../../../middleware/error";
89
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
910
import { responseBodySchema } from "./get";
1011

1112
const requestBodySchema = Type.Object({
1213
clearCacheCronSchedule: Type.String({
13-
minLength: 11,
1414
description:
1515
"Cron expression for clearing cache. It should be in the format of 'ss mm hh * * *' where ss is seconds, mm is minutes and hh is hours. Seconds should not be '*' or less than 10",
1616
default: "*/30 * * * * *",
@@ -37,12 +37,11 @@ export async function updateCacheConfiguration(fastify: FastifyInstance) {
3737
handler: async (req, res) => {
3838
const { clearCacheCronSchedule } = req.body;
3939
if (isValidCron(clearCacheCronSchedule) === false) {
40-
return res.status(400).send({
41-
error: {
42-
code: 400,
43-
message: "Invalid cron expression",
44-
},
45-
});
40+
throw createCustomError(
41+
"Invalid cron expression.",
42+
StatusCodes.BAD_REQUEST,
43+
"INVALID_CRON",
44+
);
4645
}
4746

4847
await updateConfiguration({ ...req.body });

src/server/routes/configuration/contract-subscriptions/update.ts

Lines changed: 15 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
55
import { getConfig } from "../../../../utils/cache/getConfig";
@@ -10,8 +10,12 @@ import {
1010
} from "../../../schemas/sharedApiSchemas";
1111

1212
const requestBodySchema = Type.Object({
13-
maxBlocksToIndex: Type.Optional(Type.Number({ minimum: 1, maximum: 25 })),
14-
contractSubscriptionsRequeryDelaySeconds: Type.Optional(Type.String()),
13+
maxBlocksToIndex: Type.Optional(Type.Integer({ minimum: 1, maximum: 100 })),
14+
contractSubscriptionsRequeryDelaySeconds: Type.Optional(
15+
Type.String({
16+
description: `Requery after one or more delays. Use comma-separated positive integers. Example: "2,10" means requery after 2s and 10s.`,
17+
}),
18+
),
1519
});
1620

1721
const responseSchema = Type.Object({
@@ -51,11 +55,14 @@ export async function updateContractSubscriptionsConfiguration(
5155

5256
if (contractSubscriptionsRequeryDelaySeconds) {
5357
try {
54-
contractSubscriptionsRequeryDelaySeconds.split(",").forEach((d) => {
55-
if (Number.isNaN(parseInt(d))) {
56-
throw "Invalid number";
58+
for (const delayStr of contractSubscriptionsRequeryDelaySeconds.split(
59+
",",
60+
)) {
61+
const delayInt = Number.parseInt(delayStr);
62+
if (Number.isNaN(delayInt) || delayInt <= 0) {
63+
throw `Invalid delay value. Use comma-separated positive integers: "2,10"`;
5764
}
58-
});
65+
}
5966
} catch {
6067
throw createCustomError(
6168
'At least one integer "contractSubscriptionsRequeryDelaySeconds" is required',

src/server/routes/configuration/transactions/get.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { getConfig } from "../../../../utils/cache/getConfig";
55
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
66

77
const responseBodySchema = Type.Object({
88
result: Type.Object({
9-
minTxsToProcess: Type.Number(),
10-
maxTxsToProcess: Type.Number(),
9+
minTxsToProcess: Type.Integer(),
10+
maxTxsToProcess: Type.Integer(),
1111
minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
12-
maxTxsToUpdate: Type.Number(),
12+
maxTxsToUpdate: Type.Integer(),
1313
retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
14-
minEllapsedBlocksBeforeRetry: Type.Number(),
14+
minEllapsedBlocksBeforeRetry: Type.Integer(),
1515
maxFeePerGasForRetries: Type.String(),
1616
maxPriorityFeePerGasForRetries: Type.String(),
17-
maxRetriesPerTx: Type.Number(),
17+
maxRetriesPerTx: Type.Integer(),
1818
clearCacheCronSchedule: Type.Union([Type.String(), Type.Null()]),
1919
}),
2020
});

src/server/routes/configuration/transactions/update.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,33 @@
1-
import { Static, Type } from "@sinclair/typebox";
2-
import { FastifyInstance } from "fastify";
1+
import { Type, type Static } from "@sinclair/typebox";
2+
import type { FastifyInstance } from "fastify";
33
import { StatusCodes } from "http-status-codes";
44
import { updateConfiguration } from "../../../../db/configuration/updateConfiguration";
55
import { getConfig } from "../../../../utils/cache/getConfig";
66
import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
77

88
const requestBodySchema = Type.Partial(
99
Type.Object({
10-
minTxsToProcess: Type.Number(),
11-
maxTxsToProcess: Type.Number(),
10+
maxTxsToProcess: Type.Integer({ minimum: 1, maximum: 10_000 }),
11+
maxTxsToUpdate: Type.Integer({ minimum: 1, maximum: 10_000 }),
1212
minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
13-
maxTxsToUpdate: Type.Number(),
1413
retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
15-
minEllapsedBlocksBeforeRetry: Type.Number(),
14+
minEllapsedBlocksBeforeRetry: Type.Integer({ minimum: 1, maximum: 10_000 }),
1615
maxFeePerGasForRetries: Type.String(),
17-
maxPriorityFeePerGasForRetries: Type.String(),
18-
maxRetriesPerTx: Type.Number(),
16+
maxRetriesPerTx: Type.Integer({ minimum: 0, maximum: 10_000 }),
1917
}),
2018
);
2119

2220
const responseBodySchema = Type.Object({
2321
result: Type.Object({
24-
minTxsToProcess: Type.Number(),
25-
maxTxsToProcess: Type.Number(),
22+
minTxsToProcess: Type.Integer(),
23+
maxTxsToProcess: Type.Integer(),
2624
minedTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
27-
maxTxsToUpdate: Type.Number(),
25+
maxTxsToUpdate: Type.Integer(),
2826
retryTxListenerCronSchedule: Type.Union([Type.String(), Type.Null()]),
29-
minEllapsedBlocksBeforeRetry: Type.Number(),
27+
minEllapsedBlocksBeforeRetry: Type.Integer(),
3028
maxFeePerGasForRetries: Type.String(),
3129
maxPriorityFeePerGasForRetries: Type.String(),
32-
maxRetriesPerTx: Type.Number(),
30+
maxRetriesPerTx: Type.Integer(),
3331
}),
3432
});
3533

src/server/routes/contract/events/getContractEventLogs.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -12,26 +12,26 @@ import {
1212
import { getChainIdFromChain } from "../../../utils/chain";
1313

1414
const requestQuerySchema = Type.Object({
15-
fromBlock: Type.Number(),
16-
toBlock: Type.Optional(Type.Number()),
15+
fromBlock: Type.Integer({ minimum: 0 }),
16+
toBlock: Type.Optional(Type.Integer({ minimum: 0 })),
1717
topics: Type.Optional(Type.Array(Type.String())),
1818
});
1919

2020
const responseSchema = Type.Object({
2121
result: Type.Object({
2222
logs: Type.Array(
2323
Type.Object({
24-
chainId: Type.Number(),
24+
chainId: Type.Integer(),
2525
contractAddress: AddressSchema,
26-
blockNumber: Type.Number(),
26+
blockNumber: Type.Integer(),
2727
transactionHash: TransactionHashSchema,
2828
topics: Type.Array(Type.String()),
2929
data: Type.String(),
3030
eventName: Type.Optional(Type.String()),
3131
decodedLog: Type.Any(),
32-
timestamp: Type.Number(),
33-
transactionIndex: Type.Number(),
34-
logIndex: Type.Number(),
32+
timestamp: Type.Integer(),
33+
transactionIndex: Type.Integer(),
34+
logIndex: Type.Integer(),
3535
}),
3636
),
3737
status: Type.String(),

src/server/routes/contract/events/getEventLogsByTimestamp.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@ import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
99
const requestQuerySchema = Type.Object({
1010
contractAddresses: Type.Optional(Type.Array(AddressSchema)),
1111
topics: Type.Optional(Type.Array(Type.String())),
12-
fromBlockTimestamp: Type.Number(),
13-
toBlockTimestamp: Type.Optional(Type.Number()),
12+
fromBlockTimestamp: Type.Integer({ minimum: 0 }),
13+
toBlockTimestamp: Type.Optional(Type.Integer({ minimum: 0 })),
1414
});
1515

1616
const responseSchema = Type.Object({

src/server/routes/contract/events/paginateEventLogs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { standardResponseSchema } from "../../../schemas/sharedApiSchemas";
99

1010
const requestQuerySchema = Type.Object({
1111
cursor: Type.Optional(Type.String()),
12-
pageSize: Type.Optional(Type.Number()),
12+
pageSize: Type.Optional(Type.Integer({ minimum: 1 })),
1313
topics: Type.Optional(Type.Array(Type.String())),
1414
contractAddresses: Type.Optional(Type.Array(AddressSchema)),
1515
});

src/server/routes/contract/extensions/erc1155/read/getActiveClaimConditions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
1212
// INPUT
1313
const requestSchema = contractParamSchema;
1414
const requestQueryString = Type.Object({
15-
tokenId: Type.Union([Type.String(), Type.Number()], {
15+
tokenId: Type.Union([Type.String(), Type.Integer()], {
1616
description: "The token ID of the NFT you want to claim.",
1717
}),
1818
withAllowList: Type.Optional(

src/server/routes/contract/extensions/erc1155/read/getAll.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,15 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
1313
const requestSchema = erc1155ContractParamSchema;
1414
const querystringSchema = Type.Object({
1515
start: Type.Optional(
16-
Type.Number({
16+
Type.Integer({
1717
description: "The start token ID for paginated results. Defaults to 0.",
18-
examples: ["0"],
18+
minimum: 0,
1919
}),
2020
),
2121
count: Type.Optional(
22-
Type.Number({
22+
Type.Integer({
2323
description: "The page count for paginated results. Defaults to 100.",
24-
examples: ["20"],
24+
minimum: 1,
2525
}),
2626
),
2727
});

src/server/routes/contract/extensions/erc1155/read/getAllClaimConditions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
1212
// INPUT
1313
const requestSchema = contractParamSchema;
1414
const requestQueryString = Type.Object({
15-
tokenId: Type.Union([Type.String(), Type.Number()], {
15+
tokenId: Type.Union([Type.String(), Type.Integer()], {
1616
description:
1717
"The token ID of the NFT you want to get the claim conditions for.",
1818
}),

src/server/routes/contract/extensions/erc1155/read/getClaimIneligibilityReasons.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ import { ClaimEligibility } from "@thirdweb-dev/sdk";
33
import type { FastifyInstance } from "fastify";
44
import { StatusCodes } from "http-status-codes";
55
import { getContract } from "../../../../../../utils/cache/getContract";
6+
import { AddressSchema } from "../../../../../schemas/address";
7+
import { NumberStringSchema } from "../../../../../schemas/number";
68
import {
79
contractParamSchema,
810
standardResponseSchema,
@@ -12,19 +14,18 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
1214
// INPUT
1315
const requestSchema = contractParamSchema;
1416
const requestQueryString = Type.Object({
15-
tokenId: Type.Union([Type.String(), Type.Number()], {
17+
tokenId: Type.Union([Type.String(), Type.Integer()], {
1618
description:
1719
"The token ID of the NFT you want to check if the wallet address can claim.",
1820
}),
19-
quantity: Type.String({
21+
quantity: {
22+
...NumberStringSchema,
2023
description: "The amount of tokens to claim.",
24+
},
25+
addressToCheck: Type.Optional({
26+
...AddressSchema,
27+
description: "The wallet address to check if it can claim tokens.",
2128
}),
22-
addressToCheck: Type.Optional(
23-
Type.String({
24-
description: "The wallet address to check if it can claim tokens.",
25-
examples: ["0x1946267d81Fb8aDeeEa28e6B98bcD446c8248473"],
26-
}),
27-
),
2829
});
2930

3031
// OUTPUT

src/server/routes/contract/extensions/erc1155/read/getClaimerProofs.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import { getChainIdFromChain } from "../../../../../utils/chain";
1313
// INPUT
1414
const requestSchema = contractParamSchema;
1515
const requestQueryString = Type.Object({
16-
tokenId: Type.Union([Type.String(), Type.Number()], {
16+
tokenId: Type.Union([Type.String(), Type.Integer()], {
1717
description:
1818
"The token ID of the NFT you want to get the claimer proofs for.",
1919
}),

0 commit comments

Comments
 (0)