Line data Source code
1 : import 'dart:typed_data';
2 :
3 : import 'package:walletkit_dart/src/utils/keccak.dart';
4 : import 'package:walletkit_dart/walletkit_dart.dart';
5 :
6 3 : final ensRegistryAbi = ContractABI.fromAbi(
7 : '''[{"inputs":[{"internalType":"contract ENS","name":"_old","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"operator","type":"address"},{"indexed":false,"internalType":"bool","name":"approved","type":"bool"}],"name":"ApprovalForAll","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"label","type":"bytes32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"resolver","type":"address"}],"name":"NewResolver","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"NewTTL","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"node","type":"bytes32"},{"indexed":false,"internalType":"address","name":"owner","type":"address"}],"name":"Transfer","type":"event"},{"constant":true,"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"old","outputs":[{"internalType":"contract ENS","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"recordExists","outputs":[{"internalType":"bool","name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"resolver","outputs":[{"internalType":"address","name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"setOwner","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"address","name":"resolver","type":"address"}],"name":"setResolver","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"label","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"}],"name":"setSubnodeOwner","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"bytes32","name":"label","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"resolver","type":"address"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setSubnodeRecord","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"},{"internalType":"uint64","name":"ttl","type":"uint64"}],"name":"setTTL","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes32","name":"node","type":"bytes32"}],"name":"ttl","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"payable":false,"stateMutability":"view","type":"function"}]''');
8 :
9 : const ensRegistryMainnetContractAddress =
10 : "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
11 :
12 : const znsRegistryContractAddress = "0xa0446c88240bCA2A8E0f68C93aa365d25B198aA4";
13 :
14 : class EnsRegistryContract extends InternalContract {
15 1 : EnsRegistryContract({
16 : required super.contractAddress,
17 : required super.rpc,
18 1 : }) : super(
19 1 : abi: ensRegistryAbi,
20 : );
21 :
22 1 : factory EnsRegistryContract.mainnet({required EvmRpcInterface rpc}) {
23 1 : return EnsRegistryContract(
24 : contractAddress: ensRegistryMainnetContractAddress,
25 : rpc: rpc,
26 : );
27 : }
28 :
29 0 : factory EnsRegistryContract.smartchain({required EvmRpcInterface rpc}) {
30 0 : return EnsRegistryContract(
31 : contractAddress: znsRegistryContractAddress,
32 : rpc: rpc,
33 : );
34 : }
35 :
36 1 : Future<String?> resolver({required String name}) async {
37 2 : final function = abi.getFunction('resolver')!;
38 :
39 1 : final node = namehash(name);
40 :
41 : try {
42 1 : final result = await readSafe(
43 2 : function: function.addValues(values: [node]),
44 : );
45 :
46 3 : final resolver = result.outputs.first.value as String;
47 1 : if (resolver == nullAddress) {
48 : return null;
49 : }
50 : return resolver;
51 1 : } on RangeError {
52 : return null;
53 : }
54 : }
55 : }
56 :
57 1 : Uint8List namehash(String name) {
58 1 : if (name.isEmpty) {
59 0 : return Uint8List(32);
60 : }
61 :
62 : List<int> node;
63 1 : if (name.contains('.')) {
64 1 : var labels = name.split('.');
65 3 : node = namehash(labels.sublist(1).join('.'));
66 : } else {
67 1 : node = Uint8List(32);
68 : }
69 :
70 2 : var label = name.split('.')[0];
71 3 : var labelHash = keccak256(Uint8List.fromList(label.codeUnits));
72 :
73 4 : return keccak256(Uint8List.fromList([...node, ...labelHash]));
74 : }
|