UtilResult.php
1 <?php 2 3 namespace BitcoindRPC\Util; 4 5 use BitcoindRPC\RpcResponse; 6 7 class UtilResult 8 { 9 private RpcResponse $response; 10 11 public function __construct(RpcResponse $response) 12 { 13 $this->response = $response; 14 } 15 16 public function isSuccess(): bool 17 { 18 return $this->response->isSuccess(); 19 } 20 21 public function getData(): mixed 22 { 23 return $this->response->getData(); 24 } 25 26 public function getError(): ?string 27 { 28 return $this->response->getError(); 29 } 30 31 public function getStatusCode(): int 32 { 33 return $this->response->getStatusCode(); 34 } 35 36 public function toArray(): array 37 { 38 return $this->response->toArray(); 39 } 40 41 // Multisig specific methods 42 public function getMultisigInfo(): ?array 43 { 44 $data = $this->getData(); 45 return is_array($data) ? $data : null; 46 } 47 48 public function getMultisigAddress(): ?string 49 { 50 $multisig = $this->getMultisigInfo(); 51 return $multisig['address'] ?? null; 52 } 53 54 public function getMultisigRedeemScript(): ?string 55 { 56 $multisig = $this->getMultisigInfo(); 57 return $multisig['redeemScript'] ?? null; 58 } 59 60 public function getMultisigDescriptor(): ?string 61 { 62 $multisig = $this->getMultisigInfo(); 63 return $multisig['descriptor'] ?? null; 64 } 65 66 // Address derivation methods 67 public function getDerivedAddresses(): ?array 68 { 69 $data = $this->getData(); 70 return is_array($data) ? $data : null; 71 } 72 73 public function getDerivedAddressCount(): ?int 74 { 75 $addresses = $this->getDerivedAddresses(); 76 return is_array($addresses) ? count($addresses) : null; 77 } 78 79 // Fee estimation methods 80 public function getFeeEstimation(): ?array 81 { 82 $data = $this->getData(); 83 return is_array($data) ? $data : null; 84 } 85 86 public function getFeeRate(): ?float 87 { 88 $estimation = $this->getFeeEstimation(); 89 return $estimation['feerate'] ?? null; 90 } 91 92 public function getFeeEstimationBlocks(): ?int 93 { 94 $estimation = $this->getFeeEstimation(); 95 return $estimation['blocks'] ?? null; 96 } 97 98 public function getFeeEstimationErrors(): ?array 99 { 100 $estimation = $this->getFeeEstimation(); 101 return $estimation['errors'] ?? null; 102 } 103 104 // Descriptor info methods 105 public function getDescriptorInfo(): ?array 106 { 107 $data = $this->getData(); 108 return is_array($data) ? $data : null; 109 } 110 111 public function getDescriptorString(): ?string 112 { 113 $info = $this->getDescriptorInfo(); 114 return $info['descriptor'] ?? null; 115 } 116 117 public function getDescriptorChecksum(): ?string 118 { 119 $info = $this->getDescriptorInfo(); 120 return $info['checksum'] ?? null; 121 } 122 123 public function isDescriptorRange(): ?bool 124 { 125 $info = $this->getDescriptorInfo(); 126 return $info['isrange'] ?? null; 127 } 128 129 public function isDescriptorSolvable(): ?bool 130 { 131 $info = $this->getDescriptorInfo(); 132 return $info['issolvable'] ?? null; 133 } 134 135 public function hasDescriptorPrivateKeys(): ?bool 136 { 137 $info = $this->getDescriptorInfo(); 138 return $info['hasprivatekeys'] ?? null; 139 } 140 141 // Index info methods 142 public function getIndexInfo(): ?array 143 { 144 $data = $this->getData(); 145 return is_array($data) ? $data : null; 146 } 147 148 public function getIndexCount(): ?int 149 { 150 $info = $this->getIndexInfo(); 151 return is_array($info) ? count($info) : null; 152 } 153 154 public function getIndexNames(): ?array 155 { 156 $info = $this->getIndexInfo(); 157 return is_array($info) ? array_keys($info) : null; 158 } 159 160 // Message signing methods 161 public function getSignature(): ?string 162 { 163 $data = $this->getData(); 164 return is_string($data) ? $data : null; 165 } 166 167 public function isSignatureValid(): ?bool 168 { 169 $data = $this->getData(); 170 return is_bool($data) ? $data : null; 171 } 172 173 // Address validation methods 174 public function getAddressInfo(): ?array 175 { 176 $data = $this->getData(); 177 return is_array($data) ? $data : null; 178 } 179 180 public function isAddressValid(): ?bool 181 { 182 $info = $this->getAddressInfo(); 183 return $info['isvalid'] ?? null; 184 } 185 186 public function getValidatedAddress(): ?string 187 { 188 $info = $this->getAddressInfo(); 189 return $info['address'] ?? null; 190 } 191 192 public function getScriptPubKey(): ?string 193 { 194 $info = $this->getAddressInfo(); 195 return $info['scriptPubKey'] ?? null; 196 } 197 198 public function isScript(): ?bool 199 { 200 $info = $this->getAddressInfo(); 201 return $info['isscript'] ?? null; 202 } 203 204 public function isWitness(): ?bool 205 { 206 $info = $this->getAddressInfo(); 207 return $info['iswitness'] ?? null; 208 } 209 210 public function getWitnessVersion(): ?int 211 { 212 $info = $this->getAddressInfo(); 213 return $info['witness_version'] ?? null; 214 } 215 216 public function getWitnessProgram(): ?string 217 { 218 $info = $this->getAddressInfo(); 219 return $info['witness_program'] ?? null; 220 } 221 222 // Utility methods 223 public function getUtilSummary(): array 224 { 225 $summary = [ 226 'success' => $this->isSuccess(), 227 'error' => $this->getError(), 228 'status_code' => $this->getStatusCode(), 229 'type' => 'unknown' 230 ]; 231 232 if ($this->isSuccess()) { 233 $data = $this->getData(); 234 235 if (is_array($data)) { 236 // Multisig response 237 if (isset($data['address']) && isset($data['redeemScript'])) { 238 $summary['type'] = 'multisig'; 239 $summary['address'] = $data['address']; 240 $summary['redeem_script'] = $data['redeemScript']; 241 $summary['descriptor'] = $data['descriptor'] ?? null; 242 } 243 // Fee estimation response 244 elseif (isset($data['feerate'])) { 245 $summary['type'] = 'fee_estimation'; 246 $summary['feerate'] = $data['feerate']; 247 $summary['blocks'] = $data['blocks'] ?? null; 248 $summary['errors'] = $data['errors'] ?? []; 249 } 250 // Descriptor info response 251 elseif (isset($data['descriptor'])) { 252 $summary['type'] = 'descriptor_info'; 253 $summary['descriptor'] = $data['descriptor']; 254 $summary['checksum'] = $data['checksum'] ?? null; 255 $summary['is_range'] = $data['isrange'] ?? false; 256 $summary['is_solvable'] = $data['issolvable'] ?? false; 257 $summary['has_private_keys'] = $data['hasprivatekeys'] ?? false; 258 } 259 // Index info response 260 elseif (is_array($data) && !empty($data) && is_array(reset($data))) { 261 $summary['type'] = 'index_info'; 262 $summary['index_count'] = count($data); 263 $summary['index_names'] = array_keys($data); 264 } 265 // Address validation response 266 elseif (isset($data['isvalid'])) { 267 $summary['type'] = 'address_validation'; 268 $summary['is_valid'] = $data['isvalid']; 269 $summary['address'] = $data['address'] ?? null; 270 $summary['is_script'] = $data['isscript'] ?? false; 271 $summary['is_witness'] = $data['iswitness'] ?? false; 272 } 273 // Derived addresses response 274 elseif (is_array($data) && !empty($data) && is_string(reset($data))) { 275 $summary['type'] = 'derived_addresses'; 276 $summary['address_count'] = count($data); 277 $summary['addresses'] = $data; 278 } 279 } elseif (is_string($data)) { 280 // Message signature response 281 $summary['type'] = 'signature'; 282 $summary['signature'] = $data; 283 } elseif (is_bool($data)) { 284 // Message verification response 285 $summary['type'] = 'verification'; 286 $summary['verified'] = $data; 287 } 288 } 289 290 return $summary; 291 } 292 293 public function getAddressDetails(): ?array 294 { 295 $info = $this->getAddressInfo(); 296 if (!$info) { 297 return null; 298 } 299 300 return [ 301 'valid' => $info['isvalid'] ?? false, 302 'address' => $info['address'] ?? null, 303 'script_pub_key' => $info['scriptPubKey'] ?? null, 304 'is_script' => $info['isscript'] ?? false, 305 'is_witness' => $info['iswitness'] ?? false, 306 'witness_version' => $info['witness_version'] ?? null, 307 'witness_program' => $info['witness_program'] ?? null, 308 'pubkey' => $info['pubkey'] ?? null, 309 'is_compressed' => $info['iscompressed'] ?? null 310 ]; 311 } 312 313 public function getFeeEstimationDetails(): ?array 314 { 315 $estimation = $this->getFeeEstimation(); 316 317 if (!$estimation) { 318 return null; 319 } 320 321 return [ 322 'feerate_btc_kb' => $estimation['feerate'] ?? null, 323 'feerate_sat_vbyte' => $estimation['feerate'] ? $estimation['feerate'] * 100000 : null, 324 'blocks' => $estimation['blocks'] ?? null, 325 'errors' => $estimation['errors'] ?? [], 326 'estimation_quality' => empty($estimation['errors']) ? 'high' : 'low' 327 ]; 328 } 329 330 public function getMultisigDetails(): ?array 331 { 332 $multisig = $this->getMultisigInfo(); 333 334 if (!$multisig) { 335 return null; 336 } 337 338 return [ 339 'address' => $multisig['address'] ?? null, 340 'redeem_script' => $multisig['redeemScript'] ?? null, 341 'descriptor' => $multisig['descriptor'] ?? null, 342 'address_type' => $this->inferAddressType($multisig['address'] ?? '') 343 ]; 344 } 345 346 private function inferAddressType(string $address): string 347 { 348 if (str_starts_with($address, '1')) { 349 return 'legacy'; 350 } elseif (str_starts_with($address, '3')) { 351 return 'p2sh'; 352 } elseif (str_starts_with($address, 'bc1')) { 353 return 'bech32'; 354 } else { 355 return 'unknown'; 356 } 357 } 358 }