TLD Parser Dart SDK
A Dart SDK for parsing and resolving AllDomains ANS Protocol domains on Solana. Supports any TLD including .skr, .abc, .poor, .bonk, and more.
Key Insight: ANS vs SNS
| Feature | SNS (Bonfida) | ANS (AllDomains) |
|---|---|---|
| TLDs Supported | Only .sol |
Any TLD (.skr, .abc, .poor, etc.) |
| Hash Prefix | SPL Name Service |
ALT Name Service |
| Program ID | namesLPne... |
ALTNSZ46uaAUU7XUV6awvdorLGqAsPwa9shm7h4uP2FK |
The existing SNS Dart packages only support .sol domains. This SDK is for all other TLDs.
Installation
Add to your pubspec.yaml:
dependencies:
tld_parser: ^0.1.0
Quick Start
import 'package:tld_parser/tld_parser.dart';
import 'package:solana/solana.dart';
void main() async {
// Initialize
final rpcClient = RpcClient('https://api.mainnet-beta.solana.com');
final parser = TldParser(rpcClient);
// Resolve a domain to its owner
final owner = await parser.getOwnerFromDomainTld('miester.abc');
print('Owner: ${owner?.toBase58()}');
// Get a user's main domain (reverse lookup)
final mainDomain = await parser.tryGetMainDomain(owner!);
print('Main domain: ${mainDomain?.fullDomain}');
// Fetch domain records
final twitter = await parser.getRecord('miester.abc', Record.twitter);
print('Twitter: $twitter');
// Get all domains owned by a user
final domains = await parser.getAllUserDomainsFromTld(owner, 'abc');
print('User owns ${domains.length} .abc domains');
}
Features
Domain Resolution
// Get owner of any domain
final owner = await parser.getOwnerFromDomainTld('miester.abc');
// Works with subdomains too
final subOwner = await parser.getOwnerFromDomainTld('vault.miester.abc');
// Get the full name record with metadata
final record = await parser.getNameRecordFromDomainTld('miester.abc');
print('Created: ${record?.createdAtDateTime}');
print('Expires: ${record?.expiresAtDateTime}');
print('Is valid: ${record?.isValid}');
Reverse Lookup
// Get a user's main domain
final mainDomain = await parser.getMainDomain(userPubkey);
print('${mainDomain.fullDomain}'); // e.g., 'miester.abc'
// Try without throwing (returns null if not set)
final maybe = await parser.tryGetMainDomain(userPubkey);
Domain Listing
// Get all domains owned by a user (all TLDs)
final allDomains = await parser.getAllUserDomains(userPubkey);
// Get domains in a specific TLD
final abcDomains = await parser.getAllUserDomainsFromTld(userPubkey, 'abc');
// Get parsed domain names (with reverse lookups)
final parsed = await parser.getParsedAllUserDomainsFromTld(userPubkey, 'abc');
for (final d in parsed) {
print('${d.domain} -> ${d.nameAccount.toBase58()}');
}
Record Fetching
// Get a specific record
final twitter = await parser.getRecord('miester.abc', Record.twitter);
final email = await parser.getRecord('miester.abc', Record.email);
// Get multiple records at once (efficient batching)
final records = await parser.getRecords('miester.abc', [
Record.twitter,
Record.discord,
Record.github,
Record.email,
]);
// Get all available records
final allRecords = await parser.getAllRecords('miester.abc');
Available Records
The SDK supports the following record types:
Content/Storage:
Record.ipfs- IPFS content hashRecord.arwv- Arweave content hashRecord.url- URL linkRecord.shdw- Shadow Drive
Crypto Addresses:
Record.sol,Record.eth,Record.btcRecord.aptos,Record.near,Record.suiRecord.base,Record.stacksRecord.ltc,Record.doge,Record.point,Record.lattica
Social:
Record.twitter,Record.discordRecord.github,Record.reddit,Record.telegram
Profile:
Record.pic- Profile pictureRecord.email- Email address
NFT-Wrapped Domains
The SDK automatically handles NFT-wrapped domains. When a domain is wrapped as an NFT, the SDK resolves through the NFT record to find the actual token holder:
// This works whether the domain is wrapped or not
final owner = await parser.getOwnerFromDomainTld('miester.abc');
Domain Key Derivation
For advanced use cases, you can derive domain keys directly:
// Derive a domain key
final domainKey = await getDomainKey('miester.abc');
print('Domain account: ${domainKey.pubkey.toBase58()}');
// Derive a subdomain key
final subKey = await getDomainKey('vault.miester.abc');
print('Is subdomain: ${subKey.isSub}'); // true
print('Parent: ${subKey.parent?.toBase58()}');
// Derive a record key
final recordKey = await getDomainKey('Twitter.miester.abc', record: true);
Error Handling
try {
final owner = await parser.getOwnerFromDomainTld('nonexistent.abc');
} on DomainNotFoundException catch (e) {
print('Domain not found: ${e.domain}');
} on InvalidDomainFormatException catch (e) {
print('Invalid format: ${e.message}');
} on TldParserException catch (e) {
print('Parser error: ${e.message}');
}
Architecture
tld_parser_dart/
├── lib/
│ ├── tld_parser.dart # Main export
│ └── src/
│ ├── constants.dart # Program IDs, prefixes
│ ├── utils.dart # Hashing, seeds
│ ├── pda.dart # PDA derivation
│ ├── name_record_handler.dart # getDomainKey
│ ├── tld_parser.dart # Main TldParser class
│ ├── exceptions.dart # Exception types
│ ├── state/
│ │ ├── name_record_header.dart
│ │ ├── main_domain.dart
│ │ └── nft_record.dart
│ └── types/
│ ├── records.dart
│ ├── domain_key_result.dart
│ └── tag.dart
├── test/
│ └── ...
└── example/
└── example.dart
Performance
The SDK is optimized for performance:
- Batched RPC calls: Multiple accounts are fetched in single calls
- Chunking: Large requests are automatically chunked to respect RPC limits
- Efficient PDAs: Program addresses are derived using optimized algorithms
Contributing
See CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
References
Libraries
- tld_parser
- TLD Parser - AllDomains ANS Protocol SDK for Dart