@debridge-finance/borderless-validation-sdk 0.0.0-dev-3dc1a82 → 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/helpers/address.js +18 -31
- package/dist/cjs/helpers/address.js.map +1 -1
- package/dist/cjs/helpers/constants.js +6 -0
- package/dist/cjs/helpers/constants.js.map +1 -0
- package/dist/cjs/helpers/evm-action.js +3 -3
- package/dist/cjs/helpers/evm-action.js.map +1 -1
- package/dist/cjs/helpers/evm-intent-id.js +1 -1
- package/dist/cjs/helpers/evm-intent-id.js.map +1 -1
- package/dist/cjs/helpers/evm-trade-amounts.js +1 -36
- package/dist/cjs/helpers/evm-trade-amounts.js.map +1 -1
- package/dist/cjs/types/enums.js +2 -26
- package/dist/cjs/types/enums.js.map +1 -1
- package/dist/cjs/types/request.js +2 -25
- package/dist/cjs/types/request.js.map +1 -1
- package/dist/cjs/types/response.js +4 -120
- package/dist/cjs/types/response.js.map +1 -1
- package/dist/cjs/types/validation.js +10 -74
- package/dist/cjs/types/validation.js.map +1 -1
- package/dist/cjs/validations/evm-caveats.js +14 -4
- package/dist/cjs/validations/evm-caveats.js.map +1 -1
- package/dist/cjs/validations/evm-op-budget.js +10 -13
- package/dist/cjs/validations/evm-op-budget.js.map +1 -1
- package/dist/cjs/validations/evm-op-gas-compensation.js +152 -0
- package/dist/cjs/validations/evm-op-gas-compensation.js.map +1 -0
- package/dist/cjs/validations/evm-op-hook.js +3 -410
- package/dist/cjs/validations/evm-op-hook.js.map +1 -1
- package/dist/cjs/validations/evm-op-wrap.js +7 -10
- package/dist/cjs/validations/evm-op-wrap.js.map +1 -1
- package/dist/cjs/validations/evm-required-actions.js +9 -7
- package/dist/cjs/validations/evm-required-actions.js.map +1 -1
- package/dist/cjs/validations/evm-sign712-metamask.js +94 -17
- package/dist/cjs/validations/evm-sign712-metamask.js.map +1 -1
- package/dist/cjs/validations/evm-sign7702.js +22 -34
- package/dist/cjs/validations/evm-sign7702.js.map +1 -1
- package/dist/cjs/validations/hooks-common.js +37 -252
- package/dist/cjs/validations/hooks-common.js.map +1 -1
- package/dist/cjs/validations/required-actions.js +7 -4
- package/dist/cjs/validations/required-actions.js.map +1 -1
- package/dist/cjs/validations/solana-hook.js +18 -32
- package/dist/cjs/validations/solana-hook.js.map +1 -1
- package/dist/cjs/validations/solana-op-budget.js +18 -56
- package/dist/cjs/validations/solana-op-budget.js.map +1 -1
- package/dist/cjs/validations/solana-op-wrap.js +13 -46
- package/dist/cjs/validations/solana-op-wrap.js.map +1 -1
- package/dist/cjs/validations/solana-required-actions.js +3 -3
- package/dist/cjs/validations/solana-required-actions.js.map +1 -1
- package/dist/cjs/validations/solana-transaction.js +5 -5
- package/dist/cjs/validations/solana-transaction.js.map +1 -1
- package/dist/cjs/validations/trade-grouping.js +1 -68
- package/dist/cjs/validations/trade-grouping.js.map +1 -1
- package/dist/cjs/validations/trades.js +37 -59
- package/dist/cjs/validations/trades.js.map +1 -1
- package/dist/cjs/validator.js +16 -11
- package/dist/cjs/validator.js.map +1 -1
- package/dist/cjs/whitelists/environment-config.js +28 -47
- package/dist/cjs/whitelists/environment-config.js.map +1 -1
- package/dist/cjs/whitelists/evm/caveat-enforcers.js +5 -21
- package/dist/cjs/whitelists/evm/caveat-enforcers.js.map +1 -1
- package/dist/cjs/whitelists/evm/delegation-manager.js +2 -7
- package/dist/cjs/whitelists/evm/delegation-manager.js.map +1 -1
- package/dist/cjs/whitelists/evm/eip7702-delegation.js +2 -7
- package/dist/cjs/whitelists/evm/eip7702-delegation.js.map +1 -1
- package/dist/cjs/whitelists/evm/index.js +1 -14
- package/dist/cjs/whitelists/evm/index.js.map +1 -1
- package/dist/cjs/whitelists/evm/permit2.js +12 -16
- package/dist/cjs/whitelists/evm/permit2.js.map +1 -1
- package/dist/cjs/whitelists/evm/weth.js +5 -16
- package/dist/cjs/whitelists/evm/weth.js.map +1 -1
- package/dist/cjs/whitelists/solana/intent-signature.js +1 -0
- package/dist/cjs/whitelists/solana/intent-signature.js.map +1 -1
- package/dist/cjs/whitelists/subscription-to-chain-id.js +0 -10
- package/dist/cjs/whitelists/subscription-to-chain-id.js.map +1 -1
- package/dist/cjs/whitelists/types.js +3 -13
- package/dist/cjs/whitelists/types.js.map +1 -1
- package/dist/esm/helpers/address.js +17 -28
- package/dist/esm/helpers/address.js.map +1 -1
- package/dist/esm/helpers/constants.js +3 -0
- package/dist/esm/helpers/constants.js.map +1 -0
- package/dist/esm/helpers/evm-action.js +3 -3
- package/dist/esm/helpers/evm-action.js.map +1 -1
- package/dist/esm/helpers/evm-intent-id.js +1 -1
- package/dist/esm/helpers/evm-intent-id.js.map +1 -1
- package/dist/esm/helpers/evm-trade-amounts.js +1 -36
- package/dist/esm/helpers/evm-trade-amounts.js.map +1 -1
- package/dist/esm/types/enums.js +1 -25
- package/dist/esm/types/enums.js.map +1 -1
- package/dist/esm/types/request.js +3 -26
- package/dist/esm/types/request.js.map +1 -1
- package/dist/esm/types/response.js +3 -119
- package/dist/esm/types/response.js.map +1 -1
- package/dist/esm/types/validation.js +10 -74
- package/dist/esm/types/validation.js.map +1 -1
- package/dist/esm/validations/evm-caveats.js +14 -4
- package/dist/esm/validations/evm-caveats.js.map +1 -1
- package/dist/esm/validations/evm-op-budget.js +10 -13
- package/dist/esm/validations/evm-op-budget.js.map +1 -1
- package/dist/esm/validations/evm-op-gas-compensation.js +149 -0
- package/dist/esm/validations/evm-op-gas-compensation.js.map +1 -0
- package/dist/esm/validations/evm-op-hook.js +2 -409
- package/dist/esm/validations/evm-op-hook.js.map +1 -1
- package/dist/esm/validations/evm-op-wrap.js +7 -10
- package/dist/esm/validations/evm-op-wrap.js.map +1 -1
- package/dist/esm/validations/evm-required-actions.js +9 -7
- package/dist/esm/validations/evm-required-actions.js.map +1 -1
- package/dist/esm/validations/evm-sign712-metamask.js +94 -17
- package/dist/esm/validations/evm-sign712-metamask.js.map +1 -1
- package/dist/esm/validations/evm-sign7702.js +22 -33
- package/dist/esm/validations/evm-sign7702.js.map +1 -1
- package/dist/esm/validations/hooks-common.js +38 -251
- package/dist/esm/validations/hooks-common.js.map +1 -1
- package/dist/esm/validations/required-actions.js +7 -4
- package/dist/esm/validations/required-actions.js.map +1 -1
- package/dist/esm/validations/solana-hook.js +20 -34
- package/dist/esm/validations/solana-hook.js.map +1 -1
- package/dist/esm/validations/solana-op-budget.js +18 -56
- package/dist/esm/validations/solana-op-budget.js.map +1 -1
- package/dist/esm/validations/solana-op-wrap.js +14 -47
- package/dist/esm/validations/solana-op-wrap.js.map +1 -1
- package/dist/esm/validations/solana-required-actions.js +3 -3
- package/dist/esm/validations/solana-required-actions.js.map +1 -1
- package/dist/esm/validations/solana-transaction.js +7 -7
- package/dist/esm/validations/solana-transaction.js.map +1 -1
- package/dist/esm/validations/trade-grouping.js +1 -68
- package/dist/esm/validations/trade-grouping.js.map +1 -1
- package/dist/esm/validations/trades.js +37 -59
- package/dist/esm/validations/trades.js.map +1 -1
- package/dist/esm/validator.js +16 -11
- package/dist/esm/validator.js.map +1 -1
- package/dist/esm/whitelists/environment-config.js +28 -47
- package/dist/esm/whitelists/environment-config.js.map +1 -1
- package/dist/esm/whitelists/evm/caveat-enforcers.js +4 -20
- package/dist/esm/whitelists/evm/caveat-enforcers.js.map +1 -1
- package/dist/esm/whitelists/evm/delegation-manager.js +1 -6
- package/dist/esm/whitelists/evm/delegation-manager.js.map +1 -1
- package/dist/esm/whitelists/evm/eip7702-delegation.js +1 -6
- package/dist/esm/whitelists/evm/eip7702-delegation.js.map +1 -1
- package/dist/esm/whitelists/evm/index.js +4 -4
- package/dist/esm/whitelists/evm/index.js.map +1 -1
- package/dist/esm/whitelists/evm/permit2.js +5 -9
- package/dist/esm/whitelists/evm/permit2.js.map +1 -1
- package/dist/esm/whitelists/evm/weth.js +5 -16
- package/dist/esm/whitelists/evm/weth.js.map +1 -1
- package/dist/esm/whitelists/solana/intent-signature.js +1 -0
- package/dist/esm/whitelists/solana/intent-signature.js.map +1 -1
- package/dist/esm/whitelists/subscription-to-chain-id.js +0 -9
- package/dist/esm/whitelists/subscription-to-chain-id.js.map +1 -1
- package/dist/esm/whitelists/types.js +5 -14
- package/dist/esm/whitelists/types.js.map +1 -1
- package/dist/types/helpers/address.d.ts +7 -5
- package/dist/types/helpers/address.d.ts.map +1 -1
- package/dist/types/helpers/constants.d.ts +2 -0
- package/dist/types/helpers/constants.d.ts.map +1 -0
- package/dist/types/helpers/evm-trade-amounts.d.ts +2 -2
- package/dist/types/helpers/evm-trade-amounts.d.ts.map +1 -1
- package/dist/types/types/enums.d.ts +1 -19
- package/dist/types/types/enums.d.ts.map +1 -1
- package/dist/types/types/request.d.ts +9 -19
- package/dist/types/types/request.d.ts.map +1 -1
- package/dist/types/types/response.d.ts +11 -367
- package/dist/types/types/response.d.ts.map +1 -1
- package/dist/types/types/validation.d.ts +11 -67
- package/dist/types/types/validation.d.ts.map +1 -1
- package/dist/types/validations/evm-caveats.d.ts.map +1 -1
- package/dist/types/validations/evm-op-budget.d.ts +2 -2
- package/dist/types/validations/evm-op-budget.d.ts.map +1 -1
- package/dist/types/validations/evm-op-gas-compensation.d.ts +3 -0
- package/dist/types/validations/evm-op-gas-compensation.d.ts.map +1 -0
- package/dist/types/validations/evm-op-hook.d.ts +2 -4
- package/dist/types/validations/evm-op-hook.d.ts.map +1 -1
- package/dist/types/validations/evm-op-wrap.d.ts +2 -2
- package/dist/types/validations/evm-op-wrap.d.ts.map +1 -1
- package/dist/types/validations/evm-required-actions.d.ts +2 -2
- package/dist/types/validations/evm-required-actions.d.ts.map +1 -1
- package/dist/types/validations/evm-sign712-metamask.d.ts.map +1 -1
- package/dist/types/validations/evm-sign7702.d.ts +1 -2
- package/dist/types/validations/evm-sign7702.d.ts.map +1 -1
- package/dist/types/validations/hooks-common.d.ts +0 -1
- package/dist/types/validations/hooks-common.d.ts.map +1 -1
- package/dist/types/validations/required-actions.d.ts +1 -2
- package/dist/types/validations/required-actions.d.ts.map +1 -1
- package/dist/types/validations/solana-hook.d.ts +2 -4
- package/dist/types/validations/solana-hook.d.ts.map +1 -1
- package/dist/types/validations/solana-op-budget.d.ts +2 -2
- package/dist/types/validations/solana-op-budget.d.ts.map +1 -1
- package/dist/types/validations/solana-op-wrap.d.ts +2 -2
- package/dist/types/validations/solana-op-wrap.d.ts.map +1 -1
- package/dist/types/validations/solana-required-actions.d.ts +2 -2
- package/dist/types/validations/solana-required-actions.d.ts.map +1 -1
- package/dist/types/validations/solana-transaction.d.ts +3 -3
- package/dist/types/validations/solana-transaction.d.ts.map +1 -1
- package/dist/types/validations/trade-grouping.d.ts +2 -3
- package/dist/types/validations/trade-grouping.d.ts.map +1 -1
- package/dist/types/validator.d.ts.map +1 -1
- package/dist/types/whitelists/environment-config.d.ts.map +1 -1
- package/dist/types/whitelists/evm/caveat-enforcers.d.ts +0 -8
- package/dist/types/whitelists/evm/caveat-enforcers.d.ts.map +1 -1
- package/dist/types/whitelists/evm/delegation-manager.d.ts +0 -2
- package/dist/types/whitelists/evm/delegation-manager.d.ts.map +1 -1
- package/dist/types/whitelists/evm/eip7702-delegation.d.ts +0 -2
- package/dist/types/whitelists/evm/eip7702-delegation.d.ts.map +1 -1
- package/dist/types/whitelists/evm/index.d.ts +4 -4
- package/dist/types/whitelists/evm/index.d.ts.map +1 -1
- package/dist/types/whitelists/evm/permit2.d.ts +0 -1
- package/dist/types/whitelists/evm/permit2.d.ts.map +1 -1
- package/dist/types/whitelists/evm/weth.d.ts.map +1 -1
- package/dist/types/whitelists/solana/intent-signature.d.ts.map +1 -1
- package/dist/types/whitelists/subscription-to-chain-id.d.ts +0 -1
- package/dist/types/whitelists/subscription-to-chain-id.d.ts.map +1 -1
- package/dist/types/whitelists/types.d.ts +1 -1
- package/dist/types/whitelists/types.d.ts.map +1 -1
- package/package.json +2 -2
- package/README.md +0 -164
- package/dist/cjs/helpers/evm-gas-compensation-tx.js +0 -102
- package/dist/cjs/helpers/evm-gas-compensation-tx.js.map +0 -1
- package/dist/cjs/helpers/gas-compensation.js +0 -36
- package/dist/cjs/helpers/gas-compensation.js.map +0 -1
- package/dist/cjs/helpers/placeholder.js +0 -174
- package/dist/cjs/helpers/placeholder.js.map +0 -1
- package/dist/cjs/helpers/sets.js +0 -13
- package/dist/cjs/helpers/sets.js.map +0 -1
- package/dist/cjs/validations/compensation-hook.js +0 -203
- package/dist/cjs/validations/compensation-hook.js.map +0 -1
- package/dist/cjs/validations/evm-sign712-shared.js +0 -116
- package/dist/cjs/validations/evm-sign712-shared.js.map +0 -1
- package/dist/cjs/validations/intent-destinations.js +0 -197
- package/dist/cjs/validations/intent-destinations.js.map +0 -1
- package/dist/cjs/validations/intent-tokens.js +0 -341
- package/dist/cjs/validations/intent-tokens.js.map +0 -1
- package/dist/cjs/validations/intent.js +0 -288
- package/dist/cjs/validations/intent.js.map +0 -1
- package/dist/cjs/whitelists/evm/metamask-delegation-chains.js +0 -16
- package/dist/cjs/whitelists/evm/metamask-delegation-chains.js.map +0 -1
- package/dist/esm/helpers/evm-gas-compensation-tx.js +0 -99
- package/dist/esm/helpers/evm-gas-compensation-tx.js.map +0 -1
- package/dist/esm/helpers/gas-compensation.js +0 -33
- package/dist/esm/helpers/gas-compensation.js.map +0 -1
- package/dist/esm/helpers/placeholder.js +0 -168
- package/dist/esm/helpers/placeholder.js.map +0 -1
- package/dist/esm/helpers/sets.js +0 -10
- package/dist/esm/helpers/sets.js.map +0 -1
- package/dist/esm/validations/compensation-hook.js +0 -200
- package/dist/esm/validations/compensation-hook.js.map +0 -1
- package/dist/esm/validations/evm-sign712-shared.js +0 -110
- package/dist/esm/validations/evm-sign712-shared.js.map +0 -1
- package/dist/esm/validations/intent-destinations.js +0 -194
- package/dist/esm/validations/intent-destinations.js.map +0 -1
- package/dist/esm/validations/intent-tokens.js +0 -338
- package/dist/esm/validations/intent-tokens.js.map +0 -1
- package/dist/esm/validations/intent.js +0 -285
- package/dist/esm/validations/intent.js.map +0 -1
- package/dist/esm/whitelists/evm/metamask-delegation-chains.js +0 -13
- package/dist/esm/whitelists/evm/metamask-delegation-chains.js.map +0 -1
- package/dist/types/helpers/evm-gas-compensation-tx.d.ts +0 -13
- package/dist/types/helpers/evm-gas-compensation-tx.d.ts.map +0 -1
- package/dist/types/helpers/gas-compensation.d.ts +0 -10
- package/dist/types/helpers/gas-compensation.d.ts.map +0 -1
- package/dist/types/helpers/placeholder.d.ts +0 -41
- package/dist/types/helpers/placeholder.d.ts.map +0 -1
- package/dist/types/helpers/sets.d.ts +0 -2
- package/dist/types/helpers/sets.d.ts.map +0 -1
- package/dist/types/validations/compensation-hook.d.ts +0 -3
- package/dist/types/validations/compensation-hook.d.ts.map +0 -1
- package/dist/types/validations/evm-sign712-shared.d.ts +0 -7
- package/dist/types/validations/evm-sign712-shared.d.ts.map +0 -1
- package/dist/types/validations/intent-destinations.d.ts +0 -4
- package/dist/types/validations/intent-destinations.d.ts.map +0 -1
- package/dist/types/validations/intent-tokens.d.ts +0 -4
- package/dist/types/validations/intent-tokens.d.ts.map +0 -1
- package/dist/types/validations/intent.d.ts +0 -5
- package/dist/types/validations/intent.d.ts.map +0 -1
- package/dist/types/whitelists/evm/metamask-delegation-chains.d.ts +0 -3
- package/dist/types/whitelists/evm/metamask-delegation-chains.d.ts.map +0 -1
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { ViolationCode, } from "../types/index.js";
|
|
2
|
-
import { isWhitelisted } from "../whitelists/types.js";
|
|
3
|
-
import { DELEGATION_MANAGER_CONTRACTS } from "../whitelists/evm/index.js";
|
|
4
|
-
import { addressEquals } from "../helpers/address.js";
|
|
5
|
-
import { classifyCaveats, validateExactExecutionPresence, validateExactExecutionContent, validateTimestampEnforcerValue, } from "./evm-caveats.js";
|
|
6
|
-
// Shared content-validators for `Sign712MetaMaskCaveats` /
|
|
7
|
-
// `Sign712MetaMaskCaveatsWithPlaceholders` payloads. Used both in intent-scope
|
|
8
|
-
// and hook-scope.
|
|
9
|
-
// CRITICAL: `data` must be present and contain `domain` and `message`. If this
|
|
10
|
-
// fails, downstream content-validators must not run (they assume `data.domain`
|
|
11
|
-
// and `data.message` exist).
|
|
12
|
-
export function validateSign712DataPresent(data, actionPath) {
|
|
13
|
-
if (!data || !data.domain || !data.message) {
|
|
14
|
-
return [{
|
|
15
|
-
code: ViolationCode.Sign712MetaMaskDomainNameNotDelegationManager,
|
|
16
|
-
message: "Sign712MetaMask data is missing domain or message",
|
|
17
|
-
path: `${actionPath}.data`,
|
|
18
|
-
actual: data,
|
|
19
|
-
}];
|
|
20
|
-
}
|
|
21
|
-
return [];
|
|
22
|
-
}
|
|
23
|
-
// CRITICAL: domain.name must be "DelegationManager"
|
|
24
|
-
// CRITICAL: domain.chainId must equal the real chainId
|
|
25
|
-
// CRITICAL: domain.verifyingContract must be in the DelegationManager whitelist
|
|
26
|
-
export function validateSign712Domain(data, actionPath, realChainId) {
|
|
27
|
-
const violations = [];
|
|
28
|
-
if (data.domain.name !== "DelegationManager") {
|
|
29
|
-
violations.push({
|
|
30
|
-
code: ViolationCode.Sign712MetaMaskDomainNameNotDelegationManager,
|
|
31
|
-
message: `Sign712MetaMask domain.name must be "DelegationManager"`,
|
|
32
|
-
path: `${actionPath}.data.domain.name`,
|
|
33
|
-
expected: "DelegationManager",
|
|
34
|
-
actual: data.domain.name,
|
|
35
|
-
});
|
|
36
|
-
}
|
|
37
|
-
if (data.domain.chainId !== realChainId) {
|
|
38
|
-
violations.push({
|
|
39
|
-
code: ViolationCode.Sign712MetaMaskChainIdMismatch,
|
|
40
|
-
message: `Sign712MetaMask domain.chainId does not match the real chainId`,
|
|
41
|
-
path: `${actionPath}.data.domain.chainId`,
|
|
42
|
-
expected: realChainId,
|
|
43
|
-
actual: data.domain.chainId,
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
if (data.domain.verifyingContract === undefined
|
|
47
|
-
|| !isWhitelisted(DELEGATION_MANAGER_CONTRACTS, realChainId, data.domain.verifyingContract)) {
|
|
48
|
-
violations.push({
|
|
49
|
-
code: ViolationCode.Sign712MetaMaskVerifyingContractNotWhitelisted,
|
|
50
|
-
message: `Sign712MetaMask domain.verifyingContract is not whitelisted`,
|
|
51
|
-
path: `${actionPath}.data.domain.verifyingContract`,
|
|
52
|
-
actual: data.domain.verifyingContract,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
return violations;
|
|
56
|
-
}
|
|
57
|
-
// CRITICAL: message.delegator must match the address that requested the
|
|
58
|
-
// delegation. The trust source differs per scope (intent uses the trade's
|
|
59
|
-
// `srcChainAuthorityAddress`, hook uses `hook.from`); the comparison itself is
|
|
60
|
-
// shared. Caller passes `expectedDelegator = undefined` to record the violation
|
|
61
|
-
// without an expected value.
|
|
62
|
-
export function validateSign712Delegator(data, actionPath, realChainId, expectedDelegator, expectedSourceLabel) {
|
|
63
|
-
const delegator = data.message.delegator;
|
|
64
|
-
if (expectedDelegator === undefined
|
|
65
|
-
|| delegator === undefined
|
|
66
|
-
|| !addressEquals(realChainId, delegator, expectedDelegator)) {
|
|
67
|
-
return [{
|
|
68
|
-
code: ViolationCode.Sign712MetaMaskDelegatorMismatch,
|
|
69
|
-
message: `Sign712MetaMask message.delegator must match ${expectedSourceLabel}`,
|
|
70
|
-
path: `${actionPath}.data.message.delegator`,
|
|
71
|
-
expected: expectedDelegator,
|
|
72
|
-
actual: delegator,
|
|
73
|
-
}];
|
|
74
|
-
}
|
|
75
|
-
return [];
|
|
76
|
-
}
|
|
77
|
-
// CRITICAL: caveats must contain valid IdEnforcer (replay protection),
|
|
78
|
-
// TimestampEnforcer (with correct beforeThreshold), and ExactExecution /
|
|
79
|
-
// ExactExecutionBatch caveats whose content matches `transactionCalls[]`.
|
|
80
|
-
export function validateSign712Caveats(caveats, actionId, transactionCalls, actionPath, realChainId, expirationTimestamp) {
|
|
81
|
-
const violations = [];
|
|
82
|
-
const classified = classifyCaveats(caveats, actionId, actionPath, realChainId, violations);
|
|
83
|
-
violations.push(...validateExactExecutionPresence(classified, transactionCalls, actionPath));
|
|
84
|
-
validateExactExecutionContent(classified, transactionCalls, actionPath, violations);
|
|
85
|
-
// CRITICAL: must have at least one IdEnforcer caveat (replay protection)
|
|
86
|
-
if (!classified.hasIdEnforcer) {
|
|
87
|
-
violations.push({
|
|
88
|
-
code: ViolationCode.Sign712MetaMaskMissingIdEnforcerCaveat,
|
|
89
|
-
message: "Sign712MetaMask must have an IdEnforcer caveat",
|
|
90
|
-
path: `${actionPath}.data.message.caveats`,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
// CRITICAL: must have exactly one TimestampEnforcer caveat.
|
|
94
|
-
if (classified.timestampCount !== 1) {
|
|
95
|
-
violations.push({
|
|
96
|
-
code: classified.timestampCount === 0
|
|
97
|
-
? ViolationCode.Sign712MetaMaskMissingTimestampEnforcerCaveat
|
|
98
|
-
: ViolationCode.Sign712MetaMaskDuplicateTimestampEnforcerCaveat,
|
|
99
|
-
message: "Sign712MetaMask must have exactly one TimestampEnforcer",
|
|
100
|
-
path: `${actionPath}.data.message.caveats`,
|
|
101
|
-
expected: 1,
|
|
102
|
-
actual: classified.timestampCount,
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
if (classified.firstTimestamp) {
|
|
106
|
-
validateTimestampEnforcerValue(classified.firstTimestamp.caveat, expirationTimestamp, classified.firstTimestamp.index, actionPath, violations);
|
|
107
|
-
}
|
|
108
|
-
return violations;
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=evm-sign712-shared.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"evm-sign712-shared.js","sourceRoot":"","sources":["../../../src/validations/evm-sign712-shared.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,194 +0,0 @@
|
|
|
1
|
-
import { ViolationCode, SpecialChainId, ChainEngine, } from "../types/index.js";
|
|
2
|
-
import { detectChainEngine, getChainEngine, normalizeAddress, normalizeAddressByValue, } from "../helpers/address.js";
|
|
3
|
-
import { setsEqual } from "../helpers/sets.js";
|
|
4
|
-
import { resolveChainId } from "../whitelists/subscription-to-chain-id.js";
|
|
5
|
-
export function validateIntentDestinations(intent, group, basePath, quoteMode) {
|
|
6
|
-
// Safe skip: in quote mode receiverDetails/dstAuthorityAddress contain
|
|
7
|
-
// placeholder values per the API contract
|
|
8
|
-
if (quoteMode)
|
|
9
|
-
return [];
|
|
10
|
-
return [
|
|
11
|
-
...validateDestinationList(intent.receiverDetails, group, trade => trade.dstChainTokenOutRecipient, `${basePath}.receiverDetails`, {
|
|
12
|
-
addressInvalid: ViolationCode.IntentReceiverDetailsAddressInvalid,
|
|
13
|
-
chainIdsMismatch: ViolationCode.IntentReceiverDetailsChainIdsMismatch,
|
|
14
|
-
missing: ViolationCode.IntentReceiverDetailsMissing,
|
|
15
|
-
duplicate: ViolationCode.IntentReceiverDetailsDuplicate,
|
|
16
|
-
addressChainMismatch: ViolationCode.IntentReceiverDetailsAddressChainMismatch,
|
|
17
|
-
}, "receiverDetails"),
|
|
18
|
-
...validateDestinationList(intent.dstAuthorityAddress, group, trade => trade.dstChainAuthorityAddress, `${basePath}.dstAuthorityAddress`, {
|
|
19
|
-
addressInvalid: ViolationCode.IntentDstAuthorityAddressInvalid,
|
|
20
|
-
chainIdsMismatch: ViolationCode.IntentDstAuthorityChainIdsMismatch,
|
|
21
|
-
missing: ViolationCode.IntentDstAuthorityMissing,
|
|
22
|
-
duplicate: ViolationCode.IntentDstAuthorityDuplicate,
|
|
23
|
-
addressChainMismatch: ViolationCode.IntentDstAuthorityAddressChainMismatch,
|
|
24
|
-
}, "dstAuthorityAddress"),
|
|
25
|
-
];
|
|
26
|
-
}
|
|
27
|
-
// CRITICAL: the set of unique addresses in intent.<field>[] must exactly match
|
|
28
|
-
// the set of unique addresses in request.trades[].<pick>, with destinationChainIds
|
|
29
|
-
// containing exactly the chainIds where that address was used.
|
|
30
|
-
function validateDestinationList(details, group, pick, basePath, codes, fieldLabel) {
|
|
31
|
-
const violations = [];
|
|
32
|
-
const list = details ?? [];
|
|
33
|
-
const expected = collectExpectedByAddress(group, pick);
|
|
34
|
-
for (let i = 0; i < list.length; i++) {
|
|
35
|
-
violations.push(...validateAddressChainConsistency(list[i], `${basePath}[${i}]`, codes.addressChainMismatch, fieldLabel));
|
|
36
|
-
}
|
|
37
|
-
const firstOccurrence = buildFirstOccurrence(list, basePath, codes.duplicate, fieldLabel, violations);
|
|
38
|
-
violations.push(...reportMissingAddresses(expected, firstOccurrence, basePath, codes.missing, fieldLabel));
|
|
39
|
-
violations.push(...validateEntries(list, firstOccurrence, expected, basePath, codes, fieldLabel));
|
|
40
|
-
return violations;
|
|
41
|
-
}
|
|
42
|
-
// Builds address → chainIds map from request trades, mirroring the API's
|
|
43
|
-
// grouping by address.toHexAddress(). Each address gets the full set of
|
|
44
|
-
// chainIds where it was used.
|
|
45
|
-
function collectExpectedByAddress(group, pick) {
|
|
46
|
-
const byAddress = new Map();
|
|
47
|
-
for (const trade of group.trades) {
|
|
48
|
-
const address = pick(trade);
|
|
49
|
-
if (address === undefined)
|
|
50
|
-
continue;
|
|
51
|
-
const dstRealChainId = resolveChainId(trade.dstChainId);
|
|
52
|
-
// Safe skip: unknown dstChainId is reported by validateTrades
|
|
53
|
-
if (dstRealChainId === undefined)
|
|
54
|
-
continue;
|
|
55
|
-
const normalized = normalizeAddress(dstRealChainId, address);
|
|
56
|
-
const existing = byAddress.get(normalized) ?? new Set();
|
|
57
|
-
existing.add(trade.dstChainId);
|
|
58
|
-
byAddress.set(normalized, existing);
|
|
59
|
-
}
|
|
60
|
-
return byAddress;
|
|
61
|
-
}
|
|
62
|
-
// First pass over the response list: detects duplicates and records the
|
|
63
|
-
// first occurrence index per normalized address. Duplicate violations are
|
|
64
|
-
// appended directly to the caller's violations array.
|
|
65
|
-
function buildFirstOccurrence(list, basePath, duplicateCode, fieldLabel, violations) {
|
|
66
|
-
const firstOccurrence = new Map();
|
|
67
|
-
for (let i = 0; i < list.length; i++) {
|
|
68
|
-
const normalized = normalizeAddressByValue(list[i].address);
|
|
69
|
-
const earlier = firstOccurrence.get(normalized);
|
|
70
|
-
if (earlier === undefined) {
|
|
71
|
-
firstOccurrence.set(normalized, i);
|
|
72
|
-
continue;
|
|
73
|
-
}
|
|
74
|
-
violations.push({
|
|
75
|
-
code: duplicateCode,
|
|
76
|
-
message: `intent.${fieldLabel}[${i}] duplicates the entry at`
|
|
77
|
-
+ ` index ${earlier} — each address must appear once`,
|
|
78
|
-
path: `${basePath}[${i}].address`,
|
|
79
|
-
actual: normalized,
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
return firstOccurrence;
|
|
83
|
-
}
|
|
84
|
-
function reportMissingAddresses(expected, firstOccurrence, basePath, missingCode, fieldLabel) {
|
|
85
|
-
const violations = [];
|
|
86
|
-
for (const address of expected.keys()) {
|
|
87
|
-
if (!firstOccurrence.has(address)) {
|
|
88
|
-
violations.push({
|
|
89
|
-
code: missingCode,
|
|
90
|
-
message: `an expected intent.${fieldLabel}[].address is missing`
|
|
91
|
-
+ ` from the response`,
|
|
92
|
-
path: basePath,
|
|
93
|
-
expected: address,
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return violations;
|
|
98
|
-
}
|
|
99
|
-
function validateEntries(list, firstOccurrence, expected, basePath, codes, fieldLabel) {
|
|
100
|
-
const violations = [];
|
|
101
|
-
// Validate each unique entry (duplicates are already reported above)
|
|
102
|
-
for (const [address, i] of firstOccurrence) {
|
|
103
|
-
const entry = list[i];
|
|
104
|
-
const expectedChainIds = expected.get(address);
|
|
105
|
-
if (expectedChainIds === undefined) {
|
|
106
|
-
violations.push({
|
|
107
|
-
code: codes.addressInvalid,
|
|
108
|
-
message: `intent.${fieldLabel}[].address is not present in`
|
|
109
|
-
+ ` any request trade for this group`,
|
|
110
|
-
path: `${basePath}[${i}].address`,
|
|
111
|
-
expected: Array.from(expected.keys()),
|
|
112
|
-
actual: address,
|
|
113
|
-
});
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
violations.push(...validateEntryChainIds(entry, expectedChainIds, `${basePath}[${i}].destinationChainIds`, codes.chainIdsMismatch, fieldLabel));
|
|
117
|
-
}
|
|
118
|
-
return violations;
|
|
119
|
-
}
|
|
120
|
-
// CRITICAL: destinationChainIds must be exactly the set of chainIds where
|
|
121
|
-
// this address was used in the request. The protocol reserves SpecialChainId.Any
|
|
122
|
-
// but the API does not emit it today, so we reject it for now — support will
|
|
123
|
-
// be added when the API starts producing it.
|
|
124
|
-
function validateEntryChainIds(entry, expectedChainIds, path, code, fieldLabel) {
|
|
125
|
-
if (entry.destinationChainIds === SpecialChainId.Any) {
|
|
126
|
-
return [{
|
|
127
|
-
code,
|
|
128
|
-
message: `intent.${fieldLabel}[].destinationChainIds must be a concrete`
|
|
129
|
-
+ ` list of chainIds. SpecialChainId.Any is reserved by the`
|
|
130
|
-
+ ` protocol but not yet emitted by the API.`,
|
|
131
|
-
path,
|
|
132
|
-
expected: sortChainIds(expectedChainIds),
|
|
133
|
-
actual: entry.destinationChainIds,
|
|
134
|
-
}];
|
|
135
|
-
}
|
|
136
|
-
const actualChainIds = new Set(entry.destinationChainIds);
|
|
137
|
-
if (setsEqual(actualChainIds, expectedChainIds))
|
|
138
|
-
return [];
|
|
139
|
-
return [{
|
|
140
|
-
code,
|
|
141
|
-
message: `intent.${fieldLabel}[].destinationChainIds must contain exactly`
|
|
142
|
-
+ ` the chainIds where this address was used in request`
|
|
143
|
-
+ ` (no missing, no extras)`,
|
|
144
|
-
path,
|
|
145
|
-
expected: sortChainIds(expectedChainIds),
|
|
146
|
-
actual: entry.destinationChainIds,
|
|
147
|
-
}];
|
|
148
|
-
}
|
|
149
|
-
function sortChainIds(set) {
|
|
150
|
-
return Array.from(set).sort((a, b) => a - b);
|
|
151
|
-
}
|
|
152
|
-
// CRITICAL: all chainIds in destinationChainIds (unless set to "any") must
|
|
153
|
-
// share the same address format (engine), and entry.address must be in that format.
|
|
154
|
-
// MITM could otherwise return, e.g., destinationChainIds=[Ethereum, Solana]
|
|
155
|
-
// with an EVM address, which is impossible because one string can't be valid on both.
|
|
156
|
-
function validateAddressChainConsistency(entry, basePath, code, fieldLabel) {
|
|
157
|
-
if (entry.destinationChainIds === SpecialChainId.Any)
|
|
158
|
-
return [];
|
|
159
|
-
const engines = new Set();
|
|
160
|
-
for (const chainId of entry.destinationChainIds) {
|
|
161
|
-
const realChainId = resolveChainId(chainId);
|
|
162
|
-
// Safe skip: unknown dstChainId is reported by validateTrades
|
|
163
|
-
if (realChainId === undefined)
|
|
164
|
-
continue;
|
|
165
|
-
engines.add(getChainEngine(realChainId));
|
|
166
|
-
}
|
|
167
|
-
if (engines.size === 0)
|
|
168
|
-
return [];
|
|
169
|
-
if (engines.size > 1) {
|
|
170
|
-
return [{
|
|
171
|
-
code,
|
|
172
|
-
message: `intent.${fieldLabel}[].destinationChainIds spans multiple`
|
|
173
|
-
+ ` chain engines — a single address cannot be valid across`
|
|
174
|
-
+ ` different engines (EVM / Solana / Tron / etc.)`,
|
|
175
|
-
path: `${basePath}.destinationChainIds`,
|
|
176
|
-
actual: entry.destinationChainIds,
|
|
177
|
-
}];
|
|
178
|
-
}
|
|
179
|
-
const expectedEngine = engines.values().next().value;
|
|
180
|
-
const actualEngine = detectChainEngine(entry.address);
|
|
181
|
-
if (expectedEngine !== actualEngine) {
|
|
182
|
-
return [{
|
|
183
|
-
code,
|
|
184
|
-
message: `intent.${fieldLabel}[].address format (${ChainEngine[actualEngine]})`
|
|
185
|
-
+ ` does not match the chain engine of destinationChainIds`
|
|
186
|
-
+ ` (${ChainEngine[expectedEngine]})`,
|
|
187
|
-
path: `${basePath}.address`,
|
|
188
|
-
expected: { format: ChainEngine[expectedEngine] },
|
|
189
|
-
actual: { address: entry.address, format: ChainEngine[actualEngine] },
|
|
190
|
-
}];
|
|
191
|
-
}
|
|
192
|
-
return [];
|
|
193
|
-
}
|
|
194
|
-
//# sourceMappingURL=intent-destinations.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"intent-destinations.js","sourceRoot":"","sources":["../../../src/validations/intent-destinations.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,338 +0,0 @@
|
|
|
1
|
-
import { ViolationCode, SpecialAmount, ChainEngine, } from "../types/index.js";
|
|
2
|
-
import { detectChainEngine, getChainEngine, normalizeAddress, } from "../helpers/address.js";
|
|
3
|
-
import { resolveWrappedTokenAddress } from "../helpers/evm-token.js";
|
|
4
|
-
import { resolveChainId } from "../whitelists/subscription-to-chain-id.js";
|
|
5
|
-
export function validateIntentTokens(intent, group, basePath) {
|
|
6
|
-
const resolution = resolveGroupInputTokens(group);
|
|
7
|
-
return [
|
|
8
|
-
...resolution.violations,
|
|
9
|
-
...validateInputTokens(intent.inputToken, group, resolution.expected, `${basePath}.inputToken`),
|
|
10
|
-
...validateGiveTokens(intent, group, `${basePath}.giveToken`),
|
|
11
|
-
...validateTakeTokens(intent, group, `${basePath}.takeToken`),
|
|
12
|
-
];
|
|
13
|
-
}
|
|
14
|
-
// Resolves every request trade's srcChainTokenIn to its expected on-chain
|
|
15
|
-
// address (wrapped mint for native tokens) and returns the deduplicated set.
|
|
16
|
-
// A trade fails to resolve when it specifies a native token for a chain that
|
|
17
|
-
// has no WETH mapping in our whitelist. Each failure emits a dedicated violation
|
|
18
|
-
// so the caller knows which trade is unverifiable.
|
|
19
|
-
function resolveGroupInputTokens(group) {
|
|
20
|
-
const expected = new Set();
|
|
21
|
-
const violations = [];
|
|
22
|
-
for (let i = 0; i < group.trades.length; i++) {
|
|
23
|
-
const trade = group.trades[i];
|
|
24
|
-
const resolved = resolveWrappedTokenAddress(trade.srcChainTokenIn, group.realChainId);
|
|
25
|
-
if (resolved === undefined) {
|
|
26
|
-
violations.push({
|
|
27
|
-
code: ViolationCode.IntentInputTokenWrappedAddressUnknown,
|
|
28
|
-
message: "cannot resolve wrapped token address: native token on a"
|
|
29
|
-
+ " chain with no WETH mapping in the whitelist",
|
|
30
|
-
path: `request.trades[${group.tradeIndices[i]}].srcChainTokenIn`,
|
|
31
|
-
actual: trade.srcChainTokenIn,
|
|
32
|
-
});
|
|
33
|
-
continue;
|
|
34
|
-
}
|
|
35
|
-
expected.add(normalizeAddress(group.realChainId, resolved));
|
|
36
|
-
}
|
|
37
|
-
return { expected, violations };
|
|
38
|
-
}
|
|
39
|
-
// CRITICAL: intent.inputToken[] must represent exactly the set of unique
|
|
40
|
-
// srcChainTokenIn addresses from the group's trades (native → wrapped).
|
|
41
|
-
// Missing expected addresses, duplicate entries, and unknown addresses are
|
|
42
|
-
// each reported as specific violations.
|
|
43
|
-
function validateInputTokens(inputTokens, group, expectedTokens, basePath) {
|
|
44
|
-
const actual = inputTokens ?? [];
|
|
45
|
-
const violations = [];
|
|
46
|
-
const actualAddresses = actual.map(t => normalizeAddress(group.realChainId, t.address));
|
|
47
|
-
const firstOccurrence = new Map();
|
|
48
|
-
for (let i = 0; i < actualAddresses.length; i++) {
|
|
49
|
-
const address = actualAddresses[i];
|
|
50
|
-
const earlier = firstOccurrence.get(address);
|
|
51
|
-
if (earlier !== undefined) {
|
|
52
|
-
violations.push({
|
|
53
|
-
code: ViolationCode.IntentInputTokenDuplicate,
|
|
54
|
-
message: `intent.inputToken[${i}] duplicates the entry at index `
|
|
55
|
-
+ `${earlier} — each srcChainTokenIn (or its wrapped `
|
|
56
|
-
+ `equivalent) must appear once`,
|
|
57
|
-
path: `${basePath}[${i}].address`,
|
|
58
|
-
actual: address,
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
firstOccurrence.set(address, i);
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
for (const expectedToken of expectedTokens) {
|
|
66
|
-
if (!firstOccurrence.has(expectedToken)) {
|
|
67
|
-
violations.push({
|
|
68
|
-
code: ViolationCode.IntentInputTokenMissing,
|
|
69
|
-
message: "an expected srcChainTokenIn address (or its wrapped "
|
|
70
|
-
+ "equivalent) is missing from intent.inputToken[]",
|
|
71
|
-
path: basePath,
|
|
72
|
-
expected: expectedToken,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
75
|
-
}
|
|
76
|
-
// Validate each unique entry (duplicates were already reported above)
|
|
77
|
-
for (const [address, i] of firstOccurrence) {
|
|
78
|
-
if (!expectedTokens.has(address)) {
|
|
79
|
-
violations.push({
|
|
80
|
-
code: ViolationCode.IntentInputTokenAddressMismatch,
|
|
81
|
-
message: "intent.inputToken[].address does not match any request"
|
|
82
|
-
+ " srcChainTokenIn (including native-to-wrapped resolution)",
|
|
83
|
-
path: `${basePath}[${i}].address`,
|
|
84
|
-
expected: Array.from(expectedTokens),
|
|
85
|
-
actual: address,
|
|
86
|
-
});
|
|
87
|
-
continue;
|
|
88
|
-
}
|
|
89
|
-
violations.push(...validateConstraintBudget(actual[i], group, address, `${basePath}[${i}]`));
|
|
90
|
-
}
|
|
91
|
-
return violations;
|
|
92
|
-
}
|
|
93
|
-
// CRITICAL: constraintBudget equals the sum of request amounts for trades
|
|
94
|
-
// whose srcChainTokenIn resolves to this inputToken.address.
|
|
95
|
-
// Skipped when any contributing trade has non-numeric amount ('auto'/'max')
|
|
96
|
-
// or when any has prependOperatingExpenses=true (API adds unpredictable costs).
|
|
97
|
-
function validateConstraintBudget(inputToken, group, normalizedAddress, basePath) {
|
|
98
|
-
const contributingTrades = group.trades.filter(trade => {
|
|
99
|
-
const resolved = resolveWrappedTokenAddress(trade.srcChainTokenIn, group.realChainId);
|
|
100
|
-
// Safe skip: unresolved input tokens are already reported by
|
|
101
|
-
// resolveGroupInputTokens.
|
|
102
|
-
if (resolved === undefined)
|
|
103
|
-
return false;
|
|
104
|
-
return normalizeAddress(group.realChainId, resolved) === normalizedAddress;
|
|
105
|
-
});
|
|
106
|
-
if (!canPredictBudget(contributingTrades)) {
|
|
107
|
-
return [];
|
|
108
|
-
}
|
|
109
|
-
const expectedSum = contributingTrades.reduce((acc, trade) => acc + BigInt(trade.srcChainTokenInAmount), 0n);
|
|
110
|
-
let actualBudget;
|
|
111
|
-
try {
|
|
112
|
-
actualBudget = BigInt(inputToken.constraintBudget);
|
|
113
|
-
}
|
|
114
|
-
catch (error) {
|
|
115
|
-
return [{
|
|
116
|
-
code: ViolationCode.IntentNumericValueInvalid,
|
|
117
|
-
message: "intent.inputToken[].constraintBudget is not a valid number",
|
|
118
|
-
path: `${basePath}.constraintBudget`,
|
|
119
|
-
actual: inputToken.constraintBudget,
|
|
120
|
-
details: error,
|
|
121
|
-
}];
|
|
122
|
-
}
|
|
123
|
-
if (actualBudget !== expectedSum) {
|
|
124
|
-
return [{
|
|
125
|
-
code: ViolationCode.IntentConstraintBudgetMismatch,
|
|
126
|
-
message: "intent.inputToken[].constraintBudget must equal the sum of"
|
|
127
|
-
+ " request srcChainTokenInAmount values for the matching trades",
|
|
128
|
-
path: `${basePath}.constraintBudget`,
|
|
129
|
-
expected: expectedSum.toString(),
|
|
130
|
-
actual: inputToken.constraintBudget,
|
|
131
|
-
}];
|
|
132
|
-
}
|
|
133
|
-
return [];
|
|
134
|
-
}
|
|
135
|
-
function canPredictBudget(trades) {
|
|
136
|
-
return trades.every(trade => isNumericAmount(trade.srcChainTokenInAmount) &&
|
|
137
|
-
trade.prependOperatingExpenses !== true);
|
|
138
|
-
}
|
|
139
|
-
function isNumericAmount(amount) {
|
|
140
|
-
if (amount === SpecialAmount.Auto || amount === SpecialAmount.Max)
|
|
141
|
-
return false;
|
|
142
|
-
try {
|
|
143
|
-
BigInt(amount);
|
|
144
|
-
return true;
|
|
145
|
-
}
|
|
146
|
-
catch {
|
|
147
|
-
return false;
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
// CRITICAL: each giveToken[].inputTokenAddress must equal one of
|
|
151
|
-
// intent.inputToken[].address that is used by at least one cross-chain trade
|
|
152
|
-
// in the group. Same-chain trades do not produce giveToken entries.
|
|
153
|
-
// inputToken[] is separately validated against the request, so this rule
|
|
154
|
-
// forms a chain of trust: give → input → request.
|
|
155
|
-
function validateGiveTokens(intent, group, basePath) {
|
|
156
|
-
const allowed = collectInputAddressesForCrossChainTrades(intent, group);
|
|
157
|
-
const giveTokens = intent.giveToken ?? [];
|
|
158
|
-
if (allowed.size === 0) {
|
|
159
|
-
if (giveTokens.length > 0) {
|
|
160
|
-
return [{
|
|
161
|
-
code: ViolationCode.IntentGiveTokenNotEmptyForSameChain,
|
|
162
|
-
message: "intent.giveToken[] must be empty or undefined when no"
|
|
163
|
-
+ " trade in the group is cross-chain",
|
|
164
|
-
path: basePath,
|
|
165
|
-
expected: 0,
|
|
166
|
-
actual: giveTokens.length,
|
|
167
|
-
}];
|
|
168
|
-
}
|
|
169
|
-
return [];
|
|
170
|
-
}
|
|
171
|
-
const violations = [];
|
|
172
|
-
const expectedFormat = getChainEngine(group.realChainId);
|
|
173
|
-
for (let i = 0; i < giveTokens.length; i++) {
|
|
174
|
-
const normalized = normalizeAddress(group.realChainId, giveTokens[i].inputTokenAddress);
|
|
175
|
-
if (!allowed.has(normalized)) {
|
|
176
|
-
violations.push({
|
|
177
|
-
code: ViolationCode.IntentGiveTokenInputAddressMismatch,
|
|
178
|
-
message: "intent.giveToken[].inputTokenAddress must equal one of"
|
|
179
|
-
+ " intent.inputToken[].address used by a cross-chain"
|
|
180
|
-
+ " trade in the group",
|
|
181
|
-
path: `${basePath}[${i}].inputTokenAddress`,
|
|
182
|
-
expected: Array.from(allowed),
|
|
183
|
-
actual: giveTokens[i].inputTokenAddress,
|
|
184
|
-
});
|
|
185
|
-
}
|
|
186
|
-
// CRITICAL: giveTokenAddress is a bridge token in src chain — its value
|
|
187
|
-
// is API-determined and unpredictable, but its format must match the
|
|
188
|
-
// intent chain's engine.
|
|
189
|
-
const actualFormat = detectChainEngine(giveTokens[i].giveTokenAddress);
|
|
190
|
-
if (actualFormat !== expectedFormat) {
|
|
191
|
-
violations.push({
|
|
192
|
-
code: ViolationCode.IntentGiveTokenAddressFormatMismatch,
|
|
193
|
-
message: `intent.giveToken[].giveTokenAddress format (${ChainEngine[actualFormat]})`
|
|
194
|
-
+ ` does not match the intent chain engine`
|
|
195
|
-
+ ` (${ChainEngine[expectedFormat]})`,
|
|
196
|
-
path: `${basePath}[${i}].giveTokenAddress`,
|
|
197
|
-
expected: ChainEngine[expectedFormat],
|
|
198
|
-
actual: giveTokens[i].giveTokenAddress,
|
|
199
|
-
});
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return violations;
|
|
203
|
-
}
|
|
204
|
-
// Returns the subset of intent.inputToken[].address values that also appear
|
|
205
|
-
// as the (native-resolved) srcChainTokenIn of a cross-chain trade in the group.
|
|
206
|
-
function collectInputAddressesForCrossChainTrades(intent, group) {
|
|
207
|
-
const inputAddresses = new Set((intent.inputToken ?? []).map(t => normalizeAddress(group.realChainId, t.address)));
|
|
208
|
-
const result = new Set();
|
|
209
|
-
for (const trade of group.trades) {
|
|
210
|
-
if (!isCrossChain(trade))
|
|
211
|
-
continue;
|
|
212
|
-
const resolved = resolveWrappedTokenAddress(trade.srcChainTokenIn, group.realChainId);
|
|
213
|
-
// Safe skip: unresolved input tokens are already reported by
|
|
214
|
-
// resolveGroupInputTokens.
|
|
215
|
-
if (resolved === undefined)
|
|
216
|
-
continue;
|
|
217
|
-
const normalized = normalizeAddress(group.realChainId, resolved);
|
|
218
|
-
if (inputAddresses.has(normalized)) {
|
|
219
|
-
result.add(normalized);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
return result;
|
|
223
|
-
}
|
|
224
|
-
function isCrossChain(trade) {
|
|
225
|
-
return trade.srcChainId !== trade.dstChainId;
|
|
226
|
-
}
|
|
227
|
-
// CRITICAL: intent.takeToken[] must represent exactly the set of unique
|
|
228
|
-
// (dstChainId, dstChainTokenOut) pairs from the group's trades. Missing pairs,
|
|
229
|
-
// duplicate entries, and unknown chainId/address combinations are each reported
|
|
230
|
-
// as specific violations.
|
|
231
|
-
// CRITICAL: fromTokenAddress must be in inputToken[] (same-chain) or giveToken[]
|
|
232
|
-
// (cross-chain).
|
|
233
|
-
function validateTakeTokens(intent, group, basePath) {
|
|
234
|
-
const violations = [];
|
|
235
|
-
const expectedTakeTokens = buildExpectedTakeTokens(group);
|
|
236
|
-
const actualKeys = intent.takeToken.map(takeToken => buildTakeTokenKey(takeToken));
|
|
237
|
-
const firstOccurrence = new Map();
|
|
238
|
-
for (let i = 0; i < actualKeys.length; i++) {
|
|
239
|
-
const key = actualKeys[i];
|
|
240
|
-
const earlier = firstOccurrence.get(key);
|
|
241
|
-
if (earlier !== undefined) {
|
|
242
|
-
violations.push({
|
|
243
|
-
code: ViolationCode.IntentTakeTokenDuplicate,
|
|
244
|
-
message: `intent.takeToken[${i}] duplicates the entry at`
|
|
245
|
-
+ ` index ${earlier} — each (takeTokenChainId,`
|
|
246
|
-
+ ` takeTokenAddress) pair must appear once`,
|
|
247
|
-
path: `${basePath}[${i}]`,
|
|
248
|
-
actual: key,
|
|
249
|
-
});
|
|
250
|
-
}
|
|
251
|
-
else {
|
|
252
|
-
firstOccurrence.set(key, i);
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
for (const expectedTakeToken of expectedTakeTokens) {
|
|
256
|
-
if (!firstOccurrence.has(expectedTakeToken)) {
|
|
257
|
-
violations.push({
|
|
258
|
-
code: ViolationCode.IntentTakeTokenMissing,
|
|
259
|
-
message: "an expected (dstChainId, dstChainTokenOut) pair is"
|
|
260
|
-
+ " missing from intent.takeToken[]",
|
|
261
|
-
path: basePath,
|
|
262
|
-
expected: expectedTakeToken,
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
// Validate each unique entry (duplicates are already reported above)
|
|
267
|
-
for (const [, i] of firstOccurrence) {
|
|
268
|
-
violations.push(...validateSingleTakeToken(intent, intent.takeToken[i], group, expectedTakeTokens, `${basePath}[${i}]`));
|
|
269
|
-
}
|
|
270
|
-
return violations;
|
|
271
|
-
}
|
|
272
|
-
// Single source of truth for the "chainId:normalizedAddress" key format used
|
|
273
|
-
// to compare takeToken entries as a set. If realChainId is unknown we skip
|
|
274
|
-
// normalization so the function can still produce a deterministic key for
|
|
275
|
-
// duplicate detection; the chainId mismatch is flagged separately.
|
|
276
|
-
function buildChainTokenKey(chainId, realChainId, address) {
|
|
277
|
-
const normalized = realChainId !== undefined
|
|
278
|
-
? normalizeAddress(realChainId, address)
|
|
279
|
-
: address;
|
|
280
|
-
return `${chainId}:${normalized}`;
|
|
281
|
-
}
|
|
282
|
-
function buildTakeTokenKey(takeToken) {
|
|
283
|
-
return buildChainTokenKey(takeToken.takeTokenChainId, resolveChainId(takeToken.takeTokenChainId), takeToken.takeTokenAddress);
|
|
284
|
-
}
|
|
285
|
-
function buildExpectedTakeTokens(group) {
|
|
286
|
-
const set = new Set();
|
|
287
|
-
for (const trade of group.trades) {
|
|
288
|
-
const dstRealChainId = resolveChainId(trade.dstChainId);
|
|
289
|
-
// Safe skip: unknown subscriptionId for dstChainId is reported elsewhere
|
|
290
|
-
// (validateTrades reports UnknownSubscriptionId for dstChainId)
|
|
291
|
-
if (dstRealChainId === undefined)
|
|
292
|
-
continue;
|
|
293
|
-
set.add(buildChainTokenKey(trade.dstChainId, dstRealChainId, trade.dstChainTokenOut));
|
|
294
|
-
}
|
|
295
|
-
return set;
|
|
296
|
-
}
|
|
297
|
-
function validateSingleTakeToken(intent, takeToken, group, expected, basePath) {
|
|
298
|
-
const violations = [];
|
|
299
|
-
const dstRealChainId = resolveChainId(takeToken.takeTokenChainId);
|
|
300
|
-
// Safe skip: unknown subscriptionId for dstChainId is reported elsewhere
|
|
301
|
-
// (validateTrades reports UnknownSubscriptionId for dstChainId)
|
|
302
|
-
if (dstRealChainId !== undefined) {
|
|
303
|
-
const key = buildChainTokenKey(takeToken.takeTokenChainId, dstRealChainId, takeToken.takeTokenAddress);
|
|
304
|
-
if (!expected.has(key)) {
|
|
305
|
-
violations.push({
|
|
306
|
-
code: ViolationCode.IntentTakeTokenAddressMismatch,
|
|
307
|
-
message: "intent.takeToken[] (takeTokenChainId, takeTokenAddress)"
|
|
308
|
-
+ " pair does not match any request (dstChainId,"
|
|
309
|
-
+ " dstChainTokenOut) pair in the trade group",
|
|
310
|
-
path: basePath,
|
|
311
|
-
expected: Array.from(expected),
|
|
312
|
-
actual: key,
|
|
313
|
-
});
|
|
314
|
-
}
|
|
315
|
-
}
|
|
316
|
-
violations.push(...validateTakeTokenFromAddress(intent, takeToken, group, basePath));
|
|
317
|
-
return violations;
|
|
318
|
-
}
|
|
319
|
-
function validateTakeTokenFromAddress(intent, takeToken, group, basePath) {
|
|
320
|
-
const isSameChain = takeToken.takeTokenChainId === group.srcChainId;
|
|
321
|
-
const normalized = normalizeAddress(group.realChainId, takeToken.fromTokenAddress);
|
|
322
|
-
const allowedSet = isSameChain
|
|
323
|
-
? new Set((intent.inputToken ?? []).map(t => normalizeAddress(group.realChainId, t.address)))
|
|
324
|
-
: new Set((intent.giveToken ?? []).map(t => normalizeAddress(group.realChainId, t.giveTokenAddress)));
|
|
325
|
-
if (!allowedSet.has(normalized)) {
|
|
326
|
-
return [{
|
|
327
|
-
code: ViolationCode.IntentTakeTokenFromAddressInvalid,
|
|
328
|
-
message: isSameChain
|
|
329
|
-
? "intent.takeToken[].fromTokenAddress must be present in intent.inputToken[].address for same-chain trades"
|
|
330
|
-
: "intent.takeToken[].fromTokenAddress must be present in intent.giveToken[].giveTokenAddress for cross-chain trades",
|
|
331
|
-
path: `${basePath}.fromTokenAddress`,
|
|
332
|
-
expected: Array.from(allowedSet),
|
|
333
|
-
actual: takeToken.fromTokenAddress,
|
|
334
|
-
}];
|
|
335
|
-
}
|
|
336
|
-
return [];
|
|
337
|
-
}
|
|
338
|
-
//# sourceMappingURL=intent-tokens.js.map
|