/ src / Blockchain / BlockchainResult.php
BlockchainResult.php
  1  <?php
  2  
  3  namespace BitcoindRPC\Blockchain;
  4  
  5  use BitcoindRPC\RpcResponse;
  6  
  7  class BlockchainResult
  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      // Block specific methods
 42      public function getBlockData(): ?array
 43      {
 44          $data = $this->getData();
 45          return is_array($data) ? $data : null;
 46      }
 47  
 48      public function getBlockHash(): ?string
 49      {
 50          $data = $this->getData();
 51          
 52          if (is_string($data)) {
 53              return $data;
 54          }
 55          if (is_array($data) && isset($data['hash'])) {
 56              return $data['hash'];
 57          }
 58          
 59          return null;
 60      }
 61  
 62      public function getBlockHeight(): ?int
 63      {
 64          $block = $this->getBlockData();
 65          return $block['height'] ?? null;
 66      }
 67  
 68      public function getBlockSize(): ?int
 69      {
 70          $block = $this->getBlockData();
 71          return $block['size'] ?? null;
 72      }
 73  
 74      public function getBlockWeight(): ?int
 75      {
 76          $block = $this->getBlockData();
 77          return $block['weight'] ?? null;
 78      }
 79  
 80      public function getBlockTime(): ?int
 81      {
 82          $block = $this->getBlockData();
 83          return $block['time'] ?? null;
 84      }
 85  
 86      public function getBlockMedianTime(): ?int
 87      {
 88          $block = $this->getBlockData();
 89          return $block['mediantime'] ?? null;
 90      }
 91  
 92      public function getBlockNonce(): ?int
 93      {
 94          $block = $this->getBlockData();
 95          return $block['nonce'] ?? null;
 96      }
 97  
 98      public function getBlockBits(): ?string
 99      {
100          $block = $this->getBlockData();
101          return $block['bits'] ?? null;
102      }
103  
104      public function getBlockDifficulty(): ?float
105      {
106          $block = $this->getBlockData();
107          return $block['difficulty'] ?? null;
108      }
109  
110      public function getBlockTransactionCount(): ?int
111      {
112          $block = $this->getBlockData();
113          
114          if (isset($block['tx']) && is_array($block['tx'])) {
115              return count($block['tx']);
116          }
117          
118          return null;
119      }
120  
121      public function getBlockTransactions(): ?array
122      {
123          $block = $this->getBlockData();
124          return $block['tx'] ?? null;
125      }
126  
127      // Blockchain info methods
128      public function getBlockchainInfo(): ?array
129      {
130          $data = $this->getData();
131          return is_array($data) ? $data : null;
132      }
133  
134      public function getChain(): ?string
135      {
136          $info = $this->getBlockchainInfo();
137          return $info['chain'] ?? null;
138      }
139  
140      public function getBlocks(): ?int
141      {
142          $info = $this->getBlockchainInfo();
143          return $info['blocks'] ?? null;
144      }
145  
146      public function getHeaders(): ?int
147      {
148          $info = $this->getBlockchainInfo();
149          return $info['headers'] ?? null;
150      }
151  
152      public function getBestBlockHashFromInfo(): ?string
153      {
154          $info = $this->getBlockchainInfo();
155          return $info['bestblockhash'] ?? null;
156      }
157  
158      public function getVerificationProgress(): ?float
159      {
160          $info = $this->getBlockchainInfo();
161          return $info['verificationprogress'] ?? null;
162      }
163  
164      public function isInitialBlockDownload(): ?bool
165      {
166          $info = $this->getBlockchainInfo();
167          return $info['initialblockdownload'] ?? null;
168      }
169  
170      // Mempool methods
171      public function getMempoolInfo(): ?array
172      {
173          $data = $this->getData();
174          return is_array($data) ? $data : null;
175      }
176  
177      public function getMempoolSize(): ?int
178      {
179          $info = $this->getMempoolInfo();
180          return $info['size'] ?? null;
181      }
182  
183      public function getMempoolBytes(): ?int
184      {
185          $info = $this->getMempoolInfo();
186          return $info['bytes'] ?? null;
187      }
188  
189      public function getMempoolUsage(): ?int
190      {
191          $info = $this->getMempoolInfo();
192          return $info['usage'] ?? null;
193      }
194  
195      public function getMempoolTransactions(): ?array
196      {
197          $data = $this->getData();
198          return is_array($data) ? $data : null;
199      }
200  
201      public function getMempoolTransactionIds(): ?array
202      {
203          $data = $this->getData();
204          
205          if (is_array($data)) {
206              // If verbose is false, data is an array of txids
207              if (!empty($data) && is_string(reset($data))) {
208                  return $data;
209              }
210              // If verbose is true, data is an associative array with txids as keys
211              else {
212                  return array_keys($data);
213              }
214          }
215          
216          return null;
217      }
218  
219      public function getMempoolTransactionCount(): ?int
220      {
221          $txs = $this->getMempoolTransactions();
222          return is_array($txs) ? count($txs) : null;
223      }
224  
225      // Transaction methods
226      public function getTransactionData(): ?array
227      {
228          $data = $this->getData();
229          return is_array($data) ? $data : null;
230      }
231  
232      public function getTransactionConfirmations(): ?int
233      {
234          $tx = $this->getTransactionData();
235          return $tx['confirmations'] ?? null;
236      }
237  
238      public function getTransactionBlockHash(): ?string
239      {
240          $tx = $this->getTransactionData();
241          return $tx['blockhash'] ?? null;
242      }
243  
244      public function getTransactionBlockHeight(): ?int
245      {
246          $tx = $this->getTransactionData();
247          return $tx['blockheight'] ?? null;
248      }
249  
250      public function getTransactionBlockTime(): ?int
251      {
252          $tx = $this->getTransactionData();
253          return $tx['blocktime'] ?? null;
254      }
255  
256      public function getTransactionSize(): ?int
257      {
258          $tx = $this->getTransactionData();
259          return $tx['size'] ?? null;
260      }
261  
262      public function getTransactionVsize(): ?int
263      {
264          $tx = $this->getTransactionData();
265          return $tx['vsize'] ?? null;
266      }
267  
268      public function getTransactionWeight(): ?int
269      {
270          $tx = $this->getTransactionData();
271          return $tx['weight'] ?? null;
272      }
273  
274      public function getTransactionFee(): ?float
275      {
276          $tx = $this->getTransactionData();
277          return $tx['fee'] ?? null;
278      }
279  
280      // UTXO methods
281      public function getTxOutSetInfo(): ?array
282      {
283          $data = $this->getData();
284          return is_array($data) ? $data : null;
285      }
286  
287      public function getUTXOCount(): ?int
288      {
289          $info = $this->getTxOutSetInfo();
290          return $info['txouts'] ?? null;
291      }
292  
293      public function getUTXOTotalAmount(): ?float
294      {
295          $info = $this->getTxOutSetInfo();
296          return $info['total_amount'] ?? null;
297      }
298  
299      public function getUTXOHeight(): ?int
300      {
301          $info = $this->getTxOutSetInfo();
302          return $info['height'] ?? null;
303      }
304  
305      public function getUTXOBestBlock(): ?string
306      {
307          $info = $this->getTxOutSetInfo();
308          return $info['bestblock'] ?? null;
309      }
310  
311      // Chain tips methods
312      public function getChainTips(): ?array
313      {
314          $data = $this->getData();
315          return is_array($data) ? $data : null;
316      }
317  
318      public function getChainTipCount(): ?int
319      {
320          $tips = $this->getChainTips();
321          return is_array($tips) ? count($tips) : null;
322      }
323  
324      // Block stats methods
325      public function getBlockStats(): ?array
326      {
327          $data = $this->getData();
328          return is_array($data) ? $data : null;
329      }
330  
331      public function getBlockStatsHeight(): ?int
332      {
333          $stats = $this->getBlockStats();
334          return $stats['height'] ?? null;
335      }
336  
337      public function getBlockStatsTxCount(): ?int
338      {
339          $stats = $this->getBlockStats();
340          return $stats['txs'] ?? null;
341      }
342  
343      public function getBlockStatsTotalFee(): ?float
344      {
345          $stats = $this->getBlockStats();
346          return $stats['totalfee'] ?? null;
347      }
348  
349      public function getBlockStatsTotalSize(): ?int
350      {
351          $stats = $this->getBlockStats();
352          return $stats['totalsize'] ?? null;
353      }
354  
355      // Utility methods
356      public function getBlockchainSummary(): array
357      {
358          $summary = [
359              'success' => $this->isSuccess(),
360              'error' => $this->getError(),
361              'status_code' => $this->getStatusCode(),
362              'type' => 'unknown'
363          ];
364  
365          if ($this->isSuccess()) {
366              $data = $this->getData();
367              
368              if (is_array($data)) {
369                  // Blockchain info response
370                  if (isset($data['chain'])) {
371                      $summary['type'] = 'blockchain_info';
372                      $summary['chain'] = $data['chain'];
373                      $summary['blocks'] = $data['blocks'];
374                      $summary['headers'] = $data['headers'];
375                      $summary['best_block_hash'] = $data['bestblockhash'];
376                      $summary['difficulty'] = $data['difficulty'] ?? null;
377                      $summary['verification_progress'] = $data['verificationprogress'] ?? null;
378                  }
379                  // Block response
380                  elseif (isset($data['hash']) && isset($data['height'])) {
381                      $summary['type'] = 'block';
382                      $summary['hash'] = $data['hash'];
383                      $summary['height'] = $data['height'];
384                      $summary['size'] = $data['size'] ?? null;
385                      $summary['time'] = $data['time'] ?? null;
386                      $summary['tx_count'] = count($data['tx'] ?? []);
387                  }
388                  // Mempool info response
389                  elseif (isset($data['size']) && isset($data['bytes'])) {
390                      $summary['type'] = 'mempool_info';
391                      $summary['size'] = $data['size'];
392                      $summary['bytes'] = $data['bytes'];
393                      $summary['usage'] = $data['usage'] ?? null;
394                  }
395                  // Transaction response
396                  elseif (isset($data['txid']) && isset($data['size'])) {
397                      $summary['type'] = 'transaction';
398                      $summary['txid'] = $data['txid'];
399                      $summary['size'] = $data['size'];
400                      $summary['vsize'] = $data['vsize'] ?? null;
401                      $summary['confirmations'] = $data['confirmations'] ?? 0;
402                      $summary['block_hash'] = $data['blockhash'] ?? null;
403                  }
404                  // UTXO set info response
405                  elseif (isset($data['height']) && isset($data['txouts'])) {
406                      $summary['type'] = 'utxo_set_info';
407                      $summary['height'] = $data['height'];
408                      $summary['txouts'] = $data['txouts'];
409                      $summary['total_amount'] = $data['total_amount'] ?? null;
410                      $summary['best_block'] = $data['bestblock'] ?? null;
411                  }
412                  // Chain tips response
413                  elseif (is_array($data) && !empty($data) && isset($data[0]['height'])) {
414                      $summary['type'] = 'chain_tips';
415                      $summary['tip_count'] = count($data);
416                  }
417                  // Block stats response
418                  elseif (isset($data['height']) && isset($data['txs'])) {
419                      $summary['type'] = 'block_stats';
420                      $summary['height'] = $data['height'];
421                      $summary['tx_count'] = $data['txs'];
422                      $summary['total_fee'] = $data['totalfee'] ?? null;
423                      $summary['total_size'] = $data['totalsize'] ?? null;
424                  }
425                  // Mempool transactions response
426                  elseif (is_array($data) && !empty($data)) {
427                      if (is_string(reset($data))) {
428                          $summary['type'] = 'mempool_txids';
429                          $summary['tx_count'] = count($data);
430                      } else {
431                          $summary['type'] = 'mempool_tx_details';
432                          $summary['tx_count'] = count($data);
433                      }
434                  }
435              } elseif (is_string($data)) {
436                  // Block hash or hex data response
437                  if (strlen($data) === 64) {
438                      $summary['type'] = 'block_hash';
439                      $summary['hash'] = $data;
440                  } else {
441                      $summary['type'] = 'hex_data';
442                      $summary['data_length'] = strlen($data);
443                  }
444              } elseif (is_numeric($data)) {
445                  // Block count or difficulty response
446                  $summary['type'] = 'numeric';
447                  $summary['value'] = $data;
448              } elseif (is_bool($data)) {
449                  // Verification result
450                  $summary['type'] = 'verification';
451                  $summary['verified'] = $data;
452              }
453          }
454  
455          return $summary;
456      }
457  
458      public function isBlockConfirmed(): ?bool
459      {
460          return $this->getBlockHeight() !== null;
461      }
462  
463      public function isTransactionConfirmed(): ?bool
464      {
465          return $this->getTransactionConfirmations() > 0;
466      }
467  
468      public function getTransactionFeeRate(): ?float
469      {
470          $fee = $this->getTransactionFee();
471          $vsize = $this->getTransactionVsize();
472          
473          if ($fee !== null && $vsize !== null && $vsize > 0) {
474              return ($fee * 100000000) / $vsize; // Convert to sat/vbyte
475          }
476          
477          return null;
478      }
479  }