Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/generateHtml.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import fs from 'fs';
import path from 'path';

function generateHtml() {

const config = {
repoAddress: 'https://github.com/raphjaph/ordapi',
version: 'v0.0.5'
Expand Down
2 changes: 2 additions & 0 deletions src/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ const api = {
getInscriptionInfo: (id: string) => `/inscription/${id}`,
getChild: (id: string, child: number) => `/inscription/${id}/${child}`,
getInscriptions: '/inscriptions',
getInscriptionsByIds: '/inscriptions',
getInscriptionsByPage: (page: number) => `/inscriptions/${page}`,
getInscriptionsByBlock: (height: number) => `/inscriptions/block/${height}`,
getOutput: (outpoint: string) => `/output/${outpoint}`,
getOutputs: '/outputs',
getOutputsByAddress: (address: string, type?: OutputType) => {
const base = `/outputs/${address}`;
return type ? `${base}?type=${type}` : base;
Expand Down
50 changes: 50 additions & 0 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,34 @@ export class OrdClient {
return result.data;
}

private async fetchPost<T extends z.ZodType, P extends object>(
endpoint: string,
payload: P,
schema: T,
): Promise<z.infer<T>> {
const response = await fetch(`${this.baseUrl}${endpoint}`, {
method: 'POST',
headers: {
...this.headers,
'Content-Type': 'application/json',
},
body: JSON.stringify(payload),
});

if (!response.ok) {
throw new Error(`API request failed: ${response.statusText}`);
}

const data = await response.json();
const result = schema.safeParse(data);

if (!result.success) {
throw new Error(`Validation error: ${result.error.message}`);
}

return result.data;
}

/**
* Retrieves information about a specific address including its outputs,
* inscriptions, and rune balances.
Expand Down Expand Up @@ -234,6 +262,19 @@ export class OrdClient {
return this.fetch(api.getInscriptions, InscriptionsResponseSchema);
}

/**
* Retrieves information about multiple inscriptions by their IDs.
*
* @param {string[]} ids - Array of inscription IDs to fetch
*/
async getInscriptionsByIds(ids: string[]): Promise<InscriptionInfo[]> {
return this.fetchPost(
api.getInscriptionsByIds,
ids,
z.array(InscriptionInfoSchema),
);
}

/**
* Gets inscriptions for a specific page number in paginated results.
*
Expand Down Expand Up @@ -405,6 +446,15 @@ export class OrdClient {
return this.fetch(api.getOutputAssets(outpoint), OutputAssetsSchema);
}

/**
* Gets information about multiple UTXOs.
*
* @param {string[]} outpoints - Array of outpoints to fetch
*/
async getOutputs(outpoints: string[]): Promise<OutputInfo[]> {
return this.fetchPost(api.getOutputs, outpoints, z.array(OutputInfoSchema));
}

/**
* Gets all UTXOs for a specific address, optionally filtered by type.
*
Expand Down
71 changes: 71 additions & 0 deletions src/test/integration/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,43 @@ describe('API Integration Tests', () => {
);
});

describe('getInscriptionsByIds', () => {
test(
'fetches multiple inscriptions successfully',
async () => {
const inscriptions = await client.getInscriptionsByIds([
SAMPLE_INSCRIPTION_ID,
SAMPLE_CHILD_ID,
]);
expect(Array.isArray(inscriptions)).toBe(true);
expect(inscriptions.length).toBe(2);
expect(inscriptions[0].id).toBe(SAMPLE_INSCRIPTION_ID);
expect(inscriptions[1].id).toBe(SAMPLE_CHILD_ID);
},
TIMEOUT,
);

test(
'handles server error',
async () => {
expect(
invalidClient.getInscriptionsByIds([SAMPLE_INSCRIPTION_ID]),
).rejects.toThrow();
},
TIMEOUT,
);

test(
'handles empty array',
async () => {
const inscriptions = await client.getInscriptionsByIds([]);
expect(Array.isArray(inscriptions)).toBe(true);
expect(inscriptions.length).toBe(0);
},
TIMEOUT,
);
});

describe('getOutput', () => {
test(
'fetches output successfully',
Expand Down Expand Up @@ -354,6 +391,40 @@ describe('API Integration Tests', () => {
);
});

describe('getOutputs', () => {
test(
'fetches multiple outputs successfully',
async () => {
const outpoints = [SAMPLE_OUTPOINT_A, SAMPLE_OUTPOINT_B];
const outputs = await client.getOutputs(outpoints);
expect(Array.isArray(outputs)).toBe(true);
expect(outputs[0].outpoint).toBe(SAMPLE_OUTPOINT_A);
expect(outputs[1].outpoint).toBe(SAMPLE_OUTPOINT_B);
},
TIMEOUT,
);

test(
'handles empty array',
async () => {
const outputs = await client.getOutputs([]);
expect(Array.isArray(outputs)).toBe(true);
expect(outputs.length).toBe(0);
},
TIMEOUT,
);

test(
'handles server error',
async () => {
expect(
invalidClient.getOutputs([SAMPLE_OUTPOINT_A, SAMPLE_OUTPOINT_B]),
).rejects.toThrow();
},
TIMEOUT,
);
});

describe('getOutputsByAddress', () => {
test(
'fetches outputs by address successfully',
Expand Down