github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/static/test-websocket.html (about)

     1  <!doctype html>
     2  <html lang="en">
     3  
     4  <head>
     5      <meta charset="utf-8">
     6      <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
     7      <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
     8      <style>
     9          .row {
    10              margin-top: 1%;
    11          }
    12  
    13          ::placeholder {
    14              color: #ccc !important;
    15          }
    16      </style>
    17      <title>Blockbook Websocket Test Page</title>
    18      <script>
    19          var ws;
    20          var messageID;
    21          var pendingMessages;
    22          var subscriptions;
    23          function send(method, params, callback) {
    24              var id = messageID.toString();
    25              messageID++;
    26              pendingMessages[id] = callback;
    27              var req = {
    28                  id,
    29                  method,
    30                  params
    31              }
    32              ws.send(JSON.stringify(req));
    33              return id;
    34          }
    35          function subscribe(method, params, callback) {
    36              var id = messageID.toString();
    37              messageID++;
    38              subscriptions[id] = callback;
    39              var req = {
    40                  id,
    41                  method,
    42                  params
    43              }
    44              ws.send(JSON.stringify(req));
    45              return id;
    46          }
    47          function unsubscribe(method, id, params, callback) {
    48              delete subscriptions[id];
    49              pendingMessages[id] = callback;
    50              var req = {
    51                  id,
    52                  method,
    53                  params
    54              }
    55              ws.send(JSON.stringify(req));
    56              return id;
    57          }
    58          function connect(server) {
    59              messageID = 0;
    60              pendingMessages = {};
    61              subscriptions = {};
    62              subscribeNewBlockId = "";
    63              subscribeNewTransactionId = "";
    64              subscribeAddressesId = "";
    65              if (server.startsWith("http")) {
    66                  server = server.replace("http", "ws");
    67              }
    68              if (!server.endsWith("/websocket")) {
    69                  server += "/websocket";
    70              }
    71              ws = new WebSocket(server);
    72              ws.onopen = function (e) {
    73                  console.log('socket connected', e);
    74                  document.getElementById('connectionStatus').innerText = "connected";
    75              };
    76              ws.onclose = function (e) {
    77                  console.log('socket closed', e);
    78                  document.getElementById('connectionStatus').innerText = "disconnected";
    79              };
    80              ws.onerror = function (e) {
    81                  console.log('socket error ', e);
    82                  document.getElementById('connectionStatus').innerText = "error";
    83              };
    84              ws.onmessage = function (e) {
    85                  console.log('resp ' + e.data);
    86                  var resp = JSON.parse(e.data);
    87                  var f = pendingMessages[resp.id];
    88                  if (f != undefined) {
    89                      delete pendingMessages[resp.id];
    90                      try {
    91                          f(resp.data);
    92                      } catch (e) {
    93                          alert(`Error: ${e}.\nLook into the console for websocket response.`);
    94                      }
    95                  } else {
    96                      f = subscriptions[resp.id];
    97                      if (f != undefined) {
    98                          f(resp.data);
    99                      }
   100                      else {
   101                          console.log("unkown response " + resp.id);
   102                      }
   103                  }
   104              };
   105          }
   106          function paramAsArray(name) {
   107              const p = document.getElementById(name).value;
   108              if (p) {
   109                  return p.split(",").map(s => s.trim());
   110              }
   111          }
   112  
   113          function getInfo() {
   114              const method = 'getInfo';
   115              const params = {
   116              };
   117              send(method, params, function (result) {
   118                  document.getElementById('getInfoResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   119              });
   120          }
   121  
   122          function ping() {
   123              const method = 'ping';
   124              const params = {
   125              };
   126              send(method, params, function (result) {
   127                  document.getElementById('pingResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   128              });
   129          }
   130  
   131          function getBlockHash() {
   132              const method = 'getBlockHash';
   133              const height = parseInt(document.getElementById("getBlockHashHeight").value);
   134              const params = {
   135                  height
   136              };
   137              send(method, params, function (result) {
   138                  document.getElementById('getBlockHashResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   139              });
   140          }
   141  
   142          function getBlock() {
   143              const method = "getBlock";
   144              const id = document.getElementById("getBlockId").value;
   145              const page = parseInt(document.getElementById("getBlockPage").value);
   146              const pageSize = parseInt(document.getElementById("getBlockPageSize").value);
   147              const params = {
   148                  id,
   149              };
   150              if (page) params.page = page;
   151              if (pageSize) params.pageSize = pageSize;
   152              send(method, params, function (result) {
   153                  document.getElementById("getBlockResult").innerText = JSON.stringify(result).replace(/,/g, ", ");
   154              });
   155          }
   156  
   157          function getAccountInfo() {
   158              const descriptor = document.getElementById('getAccountInfoDescriptor').value.trim();
   159              const selectDetails = document.getElementById('getAccountInfoDetails');
   160              const details = selectDetails.options[selectDetails.selectedIndex].value;
   161              const page = parseInt(document.getElementById("getAccountInfoPage").value);
   162              const from = parseInt(document.getElementById("getAccountInfoFrom").value);
   163              const to = parseInt(document.getElementById("getAccountInfoTo").value);
   164              const contractFilter = document.getElementById("getAccountInfoContract").value.trim();
   165              const secondaryCurrency = document.getElementById("getAccountInfoSecondaryCurrency").value.trim();
   166              const pageSize = 10;
   167              const method = 'getAccountInfo';
   168              const tokens = "derived"; // could be "nonzero", "used", default is "derived" i.e. all
   169              const params = {
   170                  descriptor,
   171                  details,
   172                  tokens,
   173                  page,
   174                  pageSize,
   175                  from,
   176                  to,
   177                  contractFilter,
   178                  secondaryCurrency,
   179                  // default gap=20
   180              };
   181              send(method, params, function (result) {
   182                  document.getElementById('getAccountInfoResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   183              });
   184          }
   185  
   186          function getAccountUtxo() {
   187              const descriptor = document.getElementById('getAccountUtxoDescriptor').value.trim();
   188              const method = 'getAccountUtxo';
   189              const params = {
   190                  descriptor,
   191              };
   192              send(method, params, function (result) {
   193                  document.getElementById('getAccountUtxoResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   194              });
   195          }
   196  
   197          function getBalanceHistory() {
   198              const descriptor = document.getElementById('getBalanceHistoryDescriptor').value.trim();
   199              const from = parseInt(document.getElementById("getBalanceHistoryFrom").value.trim());
   200              const to = parseInt(document.getElementById("getBalanceHistoryTo").value.trim());
   201              const currencies = paramAsArray('getBalanceHistoryFiat');
   202              const groupBy = parseInt(document.getElementById("getBalanceHistoryGroupBy").value);
   203              const method = 'getBalanceHistory';
   204              const params = {
   205                  descriptor,
   206                  from,
   207                  to,
   208                  currencies,
   209                  groupBy
   210                  // default gap=20
   211              };
   212              send(method, params, function (result) {
   213                  document.getElementById('getBalanceHistoryResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   214              });
   215          }
   216  
   217  
   218          function getTransaction() {
   219              const txid = document.getElementById('getTransactionTxid').value.trim();
   220              const method = 'getTransaction';
   221              const params = {
   222                  txid,
   223              };
   224              send(method, params, function (result) {
   225                  document.getElementById('getTransactionResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   226              });
   227          }
   228  
   229          function getTransactionSpecific() {
   230              const txid = document.getElementById('getTransactionSpecificTxid').value.trim();
   231              const method = 'getTransactionSpecific';
   232              const params = {
   233                  txid,
   234              };
   235              send(method, params, function (result) {
   236                  document.getElementById('getTransactionSpecificResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   237              });
   238          }
   239  
   240          function estimateFee() {
   241              try {
   242                  var blocks = paramAsArray('estimateFeeBlocks');
   243                  var specific = document.getElementById('estimateFeeSpecific').value.trim();
   244                  if (specific) {
   245                      // example for bitcoin type: {"conservative": false,"txsize":1234}
   246                      // example for ethereum type: {"from":"0x65513ecd11fd3a5b1fefdcc6a500b025008405a2","to":"0x65513ecd11fd3a5b1fefdcc6a500b025008405a2","data":"0xabcd","gasPrice":"0x30d40","value":"0x1234"}
   247                      specific = JSON.parse(specific)
   248                  }
   249                  else {
   250                      specific = undefined;
   251                  }
   252                  blocks = blocks.map(s => parseInt(s.trim()));
   253                  const method = 'estimateFee';
   254                  const params = {
   255                      blocks,
   256                      specific
   257                  };
   258                  send(method, params, function (result) {
   259                      document.getElementById('estimateFeeResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   260                  });
   261              }
   262              catch (e) {
   263                  document.getElementById('estimateFeeResult').innerText = e;
   264              }
   265          }
   266  
   267          function sendTransaction() {
   268              var hex = document.getElementById('sendTransactionHex').value.trim();
   269              const method = 'sendTransaction';
   270              const params = {
   271                  hex,
   272              };
   273              send(method, params, function (result) {
   274                  document.getElementById('sendTransactionResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   275              });
   276          }
   277  
   278          function subscribeNewBlock() {
   279              const method = 'subscribeNewBlock';
   280              const params = {
   281              };
   282              if (subscribeNewBlockId) {
   283                  delete subscriptions[subscribeNewBlockId];
   284                  subscribeNewBlockId = "";
   285              }
   286              subscribeNewBlockId = subscribe(method, params, function (result) {
   287                  document.getElementById('subscribeNewBlockResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   288              });
   289              document.getElementById('subscribeNewBlockId').innerText = subscribeNewBlockId;
   290              document.getElementById('unsubscribeNewBlockButton').setAttribute("style", "display: inherit;");
   291          }
   292  
   293          function unsubscribeNewBlock() {
   294              const method = 'unsubscribeNewBlock';
   295              const params = {
   296              };
   297              unsubscribe(method, subscribeNewBlockId, params, function (result) {
   298                  subscribeNewBlockId = "";
   299                  document.getElementById('subscribeNewBlockResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   300                  document.getElementById('subscribeNewBlockId').innerText = "";
   301                  document.getElementById('unsubscribeNewBlockButton').setAttribute("style", "display: none;");
   302              });
   303          }
   304  
   305          function subscribeNewTransaction() {
   306              const method = 'subscribeNewTransaction';
   307              const params = {
   308              };
   309              if (subscribeNewTransactionId) {
   310                  delete subscriptions[subscribeNewTransactionId];
   311                  subscribeNewTransactionId = "";
   312              }
   313              subscribeNewTransactionId = subscribe(method, params, function (result) {
   314                  document.getElementById('subscribeNewTransactionResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   315              });
   316              document.getElementById('subscribeNewTransactionId').innerText = subscribeNewTransactionId;
   317              document.getElementById('unsubscribeNewTransactionButton').setAttribute("style", "display: inherit;");
   318          }
   319  
   320          function unsubscribeNewTransaction() {
   321              const method = 'unsubscribeNewTransaction';
   322              const params = {
   323              };
   324              unsubscribe(method, subscribeNewTransactionId, params, function (result) {
   325                  subscribeNewTransactionId = "";
   326                  document.getElementById('subscribeNewTransactionResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   327                  document.getElementById('subscribeNewTransactionId').innerText = "";
   328                  document.getElementById('unsubscribeNewTransactionButton').setAttribute("style", "display: none;");
   329              });
   330          }
   331  
   332          function subscribeAddresses() {
   333              const method = 'subscribeAddresses';
   334              var addresses = paramAsArray('subscribeAddressesName');
   335              const params = {
   336                  addresses
   337              };
   338              if (subscribeAddressesId) {
   339                  delete subscriptions[subscribeAddressesId];
   340                  subscribeAddressesId = "";
   341              }
   342              subscribeAddressesId = subscribe(method, params, function (result) {
   343                  document.getElementById('subscribeAddressesResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   344              });
   345              document.getElementById('subscribeAddressesIds').innerText = subscribeAddressesId;
   346              document.getElementById('unsubscribeAddressesButton').setAttribute("style", "display: inherit;");
   347          }
   348  
   349          function unsubscribeAddresses() {
   350              const method = 'unsubscribeAddresses';
   351              const params = {
   352              };
   353              unsubscribe(method, subscribeAddressesId, params, function (result) {
   354                  subscribeAddressesId = "";
   355                  document.getElementById('subscribeAddressesResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   356                  document.getElementById('subscribeAddressesIds').innerText = "";
   357                  document.getElementById('unsubscribeAddressesButton').setAttribute("style", "display: none;");
   358              });
   359          }
   360  
   361          function getFiatRatesForTimestamps() {
   362              const method = 'getFiatRatesForTimestamps';
   363              var timestamps = paramAsArray('getFiatRatesForTimestampsList');
   364              var currencies = paramAsArray('getFiatRatesForTimestampsCurrency');
   365              var token = document.getElementById('getFiatRatesForTimestampsToken').value;
   366              timestamps = timestamps.map(Number);
   367              const params = {
   368                  timestamps,
   369                  'currencies': currencies,
   370                  token,
   371              };
   372              send(method, params, function (result) {
   373                  document.getElementById('getFiatRatesForTimestampsResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   374              });
   375          }
   376  
   377          function getCurrentFiatRates() {
   378              const method = 'getCurrentFiatRates';
   379              var currencies = paramAsArray('getCurrentFiatRatesCurrency');
   380              var token = document.getElementById('getCurrentFiatRatesToken').value;
   381              const params = {
   382                  "currencies": currencies,
   383                  token,
   384              };
   385              send(method, params, function (result) {
   386                  document.getElementById('getCurrentFiatRatesResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   387              });
   388          }
   389  
   390          function getFiatRatesTickersList() {
   391              const method = 'getFiatRatesTickersList';
   392              var timestamp = document.getElementById('getFiatRatesTickersListDate').value;
   393              var token = document.getElementById('getFiatRatesTickersToken').value;
   394              timestamp = parseInt(timestamp);
   395              const params = {
   396                  timestamp,
   397                  token,
   398              };
   399              send(method, params, function (result) {
   400                  document.getElementById('getFiatRatesTickersListResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   401              });
   402          }
   403  
   404          function getMempoolFilters() {
   405              const method = 'getMempoolFilters';
   406              var timestamp = document.getElementById('getMempoolFiltersFromTimestamp').value;
   407              var scriptType = document.getElementById('getMempoolFiltersScriptType').value;
   408              fromTimestamp = parseInt(timestamp);
   409              const params = {
   410                  scriptType,
   411                  fromTimestamp,
   412              };
   413              send(method, params, function (result) {
   414                  document.getElementById('getMempoolFiltersResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   415              });
   416          }
   417  
   418          function getBlockFilter() {
   419              const method = 'getBlockFilter';
   420              const blockHash = document.getElementById('getBlockFilterBlockHash').value;
   421              const scriptType = document.getElementById('getBlockFilterBlockHashScriptType').value;
   422              const params = {
   423                  blockHash,
   424                  scriptType,
   425              };
   426              send(method, params, function (result) {
   427                  document.getElementById('getBlockFilterResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   428              });
   429          }
   430  
   431          function getBlockFiltersBatch() {
   432              const method = 'getBlockFiltersBatch';
   433              const bestKnownBlockHash = document.getElementById('getBlockFiltersBatchBlockHash').value;
   434              const pageSize = parseInt(document.getElementById("getBlockFiltersBatchPageSize").value);
   435              const scriptType = document.getElementById('getBlockFiltersBatchScriptType').value;
   436              const params = {
   437                  bestKnownBlockHash,
   438                  scriptType,
   439              };
   440              if (pageSize) params.pageSize = pageSize;
   441              send(method, params, function (result) {
   442                  document.getElementById('getBlockFiltersBatchResult').innerText = JSON.stringify(result).replace(/,/g, ", ");
   443              });
   444          }
   445  
   446          function subscribeNewFiatRatesTicker() {
   447              const method = 'subscribeFiatRates';
   448              var currency = document.getElementById('subscribeFiatRatesCurrency').value;
   449              var tokens = paramAsArray('subscribeFiatRatesTokens');
   450              const params = {
   451                  "currency": currency,
   452                  tokens,
   453              };
   454              if (subscribeNewFiatRatesTickerId) {
   455                  delete subscriptions[subscribeNewFiatRatesTickerId];
   456                  subscribeNewFiatRatesTickerId = "";
   457              }
   458              subscribeNewFiatRatesTickerId = subscribe(method, params, function (result) {
   459                  document.getElementById('subscribeNewFiatRatesTickerResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   460              });
   461              document.getElementById('subscribeNewFiatRatesTickerId').innerText = subscribeNewFiatRatesTickerId;
   462              document.getElementById('unsubscribeNewFiatRatesTickerButton').setAttribute("style", "display: inherit;");
   463          }
   464  
   465          function unsubscribeNewFiatRatesTicker() {
   466              const method = 'unsubscribeFiatRates';
   467              const params = {
   468              };
   469              unsubscribe(method, subscribeNewFiatRatesTickerId, params, function (result) {
   470                  subscribeNewFiatRatesTickerId = "";
   471                  document.getElementById('subscribeNewFiatRatesTickerResult').innerText += JSON.stringify(result).replace(/,/g, ", ") + "\n";
   472                  document.getElementById('subscribeNewFiatRatesTickerId').innerText = "";
   473                  document.getElementById('unsubscribeNewFiatRatesTickerButton').setAttribute("style", "display: none;");
   474              });
   475          }
   476      </script>
   477  </head>
   478  
   479  <body>
   480      <div class="container">
   481          <div class="row justify-content-center">
   482              <h1>Blockbook Websocket Test Page</h1>
   483          </div>
   484          <div class="row">
   485              <div class="col">
   486                  <input class="btn btn-secondary" type="button" value="Login" onclick="connect(document.getElementById('serverAddress').value)">
   487              </div>
   488              <div class="col-8">
   489                  <input type="text" class="form-control" id="serverAddress" value="">
   490              </div>
   491              <div class="col form-inline">
   492                  <label id="connectionStatus">not connected</label>
   493              </div>
   494          </div>
   495          <div class="row">
   496              <div class="col">
   497                  <input class="btn btn-secondary" type="button" value="getInfo" onclick="getInfo()">
   498              </div>
   499              <div class="col-10" id="getInfoResult">
   500              </div>
   501          </div>
   502          <div class="row">
   503              <div class="col">
   504                  <input class="btn btn-secondary" type="button" value="ping" onclick="ping()">
   505              </div>
   506              <div class="col-10" id="pingResult">
   507              </div>
   508          </div>
   509          <div class="row">
   510              <div class="col">
   511                  <input class="btn btn-secondary" type="button" value="getBlockHash" onclick="getBlockHash()">
   512              </div>
   513              <div class="col-8">
   514                  <input type="text" class="form-control" placeholder="height" id="getBlockHashHeight" value="0">
   515              </div>
   516              <div class="col">
   517              </div>
   518          </div>
   519          <div class="row">
   520              <div class="col" id="getBlockHashResult"></div>
   521          </div>
   522          <div class="row">
   523              <div class="col">
   524                  <input class="btn btn-secondary" type="button" value="getBlock" onclick="getBlock()">
   525              </div>
   526              <div class="col-8">
   527                  <div class="row" style="margin: 0;">
   528                      <input type="text" class="form-control" placeholder="height/hash" style="width: 68%; margin-right: 5px;" id="getBlockId" value="">
   529                      <input type="text" class="form-control" placeholder="page" style="width: 15%; margin-right: 5px;" id="getBlockPage" value="">
   530                      <input type="text" class="form-control" placeholder="page size" style="width: 15%;" id="getBlockPageSize" value="">
   531                  </div>
   532              </div>
   533              <div class="col">
   534              </div>
   535          </div>
   536          <div class="row">
   537              <div class="col" id="getBlockResult"></div>
   538          </div>
   539          <div class="row">
   540              <div class="col">
   541                  <input class="btn btn-secondary" type="button" value="getAccountInfo" onclick="getAccountInfo()">
   542              </div>
   543              <div class="col-8">
   544                  <div class="row" style="margin: 0;">
   545                      <input type="text" placeholder="descriptor" style="width: 79%" class="form-control" id="getAccountInfoDescriptor" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd">
   546                      <select id="getAccountInfoDetails" style="width: 20%; margin-left: 5px;">
   547                          <option value="basic">Basic</option>
   548                          <option value="tokens">Tokens</option>
   549                          <option value="tokenBalances">TokenBalances</option>
   550                          <option value="txids">Txids</option>
   551                          <option value="txs">Transactions</option>
   552                      </select>
   553                  </div>
   554                  <div class="row" style="margin: 0; margin-top: 5px;">
   555                      <input type="text" placeholder="page" style="width: 10%; margin-right: 5px;" class="form-control" id="getAccountInfoPage">
   556                      <input type="text" placeholder="from" style="width: 13%;margin-left: 5px;margin-right: 5px;" class="form-control" id="getAccountInfoFrom">
   557                      <input type="text" placeholder="to" style="width: 13%; margin-left: 5px; margin-right: 5px;" class="form-control" id="getAccountInfoTo">
   558                      <input type="text" placeholder="contract" style="width: 50%; margin-left: 5px; margin-right: 5px;" class="form-control" id="getAccountInfoContract">
   559                      <input type="text" placeholder="usd" style="width: 8%; margin-left: 5px;" class="form-control" id="getAccountInfoSecondaryCurrency">
   560                  </div>
   561              </div>
   562              <div class="col form-inline"></div>
   563          </div>
   564          <div class="row">
   565              <div class="col" id="getAccountInfoResult">
   566              </div>
   567          </div>
   568          <div class="row">
   569              <div class="col">
   570                  <input class="btn btn-secondary" type="button" value="getAccountUtxo" onclick="getAccountUtxo()">
   571              </div>
   572              <div class="col-8">
   573                  <div class="row" style="margin: 0;">
   574                      <input type="text" placeholder="descriptor" class="form-control" id="getAccountUtxoDescriptor" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd">
   575                  </div>
   576              </div>
   577              <div class="col form-inline"></div>
   578          </div>
   579          <div class="row">
   580              <div class="col" id="getAccountUtxoResult">
   581              </div>
   582          </div>
   583          <div class="row">
   584              <div class="col">
   585                  <input class="btn btn-secondary" type="button" value="getBalanceHistory" onclick="getBalanceHistory()">
   586              </div>
   587              <div class="col-8">
   588                  <div class="row" style="margin: 0;">
   589                      <input type="text" placeholder="descriptor" class="form-control" id="getBalanceHistoryDescriptor" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd">
   590                  </div>
   591                  <div class="row" style="margin: 0; margin-top: 5px;">
   592                      <input type="text" placeholder="from Unix TS" style="width: 20%;margin-left: 5px;margin-right: 5px;" class="form-control" id="getBalanceHistoryFrom">
   593                      <input type="text" placeholder="to Unix TS" style="width: 20%; margin-left: 5px; margin-right: 5px;" class="form-control" id="getBalanceHistoryTo">
   594                      <input type="text" placeholder="usd,eur" style="width: 20%; margin-left: 5px; margin-right: 5px;" class="form-control" id="getBalanceHistoryFiat">
   595                      <input type="text" placeholder="group by (sec)" style="width: 20%; margin-left: 5px; margin-right: 5px;" class="form-control" id="getBalanceHistoryGroupBy">
   596                  </div>
   597              </div>
   598              <div class="col form-inline"></div>
   599          </div>
   600          <div class="row">
   601              <div class="col" id="getBalanceHistoryResult">
   602              </div>
   603          </div>
   604          <div class="row">
   605              <div class="col">
   606                  <input class="btn btn-secondary" type="button" value="getTransaction" onclick="getTransaction()">
   607              </div>
   608              <div class="col-8">
   609                  <div class="row" style="margin: 0;">
   610                      <input type="text" placeholder="txid" class="form-control" id="getTransactionTxid" value="0xb266c89f9bfefa4aa2fca4e65b7d6c918d5407f464be781c2803f3546d34a574">
   611                  </div>
   612              </div>
   613              <div class="col form-inline"></div>
   614          </div>
   615          <div class="row">
   616              <div class="col" id="getTransactionResult">
   617              </div>
   618          </div>
   619          <div class="row">
   620              <div class="col">
   621                  <input class="btn btn-secondary" type="button" value="getTransactionSpecific" onclick="getTransactionSpecific()">
   622              </div>
   623              <div class="col-8">
   624                  <div class="row" style="margin: 0;">
   625                      <input type="text" placeholder="txid" class="form-control" id="getTransactionSpecificTxid" value="0xb266c89f9bfefa4aa2fca4e65b7d6c918d5407f464be781c2803f3546d34a574">
   626                  </div>
   627              </div>
   628              <div class="col form-inline"></div>
   629          </div>
   630          <div class="row">
   631              <div class="col" id="getTransactionSpecificResult">
   632              </div>
   633          </div>
   634          <div class="row">
   635              <div class="col">
   636                  <input class="btn btn-secondary" type="button" value="estimateFee" onclick="estimateFee()">
   637              </div>
   638              <div class="col-8">
   639                  <div class="row" style="margin: 0;">
   640                      <input type="text" placeholder="comma separated list of block targets" class="form-control" id="estimateFeeBlocks" value="2,5,10,20">
   641                  </div>
   642                  <div class="row" style="margin: 0; margin-top: 5px;">
   643                      <input type="text" placeholder="tx specific JSON" class="form-control" id="estimateFeeSpecific" value="">
   644                  </div>
   645              </div>
   646              <div class="col"></div>
   647          </div>
   648          <div class="row">
   649              <div class="col" id="estimateFeeResult">
   650              </div>
   651          </div>
   652          <div class="row">
   653              <div class="col">
   654                  <input class="btn btn-secondary" type="button" value="sendTransaction" onclick="sendTransaction()">
   655              </div>
   656              <div class="col-8">
   657                  <input type="text" class="form-control" id="sendTransactionHex" value="010000000001019d64f0c72a0d206001decbffaa722eb1044534c74eee7a5df8318e42a4323ec10000000017160014550da1f5d25a9dae2eafd6902b4194c4c6500af6ffffffff02809698000000000017a914cd668d781ece600efa4b2404dc91fd26b8b8aed8870553d7360000000017a914246655bdbd54c7e477d0ea2375e86e0db2b8f80a8702473044022076aba4ad559616905fa51d4ddd357fc1fdb428d40cb388e042cdd1da4a1b7357022011916f90c712ead9a66d5f058252efd280439ad8956a967e95d437d246710bc9012102a80a5964c5612bb769ef73147b2cf3c149bc0fd4ecb02f8097629c94ab013ffd00000000">
   658              </div>
   659              <div class="col">
   660              </div>
   661          </div>
   662          <div class="row">
   663              <div class="col" id="sendTransactionResult"></div>
   664          </div>
   665          <div class="row">
   666              <div class="col-2">
   667                  <input class="btn btn-secondary" type="button" value="get fiat rates for dates" onclick="getFiatRatesForTimestamps()">
   668              </div>
   669              <div class="col-1">
   670                  <input type="text" class="form-control" id="getFiatRatesForTimestampsCurrency" placeholder="usd,eur">
   671              </div>
   672              <div class="col-7">
   673                  <input type="text" class="form-control" id="getFiatRatesForTimestampsList" value="1575288000,1575550800">
   674              </div>
   675              <div class="col-5 offset-3">
   676                  <input type="text" class="form-control" id="getFiatRatesForTimestampsToken" value="" placeholder="Token address">
   677              </div>
   678          </div>
   679          <div class="row">
   680              <div class="col" id="getFiatRatesForTimestampsResult"></div>
   681          </div>
   682          <div class="row">
   683              <div class="col-2">
   684                  <input class="btn btn-secondary" type="button" value="get current fiat rates" onclick="getCurrentFiatRates()">
   685              </div>
   686              <div class="col-1">
   687                  <input type="text" class="form-control" id="getCurrentFiatRatesCurrency" placeholder="usd">
   688              </div>
   689              <div class="col-5">
   690                  <input type="text" class="form-control" id="getCurrentFiatRatesToken" value="" placeholder="Token address">
   691              </div>
   692          </div>
   693          <div class="row">
   694              <div class="col" id="getCurrentFiatRatesResult"></div>
   695          </div>
   696          <div class="row">
   697              <div class="col-2">
   698                  <input class="btn btn-secondary" type="button" value="get available tickers" onclick="getFiatRatesTickersList()">
   699              </div>
   700              <div class="col-4">
   701                  <input type="text" class="form-control" id="getFiatRatesTickersListDate" value="1576591569" placeholder="Unix timestamp">
   702              </div>
   703              <div class="col-5">
   704                  <input type="text" class="form-control" id="getFiatRatesTickersToken" value="" placeholder="Token address">
   705              </div>
   706          </div>
   707          <div class="row">
   708              <div class="col" id="getFiatRatesTickersListResult"></div>
   709          </div>
   710          <div class="row">
   711              <div class="col-2">
   712                  <input class="btn btn-secondary" type="button" value="get mempool filters" onclick="getMempoolFilters()">
   713              </div>
   714              <div class="col-5">
   715                  <input type="text" class="form-control" id="getMempoolFiltersScriptType" value="taproot" placeholder="filter script">
   716              </div>
   717              <div class="col-4">
   718                  <input type="text" class="form-control" id="getMempoolFiltersFromTimestamp" value="" placeholder="From unix timestamp">
   719              </div>
   720          </div>
   721          <div class="row">
   722              <div class="col" id="getMempoolFiltersResult"></div>
   723          </div>
   724          <div class="row">
   725              <div class="col-2">
   726                  <input class="btn btn-secondary" type="button" value="get block filter" onclick="getBlockFilter()">
   727              </div>
   728              <div class="col-8">
   729                  <input type="text" class="form-control" id="getBlockFilterBlockHash" value="000000000000001cb4edd91be03b6775abd351fb51b1fbb0871fc1451454f362" placeholder="block hash">
   730                  <input type="text" class="form-control" id="getBlockFilterBlockHashScriptType" value="taproot-noordinals" placeholder="filter script">
   731              </div>
   732          </div>
   733          <div class="row">
   734              <div class="col" id="getBlockFilterResult"></div>
   735          </div>
   736          <div class="row">
   737              <div class="col-2">
   738                  <input class="btn btn-secondary" type="button" value="get block filter batch" onclick="getBlockFiltersBatch()">
   739              </div>
   740              <div class="col-10">
   741                  <div class="row" style="margin: 0;">
   742                      <input type="text" class="form-control" id="getBlockFiltersBatchBlockHash"  style="width: 80%; margin-right: 5px;" value="000000000000001cb4edd91be03b6775abd351fb51b1fbb0871fc1451454f362" placeholder="best known block hash">
   743                      <input type="text" class="form-control" placeholder="page size" style="width: 15%;" id="getBlockFiltersBatchPageSize" value="">
   744                      <input type="text" class="form-control" id="getBlockFiltersBatchScriptType" value="taproot-noordinals" placeholder="filter script">
   745                  </div>
   746              </div>
   747          </div>
   748          <div class="row">
   749              <div class="col" id="getBlockFiltersBatchResult"></div>
   750          </div>
   751          <div class="row">
   752              <div class="col">
   753                  <input class="btn btn-secondary" type="button" value="subscribe new block" onclick="subscribeNewBlock()">
   754              </div>
   755              <div class="col-4">
   756                  <span id="subscribeNewBlockId"></span>
   757              </div>
   758              <div class="col">
   759                  <input class="btn btn-secondary" id="unsubscribeNewBlockButton" style="display: none;" type="button" value="unsubscribe" onclick="unsubscribeNewBlock()">
   760              </div>
   761          </div>
   762          <div class="row">
   763              <div class="col" id="subscribeNewBlockResult"></div>
   764          </div>
   765          <div class="row">
   766              <div class="col">
   767                  <input class="btn btn-secondary" type="button" value="subscribe new transaction" onclick="subscribeNewTransaction()">
   768              </div>
   769              <div class="col-4">
   770                  <span id="subscribeNewTransactionId"></span>
   771              </div>
   772              <div class="col">
   773                  <input class="btn btn-secondary" id="unsubscribeNewTransactionButton" style="display: none;" type="button" value="unsubscribe" onclick="unsubscribeNewTransaction()">
   774              </div>
   775          </div>
   776          <div class="row">
   777              <div class="col" id="subscribeNewTransactionResult"></div>
   778          </div>
   779          <div class="row">
   780              <div class="col">
   781                  <input class="btn btn-secondary" type="button" value="subscribe address" onclick="subscribeAddresses()">
   782              </div>
   783              <div class="col-8">
   784                  <input type="text" class="form-control" id="subscribeAddressesName" value="0xba98d6a5ac827632e3457de7512d211e4ff7e8bd,0x73d0385f4d8e00c5e6504c6030f47bf6212736a8">
   785              </div>
   786              <div class="col">
   787                  <span id="subscribeAddressesIds"></span>
   788              </div>
   789              <div class="col">
   790                  <input class="btn btn-secondary" id="unsubscribeAddressesButton" style="display: none;" type="button" value="unsubscribe" onclick="unsubscribeAddresses()">
   791              </div>
   792          </div>
   793          <div class="row">
   794              <div class="col" id="subscribeAddressesResult"></div>
   795          </div>
   796          <div class="row">
   797              <div class="col-2">
   798                  <input class="btn btn-secondary" type="button" value="subscribe fiat rates" onclick="subscribeNewFiatRatesTicker()">
   799              </div>
   800              <div class="col-1">
   801                  <input type="text" class="form-control" id="subscribeFiatRatesCurrency" value="usd">
   802              </div>
   803              <div class="col-8">
   804                  <input type="text" class="form-control" id="subscribeFiatRatesTokens" value="" placeholder="0xdAC17F958D2ee523a2206206994597C13D831ec7,0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2">
   805              </div>
   806              <div class="col-1">
   807                  <span id="subscribeNewFiatRatesTickerId"></span>
   808              </div>
   809              <div class="col-5">
   810                  <input class="btn btn-secondary" id="unsubscribeNewFiatRatesTickerButton" style="display: none;" type="button" value="unsubscribe" onclick="unsubscribeNewFiatRatesTicker()">
   811              </div>
   812          </div>
   813          <div class="row">
   814              <div class="col" id="subscribeNewFiatRatesTickerResult"></div>
   815          </div>
   816      </div>
   817      <br><br>
   818  </body>
   819  <script>
   820      document.getElementById('serverAddress').value = window.location.protocol + "//" + window.location.host;
   821  </script>
   822  
   823  </html>