@aptos-labs/aptos-client
Version:
Client package for accessing the Aptos network API.
140 lines (120 loc) • 4.17 kB
text/typescript
/**
* Fetch-based HTTP client for runtimes with native HTTP/2 support.
*
* @remarks
* Used by Deno, Bun, React Native, and any other runtime that provides a
* spec-compliant `fetch()`. These runtimes negotiate HTTP/2 automatically
* via ALPN, so the {@link AptosClientRequest.http2 | http2} option is
* ignored.
*
* @module index.fetch
*/
import { CookieJar } from "./cookieJar.js";
import {
applyCookiesToHeaders,
applyJsonContentType,
buildUrl,
headersToRecord,
parseJsonSafely,
serializeBody,
storeResponseCookies,
} from "./shared.js";
import type { AptosClientRequest, AptosClientResponse } from "./types.js";
export type { Cookie } from "./cookieJar.js";
export { CookieJar } from "./cookieJar.js";
export type { AptosClientRequest, AptosClientResponse, CookieJarLike } from "./types.js";
const defaultCookieJar = new CookieJar();
let http2Warned = false;
/**
* Send a JSON request to an Aptos API endpoint.
*
* This is the default export and the primary entry point for most callers.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
* @returns Parsed response with status, headers, and deserialized body.
*
* @example
* ```ts
* import aptosClient from "@aptos-labs/aptos-client";
*
* const { data } = await aptosClient<{ chain_id: number }>({
* url: "https://fullnode.mainnet.aptoslabs.com/v1",
* method: "GET",
* });
* ```
*/
export default async function aptosClient<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
return jsonRequest<Res>(options);
}
/**
* Send a request and parse the response as JSON.
*
* Identical to the default export; useful when a named import is preferred.
*
* @typeParam Res - Expected shape of the JSON response body.
* @param options - Request configuration.
*/
export async function jsonRequest<Res>(options: AptosClientRequest): Promise<AptosClientResponse<Res>> {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await parseJsonSafely(res);
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/**
* Send a request and return the response as an `ArrayBuffer`.
*
* Intended for BCS-encoded responses from the Aptos API.
*
* @experimental
* @param options - Request configuration.
*/
export async function bcsRequest(options: AptosClientRequest): Promise<AptosClientResponse<ArrayBuffer>> {
const { requestUrl, requestConfig, jar } = buildRequest(options);
const res = await fetch(requestUrl, requestConfig);
storeResponseCookies(new URL(requestUrl), res.headers, jar);
const data = await res.arrayBuffer();
return {
status: res.status,
statusText: res.statusText,
data,
headers: headersToRecord(res.headers),
config: requestConfig,
};
}
/** Build the URL and `RequestInit` from the caller's options. @internal */
function buildRequest(options: AptosClientRequest) {
if (options.method !== "GET" && options.method !== "POST") {
throw new Error(`Unsupported method: ${options.method}`);
}
if (!http2Warned && options.http2 !== undefined) {
http2Warned = true;
console.warn("[aptos-client] The `http2` option is only supported by the Node entry point and is ignored here.");
}
const jar = options.cookieJar ?? defaultCookieJar;
const headers = new Headers();
for (const [key, value] of Object.entries(options?.headers ?? {})) {
if (value !== undefined) {
headers.set(key, String(value));
}
}
const requestUrl = buildUrl(options.url, options.params);
applyCookiesToHeaders(headers, requestUrl, jar);
const body = serializeBody(options.body);
if (body !== undefined) {
applyJsonContentType(options.body, headers);
}
const requestConfig: RequestInit = {
method: options.method,
headers: headersToRecord(headers) as Record<string, string>,
body,
};
return { requestUrl: requestUrl.toString(), requestConfig, jar };
}