Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nmc names #1086

Merged
merged 29 commits into from
Feb 25, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
c274eca
build runner update mocks
julian-CStack Feb 13, 2025
09da845
WIP names
julian-CStack Feb 13, 2025
80a8e46
update namecoin_dart version
julian-CStack Feb 13, 2025
4425e55
use private key for deterministic salt
julian-CStack Feb 13, 2025
406a9c2
auto focus cursor in search field on desktop
julian-CStack Feb 13, 2025
93f7433
consistent log level edit
julian-CStack Feb 13, 2025
1df4226
hack in name op utxo confirmation check
julian-CStack Feb 13, 2025
9072a13
handle name op output selection based on name op type
julian-CStack Feb 13, 2025
f864bb5
refactor auto register NAME NEW process
julian-CStack Feb 13, 2025
a4ed109
update namecoin dns More option name and icon
julian-CStack Feb 13, 2025
124c847
WIP names gui
julian-CStack Feb 14, 2025
d251627
change particl default address type to old
julian-CStack Feb 18, 2025
dae4b59
WIP: namecoin domain name buy and add record ui
julian-CStack Feb 18, 2025
54e9c97
add method to check for and ignore name outputs in balance
julian-CStack Feb 18, 2025
3314278
clean up record info display
julian-CStack Feb 18, 2025
8825710
better base dialog widget
julian-CStack Feb 18, 2025
4b86a59
validate name value length
julian-CStack Feb 19, 2025
7ee9db9
show error dialog
julian-CStack Feb 19, 2025
7ce16e0
better encoding
julian-CStack Feb 19, 2025
f5d2382
clean up logging
julian-CStack Feb 19, 2025
64564c0
fix: pop buy name dialog on success
julian-CStack Feb 19, 2025
bafb558
WIP: namecoin names desktop/mobile specific layout tweaks, and variou…
julian-CStack Feb 20, 2025
4695210
domain name input length restriction
julian-CStack Feb 20, 2025
5808988
clean up domain names management ui somewhat
julian-CStack Feb 20, 2025
ac1f991
WIP: manage domain ui
julian-CStack Feb 21, 2025
4f15af3
name tx note tweaks
julian-CStack Feb 24, 2025
f82ca2b
mobile/desktop name ui clean up and transfer name functionality
julian-CStack Feb 24, 2025
9dbf80d
disable manage for pre reg names for now
julian-CStack Feb 24, 2025
0a90948
update name functionality w/ basic json pretty view
julian-CStack Feb 25, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions lib/models/isar/models/blockchain_data/utxo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -85,9 +85,14 @@ class UTXO {
bool isConfirmed(
int currentChainHeight,
int minimumConfirms,
int minimumCoinbaseConfirms,
) {
int minimumCoinbaseConfirms, {
int? overrideMinConfirms, // added to handle namecoin name op outputs
}) {
final confirmations = getConfirmations(currentChainHeight);

if (overrideMinConfirms != null) {
return confirmations >= overrideMinConfirms;
}
return confirmations >=
(isCoinbase ? minimumCoinbaseConfirms : minimumConfirms);
}
Expand Down Expand Up @@ -180,4 +185,5 @@ class UTXO {
abstract final class UTXOOtherDataKeys {
static const keyImage = "keyImage";
static const spent = "spent";
static const nameOpData = "nameOpData";
}
25 changes: 25 additions & 0 deletions lib/models/namecoin_dns/dns_a_record_address_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
enum DNSAddressType {
IPv4,
IPv6,
Tor,
Freenet,
I2P,
ZeroNet;

String get key {
switch (this) {
case DNSAddressType.IPv4:
return "ip";
case DNSAddressType.IPv6:
return "ip6";
case DNSAddressType.Tor:
return "_tor";
case DNSAddressType.Freenet:
return "freenet";
case DNSAddressType.I2P:
return "i2p";
case DNSAddressType.ZeroNet:
return "zeronet";
}
}
}
129 changes: 129 additions & 0 deletions lib/models/namecoin_dns/dns_record.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
import 'dart:convert';

import 'package:meta/meta.dart';
import 'package:namecoin/namecoin.dart';

import '../../utilities/extensions/extensions.dart';
import 'dns_record_type.dart';

@Immutable()
abstract class DNSRecordBase {
final String name;

DNSRecordBase({required this.name});

String getValueString();
}

@Immutable()
final class RawDNSRecord extends DNSRecordBase {
final String value;

RawDNSRecord({required super.name, required this.value});

@override
String getValueString() => value;

@override
String toString() {
return "RawDNSRecord(name: $name, value: $value)";
}
}

@Immutable()
final class DNSRecord extends DNSRecordBase {
final DNSRecordType type;
final Map<String, dynamic> data;

DNSRecord({
required super.name,
required this.type,
required this.data,
});

@override
String getValueString() {
// TODO error handling
dynamic value = data;
while (value is Map) {
value = value[value.keys.first];
}

return value.toString();
}

DNSRecord copyWith({
DNSRecordType? type,
Map<String, dynamic>? data,
}) {
return DNSRecord(
type: type ?? this.type,
data: data ?? this.data,
name: name,
);
}

@override
String toString() {
return "DNSRecord(name: $name, type: $type, data: $data)";
}

static String merge(List<DNSRecord> records) {
final Map<String, dynamic> result = {};

for (final record in records) {
switch (record.type) {
case DNSRecordType.CNAME:
if (result[record.data.keys.first] != null) {
throw Exception("CNAME record already exists");
}
_deepMerge(result, record.data);
break;

case DNSRecordType.TLS:
case DNSRecordType.NS:
case DNSRecordType.DS:
case DNSRecordType.SRV:
case DNSRecordType.SSH:
case DNSRecordType.TXT:
case DNSRecordType.IMPORT:
case DNSRecordType.A:
_deepMerge(result, record.data);
break;
}
}

final string = jsonEncode(result);
if (string.toUint8ListFromUtf8.length > valueMaxLength) {
throw Exception(
"Value length (${string.toUint8ListFromUtf8.length}) exceeds maximum"
" allowed ($valueMaxLength)",
);
}

return string;
}
}

void _deepMerge(Map<String, dynamic> base, Map<String, dynamic> updates) {
updates.forEach((key, value) {
if (value is Map<String, dynamic> && base[key] is Map<String, dynamic>) {
_deepMerge(base[key] as Map<String, dynamic>, value);
} else if (value is List && base[key] is List) {
(base[key] as List).addAll(value);
} else {
if (base[key] != null) {
throw Exception(
"Attempted to overwrite value: ${base[key]} where key=$key",
);
}
if (value is Map) {
base[key] = Map<String, dynamic>.from(value);
} else if (value is List) {
base[key] = List<dynamic>.from(value);
} else {
base[key] = value;
}
}
});
}
68 changes: 68 additions & 0 deletions lib/models/namecoin_dns/dns_record_type.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
enum DNSRecordType {
A,
CNAME,
NS,
DS,
TLS,
SRV,
TXT,
IMPORT,
SSH;

String get info {
switch (this) {
case DNSRecordType.A:
return "An A record maps your domain to an address (IPv4, IPv6, Tor,"
" Freenet, I2P, or ZeroNet).";
case DNSRecordType.CNAME:
return "A CNAME record redirects your domain to another domain,"
" essentially acting as an alias.";
case DNSRecordType.NS:
return "An NS record specifies the nameservers that are authoritative"
" for your domain.";
case DNSRecordType.DS:
return "A DS record holds information about DNSSEC (DNS Security "
"Extensions) for your domain, helping with verification and "
"integrity.";
case DNSRecordType.TLS:
return "A TLS record is used for specifying details about how to "
"establish secure connections (like TLS certificates) for your"
" domain.";
case DNSRecordType.SRV:
return "An SRV record specifies the location of servers for specific"
" services, such as SIP, XMPP, or Minecraft servers.";
case DNSRecordType.TXT:
return "A TXT record allows you to add arbitrary text to your domain's"
" DNS record, often used for verification (e.g., SPF, DKIM).";
case DNSRecordType.IMPORT:
return "An IMPORT record is used to bring in DNS records from an"
" external source into your domain's configuration.";
case DNSRecordType.SSH:
return "An SSH record provides information related to SSH public keys"
" for securely connecting to your domain's services.";
}
}

String? get key {
switch (this) {
case DNSRecordType.A:
return null;
case DNSRecordType.CNAME:
return "alias";
case DNSRecordType.NS:
return "ns";
case DNSRecordType.DS:
return "ds";
case DNSRecordType.TLS:
return "tls";
case DNSRecordType.SRV:
return "srv";
case DNSRecordType.TXT:
return "txt";
case DNSRecordType.IMPORT:
return "import";
case DNSRecordType.SSH:
return "sshfp";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,12 @@ class _AddWalletViewState extends ConsumerState<AddWalletView> {
}

WidgetsBinding.instance.addPostFrameCallback((_) {
ref.refresh(addWalletSelectedEntityStateProvider);
if (mounted) {
ref.refresh(addWalletSelectedEntityStateProvider);
if (isDesktop) {
_searchFocusNode.requestFocus();
}
}
});

super.initState();
Expand Down
49 changes: 40 additions & 9 deletions lib/pages/coin_control/coin_control_view.dart
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ import '../../utilities/assets.dart';
import '../../utilities/constants.dart';
import '../../utilities/text_styles.dart';
import '../../wallets/isar/providers/wallet_info_provider.dart';
import '../../wallets/wallet/impl/namecoin_wallet.dart';
import '../../wallets/wallet/wallet.dart';
import '../../wallets/wallet/wallet_mixin_interfaces/coin_control_interface.dart';
import '../../widgets/animated_widgets/rotate_icon.dart';
import '../../widgets/app_bar_field.dart';
Expand Down Expand Up @@ -88,6 +90,18 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
await coinControlInterface.updateBalance();
}

bool _isConfirmed(UTXO utxo, int currentChainHeight, Wallet wallet) {
if (wallet is NamecoinWallet) {
return wallet.checkUtxoConfirmed(utxo, currentChainHeight);
} else {
return utxo.isConfirmed(
currentChainHeight,
wallet.cryptoCurrency.minConfirms,
wallet.cryptoCurrency.minCoinbaseConfirms,
);
}
}

@override
void initState() {
if (widget.selectedUTXOs != null) {
Expand Down Expand Up @@ -347,10 +361,15 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
CoinControlViewType.manage ||
(widget.type == CoinControlViewType.use &&
!utxo.isBlocked &&
utxo.isConfirmed(
_isConfirmed(
utxo,
currentHeight,
minConfirms,
coin.minCoinbaseConfirms,
ref.watch(
pWallets.select(
(s) => s
.getWallet(widget.walletId),
),
),
)),
initialSelectedState: isSelected,
onSelectedChanged: (value) {
Expand Down Expand Up @@ -412,10 +431,16 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
(widget.type ==
CoinControlViewType.use &&
!_showBlocked &&
utxo.isConfirmed(
_isConfirmed(
utxo,
currentHeight,
minConfirms,
coin.minCoinbaseConfirms,
ref.watch(
pWallets.select(
(s) => s.getWallet(
widget.walletId,
),
),
),
)),
initialSelectedState: isSelected,
onSelectedChanged: (value) {
Expand Down Expand Up @@ -557,10 +582,16 @@ class _CoinControlViewState extends ConsumerState<CoinControlView> {
CoinControlViewType
.use &&
!utxo.isBlocked &&
utxo.isConfirmed(
_isConfirmed(
utxo,
currentHeight,
minConfirms,
coin.minCoinbaseConfirms,
ref.watch(
pWallets.select(
(s) => s.getWallet(
widget.walletId,
),
),
),
)),
initialSelectedState: isSelected,
onSelectedChanged: (value) {
Expand Down
Loading
Loading