@@ -2,13 +2,15 @@ import { DurableObject } from 'cloudflare:workers';
2
2
import { Env } from '../../worker-configuration' ;
3
3
import { AppConfig } from '../config' ;
4
4
import { validateStacksAddress } from '@stacks/transactions' ;
5
- import { createJsonResponse } from '../utils/requests-responses-util' ;
6
5
import { getKnownAddresses } from '../utils/address-store-util' ;
7
6
import { getNameFromAddress , initStacksFetcher } from '../utils/bns-v2-util' ;
7
+ import { ApiError } from '../utils/api-error' ;
8
+ import { ErrorCode } from '../utils/error-catalog' ;
9
+ import { handleRequest } from '../utils/request-handler' ;
8
10
9
11
/**
10
12
* Durable Object class for the BNS (Blockchain Naming System) API
11
- *
13
+ *
12
14
* This Durable Object handles BNS name lookups for Stacks addresses.
13
15
* It provides endpoints to retrieve BNS names associated with Stacks addresses
14
16
* and maintains a cache of these associations to reduce API calls.
@@ -40,13 +42,13 @@ export class BnsApiDO extends DurableObject<Env> {
40
42
41
43
/**
42
44
* Alarm handler that periodically updates the BNS name cache
43
- *
45
+ *
44
46
* This method is triggered by the Durable Object's alarm system and:
45
47
* 1. Retrieves all known Stacks addresses from KV storage
46
48
* 2. Updates the BNS name for each address
47
49
* 3. Stores the results in KV cache with the configured TTL
48
50
* 4. Logs statistics about the update process
49
- *
51
+ *
50
52
* @returns A promise that resolves when the alarm handler completes
51
53
*/
52
54
async alarm ( ) : Promise < void > {
@@ -97,75 +99,81 @@ export class BnsApiDO extends DurableObject<Env> {
97
99
98
100
/**
99
101
* Main request handler for the BNS API Durable Object
100
- *
102
+ *
101
103
* Handles the following endpoints:
102
104
* - / - Returns a list of supported endpoints
103
105
* - /names/{address} - Returns the BNS name for the given Stacks address
104
- *
106
+ *
105
107
* @param request - The incoming HTTP request
106
108
* @returns A Response object with the requested data or an error message
107
109
*/
108
110
async fetch ( request : Request ) : Promise < Response > {
109
111
const url = new URL ( request . url ) ;
110
112
const path = url . pathname ;
111
113
112
- if ( ! path . startsWith ( this . BASE_PATH ) ) {
113
- return createJsonResponse (
114
- {
115
- error : `Request at ${ path } does not start with base path ${ this . BASE_PATH } ` ,
116
- } ,
117
- 404
118
- ) ;
119
- }
114
+ return handleRequest (
115
+ async ( ) => {
116
+ if ( ! path . startsWith ( this . BASE_PATH ) ) {
117
+ throw new ApiError ( ErrorCode . NOT_FOUND , {
118
+ resource : path ,
119
+ basePath : this . BASE_PATH ,
120
+ } ) ;
121
+ }
120
122
121
- // Remove base path to get the endpoint
122
- const endpoint = path . replace ( this . BASE_PATH , '' ) ;
123
+ // Remove base path to get the endpoint
124
+ const endpoint = path . replace ( this . BASE_PATH , '' ) ;
123
125
124
- // Handle root path
125
- if ( endpoint === '' || endpoint === '/' ) {
126
- return createJsonResponse ( {
127
- message : `Supported endpoints: ${ this . SUPPORTED_ENDPOINTS . join ( ', ' ) } ` ,
128
- } ) ;
129
- }
126
+ // Handle root path
127
+ if ( endpoint === '' || endpoint === '/' ) {
128
+ return {
129
+ message : `Supported endpoints: ${ this . SUPPORTED_ENDPOINTS . join ( ', ' ) } ` ,
130
+ } ;
131
+ }
130
132
131
- if ( endpoint === '/names' ) {
132
- return createJsonResponse ( {
133
- message : `Please provide an address to look up the name for, e.g. /names/SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF` ,
134
- } ) ;
135
- }
133
+ if ( endpoint === '/names' ) {
134
+ return {
135
+ message : `Please provide an address to look up the name for, e.g. /names/SP2QEZ06AGJ3RKJPBV14SY1V5BBFNAW33D96YPGZF` ,
136
+ } ;
137
+ }
136
138
137
- // Handle name lookups
138
- if ( endpoint . startsWith ( '/names/' ) ) {
139
- const address = endpoint . replace ( '/names/' , '' ) ;
140
- const validAddress = validateStacksAddress ( address ) ;
141
- if ( ! validAddress ) {
142
- return createJsonResponse ( { error : `Invalid address ${ address } , valid Stacks address required` } , 400 ) ;
143
- }
144
- const cacheKey = `${ this . CACHE_PREFIX } _names_${ address } ` ;
145
- const cachedName = await this . env . AIBTCDEV_CACHE_KV . get < string > ( cacheKey ) ;
146
- if ( cachedName ) {
147
- return createJsonResponse ( cachedName ) ;
148
- }
149
- const name = await getNameFromAddress ( address ) ;
150
-
151
- if ( name === '' ) {
152
- return createJsonResponse (
153
- {
154
- error : `No registered name found for address ${ address } ` ,
155
- } ,
156
- 404
157
- ) ;
158
- }
139
+ // Handle name lookups
140
+ if ( endpoint . startsWith ( '/names/' ) ) {
141
+ const address = endpoint . replace ( '/names/' , '' ) ;
142
+ const validAddress = validateStacksAddress ( address ) ;
143
+ if ( ! validAddress ) {
144
+ throw new ApiError ( ErrorCode . INVALID_REQUEST , {
145
+ reason : `Invalid address ${ address } , valid Stacks address required` ,
146
+ } ) ;
147
+ }
159
148
160
- await this . env . AIBTCDEV_CACHE_KV . put ( cacheKey , name , { expirationTtl : this . CACHE_TTL } ) ;
161
- return createJsonResponse ( name ) ;
162
- }
149
+ const cacheKey = `${ this . CACHE_PREFIX } _names_${ address } ` ;
150
+ const cachedName = await this . env . AIBTCDEV_CACHE_KV . get < string > ( cacheKey ) ;
151
+ if ( cachedName ) {
152
+ return cachedName ;
153
+ }
163
154
164
- return createJsonResponse (
165
- {
166
- error : `Unsupported endpoint: ${ endpoint } , supported endpoints: ${ this . SUPPORTED_ENDPOINTS . join ( ', ' ) } ` ,
155
+ const name = await getNameFromAddress ( address ) ;
156
+
157
+ if ( name === '' ) {
158
+ throw new ApiError ( ErrorCode . NOT_FOUND , {
159
+ resource : `name for address ${ address } ` ,
160
+ reason : 'No registered name found' ,
161
+ } ) ;
162
+ }
163
+
164
+ await this . env . AIBTCDEV_CACHE_KV . put ( cacheKey , name , { expirationTtl : this . CACHE_TTL } ) ;
165
+ return name ;
166
+ }
167
+
168
+ throw new ApiError ( ErrorCode . NOT_FOUND , {
169
+ resource : endpoint ,
170
+ supportedEndpoints : this . SUPPORTED_ENDPOINTS ,
171
+ } ) ;
167
172
} ,
168
- 404
173
+ this . env ,
174
+ {
175
+ slowThreshold : 2000 , // BNS lookups can be slow
176
+ }
169
177
) ;
170
178
}
171
179
}
0 commit comments