@metamask/bridge-controller 1.0.0
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/CHANGELOG.md +17 -0
- package/LICENSE +20 -0
- package/README.md +15 -0
- package/dist/bridge-controller.cjs +249 -0
- package/dist/bridge-controller.cjs.map +1 -0
- package/dist/bridge-controller.d.cts +56 -0
- package/dist/bridge-controller.d.cts.map +1 -0
- package/dist/bridge-controller.d.mts +56 -0
- package/dist/bridge-controller.d.mts.map +1 -0
- package/dist/bridge-controller.mjs +245 -0
- package/dist/bridge-controller.mjs.map +1 -0
- package/dist/constants/bridge.cjs +60 -0
- package/dist/constants/bridge.cjs.map +1 -0
- package/dist/constants/bridge.d.cts +23 -0
- package/dist/constants/bridge.d.cts.map +1 -0
- package/dist/constants/bridge.d.mts +23 -0
- package/dist/constants/bridge.d.mts.map +1 -0
- package/dist/constants/bridge.mjs +57 -0
- package/dist/constants/bridge.mjs.map +1 -0
- package/dist/constants/chains.cjs +168 -0
- package/dist/constants/chains.cjs.map +1 -0
- package/dist/constants/chains.d.cts +156 -0
- package/dist/constants/chains.d.cts.map +1 -0
- package/dist/constants/chains.d.mts +156 -0
- package/dist/constants/chains.d.mts.map +1 -0
- package/dist/constants/chains.mjs +165 -0
- package/dist/constants/chains.mjs.map +1 -0
- package/dist/constants/swaps.cjs +5 -0
- package/dist/constants/swaps.cjs.map +1 -0
- package/dist/constants/swaps.d.cts +2 -0
- package/dist/constants/swaps.d.cts.map +1 -0
- package/dist/constants/swaps.d.mts +2 -0
- package/dist/constants/swaps.d.mts.map +1 -0
- package/dist/constants/swaps.mjs +2 -0
- package/dist/constants/swaps.mjs.map +1 -0
- package/dist/constants/tokens.cjs +109 -0
- package/dist/constants/tokens.cjs.map +1 -0
- package/dist/constants/tokens.d.cts +73 -0
- package/dist/constants/tokens.d.cts.map +1 -0
- package/dist/constants/tokens.d.mts +73 -0
- package/dist/constants/tokens.d.mts.map +1 -0
- package/dist/constants/tokens.mjs +106 -0
- package/dist/constants/tokens.mjs.map +1 -0
- package/dist/index.cjs +26 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +9 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +9 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +6 -0
- package/dist/index.mjs.map +1 -0
- package/dist/types.cjs +77 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.cts +232 -0
- package/dist/types.d.cts.map +1 -0
- package/dist/types.d.mts +232 -0
- package/dist/types.d.mts.map +1 -0
- package/dist/types.mjs +74 -0
- package/dist/types.mjs.map +1 -0
- package/dist/utils/balance.cjs +31 -0
- package/dist/utils/balance.cjs.map +1 -0
- package/dist/utils/balance.d.cts +6 -0
- package/dist/utils/balance.d.cts.map +1 -0
- package/dist/utils/balance.d.mts +6 -0
- package/dist/utils/balance.d.mts.map +1 -0
- package/dist/utils/balance.mjs +25 -0
- package/dist/utils/balance.mjs.map +1 -0
- package/dist/utils/bridge.cjs +81 -0
- package/dist/utils/bridge.cjs.map +1 -0
- package/dist/utils/bridge.d.cts +31 -0
- package/dist/utils/bridge.d.cts.map +1 -0
- package/dist/utils/bridge.d.mts +31 -0
- package/dist/utils/bridge.d.mts.map +1 -0
- package/dist/utils/bridge.mjs +71 -0
- package/dist/utils/bridge.mjs.map +1 -0
- package/dist/utils/fetch.cjs +122 -0
- package/dist/utils/fetch.cjs.map +1 -0
- package/dist/utils/fetch.d.cts +33 -0
- package/dist/utils/fetch.d.cts.map +1 -0
- package/dist/utils/fetch.d.mts +33 -0
- package/dist/utils/fetch.d.mts.map +1 -0
- package/dist/utils/fetch.mjs +115 -0
- package/dist/utils/fetch.mjs.map +1 -0
- package/dist/utils/quote.cjs +27 -0
- package/dist/utils/quote.cjs.map +1 -0
- package/dist/utils/quote.d.cts +3 -0
- package/dist/utils/quote.d.cts.map +1 -0
- package/dist/utils/quote.d.mts +3 -0
- package/dist/utils/quote.d.mts.map +1 -0
- package/dist/utils/quote.mjs +23 -0
- package/dist/utils/quote.mjs.map +1 -0
- package/dist/utils/validators.cjs +112 -0
- package/dist/utils/validators.cjs.map +1 -0
- package/dist/utils/validators.d.cts +30 -0
- package/dist/utils/validators.d.cts.map +1 -0
- package/dist/utils/validators.d.mts +30 -0
- package/dist/utils/validators.d.mts.map +1 -0
- package/dist/utils/validators.mjs +104 -0
- package/dist/utils/validators.mjs.map +1 -0
- package/package.json +86 -0
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
2
|
+
import type { SwapsTokenObject } from "../constants/tokens.cjs";
|
|
3
|
+
import type { QuoteRequest, QuoteResponse, BridgeFeatureFlags, FetchFunction } from "../types.cjs";
|
|
4
|
+
export declare const getClientIdHeader: (clientId: string) => {
|
|
5
|
+
'X-Client-Id': string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Fetches the bridge feature flags
|
|
9
|
+
*
|
|
10
|
+
* @param clientId - The client ID for metrics
|
|
11
|
+
* @param fetchFn - The fetch function to use
|
|
12
|
+
* @returns The bridge feature flags
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetchBridgeFeatureFlags(clientId: string, fetchFn: FetchFunction): Promise<BridgeFeatureFlags>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a list of enabled (unblocked) tokens
|
|
17
|
+
*
|
|
18
|
+
* @param chainId - The chain ID to fetch tokens for
|
|
19
|
+
* @param clientId - The client ID for metrics
|
|
20
|
+
* @param fetchFn - The fetch function to use
|
|
21
|
+
* @returns A list of enabled (unblocked) tokens
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchBridgeTokens(chainId: Hex, clientId: string, fetchFn: FetchFunction): Promise<Record<string, SwapsTokenObject>>;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param request - The quote request
|
|
27
|
+
* @param signal - The abort signal
|
|
28
|
+
* @param clientId - The client ID for metrics
|
|
29
|
+
* @param fetchFn - The fetch function to use
|
|
30
|
+
* @returns A list of bridge tx quotes
|
|
31
|
+
*/
|
|
32
|
+
export declare function fetchBridgeQuotes(request: QuoteRequest, signal: AbortSignal, clientId: string, fetchFn: FetchFunction): Promise<QuoteResponse[]>;
|
|
33
|
+
//# sourceMappingURL=fetch.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.cts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAkB3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAA4B;AAE5D,OAAO,KAAK,EAIV,YAAY,EACZ,aAAa,EAEb,kBAAkB,EAClB,aAAa,EACd,qBAAiB;AAMlB,eAAO,MAAM,iBAAiB,aAAc,MAAM;;CAEhD,CAAC;AAEH;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAqC7B;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,GAAG,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAmC3C;AAGD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CAiD1B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { Hex } from "@metamask/utils";
|
|
2
|
+
import type { SwapsTokenObject } from "../constants/tokens.mjs";
|
|
3
|
+
import type { QuoteRequest, QuoteResponse, BridgeFeatureFlags, FetchFunction } from "../types.mjs";
|
|
4
|
+
export declare const getClientIdHeader: (clientId: string) => {
|
|
5
|
+
'X-Client-Id': string;
|
|
6
|
+
};
|
|
7
|
+
/**
|
|
8
|
+
* Fetches the bridge feature flags
|
|
9
|
+
*
|
|
10
|
+
* @param clientId - The client ID for metrics
|
|
11
|
+
* @param fetchFn - The fetch function to use
|
|
12
|
+
* @returns The bridge feature flags
|
|
13
|
+
*/
|
|
14
|
+
export declare function fetchBridgeFeatureFlags(clientId: string, fetchFn: FetchFunction): Promise<BridgeFeatureFlags>;
|
|
15
|
+
/**
|
|
16
|
+
* Returns a list of enabled (unblocked) tokens
|
|
17
|
+
*
|
|
18
|
+
* @param chainId - The chain ID to fetch tokens for
|
|
19
|
+
* @param clientId - The client ID for metrics
|
|
20
|
+
* @param fetchFn - The fetch function to use
|
|
21
|
+
* @returns A list of enabled (unblocked) tokens
|
|
22
|
+
*/
|
|
23
|
+
export declare function fetchBridgeTokens(chainId: Hex, clientId: string, fetchFn: FetchFunction): Promise<Record<string, SwapsTokenObject>>;
|
|
24
|
+
/**
|
|
25
|
+
*
|
|
26
|
+
* @param request - The quote request
|
|
27
|
+
* @param signal - The abort signal
|
|
28
|
+
* @param clientId - The client ID for metrics
|
|
29
|
+
* @param fetchFn - The fetch function to use
|
|
30
|
+
* @returns A list of bridge tx quotes
|
|
31
|
+
*/
|
|
32
|
+
export declare function fetchBridgeQuotes(request: QuoteRequest, signal: AbortSignal, clientId: string, fetchFn: FetchFunction): Promise<QuoteResponse[]>;
|
|
33
|
+
//# sourceMappingURL=fetch.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.d.mts","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,GAAG,EAAE,wBAAwB;AAkB3C,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAA4B;AAE5D,OAAO,KAAK,EAIV,YAAY,EACZ,aAAa,EAEb,kBAAkB,EAClB,aAAa,EACd,qBAAiB;AAMlB,eAAO,MAAM,iBAAiB,aAAc,MAAM;;CAEhD,CAAC;AAEH;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,kBAAkB,CAAC,CAqC7B;AAED;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,GAAG,EACZ,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC,CAmC3C;AAGD;;;;;;;GAOG;AACH,wBAAsB,iBAAiB,CACrC,OAAO,EAAE,YAAY,EACrB,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,aAAa,GACrB,OAAO,CAAC,aAAa,EAAE,CAAC,CAiD1B"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { hexToNumber, numberToHex } from "@metamask/utils";
|
|
2
|
+
import { isSwapsDefaultTokenAddress, isSwapsDefaultTokenSymbol, getBridgeApiBaseUrl } from "./bridge.mjs";
|
|
3
|
+
import { FEATURE_FLAG_VALIDATORS, QUOTE_VALIDATORS, TX_DATA_VALIDATORS, TOKEN_VALIDATORS, validateResponse, QUOTE_RESPONSE_VALIDATORS, FEE_DATA_VALIDATORS } from "./validators.mjs";
|
|
4
|
+
import { REFRESH_INTERVAL_MS } from "../constants/bridge.mjs";
|
|
5
|
+
import { SWAPS_CHAINID_DEFAULT_TOKEN_MAP } from "../constants/tokens.mjs";
|
|
6
|
+
import { BridgeFlag, FeeType, BridgeFeatureFlagsKey } from "../types.mjs";
|
|
7
|
+
// TODO put this back in once we have a fetchWithCache equivalent
|
|
8
|
+
// const CACHE_REFRESH_TEN_MINUTES = 10 * Duration.Minute;
|
|
9
|
+
export const getClientIdHeader = (clientId) => ({
|
|
10
|
+
'X-Client-Id': clientId,
|
|
11
|
+
});
|
|
12
|
+
/**
|
|
13
|
+
* Fetches the bridge feature flags
|
|
14
|
+
*
|
|
15
|
+
* @param clientId - The client ID for metrics
|
|
16
|
+
* @param fetchFn - The fetch function to use
|
|
17
|
+
* @returns The bridge feature flags
|
|
18
|
+
*/
|
|
19
|
+
export async function fetchBridgeFeatureFlags(clientId, fetchFn) {
|
|
20
|
+
const url = `${getBridgeApiBaseUrl()}/getAllFeatureFlags`;
|
|
21
|
+
const rawFeatureFlags = await fetchFn(url, {
|
|
22
|
+
headers: getClientIdHeader(clientId),
|
|
23
|
+
});
|
|
24
|
+
if (validateResponse(FEATURE_FLAG_VALIDATORS, rawFeatureFlags, url)) {
|
|
25
|
+
return {
|
|
26
|
+
[BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {
|
|
27
|
+
...rawFeatureFlags[BridgeFlag.EXTENSION_CONFIG],
|
|
28
|
+
chains: Object.entries(rawFeatureFlags[BridgeFlag.EXTENSION_CONFIG].chains).reduce((acc, [chainId, value]) => ({
|
|
29
|
+
...acc,
|
|
30
|
+
[numberToHex(Number(chainId))]: value,
|
|
31
|
+
}), {}),
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
[BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {
|
|
37
|
+
refreshRate: REFRESH_INTERVAL_MS,
|
|
38
|
+
maxRefreshCount: 5,
|
|
39
|
+
support: false,
|
|
40
|
+
chains: {},
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Returns a list of enabled (unblocked) tokens
|
|
46
|
+
*
|
|
47
|
+
* @param chainId - The chain ID to fetch tokens for
|
|
48
|
+
* @param clientId - The client ID for metrics
|
|
49
|
+
* @param fetchFn - The fetch function to use
|
|
50
|
+
* @returns A list of enabled (unblocked) tokens
|
|
51
|
+
*/
|
|
52
|
+
export async function fetchBridgeTokens(chainId, clientId, fetchFn) {
|
|
53
|
+
// TODO make token api v2 call
|
|
54
|
+
const url = `${getBridgeApiBaseUrl()}/getTokens?chainId=${hexToNumber(chainId)}`;
|
|
55
|
+
// TODO we will need to cache these. In Extension fetchWithCache is used. This is due to the following:
|
|
56
|
+
// If we allow selecting dest networks which the user has not imported,
|
|
57
|
+
// note that the Assets controller won't be able to provide tokens. In extension we fetch+cache the token list from bridge-api to handle this
|
|
58
|
+
const tokens = await fetchFn(url, {
|
|
59
|
+
headers: getClientIdHeader(clientId),
|
|
60
|
+
});
|
|
61
|
+
const nativeToken = SWAPS_CHAINID_DEFAULT_TOKEN_MAP[chainId];
|
|
62
|
+
const transformedTokens = {};
|
|
63
|
+
if (nativeToken) {
|
|
64
|
+
transformedTokens[nativeToken.address] = nativeToken;
|
|
65
|
+
}
|
|
66
|
+
tokens.forEach((token) => {
|
|
67
|
+
if (validateResponse(TOKEN_VALIDATORS, token, url, false) &&
|
|
68
|
+
!(isSwapsDefaultTokenSymbol(token.symbol, chainId) ||
|
|
69
|
+
isSwapsDefaultTokenAddress(token.address, chainId))) {
|
|
70
|
+
transformedTokens[token.address] = token;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return transformedTokens;
|
|
74
|
+
}
|
|
75
|
+
// Returns a list of bridge tx quotes
|
|
76
|
+
/**
|
|
77
|
+
*
|
|
78
|
+
* @param request - The quote request
|
|
79
|
+
* @param signal - The abort signal
|
|
80
|
+
* @param clientId - The client ID for metrics
|
|
81
|
+
* @param fetchFn - The fetch function to use
|
|
82
|
+
* @returns A list of bridge tx quotes
|
|
83
|
+
*/
|
|
84
|
+
export async function fetchBridgeQuotes(request, signal, clientId, fetchFn) {
|
|
85
|
+
const queryParams = new URLSearchParams({
|
|
86
|
+
walletAddress: request.walletAddress,
|
|
87
|
+
srcChainId: request.srcChainId.toString(),
|
|
88
|
+
destChainId: request.destChainId.toString(),
|
|
89
|
+
srcTokenAddress: request.srcTokenAddress,
|
|
90
|
+
destTokenAddress: request.destTokenAddress,
|
|
91
|
+
srcTokenAmount: request.srcTokenAmount,
|
|
92
|
+
slippage: request.slippage.toString(),
|
|
93
|
+
insufficientBal: request.insufficientBal ? 'true' : 'false',
|
|
94
|
+
resetApproval: request.resetApproval ? 'true' : 'false',
|
|
95
|
+
});
|
|
96
|
+
const url = `${getBridgeApiBaseUrl()}/getQuote?${queryParams}`;
|
|
97
|
+
const quotes = await fetchFn(url, {
|
|
98
|
+
headers: getClientIdHeader(clientId),
|
|
99
|
+
signal,
|
|
100
|
+
});
|
|
101
|
+
const filteredQuotes = quotes.filter((quoteResponse) => {
|
|
102
|
+
const { quote, approval, trade } = quoteResponse;
|
|
103
|
+
return (validateResponse(QUOTE_RESPONSE_VALIDATORS, quoteResponse, url) &&
|
|
104
|
+
validateResponse(QUOTE_VALIDATORS, quote, url) &&
|
|
105
|
+
validateResponse(TOKEN_VALIDATORS, quote.srcAsset, url) &&
|
|
106
|
+
validateResponse(TOKEN_VALIDATORS, quote.destAsset, url) &&
|
|
107
|
+
validateResponse(TX_DATA_VALIDATORS, trade, url) &&
|
|
108
|
+
validateResponse(FEE_DATA_VALIDATORS, quote.feeData[FeeType.METABRIDGE], url) &&
|
|
109
|
+
(approval
|
|
110
|
+
? validateResponse(TX_DATA_VALIDATORS, approval, url)
|
|
111
|
+
: true));
|
|
112
|
+
});
|
|
113
|
+
return filteredQuotes;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=fetch.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch.mjs","sourceRoot":"","sources":["../../src/utils/fetch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB;AAE3D,OAAO,EACL,0BAA0B,EAC1B,yBAAyB,EACzB,mBAAmB,EACpB,qBAAiB;AAClB,OAAO,EACL,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,EAClB,gBAAgB,EAChB,gBAAgB,EAChB,yBAAyB,EACzB,mBAAmB,EACpB,yBAAqB;AACtB,OAAO,EAAE,mBAAmB,EAAE,gCAA4B;AAE1D,OAAO,EAAE,+BAA+B,EAAE,gCAA4B;AAWtE,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,qBAAqB,EAAE,qBAAiB;AAEtE,iEAAiE;AACjE,0DAA0D;AAE1D,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,CAAC;IACtD,aAAa,EAAE,QAAQ;CACxB,CAAC,CAAC;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAC3C,QAAgB,EAChB,OAAsB;IAEtB,MAAM,GAAG,GAAG,GAAG,mBAAmB,EAAE,qBAAqB,CAAC;IAC1D,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QACzC,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC;KACrC,CAAC,CAAC;IAEH,IACE,gBAAgB,CACd,uBAAuB,EACvB,eAAe,EACf,GAAG,CACJ,EACD;QACA,OAAO;YACL,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,EAAE;gBACxC,GAAG,eAAe,CAAC,UAAU,CAAC,gBAAgB,CAAC;gBAC/C,MAAM,EAAE,MAAM,CAAC,OAAO,CACpB,eAAe,CAAC,UAAU,CAAC,gBAAgB,CAAC,CAAC,MAAM,CACpD,CAAC,MAAM,CACN,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC1B,GAAG,GAAG;oBACN,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,KAAK;iBACtC,CAAC,EACF,EAAE,CACH;aACF;SACF,CAAC;KACH;IAED,OAAO;QACL,CAAC,qBAAqB,CAAC,gBAAgB,CAAC,EAAE;YACxC,WAAW,EAAE,mBAAmB;YAChC,eAAe,EAAE,CAAC;YAClB,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,EAAE;SACX;KACF,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAY,EACZ,QAAgB,EAChB,OAAsB;IAEtB,8BAA8B;IAC9B,MAAM,GAAG,GAAG,GAAG,mBAAmB,EAAE,sBAAsB,WAAW,CACnE,OAAO,CACR,EAAE,CAAC;IAEJ,uGAAuG;IACvG,uEAAuE;IACvE,6IAA6I;IAC7I,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC;KACrC,CAAC,CAAC;IAEH,MAAM,WAAW,GACf,+BAA+B,CAC7B,OAAuD,CACxD,CAAC;IAEJ,MAAM,iBAAiB,GAAqC,EAAE,CAAC;IAC/D,IAAI,WAAW,EAAE;QACf,iBAAiB,CAAC,WAAW,CAAC,OAAO,CAAC,GAAG,WAAW,CAAC;KACtD;IAED,MAAM,CAAC,OAAO,CAAC,CAAC,KAAc,EAAE,EAAE;QAChC,IACE,gBAAgB,CAAmB,gBAAgB,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,CAAC;YACvE,CAAC,CACC,yBAAyB,CAAC,KAAK,CAAC,MAAM,EAAE,OAAO,CAAC;gBAChD,0BAA0B,CAAC,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CACnD,EACD;YACA,iBAAiB,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC;SAC1C;IACH,CAAC,CAAC,CAAC;IACH,OAAO,iBAAiB,CAAC;AAC3B,CAAC;AAED,qCAAqC;AACrC;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,OAAqB,EACrB,MAAmB,EACnB,QAAgB,EAChB,OAAsB;IAEtB,MAAM,WAAW,GAAG,IAAI,eAAe,CAAC;QACtC,aAAa,EAAE,OAAO,CAAC,aAAa;QACpC,UAAU,EAAE,OAAO,CAAC,UAAU,CAAC,QAAQ,EAAE;QACzC,WAAW,EAAE,OAAO,CAAC,WAAW,CAAC,QAAQ,EAAE;QAC3C,eAAe,EAAE,OAAO,CAAC,eAAe;QACxC,gBAAgB,EAAE,OAAO,CAAC,gBAAgB;QAC1C,cAAc,EAAE,OAAO,CAAC,cAAc;QACtC,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAC,QAAQ,EAAE;QACrC,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;QAC3D,aAAa,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO;KACxD,CAAC,CAAC;IACH,MAAM,GAAG,GAAG,GAAG,mBAAmB,EAAE,aAAa,WAAW,EAAE,CAAC;IAC/D,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,EAAE;QAChC,OAAO,EAAE,iBAAiB,CAAC,QAAQ,CAAC;QACpC,MAAM;KACP,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,aAA4B,EAAE,EAAE;QACpE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,aAAa,CAAC;QACjD,OAAO,CACL,gBAAgB,CACd,yBAAyB,EACzB,aAAa,EACb,GAAG,CACJ;YACD,gBAAgB,CAAQ,gBAAgB,EAAE,KAAK,EAAE,GAAG,CAAC;YACrD,gBAAgB,CACd,gBAAgB,EAChB,KAAK,CAAC,QAAQ,EACd,GAAG,CACJ;YACD,gBAAgB,CACd,gBAAgB,EAChB,KAAK,CAAC,SAAS,EACf,GAAG,CACJ;YACD,gBAAgB,CAAS,kBAAkB,EAAE,KAAK,EAAE,GAAG,CAAC;YACxD,gBAAgB,CACd,mBAAmB,EACnB,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,EACjC,GAAG,CACJ;YACD,CAAC,QAAQ;gBACP,CAAC,CAAC,gBAAgB,CAAS,kBAAkB,EAAE,QAAQ,EAAE,GAAG,CAAC;gBAC7D,CAAC,CAAC,IAAI,CAAC,CACV,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,cAAc,CAAC;AACxB,CAAC","sourcesContent":["import type { Hex } from '@metamask/utils';\nimport { hexToNumber, numberToHex } from '@metamask/utils';\n\nimport {\n isSwapsDefaultTokenAddress,\n isSwapsDefaultTokenSymbol,\n getBridgeApiBaseUrl,\n} from './bridge';\nimport {\n FEATURE_FLAG_VALIDATORS,\n QUOTE_VALIDATORS,\n TX_DATA_VALIDATORS,\n TOKEN_VALIDATORS,\n validateResponse,\n QUOTE_RESPONSE_VALIDATORS,\n FEE_DATA_VALIDATORS,\n} from './validators';\nimport { REFRESH_INTERVAL_MS } from '../constants/bridge';\nimport type { SwapsTokenObject } from '../constants/tokens';\nimport { SWAPS_CHAINID_DEFAULT_TOKEN_MAP } from '../constants/tokens';\nimport type {\n FeatureFlagResponse,\n FeeData,\n Quote,\n QuoteRequest,\n QuoteResponse,\n TxData,\n BridgeFeatureFlags,\n FetchFunction,\n} from '../types';\nimport { BridgeFlag, FeeType, BridgeFeatureFlagsKey } from '../types';\n\n// TODO put this back in once we have a fetchWithCache equivalent\n// const CACHE_REFRESH_TEN_MINUTES = 10 * Duration.Minute;\n\nexport const getClientIdHeader = (clientId: string) => ({\n 'X-Client-Id': clientId,\n});\n\n/**\n * Fetches the bridge feature flags\n *\n * @param clientId - The client ID for metrics\n * @param fetchFn - The fetch function to use\n * @returns The bridge feature flags\n */\nexport async function fetchBridgeFeatureFlags(\n clientId: string,\n fetchFn: FetchFunction,\n): Promise<BridgeFeatureFlags> {\n const url = `${getBridgeApiBaseUrl()}/getAllFeatureFlags`;\n const rawFeatureFlags = await fetchFn(url, {\n headers: getClientIdHeader(clientId),\n });\n\n if (\n validateResponse<FeatureFlagResponse>(\n FEATURE_FLAG_VALIDATORS,\n rawFeatureFlags,\n url,\n )\n ) {\n return {\n [BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {\n ...rawFeatureFlags[BridgeFlag.EXTENSION_CONFIG],\n chains: Object.entries(\n rawFeatureFlags[BridgeFlag.EXTENSION_CONFIG].chains,\n ).reduce(\n (acc, [chainId, value]) => ({\n ...acc,\n [numberToHex(Number(chainId))]: value,\n }),\n {},\n ),\n },\n };\n }\n\n return {\n [BridgeFeatureFlagsKey.EXTENSION_CONFIG]: {\n refreshRate: REFRESH_INTERVAL_MS,\n maxRefreshCount: 5,\n support: false,\n chains: {},\n },\n };\n}\n\n/**\n * Returns a list of enabled (unblocked) tokens\n *\n * @param chainId - The chain ID to fetch tokens for\n * @param clientId - The client ID for metrics\n * @param fetchFn - The fetch function to use\n * @returns A list of enabled (unblocked) tokens\n */\nexport async function fetchBridgeTokens(\n chainId: Hex,\n clientId: string,\n fetchFn: FetchFunction,\n): Promise<Record<string, SwapsTokenObject>> {\n // TODO make token api v2 call\n const url = `${getBridgeApiBaseUrl()}/getTokens?chainId=${hexToNumber(\n chainId,\n )}`;\n\n // TODO we will need to cache these. In Extension fetchWithCache is used. This is due to the following:\n // If we allow selecting dest networks which the user has not imported,\n // note that the Assets controller won't be able to provide tokens. In extension we fetch+cache the token list from bridge-api to handle this\n const tokens = await fetchFn(url, {\n headers: getClientIdHeader(clientId),\n });\n\n const nativeToken =\n SWAPS_CHAINID_DEFAULT_TOKEN_MAP[\n chainId as keyof typeof SWAPS_CHAINID_DEFAULT_TOKEN_MAP\n ];\n\n const transformedTokens: Record<string, SwapsTokenObject> = {};\n if (nativeToken) {\n transformedTokens[nativeToken.address] = nativeToken;\n }\n\n tokens.forEach((token: unknown) => {\n if (\n validateResponse<SwapsTokenObject>(TOKEN_VALIDATORS, token, url, false) &&\n !(\n isSwapsDefaultTokenSymbol(token.symbol, chainId) ||\n isSwapsDefaultTokenAddress(token.address, chainId)\n )\n ) {\n transformedTokens[token.address] = token;\n }\n });\n return transformedTokens;\n}\n\n// Returns a list of bridge tx quotes\n/**\n *\n * @param request - The quote request\n * @param signal - The abort signal\n * @param clientId - The client ID for metrics\n * @param fetchFn - The fetch function to use\n * @returns A list of bridge tx quotes\n */\nexport async function fetchBridgeQuotes(\n request: QuoteRequest,\n signal: AbortSignal,\n clientId: string,\n fetchFn: FetchFunction,\n): Promise<QuoteResponse[]> {\n const queryParams = new URLSearchParams({\n walletAddress: request.walletAddress,\n srcChainId: request.srcChainId.toString(),\n destChainId: request.destChainId.toString(),\n srcTokenAddress: request.srcTokenAddress,\n destTokenAddress: request.destTokenAddress,\n srcTokenAmount: request.srcTokenAmount,\n slippage: request.slippage.toString(),\n insufficientBal: request.insufficientBal ? 'true' : 'false',\n resetApproval: request.resetApproval ? 'true' : 'false',\n });\n const url = `${getBridgeApiBaseUrl()}/getQuote?${queryParams}`;\n const quotes = await fetchFn(url, {\n headers: getClientIdHeader(clientId),\n signal,\n });\n\n const filteredQuotes = quotes.filter((quoteResponse: QuoteResponse) => {\n const { quote, approval, trade } = quoteResponse;\n return (\n validateResponse<QuoteResponse>(\n QUOTE_RESPONSE_VALIDATORS,\n quoteResponse,\n url,\n ) &&\n validateResponse<Quote>(QUOTE_VALIDATORS, quote, url) &&\n validateResponse<SwapsTokenObject>(\n TOKEN_VALIDATORS,\n quote.srcAsset,\n url,\n ) &&\n validateResponse<SwapsTokenObject>(\n TOKEN_VALIDATORS,\n quote.destAsset,\n url,\n ) &&\n validateResponse<TxData>(TX_DATA_VALIDATORS, trade, url) &&\n validateResponse<FeeData>(\n FEE_DATA_VALIDATORS,\n quote.feeData[FeeType.METABRIDGE],\n url,\n ) &&\n (approval\n ? validateResponse<TxData>(TX_DATA_VALIDATORS, approval, url)\n : true)\n );\n });\n return filteredQuotes;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isValidQuoteRequest = void 0;
|
|
4
|
+
const isValidQuoteRequest = (partialRequest, requireAmount = true) => {
|
|
5
|
+
const stringFields = ['srcTokenAddress', 'destTokenAddress'];
|
|
6
|
+
if (requireAmount) {
|
|
7
|
+
stringFields.push('srcTokenAmount');
|
|
8
|
+
}
|
|
9
|
+
const numberFields = ['srcChainId', 'destChainId', 'slippage'];
|
|
10
|
+
return (stringFields.every((field) => field in partialRequest &&
|
|
11
|
+
typeof partialRequest[field] ===
|
|
12
|
+
'string' &&
|
|
13
|
+
partialRequest[field] !== undefined &&
|
|
14
|
+
partialRequest[field] !== '' &&
|
|
15
|
+
partialRequest[field] !== null) &&
|
|
16
|
+
numberFields.every((field) => field in partialRequest &&
|
|
17
|
+
typeof partialRequest[field] ===
|
|
18
|
+
'number' &&
|
|
19
|
+
partialRequest[field] !== undefined &&
|
|
20
|
+
!isNaN(Number(partialRequest[field])) &&
|
|
21
|
+
partialRequest[field] !== null) &&
|
|
22
|
+
(requireAmount
|
|
23
|
+
? Boolean((partialRequest.srcTokenAmount ?? '').match(/^[1-9]\d*$/u))
|
|
24
|
+
: true));
|
|
25
|
+
};
|
|
26
|
+
exports.isValidQuoteRequest = isValidQuoteRequest;
|
|
27
|
+
//# sourceMappingURL=quote.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.cjs","sourceRoot":"","sources":["../../src/utils/quote.ts"],"names":[],"mappings":";;;AAEO,MAAM,mBAAmB,GAAG,CACjC,cAAqC,EACrC,aAAa,GAAG,IAAI,EACY,EAAE;IAClC,MAAM,YAAY,GAAG,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;IAC7D,IAAI,aAAa,EAAE;QACjB,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;KACrC;IACD,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;IAE/D,OAAO,CACL,YAAY,CAAC,KAAK,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,IAAI,cAAc;QACvB,OAAO,cAAc,CAAC,KAAoC,CAAC;YACzD,QAAQ;QACV,cAAc,CAAC,KAAoC,CAAC,KAAK,SAAS;QAClE,cAAc,CAAC,KAAoC,CAAC,KAAK,EAAE;QAC3D,cAAc,CAAC,KAAoC,CAAC,KAAK,IAAI,CAChE;QACD,YAAY,CAAC,KAAK,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,IAAI,cAAc;YACvB,OAAO,cAAc,CAAC,KAAoC,CAAC;gBACzD,QAAQ;YACV,cAAc,CAAC,KAAoC,CAAC,KAAK,SAAS;YAClE,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,KAAoC,CAAC,CAAC,CAAC;YACpE,cAAc,CAAC,KAAoC,CAAC,KAAK,IAAI,CAChE;QACD,CAAC,aAAa;YACZ,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACrE,CAAC,CAAC,IAAI,CAAC,CACV,CAAC;AACJ,CAAC,CAAC;AAjCW,QAAA,mBAAmB,uBAiC9B","sourcesContent":["import type { QuoteRequest } from '../types';\n\nexport const isValidQuoteRequest = (\n partialRequest: Partial<QuoteRequest>,\n requireAmount = true,\n): partialRequest is QuoteRequest => {\n const stringFields = ['srcTokenAddress', 'destTokenAddress'];\n if (requireAmount) {\n stringFields.push('srcTokenAmount');\n }\n const numberFields = ['srcChainId', 'destChainId', 'slippage'];\n\n return (\n stringFields.every(\n (field) =>\n field in partialRequest &&\n typeof partialRequest[field as keyof typeof partialRequest] ===\n 'string' &&\n partialRequest[field as keyof typeof partialRequest] !== undefined &&\n partialRequest[field as keyof typeof partialRequest] !== '' &&\n partialRequest[field as keyof typeof partialRequest] !== null,\n ) &&\n numberFields.every(\n (field) =>\n field in partialRequest &&\n typeof partialRequest[field as keyof typeof partialRequest] ===\n 'number' &&\n partialRequest[field as keyof typeof partialRequest] !== undefined &&\n !isNaN(Number(partialRequest[field as keyof typeof partialRequest])) &&\n partialRequest[field as keyof typeof partialRequest] !== null,\n ) &&\n (requireAmount\n ? Boolean((partialRequest.srcTokenAmount ?? '').match(/^[1-9]\\d*$/u))\n : true)\n );\n};\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.d.cts","sourceRoot":"","sources":["../../src/utils/quote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAE7C,eAAO,MAAM,mBAAmB,mBACd,QAAQ,YAAY,CAAC,4DAgCtC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.d.mts","sourceRoot":"","sources":["../../src/utils/quote.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,qBAAiB;AAE7C,eAAO,MAAM,mBAAmB,mBACd,QAAQ,YAAY,CAAC,4DAgCtC,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export const isValidQuoteRequest = (partialRequest, requireAmount = true) => {
|
|
2
|
+
const stringFields = ['srcTokenAddress', 'destTokenAddress'];
|
|
3
|
+
if (requireAmount) {
|
|
4
|
+
stringFields.push('srcTokenAmount');
|
|
5
|
+
}
|
|
6
|
+
const numberFields = ['srcChainId', 'destChainId', 'slippage'];
|
|
7
|
+
return (stringFields.every((field) => field in partialRequest &&
|
|
8
|
+
typeof partialRequest[field] ===
|
|
9
|
+
'string' &&
|
|
10
|
+
partialRequest[field] !== undefined &&
|
|
11
|
+
partialRequest[field] !== '' &&
|
|
12
|
+
partialRequest[field] !== null) &&
|
|
13
|
+
numberFields.every((field) => field in partialRequest &&
|
|
14
|
+
typeof partialRequest[field] ===
|
|
15
|
+
'number' &&
|
|
16
|
+
partialRequest[field] !== undefined &&
|
|
17
|
+
!isNaN(Number(partialRequest[field])) &&
|
|
18
|
+
partialRequest[field] !== null) &&
|
|
19
|
+
(requireAmount
|
|
20
|
+
? Boolean((partialRequest.srcTokenAmount ?? '').match(/^[1-9]\d*$/u))
|
|
21
|
+
: true));
|
|
22
|
+
};
|
|
23
|
+
//# sourceMappingURL=quote.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"quote.mjs","sourceRoot":"","sources":["../../src/utils/quote.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CACjC,cAAqC,EACrC,aAAa,GAAG,IAAI,EACY,EAAE;IAClC,MAAM,YAAY,GAAG,CAAC,iBAAiB,EAAE,kBAAkB,CAAC,CAAC;IAC7D,IAAI,aAAa,EAAE;QACjB,YAAY,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;KACrC;IACD,MAAM,YAAY,GAAG,CAAC,YAAY,EAAE,aAAa,EAAE,UAAU,CAAC,CAAC;IAE/D,OAAO,CACL,YAAY,CAAC,KAAK,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,IAAI,cAAc;QACvB,OAAO,cAAc,CAAC,KAAoC,CAAC;YACzD,QAAQ;QACV,cAAc,CAAC,KAAoC,CAAC,KAAK,SAAS;QAClE,cAAc,CAAC,KAAoC,CAAC,KAAK,EAAE;QAC3D,cAAc,CAAC,KAAoC,CAAC,KAAK,IAAI,CAChE;QACD,YAAY,CAAC,KAAK,CAChB,CAAC,KAAK,EAAE,EAAE,CACR,KAAK,IAAI,cAAc;YACvB,OAAO,cAAc,CAAC,KAAoC,CAAC;gBACzD,QAAQ;YACV,cAAc,CAAC,KAAoC,CAAC,KAAK,SAAS;YAClE,CAAC,KAAK,CAAC,MAAM,CAAC,cAAc,CAAC,KAAoC,CAAC,CAAC,CAAC;YACpE,cAAc,CAAC,KAAoC,CAAC,KAAK,IAAI,CAChE;QACD,CAAC,aAAa;YACZ,CAAC,CAAC,OAAO,CAAC,CAAC,cAAc,CAAC,cAAc,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;YACrE,CAAC,CAAC,IAAI,CAAC,CACV,CAAC;AACJ,CAAC,CAAC","sourcesContent":["import type { QuoteRequest } from '../types';\n\nexport const isValidQuoteRequest = (\n partialRequest: Partial<QuoteRequest>,\n requireAmount = true,\n): partialRequest is QuoteRequest => {\n const stringFields = ['srcTokenAddress', 'destTokenAddress'];\n if (requireAmount) {\n stringFields.push('srcTokenAmount');\n }\n const numberFields = ['srcChainId', 'destChainId', 'slippage'];\n\n return (\n stringFields.every(\n (field) =>\n field in partialRequest &&\n typeof partialRequest[field as keyof typeof partialRequest] ===\n 'string' &&\n partialRequest[field as keyof typeof partialRequest] !== undefined &&\n partialRequest[field as keyof typeof partialRequest] !== '' &&\n partialRequest[field as keyof typeof partialRequest] !== null,\n ) &&\n numberFields.every(\n (field) =>\n field in partialRequest &&\n typeof partialRequest[field as keyof typeof partialRequest] ===\n 'number' &&\n partialRequest[field as keyof typeof partialRequest] !== undefined &&\n !isNaN(Number(partialRequest[field as keyof typeof partialRequest])) &&\n partialRequest[field as keyof typeof partialRequest] !== null,\n ) &&\n (requireAmount\n ? Boolean((partialRequest.srcTokenAmount ?? '').match(/^[1-9]\\d*$/u))\n : true)\n );\n};\n"]}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TX_DATA_VALIDATORS = exports.FEE_DATA_VALIDATORS = exports.QUOTE_VALIDATORS = exports.QUOTE_RESPONSE_VALIDATORS = exports.TOKEN_VALIDATORS = exports.TOKEN_AGGREGATOR_VALIDATORS = exports.FEATURE_FLAG_VALIDATORS = exports.validateResponse = exports.validateData = exports.isValidNumber = exports.truthyDigitString = exports.truthyString = void 0;
|
|
4
|
+
const controller_utils_1 = require("@metamask/controller-utils");
|
|
5
|
+
const utils_1 = require("@metamask/utils");
|
|
6
|
+
const types_1 = require("../types.cjs");
|
|
7
|
+
const truthyString = (string) => Boolean(string?.length);
|
|
8
|
+
exports.truthyString = truthyString;
|
|
9
|
+
const truthyDigitString = (string) => (0, exports.truthyString)(string) && Boolean(string.match(/^\d+$/u));
|
|
10
|
+
exports.truthyDigitString = truthyDigitString;
|
|
11
|
+
const isValidNumber = (v) => typeof v === 'number';
|
|
12
|
+
exports.isValidNumber = isValidNumber;
|
|
13
|
+
const isValidObject = (v) => typeof v === 'object' && v !== null;
|
|
14
|
+
const isValidString = (v) => typeof v === 'string' && v.length > 0;
|
|
15
|
+
const isValidHexAddress = (v) => isValidString(v) && (0, controller_utils_1.isValidHexAddress)(v, { allowNonPrefixed: false });
|
|
16
|
+
const validateData = (validators, object, urlUsed, logError = true) => {
|
|
17
|
+
return validators.every(({ property, type, validator }) => {
|
|
18
|
+
const types = type.split('|');
|
|
19
|
+
const propertyString = String(property);
|
|
20
|
+
const valid = isValidObject(object) &&
|
|
21
|
+
types.some((_type) => typeof object[propertyString] === _type) &&
|
|
22
|
+
(!validator || validator(object[propertyString]));
|
|
23
|
+
if (!valid && logError) {
|
|
24
|
+
const value = isValidObject(object)
|
|
25
|
+
? object[propertyString]
|
|
26
|
+
: undefined;
|
|
27
|
+
const typeString = isValidObject(object)
|
|
28
|
+
? typeof object[propertyString]
|
|
29
|
+
: 'undefined';
|
|
30
|
+
console.error(`response to GET ${urlUsed} invalid for property ${String(property)}; value was:`, value, '| type was: ', typeString);
|
|
31
|
+
}
|
|
32
|
+
return valid;
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
exports.validateData = validateData;
|
|
36
|
+
const validateResponse = (validators, data, urlUsed, logError = true) => {
|
|
37
|
+
return (0, exports.validateData)(validators, data, urlUsed, logError);
|
|
38
|
+
};
|
|
39
|
+
exports.validateResponse = validateResponse;
|
|
40
|
+
exports.FEATURE_FLAG_VALIDATORS = [
|
|
41
|
+
{
|
|
42
|
+
property: types_1.BridgeFlag.EXTENSION_CONFIG,
|
|
43
|
+
type: 'object',
|
|
44
|
+
validator: (v) => isValidObject(v) &&
|
|
45
|
+
'refreshRate' in v &&
|
|
46
|
+
(0, exports.isValidNumber)(v.refreshRate) &&
|
|
47
|
+
'maxRefreshCount' in v &&
|
|
48
|
+
(0, exports.isValidNumber)(v.maxRefreshCount) &&
|
|
49
|
+
'chains' in v &&
|
|
50
|
+
isValidObject(v.chains) &&
|
|
51
|
+
Object.values(v.chains).every((chain) => isValidObject(chain)) &&
|
|
52
|
+
Object.values(v.chains).every((chain) => 'isActiveSrc' in chain &&
|
|
53
|
+
'isActiveDest' in chain &&
|
|
54
|
+
typeof chain.isActiveSrc === 'boolean' &&
|
|
55
|
+
typeof chain.isActiveDest === 'boolean'),
|
|
56
|
+
},
|
|
57
|
+
];
|
|
58
|
+
exports.TOKEN_AGGREGATOR_VALIDATORS = [
|
|
59
|
+
{
|
|
60
|
+
property: 'aggregators',
|
|
61
|
+
type: 'object',
|
|
62
|
+
validator: (v) => isValidObject(v) && Object.values(v).every(isValidString),
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
exports.TOKEN_VALIDATORS = [
|
|
66
|
+
{ property: 'decimals', type: 'number' },
|
|
67
|
+
{ property: 'address', type: 'string', validator: isValidHexAddress },
|
|
68
|
+
{
|
|
69
|
+
property: 'symbol',
|
|
70
|
+
type: 'string',
|
|
71
|
+
validator: (v) => isValidString(v) && v.length <= 12,
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
exports.QUOTE_RESPONSE_VALIDATORS = [
|
|
75
|
+
{ property: 'quote', type: 'object', validator: isValidObject },
|
|
76
|
+
{ property: 'estimatedProcessingTimeInSeconds', type: 'number' },
|
|
77
|
+
{
|
|
78
|
+
property: 'approval',
|
|
79
|
+
type: 'object|undefined',
|
|
80
|
+
validator: (v) => v === undefined || isValidObject(v),
|
|
81
|
+
},
|
|
82
|
+
{ property: 'trade', type: 'object', validator: isValidObject },
|
|
83
|
+
];
|
|
84
|
+
exports.QUOTE_VALIDATORS = [
|
|
85
|
+
{ property: 'requestId', type: 'string' },
|
|
86
|
+
{ property: 'srcTokenAmount', type: 'string' },
|
|
87
|
+
{ property: 'destTokenAmount', type: 'string' },
|
|
88
|
+
{ property: 'bridgeId', type: 'string' },
|
|
89
|
+
{ property: 'bridges', type: 'object', validator: isValidObject },
|
|
90
|
+
{ property: 'srcChainId', type: 'number' },
|
|
91
|
+
{ property: 'destChainId', type: 'number' },
|
|
92
|
+
{ property: 'srcAsset', type: 'object', validator: isValidObject },
|
|
93
|
+
{ property: 'destAsset', type: 'object', validator: isValidObject },
|
|
94
|
+
{ property: 'feeData', type: 'object', validator: isValidObject },
|
|
95
|
+
];
|
|
96
|
+
exports.FEE_DATA_VALIDATORS = [
|
|
97
|
+
{
|
|
98
|
+
property: 'amount',
|
|
99
|
+
type: 'string',
|
|
100
|
+
validator: (v) => (0, exports.truthyDigitString)(String(v)),
|
|
101
|
+
},
|
|
102
|
+
{ property: 'asset', type: 'object', validator: isValidObject },
|
|
103
|
+
];
|
|
104
|
+
exports.TX_DATA_VALIDATORS = [
|
|
105
|
+
{ property: 'chainId', type: 'number' },
|
|
106
|
+
{ property: 'value', type: 'string', validator: utils_1.isStrictHexString },
|
|
107
|
+
{ property: 'gasLimit', type: 'number' },
|
|
108
|
+
{ property: 'to', type: 'string', validator: isValidHexAddress },
|
|
109
|
+
{ property: 'from', type: 'string', validator: isValidHexAddress },
|
|
110
|
+
{ property: 'data', type: 'string', validator: utils_1.isStrictHexString },
|
|
111
|
+
];
|
|
112
|
+
//# sourceMappingURL=validators.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.cjs","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"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","sourcesContent":["import { isValidHexAddress as isValidHexAddress_ } from '@metamask/controller-utils';\nimport { isStrictHexString } from '@metamask/utils';\n\nimport type { SwapsTokenObject } from '../constants/tokens';\nimport type {\n FeatureFlagResponse,\n FeeData,\n Quote,\n QuoteResponse,\n TxData,\n} from '../types';\nimport { BridgeFlag } from '../types';\n\nexport const truthyString = (string: string) => Boolean(string?.length);\nexport const truthyDigitString = (string: string) =>\n truthyString(string) && Boolean(string.match(/^\\d+$/u));\n\nexport const isValidNumber = (v: unknown): v is number => typeof v === 'number';\nconst isValidObject = (v: unknown): v is object =>\n typeof v === 'object' && v !== null;\nconst isValidString = (v: unknown): v is string =>\n typeof v === 'string' && v.length > 0;\nconst isValidHexAddress = (v: unknown) =>\n isValidString(v) && isValidHexAddress_(v, { allowNonPrefixed: false });\n\ntype Validator<ExpectedResponse> = {\n property: keyof ExpectedResponse;\n type: string;\n validator?: (value: unknown) => boolean;\n};\n\nexport const validateData = <ExpectedResponse>(\n validators: Validator<ExpectedResponse>[],\n object: unknown,\n urlUsed: string,\n logError = true,\n): object is ExpectedResponse => {\n return validators.every(({ property, type, validator }) => {\n const types = type.split('|');\n const propertyString = String(property);\n\n const valid =\n isValidObject(object) &&\n types.some(\n (_type) =>\n typeof object[propertyString as keyof typeof object] === _type,\n ) &&\n (!validator || validator(object[propertyString as keyof typeof object]));\n\n if (!valid && logError) {\n const value = isValidObject(object)\n ? object[propertyString as keyof typeof object]\n : undefined;\n const typeString = isValidObject(object)\n ? typeof object[propertyString as keyof typeof object]\n : 'undefined';\n\n console.error(\n `response to GET ${urlUsed} invalid for property ${String(property)}; value was:`,\n value,\n '| type was: ',\n typeString,\n );\n }\n return valid;\n });\n};\n\nexport const validateResponse = <ExpectedResponse>(\n validators: Validator<ExpectedResponse>[],\n data: unknown,\n urlUsed: string,\n logError = true,\n): data is ExpectedResponse => {\n return validateData(validators, data, urlUsed, logError);\n};\n\nexport const FEATURE_FLAG_VALIDATORS = [\n {\n property: BridgeFlag.EXTENSION_CONFIG,\n type: 'object',\n validator: (\n v: unknown,\n ): v is Pick<FeatureFlagResponse, BridgeFlag.EXTENSION_CONFIG> =>\n isValidObject(v) &&\n 'refreshRate' in v &&\n isValidNumber(v.refreshRate) &&\n 'maxRefreshCount' in v &&\n isValidNumber(v.maxRefreshCount) &&\n 'chains' in v &&\n isValidObject(v.chains) &&\n Object.values(v.chains).every((chain) => isValidObject(chain)) &&\n Object.values(v.chains).every(\n (chain) =>\n 'isActiveSrc' in chain &&\n 'isActiveDest' in chain &&\n typeof chain.isActiveSrc === 'boolean' &&\n typeof chain.isActiveDest === 'boolean',\n ),\n },\n];\n\nexport const TOKEN_AGGREGATOR_VALIDATORS = [\n {\n property: 'aggregators',\n type: 'object',\n validator: (v: unknown): v is number[] =>\n isValidObject(v) && Object.values(v).every(isValidString),\n },\n];\n\nexport const TOKEN_VALIDATORS: Validator<SwapsTokenObject>[] = [\n { property: 'decimals', type: 'number' },\n { property: 'address', type: 'string', validator: isValidHexAddress },\n {\n property: 'symbol',\n type: 'string',\n validator: (v: unknown) => isValidString(v) && v.length <= 12,\n },\n];\n\nexport const QUOTE_RESPONSE_VALIDATORS: Validator<QuoteResponse>[] = [\n { property: 'quote', type: 'object', validator: isValidObject },\n { property: 'estimatedProcessingTimeInSeconds', type: 'number' },\n {\n property: 'approval',\n type: 'object|undefined',\n validator: (v: unknown) => v === undefined || isValidObject(v),\n },\n { property: 'trade', type: 'object', validator: isValidObject },\n];\n\nexport const QUOTE_VALIDATORS: Validator<Quote>[] = [\n { property: 'requestId', type: 'string' },\n { property: 'srcTokenAmount', type: 'string' },\n { property: 'destTokenAmount', type: 'string' },\n { property: 'bridgeId', type: 'string' },\n { property: 'bridges', type: 'object', validator: isValidObject },\n { property: 'srcChainId', type: 'number' },\n { property: 'destChainId', type: 'number' },\n { property: 'srcAsset', type: 'object', validator: isValidObject },\n { property: 'destAsset', type: 'object', validator: isValidObject },\n { property: 'feeData', type: 'object', validator: isValidObject },\n];\n\nexport const FEE_DATA_VALIDATORS: Validator<FeeData>[] = [\n {\n property: 'amount',\n type: 'string',\n validator: (v: unknown) => truthyDigitString(String(v)),\n },\n { property: 'asset', type: 'object', validator: isValidObject },\n];\n\nexport const TX_DATA_VALIDATORS: Validator<TxData>[] = [\n { property: 'chainId', type: 'number' },\n { property: 'value', type: 'string', validator: isStrictHexString },\n { property: 'gasLimit', type: 'number' },\n { property: 'to', type: 'string', validator: isValidHexAddress },\n { property: 'from', type: 'string', validator: isValidHexAddress },\n { property: 'data', type: 'string', validator: isStrictHexString },\n];\n"]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SwapsTokenObject } from "../constants/tokens.cjs";
|
|
2
|
+
import type { FeatureFlagResponse, FeeData, Quote, QuoteResponse, TxData } from "../types.cjs";
|
|
3
|
+
import { BridgeFlag } from "../types.cjs";
|
|
4
|
+
export declare const truthyString: (string: string) => boolean;
|
|
5
|
+
export declare const truthyDigitString: (string: string) => boolean;
|
|
6
|
+
export declare const isValidNumber: (v: unknown) => v is number;
|
|
7
|
+
type Validator<ExpectedResponse> = {
|
|
8
|
+
property: keyof ExpectedResponse;
|
|
9
|
+
type: string;
|
|
10
|
+
validator?: (value: unknown) => boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const validateData: <ExpectedResponse>(validators: Validator<ExpectedResponse>[], object: unknown, urlUsed: string, logError?: boolean) => object is ExpectedResponse;
|
|
13
|
+
export declare const validateResponse: <ExpectedResponse>(validators: Validator<ExpectedResponse>[], data: unknown, urlUsed: string, logError?: boolean) => data is ExpectedResponse;
|
|
14
|
+
export declare const FEATURE_FLAG_VALIDATORS: {
|
|
15
|
+
property: BridgeFlag;
|
|
16
|
+
type: string;
|
|
17
|
+
validator: (v: unknown) => v is Pick<FeatureFlagResponse, BridgeFlag>;
|
|
18
|
+
}[];
|
|
19
|
+
export declare const TOKEN_AGGREGATOR_VALIDATORS: {
|
|
20
|
+
property: string;
|
|
21
|
+
type: string;
|
|
22
|
+
validator: (v: unknown) => v is number[];
|
|
23
|
+
}[];
|
|
24
|
+
export declare const TOKEN_VALIDATORS: Validator<SwapsTokenObject>[];
|
|
25
|
+
export declare const QUOTE_RESPONSE_VALIDATORS: Validator<QuoteResponse>[];
|
|
26
|
+
export declare const QUOTE_VALIDATORS: Validator<Quote>[];
|
|
27
|
+
export declare const FEE_DATA_VALIDATORS: Validator<FeeData>[];
|
|
28
|
+
export declare const TX_DATA_VALIDATORS: Validator<TxData>[];
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=validators.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.cts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAA4B;AAC5D,OAAO,KAAK,EACV,mBAAmB,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,MAAM,EACP,qBAAiB;AAClB,OAAO,EAAE,UAAU,EAAE,qBAAiB;AAEtC,eAAO,MAAM,YAAY,WAAY,MAAM,YAA4B,CAAC;AACxE,eAAO,MAAM,iBAAiB,WAAY,MAAM,YACS,CAAC;AAE1D,eAAO,MAAM,aAAa,MAAO,OAAO,gBAAuC,CAAC;AAQhF,KAAK,SAAS,CAAC,gBAAgB,IAAI;IACjC,QAAQ,EAAE,MAAM,gBAAgB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,YAAY,wEAEf,OAAO,WACN,MAAM,mDAgChB,CAAC;AAEF,eAAO,MAAM,gBAAgB,sEAErB,OAAO,WACJ,MAAM,iDAIhB,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;mBAK3B,OAAO;GAkBf,CAAC;AAEF,eAAO,MAAM,2BAA2B;;;mBAIrB,OAAO;GAGzB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CAAC,EAQzD,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,SAAS,CAAC,aAAa,CAAC,EAS/D,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,KAAK,CAAC,EAW9C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,OAAO,CAAC,EAOnD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,MAAM,CAAC,EAOjD,CAAC"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import type { SwapsTokenObject } from "../constants/tokens.mjs";
|
|
2
|
+
import type { FeatureFlagResponse, FeeData, Quote, QuoteResponse, TxData } from "../types.mjs";
|
|
3
|
+
import { BridgeFlag } from "../types.mjs";
|
|
4
|
+
export declare const truthyString: (string: string) => boolean;
|
|
5
|
+
export declare const truthyDigitString: (string: string) => boolean;
|
|
6
|
+
export declare const isValidNumber: (v: unknown) => v is number;
|
|
7
|
+
type Validator<ExpectedResponse> = {
|
|
8
|
+
property: keyof ExpectedResponse;
|
|
9
|
+
type: string;
|
|
10
|
+
validator?: (value: unknown) => boolean;
|
|
11
|
+
};
|
|
12
|
+
export declare const validateData: <ExpectedResponse>(validators: Validator<ExpectedResponse>[], object: unknown, urlUsed: string, logError?: boolean) => object is ExpectedResponse;
|
|
13
|
+
export declare const validateResponse: <ExpectedResponse>(validators: Validator<ExpectedResponse>[], data: unknown, urlUsed: string, logError?: boolean) => data is ExpectedResponse;
|
|
14
|
+
export declare const FEATURE_FLAG_VALIDATORS: {
|
|
15
|
+
property: BridgeFlag;
|
|
16
|
+
type: string;
|
|
17
|
+
validator: (v: unknown) => v is Pick<FeatureFlagResponse, BridgeFlag>;
|
|
18
|
+
}[];
|
|
19
|
+
export declare const TOKEN_AGGREGATOR_VALIDATORS: {
|
|
20
|
+
property: string;
|
|
21
|
+
type: string;
|
|
22
|
+
validator: (v: unknown) => v is number[];
|
|
23
|
+
}[];
|
|
24
|
+
export declare const TOKEN_VALIDATORS: Validator<SwapsTokenObject>[];
|
|
25
|
+
export declare const QUOTE_RESPONSE_VALIDATORS: Validator<QuoteResponse>[];
|
|
26
|
+
export declare const QUOTE_VALIDATORS: Validator<Quote>[];
|
|
27
|
+
export declare const FEE_DATA_VALIDATORS: Validator<FeeData>[];
|
|
28
|
+
export declare const TX_DATA_VALIDATORS: Validator<TxData>[];
|
|
29
|
+
export {};
|
|
30
|
+
//# sourceMappingURL=validators.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validators.d.mts","sourceRoot":"","sources":["../../src/utils/validators.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,gCAA4B;AAC5D,OAAO,KAAK,EACV,mBAAmB,EACnB,OAAO,EACP,KAAK,EACL,aAAa,EACb,MAAM,EACP,qBAAiB;AAClB,OAAO,EAAE,UAAU,EAAE,qBAAiB;AAEtC,eAAO,MAAM,YAAY,WAAY,MAAM,YAA4B,CAAC;AACxE,eAAO,MAAM,iBAAiB,WAAY,MAAM,YACS,CAAC;AAE1D,eAAO,MAAM,aAAa,MAAO,OAAO,gBAAuC,CAAC;AAQhF,KAAK,SAAS,CAAC,gBAAgB,IAAI;IACjC,QAAQ,EAAE,MAAM,gBAAgB,CAAC;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,OAAO,CAAC;CACzC,CAAC;AAEF,eAAO,MAAM,YAAY,wEAEf,OAAO,WACN,MAAM,mDAgChB,CAAC;AAEF,eAAO,MAAM,gBAAgB,sEAErB,OAAO,WACJ,MAAM,iDAIhB,CAAC;AAEF,eAAO,MAAM,uBAAuB;;;mBAK3B,OAAO;GAkBf,CAAC;AAEF,eAAO,MAAM,2BAA2B;;;mBAIrB,OAAO;GAGzB,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,gBAAgB,CAAC,EAQzD,CAAC;AAEF,eAAO,MAAM,yBAAyB,EAAE,SAAS,CAAC,aAAa,CAAC,EAS/D,CAAC;AAEF,eAAO,MAAM,gBAAgB,EAAE,SAAS,CAAC,KAAK,CAAC,EAW9C,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,SAAS,CAAC,OAAO,CAAC,EAOnD,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,SAAS,CAAC,MAAM,CAAC,EAOjD,CAAC"}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { isValidHexAddress as isValidHexAddress_ } from "@metamask/controller-utils";
|
|
2
|
+
import { isStrictHexString } from "@metamask/utils";
|
|
3
|
+
import { BridgeFlag } from "../types.mjs";
|
|
4
|
+
export const truthyString = (string) => Boolean(string?.length);
|
|
5
|
+
export const truthyDigitString = (string) => truthyString(string) && Boolean(string.match(/^\d+$/u));
|
|
6
|
+
export const isValidNumber = (v) => typeof v === 'number';
|
|
7
|
+
const isValidObject = (v) => typeof v === 'object' && v !== null;
|
|
8
|
+
const isValidString = (v) => typeof v === 'string' && v.length > 0;
|
|
9
|
+
const isValidHexAddress = (v) => isValidString(v) && isValidHexAddress_(v, { allowNonPrefixed: false });
|
|
10
|
+
export const validateData = (validators, object, urlUsed, logError = true) => {
|
|
11
|
+
return validators.every(({ property, type, validator }) => {
|
|
12
|
+
const types = type.split('|');
|
|
13
|
+
const propertyString = String(property);
|
|
14
|
+
const valid = isValidObject(object) &&
|
|
15
|
+
types.some((_type) => typeof object[propertyString] === _type) &&
|
|
16
|
+
(!validator || validator(object[propertyString]));
|
|
17
|
+
if (!valid && logError) {
|
|
18
|
+
const value = isValidObject(object)
|
|
19
|
+
? object[propertyString]
|
|
20
|
+
: undefined;
|
|
21
|
+
const typeString = isValidObject(object)
|
|
22
|
+
? typeof object[propertyString]
|
|
23
|
+
: 'undefined';
|
|
24
|
+
console.error(`response to GET ${urlUsed} invalid for property ${String(property)}; value was:`, value, '| type was: ', typeString);
|
|
25
|
+
}
|
|
26
|
+
return valid;
|
|
27
|
+
});
|
|
28
|
+
};
|
|
29
|
+
export const validateResponse = (validators, data, urlUsed, logError = true) => {
|
|
30
|
+
return validateData(validators, data, urlUsed, logError);
|
|
31
|
+
};
|
|
32
|
+
export const FEATURE_FLAG_VALIDATORS = [
|
|
33
|
+
{
|
|
34
|
+
property: BridgeFlag.EXTENSION_CONFIG,
|
|
35
|
+
type: 'object',
|
|
36
|
+
validator: (v) => isValidObject(v) &&
|
|
37
|
+
'refreshRate' in v &&
|
|
38
|
+
isValidNumber(v.refreshRate) &&
|
|
39
|
+
'maxRefreshCount' in v &&
|
|
40
|
+
isValidNumber(v.maxRefreshCount) &&
|
|
41
|
+
'chains' in v &&
|
|
42
|
+
isValidObject(v.chains) &&
|
|
43
|
+
Object.values(v.chains).every((chain) => isValidObject(chain)) &&
|
|
44
|
+
Object.values(v.chains).every((chain) => 'isActiveSrc' in chain &&
|
|
45
|
+
'isActiveDest' in chain &&
|
|
46
|
+
typeof chain.isActiveSrc === 'boolean' &&
|
|
47
|
+
typeof chain.isActiveDest === 'boolean'),
|
|
48
|
+
},
|
|
49
|
+
];
|
|
50
|
+
export const TOKEN_AGGREGATOR_VALIDATORS = [
|
|
51
|
+
{
|
|
52
|
+
property: 'aggregators',
|
|
53
|
+
type: 'object',
|
|
54
|
+
validator: (v) => isValidObject(v) && Object.values(v).every(isValidString),
|
|
55
|
+
},
|
|
56
|
+
];
|
|
57
|
+
export const TOKEN_VALIDATORS = [
|
|
58
|
+
{ property: 'decimals', type: 'number' },
|
|
59
|
+
{ property: 'address', type: 'string', validator: isValidHexAddress },
|
|
60
|
+
{
|
|
61
|
+
property: 'symbol',
|
|
62
|
+
type: 'string',
|
|
63
|
+
validator: (v) => isValidString(v) && v.length <= 12,
|
|
64
|
+
},
|
|
65
|
+
];
|
|
66
|
+
export const QUOTE_RESPONSE_VALIDATORS = [
|
|
67
|
+
{ property: 'quote', type: 'object', validator: isValidObject },
|
|
68
|
+
{ property: 'estimatedProcessingTimeInSeconds', type: 'number' },
|
|
69
|
+
{
|
|
70
|
+
property: 'approval',
|
|
71
|
+
type: 'object|undefined',
|
|
72
|
+
validator: (v) => v === undefined || isValidObject(v),
|
|
73
|
+
},
|
|
74
|
+
{ property: 'trade', type: 'object', validator: isValidObject },
|
|
75
|
+
];
|
|
76
|
+
export const QUOTE_VALIDATORS = [
|
|
77
|
+
{ property: 'requestId', type: 'string' },
|
|
78
|
+
{ property: 'srcTokenAmount', type: 'string' },
|
|
79
|
+
{ property: 'destTokenAmount', type: 'string' },
|
|
80
|
+
{ property: 'bridgeId', type: 'string' },
|
|
81
|
+
{ property: 'bridges', type: 'object', validator: isValidObject },
|
|
82
|
+
{ property: 'srcChainId', type: 'number' },
|
|
83
|
+
{ property: 'destChainId', type: 'number' },
|
|
84
|
+
{ property: 'srcAsset', type: 'object', validator: isValidObject },
|
|
85
|
+
{ property: 'destAsset', type: 'object', validator: isValidObject },
|
|
86
|
+
{ property: 'feeData', type: 'object', validator: isValidObject },
|
|
87
|
+
];
|
|
88
|
+
export const FEE_DATA_VALIDATORS = [
|
|
89
|
+
{
|
|
90
|
+
property: 'amount',
|
|
91
|
+
type: 'string',
|
|
92
|
+
validator: (v) => truthyDigitString(String(v)),
|
|
93
|
+
},
|
|
94
|
+
{ property: 'asset', type: 'object', validator: isValidObject },
|
|
95
|
+
];
|
|
96
|
+
export const TX_DATA_VALIDATORS = [
|
|
97
|
+
{ property: 'chainId', type: 'number' },
|
|
98
|
+
{ property: 'value', type: 'string', validator: isStrictHexString },
|
|
99
|
+
{ property: 'gasLimit', type: 'number' },
|
|
100
|
+
{ property: 'to', type: 'string', validator: isValidHexAddress },
|
|
101
|
+
{ property: 'from', type: 'string', validator: isValidHexAddress },
|
|
102
|
+
{ property: 'data', type: 'string', validator: isStrictHexString },
|
|
103
|
+
];
|
|
104
|
+
//# sourceMappingURL=validators.mjs.map
|