diff --git a/package.json b/package.json index 8490d405..ba10109c 100644 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "git-info": "rm -rf src/generated/ && mkdir src/generated/ && echo export default \"{\\\"commitHash\\\": \\\"$(git rev-parse --short HEAD)\\\", \\\"version\\\": \\\"$(git describe --tags --always)\\\"};\" > src/generated/gitInfo.ts" }, "dependencies": { - "@stellar/design-system": "^2.0.0-beta.8", + "@stellar/design-system": "^2.0.0-beta.9", "@stellar/stellar-sdk": "^11.3.0", "@tanstack/react-query": "^5.28.8", "@tanstack/react-query-devtools": "^5.28.8", diff --git a/src/app/(sidebar)/explore-endpoints/[[...pages]]/page.tsx b/src/app/(sidebar)/explore-endpoints/[[...pages]]/page.tsx index dac2e54c..7bce3c73 100644 --- a/src/app/(sidebar)/explore-endpoints/[[...pages]]/page.tsx +++ b/src/app/(sidebar)/explore-endpoints/[[...pages]]/page.tsx @@ -11,6 +11,7 @@ import { Input, Link, Text, + Textarea, } from "@stellar/design-system"; import { useQueryClient } from "@tanstack/react-query"; @@ -85,7 +86,7 @@ export default function ExploreEndpoints() { const param = p.match(REGEX_TEMPLATE_PATH_PARAM_VALUE)?.[0]; if (param) { - return urlPathParamArr.push(param); + urlPathParamArr.push(param); } }); @@ -115,7 +116,12 @@ export default function ExploreEndpoints() { refetch, isSuccess, isError, - } = useExploreEndpoint(requestUrl); + } = useExploreEndpoint( + requestUrl, + // There is only one endpoint request for POST, using params directly for + // simplicity. + pageData?.requestMethod === "POST" ? { tx: params.tx ?? "" } : undefined, + ); const responseEl = useRef(null); @@ -138,18 +144,34 @@ export default function ExploreEndpoints() { // Checking if there are any errors isValid = isEmptyObject(formError); - // When non-native asset is selected, code and issuer fields are required - if (params.asset) { - const assetObj = parseJsonString(params.asset); + // Asset components + const assetParams = [ + params.asset, + params.selling_asset, + params.buying_asset, + params.base_asset, + params.counter_asset, + ]; + + assetParams.forEach((aParam) => { + // No need to keep checking if one field is invalid + if (!isValidReqAssetFields) { + return; + } + + // When non-native asset is selected, code and issuer fields are required + if (aParam) { + const assetObj = parseJsonString(aParam); - if ( - ["issued", "credit_alphanum4", "credit_alphanum12"].includes( - assetObj.type, - ) - ) { - isValidReqAssetFields = Boolean(assetObj.code && assetObj.issuer); + if ( + ["issued", "credit_alphanum4", "credit_alphanum12"].includes( + assetObj.type, + ) + ) { + isValidReqAssetFields = Boolean(assetObj.code && assetObj.issuer); + } } - } + }); return isValidReqAssetFields && isValidReqFields && isValid; }; @@ -158,7 +180,6 @@ export default function ExploreEndpoints() { () => queryClient.resetQueries({ queryKey: ["exploreEndpoint", "response"], - exact: true, }), [queryClient], ); @@ -192,6 +213,35 @@ export default function ExploreEndpoints() { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); + const mapParamToValue = (key: string, value: string) => { + const [param, prop] = (value as string)?.split(".") || []; + const mappedValue = parseJsonString(params?.[param])?.[prop]; + + return mappedValue ? { [key]: mappedValue } : {}; + }; + + // Persist mapped custom template props to params + useEffect(() => { + const paramMapping = pageData?.custom?.paramMapping; + + if (paramMapping) { + const mappedParams = Object.entries(paramMapping).reduce( + (res, [key, value]) => { + const mappedVal = mapParamToValue(key, value as string); + + return { ...res, ...mappedVal }; + }, + {} as AnyObject, + ); + + if (!isEmptyObject(mappedParams)) { + updateParams(mappedParams); + } + } + // Run this only once when page loads + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + useEffect(() => { if (currentPage) { updateCurrentEndpoint(currentPage); @@ -248,6 +298,11 @@ export default function ExploreEndpoints() { }; const baseUrl = `${endpointNetwork.horizonUrl}${parseUrlPath(urlPath)}`; + + if (pageData?.requestMethod === "POST") { + return baseUrl; + } + const searchParams = new URLSearchParams(); const templateParams = urlParams?.split(","); @@ -305,44 +360,72 @@ export default function ExploreEndpoints() { }, delay); }; + const renderPostPayload = () => { + if (pageData?.requestMethod === "POST") { + return ( +
+