Skip to content

Commit c0d42d1

Browse files
codybornclaude
andcommitted
refactor: drop isSupported gate; trust boundary SUPPORTED_CHAINS validation
The HTTP request boundary already enforces chainId ∈ SUPPORTED_CHAINS via Joi (lib/util/field-validator.ts:59, CHAIN_ID_JOI). Step Functions events in check-order-status are seeded by post-order, which inherits that validation. With the boundary trusted, the duplicated isSupported predicates in OnChainValidatorMap factories and the supported set in LazyProviderMap were dead weight. - OnChainValidatorMap: drop OnChainValidatorMapOptions and the has() method. Factory now passed positionally; get() always calls it on cache miss. has() had a single caller (V4 quoter check in UniswapXOrderService) handled below. - LazyProviderMap: drop the supported constructor param and getOrThrow(). get() now constructs+caches unconditionally and returns a StaticJsonRpcProvider non-null. The ProviderMap structural interface still allows undefined for Map<> compatibility. - UniswapXOrderService: replace this.onChainV4ValidatorMap?.has(chainId) with a direct UNISWAPX_V4_ORDER_QUOTER_MAPPING[chainId] lookup. The V4 quoter mapping is a property of the SDK + per-chain reactor deploys, not of the validator-map abstraction — keeping it at the call site removes the abstraction's only V4-specific concern. - Handlers: drop the supportedChainSet/isSupportedChain boilerplate; factory closures pass providerMap.get(chainId) directly. Net: -37 lines, no remaining duplicate "is this chain supported" logic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent d03d217 commit c0d42d1

6 files changed

Lines changed: 33 additions & 70 deletions

File tree

lib/handlers/OnChainValidatorMap.ts

Lines changed: 5 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,21 @@
11
import { OrderValidator, RelayOrderValidator, V4OrderValidator } from '@uniswap/uniswapx-sdk'
22
import { ChainId } from '../util/chain'
33

