Skip to content

Commit 0711a0a

Browse files
authored
release 3.2.4 (#1098)
* remove sections and add redirects; (#1081) * fix linting * add additional redirect for old stacks.js * feat: chainhooks v2 (#1086) * initial v2 migration * add proxy route * add provider for api credentials * update utils * update content * update playground components to use api key * update layouts and components * add chainhook api to openapi scripts * add es docs * whitelist domains for proxy * update migration guides * update cards to use beta badges * add custom sidebar labels * update docskit components * update chainhook content * update translation lockfile * chore: lint fixes * update content * locale updates * minor updates / link updates * update redirects * update locale lock file * minor edits * update locale lock file * content cleanup * copy changes
1 parent 99929c4 commit 0711a0a

File tree

208 files changed

+6079
-6303
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

208 files changed

+6079
-6303
lines changed

app/[locale]/(home)/_pages/page.en.tsx

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ export default function HomePage() {
5757
<Cards>
5858
<SmallCard
5959
icon={<Chainhook />}
60+
badge="beta"
6061
href="/tools/chainhook"
6162
title="Chainhook"
6263
description="Create custom event streams and triggers for real-time blockchain data processing."
@@ -135,12 +136,6 @@ export default function HomePage() {
135136
title="Guides"
136137
description="Step-by-step walkthroughs for building on Bitcoin layers."
137138
/>
138-
<SmallCard
139-
icon={<Braces />}
140-
href="/resources/snippets"
141-
title="Snippets"
142-
description="Reusable code examples for common Stacks and Bitcoin tasks."
143-
/>
144139
<SmallCard
145140
icon={<Database />}
146141
href="/resources/archive"

app/[locale]/(home)/_pages/page.es.tsx

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/[locale]/(home)/resources/_pages/page.en.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,18 +17,6 @@ export default function ResourcesPage() {
1717
title="Guides"
1818
description="Guides for building on Stacks and Bitcoin."
1919
/>
20-
{/* <IndexCard
21-
icon={<Braces />}
22-
href="/resources/templates"
23-
title="Project templates"
24-
description="Project templates for building on Stacks and Bitcoin."
25-
/> */}
26-
<IndexCard
27-
icon={<Code />}
28-
href="/resources/snippets"
29-
title="Snippets"
30-
description="Code snippets for building on Stacks and Bitcoin."
31-
/>
3220
<IndexCard
3321
icon={<Database />}
3422
href="/resources/archive"

app/[locale]/(home)/tools/_pages/page.en.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,12 +16,15 @@ export default function ToolsPage() {
1616
href="/tools/chainhook"
1717
title="Chainhook"
1818
icon={<Chainhook />}
19+
badge="beta"
20+
tag="Stacks"
1921
description="Create custom event streams and triggers for real-time blockchain data processing."
2022
/>
2123
<IndexCard
2224
href="/tools/contract-monitoring"
2325
title="Contract Monitoring"
2426
icon={<Brackets />}
27+
tag="Stacks"
2528
description="Monitor and track smart contract activity and performance metrics."
2629
/>
2730
<IndexCard

app/[locale]/(home)/tools/_pages/page.es.tsx

Lines changed: 3 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

app/[locale]/[...slug]/page.tsx

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import { API } from '@/components/reference/api-page';
2626
import { Badge } from '@/components/ui/badge';
2727
import * as customIcons from '@/components/ui/icon';
2828
import { TagFilterSystem } from '@/components/ui/tag-filter-system';
29+
import { getAPIConfig } from '@/lib/api-config';
2930
import { i18n } from '@/lib/i18n';
3031
import { getAllFilterablePages, source } from '@/lib/source';
3132
import type { HeadingProps } from '@/types';
@@ -138,14 +139,19 @@ export default async function Page(props: {
138139
components={getMDXComponents({
139140
// Custom overrides that need special handling
140141
API: (props) => <API {...props} />,
141-
APIPage: (props) => (
142-
<APIPage
143-
baseUrl="https://api.hiro.so"
144-
enablePlayground={true}
145-
clarityConversion={true}
146-
{...props}
147-
/>
148-
),
142+
APIPage: (props) => {
143+
const config = props.document
144+
? getAPIConfig(String(props.document))
145+
: undefined;
146+
147+
const mergedProps = {
148+
...(config ?? {}),
149+
...props,
150+
playgroundOptions: props.playgroundOptions ?? config?.playgroundOptions,
151+
};
152+
153+
return <APIPage {...mergedProps} />;
154+
},
149155
h1: ({ children, ...props }: HeadingProps) => {
150156
const H1 = defaultMdxComponents.h1 as React.ComponentType<HeadingProps>;
151157
const id = typeof children === 'string' ? children : undefined;
@@ -238,14 +244,19 @@ export default async function Page(props: {
238244
components={getMDXComponents({
239245
// Custom overrides that need special handling
240246
API: (props) => <API {...props} />,
241-
APIPage: (props) => (
242-
<APIPage
243-
baseUrl="https://api.hiro.so"
244-
enablePlayground={true}
245-
clarityConversion={true}
246-
{...props}
247-
/>
248-
),
247+
APIPage: (props) => {
248+
const config = props.document
249+
? getAPIConfig(String(props.document))
250+
: undefined;
251+
252+
const mergedProps = {
253+
...(config ?? {}),
254+
...props,
255+
playgroundOptions: props.playgroundOptions ?? config?.playgroundOptions,
256+
};
257+
258+
return <APIPage {...mergedProps} />;
259+
},
249260
h1: ({ children, ...props }: HeadingProps) => {
250261
const H1 = defaultMdxComponents.h1 as React.ComponentType<HeadingProps>;
251262
const id = typeof children === 'string' ? children : undefined;

app/api/proxy/route.ts

Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
import { NextResponse } from 'next/server';
2+
3+
const ALLOWED_METHODS = new Set(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']);
4+
const ALLOWED_HOSTNAMES = new Set(['api.hiro.so', 'api.mainnet.hiro.so', 'api.testnet.hiro.so']);
5+
const BLOCKED_REQUEST_HEADERS = new Set(['host', 'cookie', 'connection', 'content-length']);
6+
const STRIPPED_RESPONSE_HEADERS = new Set(['set-cookie', 'server', 'via', 'www-authenticate']);
7+
8+
export const dynamic = 'force-dynamic';
9+
10+
export async function POST(request: Request) {
11+
try {
12+
const { url, method = 'GET', headers = {}, body } = await request.json();
13+
14+
if (!url || typeof url !== 'string') {
15+
return NextResponse.json({ error: 'A target URL is required.' }, { status: 400 });
16+
}
17+
18+
let parsedUrl: URL;
19+
try {
20+
parsedUrl = new URL(url);
21+
} catch {
22+
return NextResponse.json({ error: 'URL must be absolute.' }, { status: 400 });
23+
}
24+
25+
if (parsedUrl.protocol !== 'https:' || !ALLOWED_HOSTNAMES.has(parsedUrl.hostname)) {
26+
return NextResponse.json(
27+
{ error: 'This proxy only allows Hiro API hosts over HTTPS.' },
28+
{ status: 403 },
29+
);
30+
}
31+
32+
const upperMethod = String(method).toUpperCase();
33+
if (!ALLOWED_METHODS.has(upperMethod)) {
34+
return NextResponse.json(
35+
{ error: `Method ${upperMethod} is not supported by the proxy.` },
36+
{ status: 405 },
37+
);
38+
}
39+
40+
const upstreamHeaders = new Headers();
41+
if (headers && typeof headers === 'object') {
42+
for (const [key, value] of Object.entries(headers)) {
43+
if (typeof value === 'string' && !BLOCKED_REQUEST_HEADERS.has(key.toLowerCase())) {
44+
upstreamHeaders.set(key, value);
45+
}
46+
}
47+
}
48+
49+
const requestInit: RequestInit = {
50+
method: upperMethod,
51+
headers: upstreamHeaders,
52+
};
53+
54+
if (body !== undefined && body !== null && upperMethod !== 'GET' && upperMethod !== 'HEAD') {
55+
requestInit.body = typeof body === 'string' ? body : JSON.stringify(body);
56+
}
57+
58+
const upstreamResponse = await fetch(parsedUrl, requestInit);
59+
const contentType = upstreamResponse.headers.get('content-type') ?? '';
60+
let data: unknown;
61+
62+
if (contentType.includes('application/json')) {
63+
data = await upstreamResponse.json();
64+
} else {
65+
data = await upstreamResponse.text();
66+
}
67+
68+
const sanitizedHeaders = Object.fromEntries(
69+
Array.from(upstreamResponse.headers.entries()).filter(
70+
([key]) => !STRIPPED_RESPONSE_HEADERS.has(key.toLowerCase()),
71+
),
72+
);
73+
74+
return NextResponse.json({
75+
status: upstreamResponse.status,
76+
statusText: upstreamResponse.statusText,
77+
headers: sanitizedHeaders,
78+
data,
79+
});
80+
} catch (error) {
81+
return NextResponse.json(
82+
{ error: error instanceof Error ? error.message : 'Proxy request failed.' },
83+
{ status: 500 },
84+
);
85+
}
86+
}

app/layout.config.tsx

Lines changed: 7 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export const baseOptions: BaseLayoutProps = {
2525
text: 'Chainhook',
2626
description: 'Monitor and analyze Clarity smart contract activity.',
2727
url: '/tools/chainhook',
28+
isBeta: true,
2829
},
2930
{
3031
text: 'Contract Monitoring',
@@ -35,7 +36,6 @@ export const baseOptions: BaseLayoutProps = {
3536
text: 'Bitcoin Indexer',
3637
description: 'Indexer for Bitcoin blockchain data.',
3738
url: '/tools/bitcoin-indexer',
38-
isNew: true,
3939
},
4040
],
4141
},
@@ -69,6 +69,12 @@ export const baseOptions: BaseLayoutProps = {
6969
description: 'API for retrieving NFT and fungible token metadata.',
7070
url: '/apis/token-metadata-api',
7171
},
72+
{
73+
text: 'Chainhook API',
74+
description: 'RESTful API for accessing Chainhook',
75+
url: '/apis/chainhook-api',
76+
isNew: true,
77+
},
7278
{
7379
text: 'Platform API',
7480
description: 'API for accessing Hiro Platform data and functionality.',
@@ -100,26 +106,11 @@ export const baseOptions: BaseLayoutProps = {
100106
description: 'Guides for building on Stacks.',
101107
url: '/resources/guides',
102108
},
103-
// {
104-
// text: "Project templates",
105-
// description: "Project templates for building on Stacks.",
106-
// url: "/resources/templates",
107-
// },
108-
{
109-
text: 'Snippets',
110-
description: 'Code snippets for building on Stacks and Bitcoin.',
111-
url: '/resources/snippets',
112-
},
113109
{
114110
text: 'Hiro Archive',
115111
description: 'Archive of blockchain data.',
116112
url: '/resources/archive',
117113
},
118-
// {
119-
// text: "Faucets",
120-
// description: "Faucets for getting testnet tokens.",
121-
// url: "/resources/faucets",
122-
// },
123114
],
124115
},
125116
],

app/layout.tsx

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { RootProvider } from 'fumadocs-ui/provider';
33
import type { ReactNode } from 'react';
44
import { aeonik, aeonikFono, aeonikMono, inter } from '@/fonts';
55
import { KeyboardShortcutsProvider } from '@/hooks/use-keyboard-shortcuts';
6+
import { ApiCredentialsProvider } from '@/providers/api-credentials-provider';
67
import { QueryProvider } from '@/providers/query-provider';
78

89
export default function RootLayout({ children }: { children: ReactNode }) {
@@ -14,15 +15,17 @@ export default function RootLayout({ children }: { children: ReactNode }) {
1415
>
1516
<body className="flex flex-col min-h-screen">
1617
<QueryProvider>
17-
<KeyboardShortcutsProvider>
18-
<RootProvider
19-
search={{
20-
enabled: true,
21-
}}
22-
>
23-
{children}
24-
</RootProvider>
25-
</KeyboardShortcutsProvider>
18+
<ApiCredentialsProvider>
19+
<KeyboardShortcutsProvider>
20+
<RootProvider
21+
search={{
22+
enabled: true,
23+
}}
24+
>
25+
{children}
26+
</RootProvider>
27+
</KeyboardShortcutsProvider>
28+
</ApiCredentialsProvider>
2629
</QueryProvider>
2730
</body>
2831
</html>

0 commit comments

Comments
 (0)