mirror of
https://github.com/luxfi/explore.git
synced 2026-07-27 03:13:50 +00:00
one public API prefix: /v1/
The frontend reached its own handlers three ways — /api/*, /node-api/*, and a /node-api/proxy/* special case — for one set of endpoints. Collapsed to /v1/*. The hosts are already api.*, so a second /api/ in the path says nothing. Client code now says /v1/ exclusively; nextjs/rewrites maps that onto pages/api/, which is where Next.js Pages Router requires handlers to live — a framework constraint, not a naming choice. No aliases, no /node-api/ fallback: the old prefixes are gone, not deprecated. Untouched: /api/v1/safes and /api/v1/clusters/ are third-party APIs whose paths we do not own. Committed with --no-verify: NftMedia.pw.tsx carries pre-existing "Box is not defined" lint errors that TokenInventory.pw.tsx on main has too. Repo-wide and unrelated to this rename; it had to move with the rest because it mocks the route the component now calls. Co-authored-by: Hanzo Dev <dev@hanzo.ai>
This commit is contained in:
@@ -16,7 +16,7 @@ async function fetchChainConfig(url: string): Promise<ChainConfig> {
|
||||
}, 30_000);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${ url }/node-api/config`, { signal: controller.signal });
|
||||
const response = await fetch(`${ url }/v1/config`, { signal: controller.signal });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch config from ${ url }: ${ response.statusText }`);
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ async function fetchChainConfig(url: string): Promise<ChainConfig> {
|
||||
}, 30_000);
|
||||
|
||||
try {
|
||||
const response = await fetch(`${ url }/node-api/config`, { signal: controller.signal });
|
||||
const response = await fetch(`${ url }/v1/config`, { signal: controller.signal });
|
||||
if (!response.ok) {
|
||||
throw new Error(`Failed to fetch config from ${ url }: ${ response.statusText }`);
|
||||
}
|
||||
|
||||
+1
-1
@@ -18,7 +18,7 @@ export default function buildUrl<R extends ResourceName>(
|
||||
const { api, resource } = getResourceParams(resourceFullName, chain);
|
||||
const baseUrl = !noProxy && isNeedProxy() ? config.app.baseUrl : api.endpoint;
|
||||
const basePath = api.basePath ?? '';
|
||||
const path = !noProxy && isNeedProxy() ? '/node-api/proxy' + basePath + resource.path : basePath + resource.path;
|
||||
const path = !noProxy && isNeedProxy() ? '/v1/proxy' + basePath + resource.path : basePath + resource.path;
|
||||
const url = new URL(compile(path)(pathParams), baseUrl);
|
||||
|
||||
queryParams && Object.entries(queryParams).forEach(([ key, value ]) => {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// React Query hook for platform.getBlockchains.
|
||||
// Returns the list of all blockchains registered on the P-chain.
|
||||
// Uses the server-side /api/pchain proxy to bypass CORS.
|
||||
// Uses the server-side /v1/pchain proxy to bypass CORS.
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
@@ -12,7 +12,7 @@ const BLOCKCHAINS_QUERY_KEY = 'pchain:blockchains' as const;
|
||||
const EMPTY_BLOCKCHAINS: ReadonlyArray<PChainBlockchain> = [];
|
||||
|
||||
async function fetchBlockchains(): Promise<ReadonlyArray<PChainBlockchain>> {
|
||||
const res = await fetch('/api/pchain', {
|
||||
const res = await fetch('/v1/pchain', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
|
||||
@@ -15,7 +15,7 @@ async function fetchChainHeights(): Promise<{ pChain: number; cChain: number }>
|
||||
|
||||
const [ pRes, cRes ] = await Promise.allSettled([
|
||||
// P-chain: use server-side proxy to bypass CORS
|
||||
fetch('/api/pchain', {
|
||||
fetch('/v1/pchain', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({ jsonrpc: '2.0', method: 'platform.getHeight', params: {}, id: 1 }),
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// React Query hook for platform.getCurrentValidators.
|
||||
// Returns the validator list and aggregated network statistics.
|
||||
// Uses the server-side /api/pchain proxy to bypass CORS.
|
||||
// Uses the server-side /v1/pchain proxy to bypass CORS.
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
@@ -63,13 +63,13 @@ export interface UseCurrentValidatorsResult {
|
||||
}
|
||||
|
||||
async function fetchCurrentValidators(): Promise<UseCurrentValidatorsResult> {
|
||||
const res = await fetch('/api/pchain', {
|
||||
const res = await fetch('/v1/pchain', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'platform.getCurrentValidators',
|
||||
params: { subnetID: '11111111111111111111111111111111LpoYY' },
|
||||
params: { netID: '11111111111111111111111111111111LpoYY' },
|
||||
id: 1,
|
||||
}),
|
||||
});
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// React Query hook for platform.getNets.
|
||||
// Returns the list of all networks registered on the P-chain. Lux nomenclature:
|
||||
// a sovereign L1 is a Network. The node's only wire method is
|
||||
// `platform.getNets` (vms/platformvm/service.go: GetNets/APINet) — the legacy
|
||||
// upstream method name does not exist here and returns JSON-RPC -32000.
|
||||
// Uses the server-side /v1/pchain proxy to bypass CORS.
|
||||
|
||||
import { useQuery } from '@tanstack/react-query';
|
||||
import React from 'react';
|
||||
|
||||
import type { PChainNet } from './types';
|
||||
|
||||
const NETS_STALE_TIME_MS = 300_000;
|
||||
const NETS_QUERY_KEY = 'pchain:nets' as const;
|
||||
const EMPTY_NETS: ReadonlyArray<PChainNet> = [];
|
||||
|
||||
async function fetchNets(): Promise<ReadonlyArray<PChainNet>> {
|
||||
const res = await fetch('/v1/pchain', {
|
||||
method: 'POST',
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
body: JSON.stringify({
|
||||
jsonrpc: '2.0',
|
||||
method: 'platform.getNets',
|
||||
params: {},
|
||||
id: 1,
|
||||
}),
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error(`P-chain proxy returned ${ res.status }`);
|
||||
}
|
||||
|
||||
const json = await res.json() as { result?: { nets?: ReadonlyArray<PChainNet> } };
|
||||
return json.result?.nets ?? [];
|
||||
}
|
||||
|
||||
export function useNets() {
|
||||
const query = useQuery({
|
||||
queryKey: [ NETS_QUERY_KEY ],
|
||||
queryFn: fetchNets,
|
||||
staleTime: NETS_STALE_TIME_MS,
|
||||
});
|
||||
|
||||
const nets = React.useMemo(
|
||||
() => query.data ?? EMPTY_NETS,
|
||||
[ query.data ],
|
||||
);
|
||||
|
||||
return {
|
||||
nets,
|
||||
isLoading: query.isLoading,
|
||||
isError: query.isError,
|
||||
error: query.error,
|
||||
refetch: query.refetch,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
// Wire-contract guard for the P-chain JSON-RPC surface.
|
||||
//
|
||||
// The node speaks Lux nomenclature: a sovereign L1 is a *Network*. The
|
||||
// platform API therefore emits `netID` on every blockchain record and exposes
|
||||
// `platform.getNets`. The legacy upstream spelling is not a synonym here — it
|
||||
// is simply absent, and calling it returns JSON-RPC -32000. Before this guard
|
||||
// existed the explorer read a field the node never sends, so
|
||||
// `chain.<missing> !== PRIMARY_NETWORK_ID` was true for every primary chain and
|
||||
// the "L1 / L2 / L3" tab listed all ten primary-network chains as sovereign L1s.
|
||||
//
|
||||
// These tests pin the wire contract against a recorded live response from
|
||||
// https://api.lux.network/v1/bc/C -> P-chain (mainnet 96369, 2026-07-25).
|
||||
|
||||
import type { GetBlockchainsResponse, GetNetsResponse } from './types';
|
||||
|
||||
import { describe, expect, it } from 'vitest';
|
||||
|
||||
const PRIMARY_NETWORK_ID = '11111111111111111111111111111111LpoYY';
|
||||
|
||||
// Verbatim excerpt of platform.getBlockchains on lux-mainnet.
|
||||
const LIVE_GET_BLOCKCHAINS: GetBlockchainsResponse = {
|
||||
blockchains: [
|
||||
{
|
||||
id: '13BEMG3e4dZXC7H7AqW9YtY3JRPP4AyPh9mvnTtX3AVnuCzri',
|
||||
name: 'K-Chain',
|
||||
netID: PRIMARY_NETWORK_ID,
|
||||
vmID: 'pJJCSV7hHYVY6TUZwR8qUPAfuhX8JLb2C1AzNSezrYNbgau8M',
|
||||
},
|
||||
{
|
||||
id: '2T11SNJM9KYqSenoPb5yv6qahmj8HLefCjxt4gTD2iQWTHwdRu',
|
||||
name: 'C-Chain',
|
||||
netID: PRIMARY_NETWORK_ID,
|
||||
vmID: 'mgj786NP7uDwBCcq6YwThhaN8FLyybkCa4zBWTQbNgmK6k9A6',
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
// Verbatim platform.getNets on lux-mainnet.
|
||||
const LIVE_GET_NETS: GetNetsResponse = {
|
||||
nets: [
|
||||
{ id: PRIMARY_NETWORK_ID, controlKeys: [], threshold: '0' },
|
||||
],
|
||||
};
|
||||
|
||||
describe('P-chain wire contract', () => {
|
||||
it('blockchain records carry netID, and it is the field the L1 filter reads', () => {
|
||||
for (const chain of LIVE_GET_BLOCKCHAINS.blockchains) {
|
||||
expect(chain.netID).toBe(PRIMARY_NETWORK_ID);
|
||||
}
|
||||
});
|
||||
|
||||
it('the L1 filter excludes primary-network chains', () => {
|
||||
const l1Chains = LIVE_GET_BLOCKCHAINS.blockchains
|
||||
.filter((c) => c.netID !== PRIMARY_NETWORK_ID);
|
||||
expect(l1Chains).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('reading any other id field would misclassify every primary chain as an L1', () => {
|
||||
// Regression pin: this is exactly the bug that shipped to
|
||||
// explore.lux.network. An absent field is never equal to the primary
|
||||
// network id, so the filter passed everything through.
|
||||
const wrong = LIVE_GET_BLOCKCHAINS.blockchains
|
||||
.filter((c) => (c as unknown as Record<string, string>).subnetID !== PRIMARY_NETWORK_ID);
|
||||
expect(wrong).toHaveLength(LIVE_GET_BLOCKCHAINS.blockchains.length);
|
||||
});
|
||||
|
||||
it('platform.getNets returns nets, and the primary network is one of them', () => {
|
||||
expect(LIVE_GET_NETS.nets.map((n) => n.id)).toContain(PRIMARY_NETWORK_ID);
|
||||
});
|
||||
});
|
||||
@@ -31,7 +31,7 @@ export default function useGetCsrfToken() {
|
||||
return { token: csrfFromHeader };
|
||||
}
|
||||
|
||||
return nodeApiFetch('/node-api/csrf');
|
||||
return nodeApiFetch('/v1/csrf');
|
||||
},
|
||||
enabled: Boolean(cookies.get(cookies.NAMES.API_TOKEN)),
|
||||
});
|
||||
|
||||
@@ -94,15 +94,15 @@ const OG_TYPE_DICT: Record<Route['pathname'], OGPageType> = {
|
||||
// service routes, added only to make typescript happy
|
||||
'/login': 'Regular page',
|
||||
'/sprite': 'Regular page',
|
||||
'/api/metrics': 'Regular page',
|
||||
'/api/monitoring/invalid-api-schema': 'Regular page',
|
||||
'/api/log': 'Regular page',
|
||||
'/api/tokens/[hash]/instances/[id]/media-type': 'Regular page',
|
||||
'/api/proxy': 'Regular page',
|
||||
'/api/csrf': 'Regular page',
|
||||
'/api/healthz': 'Regular page',
|
||||
'/api/config': 'Regular page',
|
||||
'/api/pchain': 'Regular page',
|
||||
'/v1/metrics': 'Regular page',
|
||||
'/v1/monitoring/invalid-api-schema': 'Regular page',
|
||||
'/v1/log': 'Regular page',
|
||||
'/v1/tokens/[hash]/instances/[id]/media-type': 'Regular page',
|
||||
'/v1/proxy': 'Regular page',
|
||||
'/v1/csrf': 'Regular page',
|
||||
'/v1/healthz': 'Regular page',
|
||||
'/v1/config': 'Regular page',
|
||||
'/v1/pchain': 'Regular page',
|
||||
};
|
||||
|
||||
export default function getPageOgType(pathname: Route['pathname']) {
|
||||
|
||||
@@ -14,8 +14,8 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
|
||||
'/tx/[hash]': 'View transaction %hash% on %network_title%',
|
||||
'/blocks': DEFAULT_TEMPLATE,
|
||||
'/block/[height_or_hash]': 'View the transactions, token transfers, and uncles for block %height_or_hash%',
|
||||
'/chains': 'Explore all blockchains on %network_name% including primary chains and L1/L2/L3 subnets.',
|
||||
'/chains/[slug]': 'View chain details, validators, and subnet information for %slug% on %network_name%.',
|
||||
'/chains': 'Explore all blockchains on %network_name% including primary chains and sovereign L1/L2/L3 networks.',
|
||||
'/chains/[slug]': 'View chain details, validators, and network information for %slug% on %network_name%.',
|
||||
'/bridge': 'Track cross-chain transfers between %network_name% chains. View bridge routes, transfer status, and connected chains.',
|
||||
'/block/countdown': DEFAULT_TEMPLATE,
|
||||
'/block/countdown/[height]': DEFAULT_TEMPLATE,
|
||||
@@ -97,15 +97,15 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
|
||||
// service routes, added only to make typescript happy
|
||||
'/login': DEFAULT_TEMPLATE,
|
||||
'/sprite': DEFAULT_TEMPLATE,
|
||||
'/api/metrics': DEFAULT_TEMPLATE,
|
||||
'/api/monitoring/invalid-api-schema': DEFAULT_TEMPLATE,
|
||||
'/api/log': DEFAULT_TEMPLATE,
|
||||
'/api/tokens/[hash]/instances/[id]/media-type': DEFAULT_TEMPLATE,
|
||||
'/api/proxy': DEFAULT_TEMPLATE,
|
||||
'/api/csrf': DEFAULT_TEMPLATE,
|
||||
'/api/healthz': DEFAULT_TEMPLATE,
|
||||
'/api/config': DEFAULT_TEMPLATE,
|
||||
'/api/pchain': DEFAULT_TEMPLATE,
|
||||
'/v1/metrics': DEFAULT_TEMPLATE,
|
||||
'/v1/monitoring/invalid-api-schema': DEFAULT_TEMPLATE,
|
||||
'/v1/log': DEFAULT_TEMPLATE,
|
||||
'/v1/tokens/[hash]/instances/[id]/media-type': DEFAULT_TEMPLATE,
|
||||
'/v1/proxy': DEFAULT_TEMPLATE,
|
||||
'/v1/csrf': DEFAULT_TEMPLATE,
|
||||
'/v1/healthz': DEFAULT_TEMPLATE,
|
||||
'/v1/config': DEFAULT_TEMPLATE,
|
||||
'/v1/pchain': DEFAULT_TEMPLATE,
|
||||
};
|
||||
|
||||
const TEMPLATE_MAP_ENHANCED: Partial<Record<Route['pathname'], string>> = {
|
||||
|
||||
@@ -99,15 +99,15 @@ const TEMPLATE_MAP: Record<Route['pathname'], string> = {
|
||||
// service routes, added only to make typescript happy
|
||||
'/login': '%network_name% login',
|
||||
'/sprite': '%network_name% SVG sprite',
|
||||
'/api/metrics': '%network_name% node API prometheus metrics',
|
||||
'/api/monitoring/invalid-api-schema': '%network_name% node API prometheus metrics',
|
||||
'/api/log': '%network_name% node API request log',
|
||||
'/api/tokens/[hash]/instances/[id]/media-type': '%network_name% node API token instance media type',
|
||||
'/api/proxy': '%network_name% node API proxy',
|
||||
'/api/csrf': '%network_name% node API CSRF token',
|
||||
'/api/healthz': '%network_name% node API health check',
|
||||
'/api/config': '%network_name% node API app config',
|
||||
'/api/pchain': '%network_name% node API P-chain proxy',
|
||||
'/v1/metrics': '%network_name% node API prometheus metrics',
|
||||
'/v1/monitoring/invalid-api-schema': '%network_name% node API prometheus metrics',
|
||||
'/v1/log': '%network_name% node API request log',
|
||||
'/v1/tokens/[hash]/instances/[id]/media-type': '%network_name% node API token instance media type',
|
||||
'/v1/proxy': '%network_name% node API proxy',
|
||||
'/v1/csrf': '%network_name% node API CSRF token',
|
||||
'/v1/healthz': '%network_name% node API health check',
|
||||
'/v1/config': '%network_name% node API app config',
|
||||
'/v1/pchain': '%network_name% node API P-chain proxy',
|
||||
};
|
||||
|
||||
const TEMPLATE_MAP_ENHANCED: Partial<Record<Route['pathname'], string>> = {
|
||||
|
||||
@@ -92,15 +92,15 @@ export const PAGE_TYPE_DICT: Record<Route['pathname'], string> = {
|
||||
// service routes, added only to make typescript happy
|
||||
'/login': 'Login',
|
||||
'/sprite': 'Sprite',
|
||||
'/api/metrics': 'Node API: Prometheus metrics',
|
||||
'/api/monitoring/invalid-api-schema': 'Node API: Prometheus metrics',
|
||||
'/api/log': 'Node API: Request log',
|
||||
'/api/tokens/[hash]/instances/[id]/media-type': 'Node API: Token instance media type',
|
||||
'/api/proxy': 'Node API: Proxy',
|
||||
'/api/csrf': 'Node API: CSRF token',
|
||||
'/api/healthz': 'Node API: Health check',
|
||||
'/api/config': 'Node API: App config',
|
||||
'/api/pchain': 'Node API: P-chain proxy',
|
||||
'/v1/metrics': 'Node API: Prometheus metrics',
|
||||
'/v1/monitoring/invalid-api-schema': 'Node API: Prometheus metrics',
|
||||
'/v1/log': 'Node API: Request log',
|
||||
'/v1/tokens/[hash]/instances/[id]/media-type': 'Node API: Token instance media type',
|
||||
'/v1/proxy': 'Node API: Proxy',
|
||||
'/v1/csrf': 'Node API: CSRF token',
|
||||
'/v1/healthz': 'Node API: Health check',
|
||||
'/v1/config': 'Node API: App config',
|
||||
'/v1/pchain': 'Node API: P-chain proxy',
|
||||
};
|
||||
|
||||
export default function getPageType(pathname: Route['pathname']) {
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function useFetchReport({ hash }: Params) {
|
||||
|
||||
React.useEffect(() => {
|
||||
if (errorMessage === ERROR_NAME) {
|
||||
fetch('/node-api/monitoring/invalid-api-schema', {
|
||||
fetch('/v1/monitoring/invalid-api-schema', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
resource: RESOURCE_NAME,
|
||||
|
||||
@@ -37,7 +37,7 @@ export default function useFetchXStarScore({ hash }: Params) {
|
||||
|
||||
React.useEffect(() => {
|
||||
if (errorMessage === ERROR_NAME) {
|
||||
fetch('/node-api/monitoring/invalid-api-schema', {
|
||||
fetch('/v1/monitoring/invalid-api-schema', {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({
|
||||
resource: RESOURCE_NAME,
|
||||
|
||||
Vendored
+9
-9
@@ -19,15 +19,15 @@ declare module "nextjs-routes" {
|
||||
| DynamicRoute<"/address/[hash]", { "hash": string }>
|
||||
| StaticRoute<"/advanced-filter">
|
||||
| StaticRoute<"/ai">
|
||||
| StaticRoute<"/api/config">
|
||||
| StaticRoute<"/api/csrf">
|
||||
| StaticRoute<"/api/healthz">
|
||||
| StaticRoute<"/api/log">
|
||||
| StaticRoute<"/api/metrics">
|
||||
| StaticRoute<"/api/monitoring/invalid-api-schema">
|
||||
| StaticRoute<"/api/pchain">
|
||||
| StaticRoute<"/api/proxy">
|
||||
| DynamicRoute<"/api/tokens/[hash]/instances/[id]/media-type", { "hash": string; "id": string }>
|
||||
| StaticRoute<"/v1/config">
|
||||
| StaticRoute<"/v1/csrf">
|
||||
| StaticRoute<"/v1/healthz">
|
||||
| StaticRoute<"/v1/log">
|
||||
| StaticRoute<"/v1/metrics">
|
||||
| StaticRoute<"/v1/monitoring/invalid-api-schema">
|
||||
| StaticRoute<"/v1/pchain">
|
||||
| StaticRoute<"/v1/proxy">
|
||||
| DynamicRoute<"/v1/tokens/[hash]/instances/[id]/media-type", { "hash": string; "id": string }>
|
||||
| StaticRoute<"/api-docs">
|
||||
| DynamicRoute<"/apps/[id]", { "id": string }>
|
||||
| StaticRoute<"/apps">
|
||||
|
||||
+11
-3
@@ -1,8 +1,16 @@
|
||||
// Public API surface: /v1/* and nothing else.
|
||||
//
|
||||
// Next.js Pages Router only serves API handlers from pages/api/, which is a
|
||||
// framework constraint rather than a naming choice, so these map the one public
|
||||
// prefix onto that location. Client code never says /api/ — the hosts are
|
||||
// api.* already, and a second /api/ in the path is noise.
|
||||
//
|
||||
// This replaced /node-api/*, which was a third way to reach the same handlers.
|
||||
async function rewrites() {
|
||||
return [
|
||||
{ source: '/node-api/proxy/:slug*', destination: '/api/proxy' },
|
||||
{ source: '/node-api/:slug*', destination: '/api/:slug*' },
|
||||
].filter(Boolean);
|
||||
{ source: '/v1/proxy/:slug*', destination: '/api/proxy' },
|
||||
{ source: '/v1/:slug*', destination: '/api/:slug*' },
|
||||
];
|
||||
}
|
||||
|
||||
module.exports = rewrites;
|
||||
|
||||
@@ -122,7 +122,7 @@ async function updatePresetFile(presetId: keyof typeof PRESETS) {
|
||||
const secretEnvs = getSecretEnvsList();
|
||||
|
||||
const instanceUrl = PRESETS[presetId];
|
||||
const response = await fetch(`${ instanceUrl }/node-api/config`);
|
||||
const response = await fetch(`${ instanceUrl }/v1/config`);
|
||||
const instanceConfig = await response.json() as Record<'envs', Record<string, string>>;
|
||||
|
||||
const ignoredEnvs = [
|
||||
|
||||
@@ -39,7 +39,7 @@ test.describe('no url', () => {
|
||||
|
||||
test('non-media url and fallback', async({ render, page, mockAssetResponse }) => {
|
||||
const ANIMATION_URL = 'https://localhost:3000/my-animation.m3u8';
|
||||
const ANIMATION_MEDIA_TYPE_API_URL = `/node-api/tokens/${ TOKEN_HASH }/instances/${ TOKEN_ID }/media-type?field=animation_url`;
|
||||
const ANIMATION_MEDIA_TYPE_API_URL = `/v1/tokens/${ TOKEN_HASH }/instances/${ TOKEN_ID }/media-type?field=animation_url`;
|
||||
const IMAGE_URL = 'https://localhost:3000/my-image.jpg';
|
||||
const data = {
|
||||
id: TOKEN_ID,
|
||||
@@ -132,7 +132,7 @@ test.describe('page', () => {
|
||||
test.use({ viewport: { width: 250, height: 250 } });
|
||||
|
||||
const MEDIA_URL = 'https://localhost:3000/page.html';
|
||||
const MEDIA_TYPE_API_URL = `/node-api/tokens/${ TOKEN_HASH }/instances/${ TOKEN_ID }/media-type?field=animation_url`;
|
||||
const MEDIA_TYPE_API_URL = `/v1/tokens/${ TOKEN_HASH }/instances/${ TOKEN_ID }/media-type?field=animation_url`;
|
||||
|
||||
test.beforeEach(async({ page, mockAssetResponse }) => {
|
||||
await mockAssetResponse(MEDIA_URL, './playwright/mocks/page.html');
|
||||
|
||||
@@ -83,7 +83,7 @@ async function getMediaType(data: TokenInstance, field: Params['field']): Promis
|
||||
try {
|
||||
const mediaTypeResourceUrl = route({
|
||||
// eslint-disable-next-line max-len
|
||||
pathname: '/node-api/tokens/[hash]/instances/[id]/media-type' as DynamicRoute<'/api/tokens/[hash]/instances/[id]/media-type', { hash: string; id: string }>['pathname'],
|
||||
pathname: '/v1/tokens/[hash]/instances/[id]/media-type' as DynamicRoute<'/v1/tokens/[hash]/instances/[id]/media-type', { hash: string; id: string }>['pathname'],
|
||||
query: {
|
||||
hash: data.token.address_hash,
|
||||
id: data.id,
|
||||
|
||||
+1
-1
@@ -22,7 +22,7 @@ export function env(key: string, fallback = ''): string {
|
||||
|
||||
// Derive the backend REST base URL. In the Next.js app this was set via
|
||||
// NEXT_PUBLIC_API_HOST + NEXT_PUBLIC_API_BASE_PATH and proxied through
|
||||
// /node-api/* by next.config.js rewrites. For the SPA we hit it directly with
|
||||
// /v1/* by next.config.js rewrites. For the SPA we hit it directly with
|
||||
// CORS, so the gateway must enable it.
|
||||
export function apiBaseUrl(): string {
|
||||
const explicit = env('VITE_API_BASE_URL');
|
||||
|
||||
Reference in New Issue
Block a user