4-
export interface OnChainValidatorMapOptions<T> {
5-
factory: (chainId: ChainId) => T
6-
isSupported: (chainId: ChainId) => boolean
7-
}
8-
94
export class OnChainValidatorMap<T extends OrderValidator | RelayOrderValidator | V4OrderValidator> {
105
private chainIdToValidators: Map<ChainId, T> = new Map()
11-
private readonly options?: OnChainValidatorMapOptions<T>
6+
private readonly factory?: (chainId: ChainId) => T
127

13-
constructor(initial: Array<[ChainId, T]> = [], options?: OnChainValidatorMapOptions<T>) {
8+
constructor(initial: Array<[ChainId, T]> = [], factory?: (chainId: ChainId) => T) {
149
for (const [chainId, validator] of initial) {
1510
this.chainIdToValidators.set(chainId, validator)
1611
}
17-
this.options = options
12+
this.factory = factory
1813
}
1914

2015
get(chainId: ChainId): T {
2116
let validator = this.chainIdToValidators.get(chainId)
22-
if (!validator && this.options && this.options.isSupported(chainId)) {
23-
validator = this.options.factory(chainId)
17+
if (!validator && this.factory) {
18+
validator = this.factory(chainId)
2419
this.chainIdToValidators.set(chainId, validator)
2520
}
2621
if (!validator) {
@@ -30,11 +25,6 @@ export class OnChainValidatorMap<T extends OrderValidator | RelayOrderValidator
3025
return validator
3126
}
3227

33-
has(chainId: ChainId): boolean {
34-
if (this.chainIdToValidators.has(chainId)) return true
35-
return !!this.options && this.options.isSupported(chainId)
36-
}
37-
3828
set(chainId: ChainId, validator: T): void {
3929
this.chainIdToValidators.set(chainId, validator)
4030
}

lib/handlers/check-order-status/index.ts

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { LimitOrdersRepository } from '../../repositories/limit-orders-repositor
77
import { RelayOrderRepository } from '../../repositories/RelayOrderRepository'
88
import { AnalyticsService } from '../../services/analytics-service'
99
import { RelayOrderService } from '../../services/RelayOrderService'
10-
import { ChainId, SUPPORTED_CHAINS } from '../../util/chain'
1110
import { OffChainRelayOrderValidator } from '../../util/OffChainRelayOrderValidator'
1211
import { FillEventLogger } from '../check-order-status/fill-event-logger'
1312
import { calculateDutchRetryWaitSeconds, FILL_EVENT_LOOKBACK_BLOCKS_ON } from '../check-order-status/util'
@@ -19,14 +18,13 @@ import { CheckOrderStatusHandler } from './handler'
1918
import { CheckOrderStatusInjector } from './injector'
2019
import { CheckOrderStatusService, CheckOrderStatusUtils } from './service'
2120

22-
const supportedChainSet = new Set<ChainId>(SUPPORTED_CHAINS)
2321
const providerMap = new LazyProviderMap()
2422

2523
const relayOrderValidator = new OffChainRelayOrderValidator(() => new Date().getTime() / 1000)
26-
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>([], {
27-
factory: (chainId) => new OnChainRelayOrderValidator(providerMap.getOrThrow(chainId), chainId),
28-
isSupported: (chainId) => supportedChainSet.has(chainId),
29-
})
24+
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>(
25+
[],
26+
(chainId) => new OnChainRelayOrderValidator(providerMap.get(chainId), chainId)
27+
)
3028

3129
const relayOrderService = new RelayOrderService(
3230
relayOrderValidator,

lib/handlers/post-limit-order/index.ts

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import { AnalyticsService } from '../../services/analytics-service'
1010
import { OrderDispatcher } from '../../services/OrderDispatcher'
1111
import { RelayOrderService } from '../../services/RelayOrderService'
1212
import { UniswapXOrderService } from '../../services/UniswapXOrderService'
13-
import { ChainId, SUPPORTED_CHAINS } from '../../util/chain'
1413
import { ONE_YEAR_IN_SECONDS } from '../../util/constants'
1514
import { OffChainRelayOrderValidator } from '../../util/OffChainRelayOrderValidator'
1615
import { OffChainUniswapXOrderValidator } from '../../util/OffChainUniswapXOrderValidator'
@@ -24,20 +23,17 @@ import { LazyProviderMap } from '../shared'
2423
import { getMaxLimitOpenOrders, PostLimitOrderInjector } from './injector'
2524
import { DynamoQuoteMetadataRepository } from '../../repositories/quote-metadata-repository'
2625

27-
const supportedChainSet = new Set<ChainId>(SUPPORTED_CHAINS)
28-
const isSupportedChain = (chainId: ChainId) => supportedChainSet.has(chainId)
29-
3026
const providerMap = new LazyProviderMap()
3127

32-
const onChainValidatorMap = new OnChainValidatorMap<OnChainOrderValidator>([], {
33-
factory: (chainId) => new OnChainOrderValidator(providerMap.getOrThrow(chainId), chainId),
34-
isSupported: isSupportedChain,
35-
})
28+
const onChainValidatorMap = new OnChainValidatorMap<OnChainOrderValidator>(
29+
[],
30+
(chainId) => new OnChainOrderValidator(providerMap.get(chainId), chainId)
31+
)
3632

37-
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>([], {
38-
factory: (chainId) => new OnChainRelayOrderValidator(providerMap.getOrThrow(chainId), chainId),
39-
isSupported: isSupportedChain,
40-
})
33+
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>(
34+
[],
35+
(chainId) => new OnChainRelayOrderValidator(providerMap.get(chainId), chainId)
36+
)
4137

4238
const orderValidator = new OffChainUniswapXOrderValidator(() => new Date().getTime() / 1000, ONE_YEAR_IN_SECONDS, {
4339
SkipDecayStartTimeValidation: true,

lib/handlers/post-order/index.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import {
22
OrderValidator as OnChainOrderValidator,
33
RelayOrderValidator as OnChainRelayOrderValidator,
44
V4OrderValidator as OnChainV4OrderValidator,
5-
UNISWAPX_V4_ORDER_QUOTER_MAPPING as OnChainV4QuoterMapping
65
} from '@uniswap/uniswapx-sdk'
76
import { DynamoDB } from 'aws-sdk'
87
import { log } from '../../Logging'
@@ -18,7 +17,6 @@ import { S3WebhookConfigurationProvider } from '../../providers/s3-webhook-provi
1817
import { BETA_WEBHOOK_CONFIG_KEY, PRODUCTION_WEBHOOK_CONFIG_KEY, WEBHOOK_CONFIG_BUCKET } from '../../util/constants'
1918
import { STAGE } from '../../util/stage'
2019
import { checkDefined } from '../../preconditions/preconditions'
21-
import { ChainId, SUPPORTED_CHAINS } from '../../util/chain'
2220
import { ONE_DAY_IN_SECONDS } from '../../util/constants'
2321
import { OffChainRelayOrderValidator } from '../../util/OffChainRelayOrderValidator'
2422
import { OffChainUniswapXOrderValidator } from '../../util/OffChainUniswapXOrderValidator'
@@ -31,25 +29,22 @@ import { PostOrderHandler } from './handler'
3129
import { getMaxOpenOrders, PostOrderInjector } from './injector'
3230
import { PostOrderBodyParser } from './PostOrderBodyParser'
3331

34-
const supportedChainSet = new Set<ChainId>(SUPPORTED_CHAINS)
35-
const isSupportedChain = (chainId: ChainId) => supportedChainSet.has(chainId)
36-
3732
const providerMap = new LazyProviderMap()
3833

39-
const onChainValidatorMap = new OnChainValidatorMap<OnChainOrderValidator>([], {
40-
factory: (chainId) => new OnChainOrderValidator(providerMap.getOrThrow(chainId), chainId),
41-
isSupported: isSupportedChain,
42-
})
34+
const onChainValidatorMap = new OnChainValidatorMap<OnChainOrderValidator>(
35+
[],
36+
(chainId) => new OnChainOrderValidator(providerMap.get(chainId), chainId)
37+
)
4338

44-
const onChainV4ValidatorMap = new OnChainValidatorMap<OnChainV4OrderValidator>([], {
45-
factory: (chainId) => new OnChainV4OrderValidator(providerMap.getOrThrow(chainId), chainId),
46-
isSupported: (chainId) => isSupportedChain(chainId) && !!OnChainV4QuoterMapping[chainId],
47-
})
39+
const onChainV4ValidatorMap = new OnChainValidatorMap<OnChainV4OrderValidator>(
40+
[],
41+
(chainId) => new OnChainV4OrderValidator(providerMap.get(chainId), chainId)
42+
)
4843

49-
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>([], {
50-
factory: (chainId) => new OnChainRelayOrderValidator(providerMap.getOrThrow(chainId), chainId),
51-
isSupported: isSupportedChain,
52-
})
44+
const relayOrderValidatorMap = new OnChainValidatorMap<OnChainRelayOrderValidator>(
45+
[],
46+
(chainId) => new OnChainRelayOrderValidator(providerMap.get(chainId), chainId)
47+
)
5348

5449
const postOrderInjectorPromise = new PostOrderInjector('postOrderInjector').build()
5550

lib/handlers/shared/index.ts

Lines changed: 2 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { StaticJsonRpcProvider } from '@ethersproject/providers'
22
import { ethers } from 'ethers'
33
import { CONFIG } from '../../Config'
4-
import { ChainId, SUPPORTED_CHAINS } from '../../util/chain'
4+
import { ChainId } from '../../util/chain'
55
import { RPC_HEADERS } from '../../util/constants'
66

77
export interface ProviderMap {
@@ -10,14 +10,8 @@ export interface ProviderMap {
1010

1111
export class LazyProviderMap implements ProviderMap {
1212
private readonly providers: Map<ChainId, StaticJsonRpcProvider> = new Map()
13-
private readonly supported: Set<ChainId>
1413

15-
constructor(supported: readonly ChainId[] = SUPPORTED_CHAINS) {
16-
this.supported = new Set(supported)
17-
}
18-
19-
get(chainId: ChainId): StaticJsonRpcProvider | undefined {
20-
if (!this.supported.has(chainId)) return undefined
14+
get(chainId: ChainId): StaticJsonRpcProvider {
2115
let provider = this.providers.get(chainId)
2216
if (!provider) {
2317
provider = new ethers.providers.StaticJsonRpcProvider(
@@ -28,15 +22,4 @@ export class LazyProviderMap implements ProviderMap {
2822
}
2923
return provider
3024
}
31-
32-
// Strict variant for callers (e.g. validator factories) that must receive a
33-
// provider. Throws if the chainId is outside this map's supported set
34-
// instead of returning undefined.
35-
getOrThrow(chainId: ChainId): StaticJsonRpcProvider {
36-
const provider = this.get(chainId)
37-
if (!provider) {
38-
throw new Error(`No RPC provider configured for chain ${chainId}`)
39-
}
40-
return provider
41-
}
4225
}

lib/services/UniswapXOrderService.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
OrderValidator as OnChainOrderValidator,
1313
PermissionedTokenValidator,
1414
V4OrderValidator as OnChainV4OrderValidator,
15+
UNISWAPX_V4_ORDER_QUOTER_MAPPING as OnChainV4QuoterMapping,
1516
} from '@uniswap/uniswapx-sdk'
1617
import { ethers } from 'ethers'
1718
import { ORDER_STATUS, UniswapXOrderEntity } from '../entities'
@@ -208,7 +209,7 @@ export class UniswapXOrderService {
208209

209210
// Use V4 quoter for Hybrid orders if available on this chain
210211
if (order instanceof CosignedHybridOrder) {
211-
if (this.onChainV4ValidatorMap?.has(chainId)) {
212+
if (this.onChainV4ValidatorMap && OnChainV4QuoterMapping[chainId]) {
212213
const onChainV4Validator = this.onChainV4ValidatorMap.get(chainId)
213214
onChainValidationResult = await onChainV4Validator.validate({ order: order, signature: signature })
214215
} else {

0 commit comments

Comments
 (0)