Skip to content
Closed
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
72 changes: 72 additions & 0 deletions data/docs/get-domains.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
# Get Domains

This GET route retrieves all domains where the specified address is an admin. It returns information about each domain including address, contenthash, text records, and coin types.

## Parameters

| Parameter | Type | Required | Description |
| --------------- | ------ | -------- | ----------------------------------------------------------------------------------- |
| `admin-address` | string | Yes | The Ethereum address that is an admin of the domains to retrieve. |
| `limit` | number | No | The number of domains to return (default: 50, max: 1000). |
| `offset` | number | No | The number of domains to skip (default: 0). |
| `text_records` | string | No | Set to "0" to exclude text records and coin types from the response (default: "1"). |

## Response

The response is an array of domain objects with the following properties:

| Property | Type | Description |
| -------------- | ------ | ------------------------------------------------------------------------------- |
| `domain` | string | The domain name (e.g., "namestone.xyz"). |
| `address` | string | The Ethereum address the domain resolves to. |
| `contenthash` | string | The IPFS or IPNS contenthash for the domain's website, if set. |
| `text_records` | object | An object containing key-value pairs of the domain's text records (if included).|
| `coin_types` | object | An object containing key-value pairs of L2 chains and their addresses (if included). |

## Error Codes

| Status Code | Description |
| ----------- | ------------------------------------------------- |
| 400 | Bad request. Invalid parameters or network. |
| 500 | Server error. |

## Curl Example

```
curl -X GET \
-H 'Content-Type: application/json' \
'https://namestone.com/api/public_v1/get-domains?admin-address=0x534631Bcf33BDb069fB20A93d2fdb9e4D4dD42CF'
```

## Example Response

```json
[
{
"domain": "namestone.xyz",
"address": "0x534631Bcf33BDb069fB20A93d2fdb9e4D4dD42CF",
"contenthash": "ipfs://QmUbTVz1L4uEvAPg5QcSu8Rifq2CtTc4SYmasXLAYkFQbp",
"text_records": {
"com.twitter": "namestonehq",
"com.github": "resolverworks",
"url": "https://www.namestone.xyz",
"description": "Namestone ENS Resolver"
},
"coin_types": {
"60": "0x534631Bcf33BDb069fB20A93d2fdb9e4D4dD42CF",
"2147483785": "0x534631Bcf33BDb069fB20A93d2fdb9e4D4dD42CF"
}
},
{
"domain": "example.eth",
"address": "0xA47632346786AD59c8590Bd4898D84B4eAB97644",
"contenthash": null,
"text_records": {
"description": "Example domain"
},
"coin_types": {}
}
]
```

This endpoint is particularly useful for domain administrators who need to manage multiple domains and want to retrieve a comprehensive list of all domains under their administration.
104 changes: 104 additions & 0 deletions pages/api/[network]/get-domains.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import sql from "../../../lib/db";
import Cors from "micro-cors";
import { getNetwork } from "../../../utils/ServerUtils";

const cors = Cors({
allowMethods: ["GET", "HEAD", "POST", "OPTIONS"],
origin: "*",
});

async function handler(req, res) {
const network = getNetwork(req);
if (!network) {
return res.status(400).json({ error: "Invalid network" });
}

const { headers } = req;

// Check required parameters
const adminAddress = req.query["admin-address"];
if (!adminAddress) {
return res.status(400).json({ error: "Missing required admin-address parameter" });
}

// get offset and limit
let limit = req.query.limit;
// Check that limit is a number and >= 0
if (limit && (isNaN(Number(limit)) || Number(limit) < 0)) {
return res.status(400).json({ error: "Invalid limit parameter" });
}
if (!limit) {
limit = 50;
}
limit = Math.min(limit, 1000);

let offset = req.query.offset;
// Check that offset is a number and >= 0
if (offset && (isNaN(Number(offset)) || Number(offset) < 0)) {
return res.status(400).json({ error: "Invalid offset parameter" });
}
if (!offset) {
offset = 0;
}

const includeTextRecords = req.query.text_records;

// Get domains where the provided address is an admin
const domainQuery = await sql`
SELECT domain.id, domain.name, domain.address, domain.contenthash_raw as contenthash
FROM domain
JOIN admin ON admin.domain_id = domain.id
WHERE LOWER(admin.address) = LOWER(${adminAddress})
AND domain.network = ${network}
ORDER BY domain.name ASC
LIMIT ${limit} OFFSET ${offset}`;

if (domainQuery.length === 0) {
return res.status(200).json([]);
}

const domainPayloads = [];

if (includeTextRecords === "0") {
domainQuery.forEach((entry) => {
const { id, ...domainInfo } = entry;
domainPayloads.push({
...domainInfo,
domain: entry.name,
});
});
} else {
for (const entry of domainQuery) {
// Get text records from db
const textRecords = await sql`
SELECT * FROM domain_text_record WHERE domain_id = ${entry.id}`;

const textRecordDict = {};
textRecords.forEach((record) => {
textRecordDict[record.key] = record.value;
});

// get coin types from db
const coinTypes = await sql`
SELECT * FROM domain_coin_type WHERE domain_id = ${entry.id}`;

const coinTypeDict = {};
coinTypes.forEach((coin) => {
coinTypeDict[coin.coin_type] = coin.address;
});

const domainPayload = {
address: entry.address,
domain: entry.name,
text_records: textRecordDict,
coin_types: coinTypeDict,
contenthash: entry.contenthash,
};
domainPayloads.push(domainPayload);
}
}

return res.status(200).json(domainPayloads);
}

export default cors(handler);
Loading