Skip to content

Commit f5de8f3

Browse files
Add back POST endpoints (#25)
1 parent 521e5a8 commit f5de8f3

File tree

4 files changed

+124
-0
lines changed

4 files changed

+124
-0
lines changed

docs/generateHtml.ts

+1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import fs from 'fs';
22
import path from 'path';
33

44
function generateHtml() {
5+
56
const config = {
67
repoAddress: 'https://github.com/raphjaph/ordapi',
78
version: 'v0.0.5'

src/api.ts

+2
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,11 @@ const api = {
1212
getInscriptionInfo: (id: string) => `/inscription/${id}`,
1313
getChild: (id: string, child: number) => `/inscription/${id}/${child}`,
1414
getInscriptions: '/inscriptions',
15+
getInscriptionsByIds: '/inscriptions',
1516
getInscriptionsByPage: (page: number) => `/inscriptions/${page}`,
1617
getInscriptionsByBlock: (height: number) => `/inscriptions/block/${height}`,
1718
getOutput: (outpoint: string) => `/output/${outpoint}`,
19+
getOutputs: '/outputs',
1820
getOutputsByAddress: (address: string, type?: OutputType) => {
1921
const base = `/outputs/${address}`;
2022
return type ? `${base}?type=${type}` : base;

src/client.ts

+50
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,34 @@ export class OrdClient {
9191
return result.data;
9292
}
9393

94+
private async fetchPost<T extends z.ZodType, P extends object>(
95+
endpoint: string,
96+
payload: P,
97+
schema: T,
98+
): Promise<z.infer<T>> {
99+
const response = await fetch(`${this.baseUrl}${endpoint}`, {
100+
method: 'POST',
101+
headers: {
102+
...this.headers,
103+
'Content-Type': 'application/json',
104+
},
105+
body: JSON.stringify(payload),
106+
});
107+
108+
if (!response.ok) {
109+
throw new Error(`API request failed: ${response.statusText}`);
110+
}
111+
112+
const data = await response.json();
113+
const result = schema.safeParse(data);
114+
115+
if (!result.success) {
116+
throw new Error(`Validation error: ${result.error.message}`);
117+
}
118+
119+
return result.data;
120+
}
121+
94122
/**
95123
* Retrieves information about a specific address including its outputs,
96124
* inscriptions, and rune balances.
@@ -234,6 +262,19 @@ export class OrdClient {
234262
return this.fetch(api.getInscriptions, InscriptionsResponseSchema);
235263
}
236264

265+
/**
266+
* Retrieves information about multiple inscriptions by their IDs.
267+
*
268+
* @param {string[]} ids - Array of inscription IDs to fetch
269+
*/
270+
async getInscriptionsByIds(ids: string[]): Promise<InscriptionInfo[]> {
271+
return this.fetchPost(
272+
api.getInscriptionsByIds,
273+
ids,
274+
z.array(InscriptionInfoSchema),
275+
);
276+
}
277+
237278
/**
238279
* Gets inscriptions for a specific page number in paginated results.
239280
*
@@ -405,6 +446,15 @@ export class OrdClient {
405446
return this.fetch(api.getOutputAssets(outpoint), OutputAssetsSchema);
406447
}
407448

449+
/**
450+
* Gets information about multiple UTXOs.
451+
*
452+
* @param {string[]} outpoints - Array of outpoints to fetch
453+
*/
454+
async getOutputs(outpoints: string[]): Promise<OutputInfo[]> {
455+
return this.fetchPost(api.getOutputs, outpoints, z.array(OutputInfoSchema));
456+
}
457+
408458
/**
409459
* Gets all UTXOs for a specific address, optionally filtered by type.
410460
*

src/test/integration/api.test.ts

+71
Original file line numberDiff line numberDiff line change
@@ -325,6 +325,43 @@ describe('API Integration Tests', () => {
325325
);
326326
});
327327

328+
describe('getInscriptionsByIds', () => {
329+
test(
330+
'fetches multiple inscriptions successfully',
331+
async () => {
332+
const inscriptions = await client.getInscriptionsByIds([
333+
SAMPLE_INSCRIPTION_ID,
334+
SAMPLE_CHILD_ID,
335+
]);
336+
expect(Array.isArray(inscriptions)).toBe(true);
337+
expect(inscriptions.length).toBe(2);
338+
expect(inscriptions[0].id).toBe(SAMPLE_INSCRIPTION_ID);
339+
expect(inscriptions[1].id).toBe(SAMPLE_CHILD_ID);
340+
},
341+
TIMEOUT,
342+
);
343+
344+
test(
345+
'handles server error',
346+
async () => {
347+
expect(
348+
invalidClient.getInscriptionsByIds([SAMPLE_INSCRIPTION_ID]),
349+
).rejects.toThrow();
350+
},
351+
TIMEOUT,
352+
);
353+
354+
test(
355+
'handles empty array',
356+
async () => {
357+
const inscriptions = await client.getInscriptionsByIds([]);
358+
expect(Array.isArray(inscriptions)).toBe(true);
359+
expect(inscriptions.length).toBe(0);
360+
},
361+
TIMEOUT,
362+
);
363+
});
364+
328365
describe('getOutput', () => {
329366
test(
330367
'fetches output successfully',
@@ -354,6 +391,40 @@ describe('API Integration Tests', () => {
354391
);
355392
});
356393

394+
describe('getOutputs', () => {
395+
test(
396+
'fetches multiple outputs successfully',
397+
async () => {
398+
const outpoints = [SAMPLE_OUTPOINT_A, SAMPLE_OUTPOINT_B];
399+
const outputs = await client.getOutputs(outpoints);
400+
expect(Array.isArray(outputs)).toBe(true);
401+
expect(outputs[0].outpoint).toBe(SAMPLE_OUTPOINT_A);
402+
expect(outputs[1].outpoint).toBe(SAMPLE_OUTPOINT_B);
403+
},
404+
TIMEOUT,
405+
);
406+
407+
test(
408+
'handles empty array',
409+
async () => {
410+
const outputs = await client.getOutputs([]);
411+
expect(Array.isArray(outputs)).toBe(true);
412+
expect(outputs.length).toBe(0);
413+
},
414+
TIMEOUT,
415+
);
416+
417+
test(
418+
'handles server error',
419+
async () => {
420+
expect(
421+
invalidClient.getOutputs([SAMPLE_OUTPOINT_A, SAMPLE_OUTPOINT_B]),
422+
).rejects.toThrow();
423+
},
424+
TIMEOUT,
425+
);
426+
});
427+
357428
describe('getOutputsByAddress', () => {
358429
test(
359430
'fetches outputs by address successfully',

0 commit comments

Comments
 (0)