@@ -12,6 +12,7 @@ import {
12
12
bnsHexValueToName ,
13
13
bnsNameCV ,
14
14
getBnsSmartContractId ,
15
+ bnsNameFromSubdomain ,
15
16
} from '../helpers' ;
16
17
import { PgStoreEventEmitter } from './pg-store-event-emitter' ;
17
18
import {
@@ -3219,14 +3220,17 @@ export class PgStore {
3219
3220
const queryResult = await this . sqlTransaction ( async sql => {
3220
3221
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3221
3222
return await sql < { name : string } [ ] > `
3222
- SELECT DISTINCT ON (name) name
3223
- FROM names
3224
- WHERE namespace_id = ${ namespace }
3225
- AND registered_at <= ${ maxBlockHeight }
3226
- AND canonical = true AND microblock_canonical = true
3227
- ORDER BY name, registered_at DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
3228
- LIMIT 100
3229
- OFFSET ${ offset }
3223
+ SELECT name FROM (
3224
+ SELECT DISTINCT ON (name) name, status
3225
+ FROM names
3226
+ WHERE namespace_id = ${ namespace }
3227
+ AND registered_at <= ${ maxBlockHeight }
3228
+ AND canonical = true AND microblock_canonical = true
3229
+ ORDER BY name, registered_at DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
3230
+ LIMIT 100
3231
+ OFFSET ${ offset }
3232
+ ) AS name_status
3233
+ WHERE status <> 'name-revoke'
3230
3234
` ;
3231
3235
} ) ;
3232
3236
const results = queryResult . map ( r => r . name ) ;
@@ -3290,7 +3294,7 @@ export class PgStore {
3290
3294
n.event_index DESC
3291
3295
LIMIT 1
3292
3296
` ;
3293
- if ( nameZonefile . length === 0 ) {
3297
+ if ( nameZonefile . length === 0 || nameZonefile [ 0 ] . status === 'name-revoke' ) {
3294
3298
return ;
3295
3299
}
3296
3300
return nameZonefile [ 0 ] ;
@@ -3312,12 +3316,21 @@ export class PgStore {
3312
3316
name : string ;
3313
3317
zoneFileHash : string ;
3314
3318
includeUnanchored : boolean ;
3319
+ chainId : ChainID ;
3315
3320
} ) : Promise < FoundOrNot < DbBnsZoneFile > > {
3316
3321
const queryResult = await this . sqlTransaction ( async sql => {
3317
3322
const maxBlockHeight = await this . getMaxBlockHeight ( sql , {
3318
3323
includeUnanchored : args . includeUnanchored ,
3319
3324
} ) ;
3320
3325
const validZonefileHash = validateZonefileHash ( args . zoneFileHash ) ;
3326
+ const parentNameStatus = await this . getName ( {
3327
+ name : bnsNameFromSubdomain ( args . name ) ,
3328
+ includeUnanchored : args . includeUnanchored ,
3329
+ chainId : args . chainId ,
3330
+ } ) ;
3331
+ if ( ! parentNameStatus . found ) {
3332
+ return [ ] as { zonefile : string } [ ] ;
3333
+ }
3321
3334
// Depending on the kind of name we got, use the correct table to pivot on canonical chain
3322
3335
// state to get the zonefile. We can't pivot on the `txs` table because some names/subdomains
3323
3336
// were imported from Stacks v1 and they don't have an associated tx.
@@ -3365,12 +3378,22 @@ export class PgStore {
3365
3378
async getLatestZoneFile ( {
3366
3379
name,
3367
3380
includeUnanchored,
3381
+ chainId,
3368
3382
} : {
3369
3383
name : string ;
3370
3384
includeUnanchored : boolean ;
3385
+ chainId : ChainID ;
3371
3386
} ) : Promise < FoundOrNot < DbBnsZoneFile > > {
3372
3387
const queryResult = await this . sqlTransaction ( async sql => {
3373
3388
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3389
+ const parentNameStatus = await this . getName ( {
3390
+ name : bnsNameFromSubdomain ( name ) ,
3391
+ includeUnanchored,
3392
+ chainId,
3393
+ } ) ;
3394
+ if ( ! parentNameStatus . found ) {
3395
+ return [ ] as { zonefile : string } [ ] ;
3396
+ }
3374
3397
// Depending on the kind of name we got, use the correct table to pivot on canonical chain
3375
3398
// state to get the zonefile. We can't pivot on the `txs` table because some names/subdomains
3376
3399
// were imported from Stacks v1 and they don't have an associated tx.
@@ -3424,8 +3447,8 @@ export class PgStore {
3424
3447
} ) : Promise < FoundOrNot < string [ ] > > {
3425
3448
const queryResult = await this . sqlTransaction ( async sql => {
3426
3449
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3427
- // 1. Get subdomains owned by this address.
3428
- // These don't produce NFT events so we have to look directly at the `subdomains` table.
3450
+ // 1. Get subdomains owned by this address. These don't produce NFT events so we have to look
3451
+ // directly at the `subdomains` table.
3429
3452
const subdomainsQuery = await sql < { fully_qualified_subdomain : string } [ ] > `
3430
3453
WITH addr_subdomains AS (
3431
3454
SELECT DISTINCT ON (fully_qualified_subdomain)
@@ -3449,9 +3472,9 @@ export class PgStore {
3449
3472
ORDER BY
3450
3473
fully_qualified_subdomain
3451
3474
` ;
3452
- // 2. Get names owned by this address which were imported from Blockstack v1.
3453
- // These also don't have an associated NFT event so we have to look directly at the `names` table,
3454
- // however, we'll also check if any of these names are still owned by the same user.
3475
+ // 2. Get names owned by this address which were imported from Blockstack v1. These also don't
3476
+ // have an associated NFT event so we have to look directly at the `names` table, however ,
3477
+ // we'll also check if any of these names are still owned by the same user.
3455
3478
const importedNamesQuery = await sql < { name : string } [ ] > `
3456
3479
SELECT
3457
3480
name
@@ -3484,7 +3507,20 @@ export class PgStore {
3484
3507
...importedNamesQuery . map ( i => i . name ) . filter ( i => ! oldImportedNames . includes ( i ) ) ,
3485
3508
...nftNamesQuery . map ( i => bnsHexValueToName ( i . value ) ) ,
3486
3509
] ) ;
3487
- return Array . from ( results . values ( ) ) . sort ( ) ;
3510
+ // 4. Now that we've acquired all names owned by this address, filter out the ones that are
3511
+ // revoked.
3512
+ const validatedResults : string [ ] = [ ] ;
3513
+ for ( const result of results ) {
3514
+ const valid = await this . getName ( {
3515
+ name : bnsNameFromSubdomain ( result ) ,
3516
+ includeUnanchored,
3517
+ chainId,
3518
+ } ) ;
3519
+ if ( valid . found ) {
3520
+ validatedResults . push ( result ) ;
3521
+ }
3522
+ }
3523
+ return validatedResults . sort ( ) ;
3488
3524
} ) ;
3489
3525
if ( queryResult . length > 0 ) {
3490
3526
return {
@@ -3502,12 +3538,18 @@ export class PgStore {
3502
3538
async getSubdomainsListInName ( {
3503
3539
name,
3504
3540
includeUnanchored,
3541
+ chainId,
3505
3542
} : {
3506
3543
name : string ;
3507
3544
includeUnanchored : boolean ;
3545
+ chainId : ChainID ;
3508
3546
} ) : Promise < { results : string [ ] } > {
3509
3547
const queryResult = await this . sqlTransaction ( async sql => {
3510
3548
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3549
+ const status = await this . getName ( { name, includeUnanchored, chainId } ) ;
3550
+ if ( ! status . found ) {
3551
+ return [ ] as { fully_qualified_subdomain : string } [ ] ;
3552
+ }
3511
3553
return await sql < { fully_qualified_subdomain : string } [ ] > `
3512
3554
SELECT DISTINCT ON (fully_qualified_subdomain) fully_qualified_subdomain
3513
3555
FROM subdomains
@@ -3522,6 +3564,9 @@ export class PgStore {
3522
3564
return { results } ;
3523
3565
}
3524
3566
3567
+ /**
3568
+ * @deprecated This function is only used for testing.
3569
+ */
3525
3570
async getSubdomainsList ( {
3526
3571
page,
3527
3572
includeUnanchored,
@@ -3551,11 +3596,15 @@ export class PgStore {
3551
3596
const queryResult = await this . sqlTransaction ( async sql => {
3552
3597
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3553
3598
return await sql < { name : string } [ ] > `
3554
- SELECT DISTINCT ON (name) name
3555
- FROM names
3556
- WHERE canonical = true AND microblock_canonical = true
3557
- AND registered_at <= ${ maxBlockHeight }
3558
- ORDER BY name, registered_at DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
3599
+ WITH name_results AS (
3600
+ SELECT DISTINCT ON (name) name, status
3601
+ FROM names
3602
+ WHERE canonical = true AND microblock_canonical = true
3603
+ AND registered_at <= ${ maxBlockHeight }
3604
+ ORDER BY name, registered_at DESC, microblock_sequence DESC, tx_index DESC, event_index DESC
3605
+ )
3606
+ SELECT name FROM name_results
3607
+ WHERE status <> 'name-revoke'
3559
3608
LIMIT 100
3560
3609
OFFSET ${ offset }
3561
3610
` ;
@@ -3567,12 +3616,22 @@ export class PgStore {
3567
3616
async getSubdomain ( {
3568
3617
subdomain,
3569
3618
includeUnanchored,
3619
+ chainId,
3570
3620
} : {
3571
3621
subdomain : string ;
3572
3622
includeUnanchored : boolean ;
3623
+ chainId : ChainID ;
3573
3624
} ) : Promise < FoundOrNot < DbBnsSubdomain & { index_block_hash : string } > > {
3574
3625
const queryResult = await this . sqlTransaction ( async sql => {
3575
3626
const maxBlockHeight = await this . getMaxBlockHeight ( sql , { includeUnanchored } ) ;
3627
+ const status = await this . getName ( {
3628
+ name : bnsNameFromSubdomain ( subdomain ) ,
3629
+ includeUnanchored,
3630
+ chainId,
3631
+ } ) ;
3632
+ if ( ! status . found ) {
3633
+ return [ ] as ( DbBnsSubdomain & { tx_id : string ; index_block_hash : string } ) [ ] ;
3634
+ }
3576
3635
return await sql < ( DbBnsSubdomain & { tx_id : string ; index_block_hash : string } ) [ ] > `
3577
3636
SELECT s.*, z.zonefile
3578
3637
FROM subdomains AS s
0 commit comments