Skip to content

Commit e34120f

Browse files
authored
feat: fetch subdomain list for bns name (#1132)
* feat: endpoint to fetch subdomains for a name * fix: resolved docs error * fix: made requested changes * style: minor changes
1 parent da992d7 commit e34120f

File tree

7 files changed

+98
-0
lines changed

7 files changed

+98
-0
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[
2+
"address_test.id.blockstack",
3+
"previous_subdomain.id.blockstack",
4+
"subdomain.id.blockstack",
5+
"zonefile_test.id.blockstack",
6+
"zone_test.id.blockstack"
7+
]
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema",
3+
"$id": "subdomains-list-in-name",
4+
"title": "GetAllSubdomainsInName",
5+
"description": "Fetch a list of subdomains in a name.",
6+
"type": "array",
7+
"items": {
8+
"type": "string",
9+
"pattern": "^([a-z0-9-_.+]{3,37})$"
10+
}
11+
}

docs/openapi.yaml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2536,6 +2536,32 @@ paths:
25362536
example:
25372537
$ref: ./api/bns/errors/bns-no-such-name.example.json
25382538

2539+
/v1/names/{name}/subdomains:
2540+
get:
2541+
summary: Get Name Subdomains
2542+
description: Retrieves the list of subdomains for a specific name
2543+
tags:
2544+
- Names
2545+
operationId: fetch_subdomains_list_for_name
2546+
parameters:
2547+
- name: name
2548+
in: path
2549+
description: fully-qualified name
2550+
required: true
2551+
example: id.blockstack
2552+
schema:
2553+
type: string
2554+
responses:
2555+
200:
2556+
description: Success
2557+
content:
2558+
application/json:
2559+
schema:
2560+
$ref: ./api/bns/subdomains/subdomains-list.schema.json
2561+
example:
2562+
$ref: ./api/bns/subdomains/subdomains-list.example.json
2563+
2564+
25392565
/v1/names/{name}/zonefile:
25402566
get:
25412567
summary: Get Zone File

src/api/routes/bns/names.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ export function createBnsNamesRouter(db: DataStore): express.Router {
3636
})
3737
);
3838

39+
router.get(
40+
'/:name/subdomains',
41+
asyncHandler(async (req, res, next) => {
42+
const { name } = req.params;
43+
const includeUnanchored = isUnanchoredRequest(req, res, next);
44+
const subdomainsList = await db.getSubdomainsListInName({ name, includeUnanchored });
45+
res.json(subdomainsList.results);
46+
})
47+
);
48+
3949
router.get(
4050
'/:name/zonefile',
4151
asyncHandler(async (req, res, next) => {

src/datastore/common.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -924,6 +924,14 @@ export interface DataStore extends DataStoreEventEmitter {
924924
}): Promise<{
925925
results: string[];
926926
}>;
927+
/**
928+
* This function returns the subdomains for a specific name
929+
* @param name - The name for which subdomains are required
930+
*/
931+
getSubdomainsListInName(args: {
932+
name: string;
933+
includeUnanchored: boolean;
934+
}): Promise<{ results: string[] }>;
927935
getSubdomainsList(args: {
928936
page: number;
929937
includeUnanchored: boolean;

src/datastore/postgres-store.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6916,6 +6916,30 @@ export class PgDataStore
69166916
return { found: false } as const;
69176917
}
69186918

6919+
async getSubdomainsListInName({
6920+
name,
6921+
includeUnanchored,
6922+
}: {
6923+
name: string;
6924+
includeUnanchored: boolean;
6925+
}): Promise<{ results: string[] }> {
6926+
const queryResult = await this.queryTx(async client => {
6927+
const maxBlockHeight = await this.getMaxBlockHeight(client, { includeUnanchored });
6928+
return await client.query<{ fully_qualified_subdomain: string }>(
6929+
`
6930+
SELECT DISTINCT ON (fully_qualified_subdomain) fully_qualified_subdomain
6931+
FROM subdomains
6932+
WHERE name = $1 AND block_height <= $2
6933+
AND canonical = true AND microblock_canonical = true
6934+
ORDER BY fully_qualified_subdomain, block_height DESC, microblock_sequence DESC, tx_index DESC
6935+
`,
6936+
[name, maxBlockHeight]
6937+
);
6938+
});
6939+
const results = queryResult.rows.map(r => r.fully_qualified_subdomain);
6940+
return { results };
6941+
}
6942+
69196943
async getSubdomainsList({
69206944
page,
69216945
includeUnanchored,

src/tests-bns/api.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -742,6 +742,18 @@ describe('BNS API tests', () => {
742742
);
743743
});
744744

745+
test('Success: subdomains in name', async () => {
746+
const query = await supertest(api.server).get(`/v1/names/id.blockstack/subdomains/`);
747+
const expectedResult = [
748+
'address_test.id.blockstack',
749+
'previous_subdomain.id.blockstack',
750+
'subdomain.id.blockstack',
751+
'zonefile_test.id.blockstack',
752+
'zone_test.id.blockstack'
753+
];
754+
expect(query.body).toEqual(expectedResult);
755+
});
756+
745757
afterAll(async () => {
746758
await api.terminate();
747759
client.release();

0 commit comments

Comments
 (0)