Line data Source code
1 : library extensions;
2 :
3 : import 'dart:convert';
4 : import 'dart:typed_data';
5 :
6 : import 'package:convert/convert.dart';
7 : import 'package:walletkit_dart/src/domain/entities/node.dart';
8 : // ignore: implementation_imports
9 : import 'package:pointycastle/src/utils.dart' as p_utils;
10 : import 'package:walletkit_dart/src/utils/var_uint.dart';
11 :
12 : extension ExtFixedPrecision on double {
13 0 : double toPrecision(int n) => double.parse(toStringAsFixed(n));
14 : }
15 :
16 : extension BigIntUtil on BigInt {
17 6 : Uint8List get toBytesUnsigned {
18 18 : assert(this >= BigInt.zero, "BigInt must be positive");
19 6 : return p_utils.encodeBigIntAsUnsigned(this);
20 : }
21 :
22 0 : Uint8List get toBytes {
23 0 : return p_utils.encodeBigInt(this);
24 : }
25 :
26 2 : String get toHex => toRadixString(16);
27 :
28 3 : String get toHexWithPrefix => "0x" + toHex;
29 : }
30 :
31 : extension IntListUtil on List<int> {
32 : // BigInt get toBigInt => BigInt.parse(hex.encode(this), radix: 16);
33 :
34 26 : Uint8List get toUint8List => Uint8List.fromList(this);
35 :
36 5 : List<BigInt> get toBigIntList => map((e) => BigInt.from(e)).toList();
37 : }
38 :
39 : extension BufferUtil on Uint8List {
40 : /// Decode a unsigned big-endian integer from the buffer.
41 6 : int get toUInt {
42 : int result = 0;
43 18 : for (var i = 0; i < length; i++) {
44 18 : result = result * 256 + this[i];
45 : }
46 : return result;
47 : }
48 :
49 : /// Decode a big-endian integer from the buffer.
50 : /// Can be positive or negative.
51 0 : int get toInt {
52 0 : bool negative = length > 0 && (this[0] & 0x80) == 0x80;
53 : int result = 0;
54 :
55 0 : for (var i = 0; i < length; i++) {
56 0 : result = result * 256 + this[i];
57 : }
58 :
59 0 : return negative ? -(~result + 1) : result;
60 : }
61 :
62 : /// Decode a signed big-endian integer from the buffer.
63 : /// Can be positive or negative.
64 : // BigInt get toBigInt => p_utils.decodeBigInt(this);
65 :
66 12 : BigInt get toUBigInt {
67 12 : BigInt result = BigInt.zero;
68 36 : for (var i = 0; i < length; i++) {
69 60 : result = result * BigInt.from(256) + BigInt.from(this[i]);
70 : }
71 : return result;
72 : }
73 :
74 56 : String get toHex => hex.encode(this);
75 :
76 2 : String get bytesToUTF8 => utf8.decode(this, allowMalformed: true);
77 :
78 36 : Uint8List get rev => Uint8List.fromList(reversed.toList());
79 :
80 0 : Uint8List padToSize(int size) {
81 0 : if (length >= size) {
82 : return this;
83 : }
84 0 : final buffer = Uint8List(size);
85 0 : buffer.writeSlice(size - length, this);
86 : return buffer;
87 : }
88 : }
89 :
90 : extension ConvUtil on String {
91 78 : Uint8List get hexToBytes => Uint8List.fromList(hex.decode(this));
92 :
93 0 : Uint8List? get hexToBytesOrNull {
94 : try {
95 0 : return hexToBytes;
96 : } catch (e) {
97 : return null;
98 : }
99 : }
100 :
101 24 : Uint8List get hexToBytesWithPrefix => substring(2).hexToBytes;
102 :
103 2 : Uint8List? get hexToBytesWithPrefixOrNull {
104 : try {
105 2 : return hexToBytesWithPrefix;
106 : } catch (e) {
107 : return null;
108 : }
109 : }
110 :
111 2 : Uint8List get asUTF8 => utf8.encode(this);
112 :
113 2 : int? get toIntOrNull => int.tryParse(this);
114 :
115 4 : int get toInt => int.parse(this);
116 :
117 10 : BigInt? get toBigIntOrNull => BigInt.tryParse(this);
118 :
119 4 : BigInt get toBigInt => BigInt.parse(this);
120 :
121 2 : BigInt get toBigIntFromHex => BigInt.parse(this, radix: 16);
122 :
123 0 : BigInt? get toBigIntFromHexOrNull => BigInt.tryParse(this, radix: 16);
124 : }
125 :
126 : extension IterableUtil<E> on Iterable<E> {
127 9 : operator [](int index) {
128 9 : if (index < 0) {
129 0 : throw RangeError("index must be positive");
130 : }
131 : var i = 0;
132 18 : for (var element in this) {
133 9 : if (i == index) {
134 : return element;
135 : }
136 9 : i++;
137 : }
138 0 : throw RangeError("index out of range");
139 : }
140 : }
141 :
142 : extension NumUtil on num {
143 16 : BigInt get toBigInt => BigInt.from(this);
144 :
145 0 : String get toHex => toInt().toRadixString(16);
146 :
147 0 : String get toHexWithPrefix => "0x" + toHex;
148 : }
149 :
150 : extension FutureUtil<T> on Future<T> {
151 0 : Future<T> withRetry({
152 : int maxRetries = 3,
153 : Duration delay = const Duration(seconds: 1),
154 : }) async {
155 : int retries = 0;
156 0 : while (retries < maxRetries) {
157 : try {
158 : return this;
159 : } catch (e) {
160 0 : retries++;
161 0 : if (retries == maxRetries) {
162 : rethrow;
163 : }
164 0 : await Future.delayed(delay);
165 : }
166 : }
167 0 : throw Exception("Retry failed");
168 : }
169 : }
170 :
171 : extension FuturesUtil<T> on Iterable<Future<T>> {
172 0 : Future<List<T>> waitAll({
173 : int batchSize = 50,
174 : }) async {
175 0 : final futures = List<Future<T>>.from(this);
176 0 : final results = <T>[];
177 0 : while (futures.isNotEmpty) {
178 0 : final batch = futures.take(batchSize).toList();
179 0 : futures.removeRange(0, batch.length);
180 0 : final batchResults = await Future.wait(batch);
181 0 : results.addAll(batchResults);
182 : }
183 : return results;
184 : }
185 : }
186 :
187 : extension NodesUtil on Iterable<NodeWithAddress> {
188 32 : Iterable<String> get addresses => map((e) => e.address);
189 16 : Iterable<ChangeNode> get changeNodes => whereType<ChangeNode>();
190 16 : Iterable<ReceiveNode> get receiveNodes => whereType<ReceiveNode>();
191 0 : Iterable<NodeWithAddress> get neutered => map((node) => node.neutered);
192 : }
193 :
194 : extension ListUtil<T> on List<T> {
195 0 : List<T> get growable => List<T>.from(this, growable: true);
196 : }
|