@@ -40,6 +40,8 @@ import {
40
40
isValidPrincipal ,
41
41
isSmartContractTx ,
42
42
bnsNameCV ,
43
+ getBnsSmartContractId ,
44
+ bnsHexValueToName ,
43
45
} from '../helpers' ;
44
46
import {
45
47
DataStore ,
@@ -104,7 +106,7 @@ import {
104
106
} from '@stacks/stacks-blockchain-api-types' ;
105
107
import { getTxTypeId } from '../api/controllers/db-controller' ;
106
108
import { isProcessableTokenMetadata } from '../event-stream/tokens-contract-handler' ;
107
- import { ChainID , ClarityAbi } from '@stacks/transactions' ;
109
+ import { ChainID , ClarityAbi , hexToCV , TupleCV } from '@stacks/transactions' ;
108
110
import {
109
111
PgAddressNotificationPayload ,
110
112
PgBlockNotificationPayload ,
@@ -7032,18 +7034,13 @@ export class PgDataStore
7032
7034
} catch ( error ) {
7033
7035
return ;
7034
7036
}
7035
- const assetIdentifier =
7036
- chainId === ChainID . Mainnet
7037
- ? 'SP000000000000000000002Q6VF78.bns::names'
7038
- : 'ST000000000000000000002AMW42H.bns::names' ;
7039
- const nftCustody = includeUnanchored ? 'nft_custody_unanchored' : 'nft_custody' ;
7040
7037
const nameCustody = await client . query < { recipient : string } > (
7041
7038
`
7042
7039
SELECT recipient
7043
- FROM ${ nftCustody }
7040
+ FROM ${ includeUnanchored ? 'nft_custody_unanchored' : 'nft_custody' }
7044
7041
WHERE asset_identifier = $1 AND value = $2
7045
7042
` ,
7046
- [ assetIdentifier , value ]
7043
+ [ getBnsSmartContractId ( chainId ) , value ]
7047
7044
) ;
7048
7045
if ( nameCustody . rowCount === 0 ) {
7049
7046
return ;
@@ -7167,59 +7164,88 @@ export class PgDataStore
7167
7164
async getNamesByAddressList ( {
7168
7165
address,
7169
7166
includeUnanchored,
7167
+ chainId,
7170
7168
} : {
7171
7169
address : string ;
7172
7170
includeUnanchored : boolean ;
7171
+ chainId : ChainID ;
7173
7172
} ) : Promise < FoundOrNot < string [ ] > > {
7174
7173
const queryResult = await this . queryTx ( async client => {
7175
7174
const maxBlockHeight = await this . getMaxBlockHeight ( client , { includeUnanchored } ) ;
7176
- const query = await client . query < { name : string } > (
7175
+ // 1. Get subdomains owned by this address.
7176
+ // These don't produce NFT events so we have to look directly at the `subdomains` table.
7177
+ const subdomainsQuery = await client . query < { fully_qualified_subdomain : string } > (
7177
7178
`
7178
- WITH address_names AS(
7179
- (
7180
- SELECT name
7181
- FROM names
7182
- WHERE address = $1
7183
- AND registered_at <= $2
7184
- AND canonical = true AND microblock_canonical = true
7179
+ WITH addr_subdomains AS (
7180
+ SELECT DISTINCT ON (fully_qualified_subdomain)
7181
+ fully_qualified_subdomain
7182
+ FROM
7183
+ subdomains
7184
+ WHERE
7185
+ owner = $1
7186
+ AND block_height <= $2
7187
+ AND canonical = TRUE
7188
+ AND microblock_canonical = TRUE
7185
7189
)
7186
- UNION ALL (
7187
- SELECT DISTINCT ON (fully_qualified_subdomain) fully_qualified_subdomain as name
7188
- FROM subdomains
7189
- WHERE owner = $1
7190
- AND block_height <= $2
7191
- AND canonical = true AND microblock_canonical = true
7192
- )),
7193
-
7194
- latest_names AS(
7195
- (
7196
- SELECT DISTINCT ON (names.name) names.name, address, registered_at as block_height, tx_index
7197
- FROM names, address_names
7198
- WHERE address_names.name = names.name
7199
- AND canonical = true AND microblock_canonical = true
7200
- ORDER BY names.name, registered_at DESC, tx_index DESC
7201
- )
7202
- UNION ALL(
7203
- SELECT DISTINCT ON (fully_qualified_subdomain) fully_qualified_subdomain as name, owner as address, block_height, tx_index
7204
- FROM subdomains, address_names
7205
- WHERE fully_qualified_subdomain = address_names.name
7206
- AND canonical = true AND microblock_canonical = true
7207
- ORDER BY fully_qualified_subdomain, block_height DESC, tx_index DESC
7208
- ))
7209
-
7210
- SELECT name from latest_names
7211
- WHERE address = $1
7212
- ORDER BY name, block_height DESC, tx_index DESC
7190
+ SELECT DISTINCT ON (fully_qualified_subdomain)
7191
+ fully_qualified_subdomain
7192
+ FROM
7193
+ subdomains
7194
+ INNER JOIN addr_subdomains USING (fully_qualified_subdomain)
7195
+ WHERE
7196
+ canonical = TRUE
7197
+ AND microblock_canonical = TRUE
7198
+ ORDER BY
7199
+ fully_qualified_subdomain
7213
7200
` ,
7214
7201
[ address , maxBlockHeight ]
7215
7202
) ;
7216
- return query ;
7203
+ // 2. Get names owned by this address which were imported from Blockstack v1.
7204
+ // These also don't have an associated NFT event so we have to look directly at the `names` table,
7205
+ // however, we'll also check if any of these names are still owned by the same user.
7206
+ const importedNamesQuery = await client . query < { name : string } > (
7207
+ `
7208
+ SELECT
7209
+ name
7210
+ FROM
7211
+ names
7212
+ WHERE
7213
+ address = $1
7214
+ AND registered_at = 0
7215
+ AND canonical = TRUE
7216
+ AND microblock_canonical = TRUE
7217
+ ` ,
7218
+ [ address ]
7219
+ ) ;
7220
+ const oldImportedNamesQuery = await client . query < { value : string } > (
7221
+ `
7222
+ SELECT value
7223
+ FROM ${ includeUnanchored ? 'nft_custody_unanchored' : 'nft_custody' }
7224
+ WHERE recipient <> $1 AND value = ANY($2)
7225
+ ` ,
7226
+ [ address , importedNamesQuery . rows . map ( i => bnsNameCV ( i . name ) ) ]
7227
+ ) ;
7228
+ const oldImportedNames = oldImportedNamesQuery . rows . map ( i => bnsHexValueToName ( i . value ) ) ;
7229
+ // 3. Get newer NFT names owned by this address.
7230
+ const nftNamesQuery = await client . query < { value : string } > (
7231
+ `
7232
+ SELECT value
7233
+ FROM ${ includeUnanchored ? 'nft_custody_unanchored' : 'nft_custody' }
7234
+ WHERE recipient = $1 AND asset_identifier = $2
7235
+ ` ,
7236
+ [ address , getBnsSmartContractId ( chainId ) ]
7237
+ ) ;
7238
+ const results : Set < string > = new Set ( [
7239
+ ...subdomainsQuery . rows . map ( i => i . fully_qualified_subdomain ) ,
7240
+ ...importedNamesQuery . rows . map ( i => i . name ) . filter ( i => ! oldImportedNames . includes ( i ) ) ,
7241
+ ...nftNamesQuery . rows . map ( i => bnsHexValueToName ( i . value ) ) ,
7242
+ ] ) ;
7243
+ return Array . from ( results . values ( ) ) . sort ( ) ;
7217
7244
} ) ;
7218
-
7219
- if ( queryResult . rowCount > 0 ) {
7245
+ if ( queryResult . length > 0 ) {
7220
7246
return {
7221
7247
found : true ,
7222
- result : queryResult . rows . map ( r => r . name ) ,
7248
+ result : queryResult ,
7223
7249
} ;
7224
7250
}
7225
7251
return { found : false } as const ;
0 commit comments