Hier zeige ich Euch eine kleine Anwendung zur Speicherung von beliebigen Daten in der Blockchain. Wir nutzen dafür eine besondere Transaktionsart des Bitcoins, nämlich der „OP_RETURN“-Transaktion.
Bei einer normalen Transaktion gebe ich einen Empfänger und den Überweisungsbetrag an, bei einer OP_RETURN-Transaktion fehlen diese beiden Angaben. Stattdessen wird als Überweisungsbetrag 0 Coins genannt und der Empfänger fällt komplett weg (markierte Zeilen 127 bis 129).
Dafür kann ich der Transaktion über ein besonderes Script ein Byte Array mit maximal 40 Bytes Länge mitgeben. Wenn Ihr das folgende Programm ausführt, werdet Ihr sehen, das mit einem Klick auf die Checkbox auch 80 Zeichen zugelassen sind. Es gibt aber leider keine Garantie dafür, das eine derartige Transaktion (insbesondere im Mainnetz) von allen Gegenstellen und Minern akzeptiert und somit auch final in einen Block aufgenommen und damit dauerhaft gespeichert wird.
Eine weitere Besonderheit dieses Programms ist es, die Minimum-Gebühr für die Transaktion zu minimieren (Faktor 100) und nutze dafür den Code in den Zeilen 134-137. Auch diese Herabstufung kann im Echtnetz (Mainnet) dazu führen, das die Transaktion nicht bearbeitet wird. Ich habe die Reduzierung hier aufgenommen, damit Euer Guthaben etwas länger vorhält und nicht durch die Transaktionsgebühren vorschnell aufgezehrt wird.
Die Benutzung des Programms ist sehr einfach – zuerst muss das Wallet gestartet und online aktualisiert werden:
Die Wartezeit kann bis 3 Minuten andauern:
Danach gebe ich einen Zeichenkette in das Feld OP_RETURN ein (die Zeichenanzahl ist auf 40 Zeichen begrenzt) – hier benutze ich „github.com/java-crypto/BitcoinJTimestamp“:
Nach dem Klick auf „senden einer OP-Return-Transaktion“ erfolgt das Senden der Transaktion und die „grüne“ Rückbestätigung – im Beispiel wird die Transaktions-Id „541f90f18a7698455edd226c2b9ed77c562ce2d9320da01f4d76d7cc351acedb“ ausgegeben. Das Label „Link“ ist mit einem Maus-Listener ausgestattet und bei einem Klick darauf öffnet sich der Browser mit einem Bitcoin Testnetz Blockexplorer (Direktlink: https://tbtc.bitaps.com/541f90f18a7698455edd226c2b9ed77c562ce2d9320da01f4d76d7cc351acedb) :
Hier die Ansicht im Bitcoin Explorer – unsere eingegebenen Daten erscheinen unveränderbar in der Blockchain:
Hier noch ein Beispiel für die Nutzung von 80 Zeichen – ich klicke die Checkbox „80 Zeichen“ an und gebe diese Zeichen ein: „visit http://java-crypto.bplaced.net and http://javacrypto.bplaced.net“:
Auch diese Daten werden in der Blockchain gespeichert und die Transaktions-Id ist „d8a3ee0b792acd8b7fa78f0589f5c7adace8438816dd9b64bf5e029a3b137687“. Abrufbar ist die dazugehörende volle Information per Direktlink (https://tbtc.bitaps.com/d8a3ee0b792acd8b7fa78f0589f5c7adace8438816dd9b64bf5e029a3b137687):
Bitte beachtet noch den folgenden Hinweis: wenn ich von „ewiger“ Speicherung der OP_RETURN-Transaktion in der Blockchain spreche meine ich das Main-Netzwerk und nicht das hier genutzte Testnetz. Das Testnetz kann jederzeit zurückgesetzt werden und alle bis dahin gespeicherten Daten werden verschwinden – speichert bitte keine wichtigen Informationen alleine im Bitcoin Testnetzwerk!
Alle Quellcodes zu BitcoinJ Timestamps & OP_RETURN findet Ihr zum Download in meinem GitHub-Repository BitcoinJTimestamp, welches Ihr über diesen Link erreicht: https://github.com/java-crypto/BitcoinJTimestamp. Alle Programme sind unter Java 11 lauffähig (vermutlich auch unter Java 8) und wurden mit intelliJ IDEA entwickelt, welches für dieses Programm aber nicht notwendig ist.
Zur Nutzung der Programme benötigt Ihr diverse Bibliotheken – ladet Euch diese aus dem separaten GitHub-Archiv (https://github.com/java-crypto/BitcoinJ_Libraries) herunter und bindet Sie über Eure Entwicklungsumgebung ein.
Noch ein Wort zum Thema „Lizenz“: Das Programm steht unter unterschiedlichen Lizenzen, die Ihr bitte beachten solltet. Die von mir erstellten Beispiele selber stehen unter der „Unlicense“-Lizenz, allerdings werden zur Laufzeit diverse Bibliotheken eingebunden, welche zum Teil ganz eigene Lizenzen mitbringen. Darauf kann ich in meinen Lizenzhinweisen nicht hinweisen.
Letzte Bearbeitung: 24.03.2020
Hier der Quellcode und die dazugehörende Form (Ihr benötigt intelliJ IDEA zum Nachbau):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 |
/* * Herkunft/Origin: http://javacrypto.bplaced.net/ * Programmierer/Programmer: Michael Fehr * Copyright/Copyright: Michael Fehr * Lizenttext/Licence: verschiedene Lizenzen / several licenses * getestet mit/tested with: Java Runtime Environment 11.0.5 x64 * verwendete IDE/used IDE: intelliJ IDEA 2019.3.1 * Datum/Date (dd.mm.jjjj): 24.03.2020 * Funktion: Erzeugt eine OP_RETURN-Transaktion in der Bitcoin Blockchain * Function: create an OP_RETURN transaction in the Bitcoin blockchain * * Sicherheitshinweis/Security notice * Die Programmroutinen dienen nur der Darstellung und haben keinen Anspruch auf eine korrekte Funktion, * insbesondere mit Blick auf die Sicherheit ! * Prüfen Sie die Sicherheit bevor das Programm in der echten Welt eingesetzt wird. * The program routines just show the function but please be aware of the security part - * check yourself before using in the real world ! * * Sie benötigen diverse Bibliotheken (alle im Github-Archiv im Unterordner "libs") * You need a lot of libraries (see my Github-repository in subfolder "libs") * verwendete BitcoinJ-Bibliothek / used BitcoinJ Library: bitcoinj-core-0.15.6.jar * my Github-Repository: https://github.com/java-crypto/BitcoinJ * libs in my Github-Repo: https://github.com/java-crypto/BitcoinJ_Libraries * */ import org.bitcoinj.core.*; import org.bitcoinj.kits.WalletAppKit; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; import org.bitcoinj.params.TestNet3Params; import org.bitcoinj.script.ScriptBuilder; import org.bitcoinj.wallet.SendRequest; import org.bitcoinj.wallet.Wallet; import javax.swing.*; import java.awt.*; import java.awt.event.*; import java.io.*; import java.net.URI; import java.net.URISyntaxException; import java.time.LocalDateTime; import java.time.format.DateTimeFormatter; import java.util.concurrent.TimeUnit; public class BitcoinJCreateAnOp_Return { private WalletAppKit kit; boolean kitIsRunning = false; private NetworkParameters netParams; private LocalDateTime localDateTimeStart; private LocalDateTime localDateTimeEnd; private String filenameWallet = "TimestampOwn"; private Coin balance; private Sha256Hash sha256Hash; private Color colorStatus; private String labelLinkPreset = "noch kein Link vorhanden"; public BitcoinJCreateAnOp_Return() throws IOException, InterruptedException { // choose network type (MAIN, TEST or REG) //String networkType = "MAIN"; String networkType = "TEST"; //String networkType = "REG"; switch (networkType) { case "MAIN": { netParams = MainNetParams.get(); filenameWallet = filenameWallet + "_Mainnet"; break; } case "TEST": { netParams = TestNet3Params.get(); filenameWallet = filenameWallet + "_Testnet"; break; } case "REG": { netParams = RegTestParams.get(); filenameWallet = filenameWallet + "_Regtest"; break; } default: { System.out.println("Es ist kein networkType angegeben, das Programm wird in 10 Sekunden beendet"); tfStatus.setText("Kein networkType angegeben, Programm endet in 10 Sekunden"); tfStatus.setBackground(Color.RED); TimeUnit.SECONDS.sleep(10); System.exit(0); } } System.out.println("Das Programm arbeitet im Netzwerk: " + netParams.getId()); System.out.println("Guten Tag, zum Start bitte den Button 'starte das wallet' druecken"); localDateTimeStart = LocalDateTime.now(); kitIsRunning = false; colorStatus = tfStatus.getBackground(); lblLink.setText(labelLinkPreset); btnSendOpReturn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { tfStatus.setText(""); tfTxId.setText(""); lblLink.setText(labelLinkPreset); lblLink.setToolTipText(""); lblLink.setCursor(Cursor.getDefaultCursor()); tfStatus.setBackground(colorStatus); sha256Hash = null; // is an op_return string provided? String txOpReturn = tfOpReturn.getText(); if (txOpReturn.length() == 0) { System.out.println("Bitte einen OP_RETURN-Wert eingeben"); tfStatus.setText("Kein OP_RETURN angegeben"); tfStatus.setBackground(Color.YELLOW); } byte[] txOpReturnByte = new byte[0]; try { txOpReturnByte = txOpReturn.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } if (cbxExtendedOpReturn.isSelected()) { System.out.println("OP_RETURN Laenge: " + txOpReturn.length() + " (maximal 80 Zeichen) : " + txOpReturn); } else { System.out.println("OP_RETURN Laenge: " + txOpReturn.length() + " (maximal 40 Zeichen) : " + txOpReturn); } System.out.println("OP_Return als ByteArray: " + bytesToHex(txOpReturnByte)); System.out.println("\nErzeugung einer Transaktion und des SendRequests"); // construct an OP_RETURN transaction Transaction transaction = new Transaction(netParams); transaction.addOutput( Coin.ZERO, ScriptBuilder.createOpReturnScript(txOpReturnByte) ); // transaction is used to create a sendrequest SendRequest sendRequest = SendRequest.forTx(transaction); System.out.println("Transaktion : " + transaction); Coin coinsFee = Coin.valueOf(1000); // reduced fee may not work in MainNet System.out.println("Standard Fee per KB : " + sendRequest.feePerKb.toFriendlyString()); System.out.println("Reduzierte Fee per KB : " + coinsFee.toFriendlyString()); sendRequest.feePerKb = coinsFee; System.out.println("SendRequest : " + sendRequest); System.out.println("\nSende den SendRequest ueber das Wallet und erhalte ein SendResult"); Wallet.SendResult sendResult = null; try { sendResult = kit.wallet().sendCoins(sendRequest); } catch (InsufficientMoneyException e) { System.out.println("Fehler: ungenuegendes Guthaben - laden Sie Bitcons in das Wallet"); tfStatus.setText("Fehler: ungenuegendes Guthaben - laden Sie Bitcons in das Wallet"); tfStatus.setBackground(Color.RED); System.out.println("Aktuelle Empfangsadresse: " + kit.wallet().currentReceiveAddress()); btnSendOpReturn.setEnabled(false); e.printStackTrace(); } System.out.println("SendResult : " + sendResult.tx); System.out.println("Transaktions Id : " + sendResult.tx.getTxId().toString()); tfTxId.setText(sendResult.tx.getTxId().toString()); lblLink.setText("<HTML><FONT color=\"#000099\"><u>" + "https://tbtc.bitaps.com/" + tfTxId.getText() + "</u></FONT></HTML>"); if (!tfTxId.getText().equals("")) lblLink.setToolTipText("https://tbtc.bitaps.com/" + tfTxId.getText()); lblLink.setCursor(new Cursor(Cursor.HAND_CURSOR)); System.out.println("Direktlink zur Onlineanzeige: " + "https://tbtc.bitaps.com/" + tfTxId.getText()); System.out.println("Das aktuell verfuegbare Guthaben ist: " + kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); tfBalance.setText(kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); System.out.println("Aktuelle Empfangsadresse : " + kit.wallet().currentReceiveAddress()); tfStatus.setText("OP_RETURN gespeichert"); tfStatus.setBackground(Color.GREEN); } // do nothing }); btnClose.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { btnSendOpReturn.setEnabled(false); btnClose.setEnabled(false); btnStartKit.setEnabled(false); progressBarWait.setString("Das Programm wird beendet, bitte warten ..."); tfStatus.setText("Das Programm wird beendet, bitte warten ..."); progressBarWait.setStringPainted(true); progressBarWait.setVisible(true); progressBarWait.setIndeterminate(true); Thread thread = new Thread() { public void run() { System.out.println("btnClose laeuft im separaten Thread"); // stop kit try { Thread.sleep(1000); // 5 seconds to end } catch (InterruptedException e) { } if (kitIsRunning) { kit.stopAsync(); kit.awaitTerminated(); } localDateTimeEnd = LocalDateTime.now(); System.out.println("Das Programm endet jetzt"); System.out.println("Datum & Zeit am Start: " + localDateTimeStart.toString()); System.out.println("Datum & Zeit am Ende : " + localDateTimeEnd.toString()); System.exit(0); } }; thread.start(); } }); btnStartKit.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { // disable start button to prevent a second start btnStartKit.setEnabled(false); progressBarWait.setString("Das Wallet wird aktualisiert, bitte warten ..."); progressBarWait.setStringPainted(true); progressBarWait.setVisible(true); progressBarWait.setIndeterminate(true); if (kitIsRunning) { System.out.println("Das Wallet ist bereits gestartet"); return; } // actual date and time localDateTimeStart = LocalDateTime.now(); System.out.println("Lade ein HD-Wallet mit BitcoinJ im Bitcoin Testnet und erzeuge eine OP_RETURN Transaktion mit reduzierten Kosten\n"); System.out.println("Das Programm benutzt das BitcoinJ WalletAppKit\n"); System.out.println("Bitte benutzen Sie Java 11 und bitcoinj-core-0.15.6.jar fuer dieses Programm\n"); Thread thread = new Thread() { public void run() { System.out.println("btnStartKit laeuft im separaten Thread"); kit = new WalletAppKit(netParams, new File("."), filenameWallet); kit.setAutoSave(true); if (netParams == RegTestParams.get()) { kit.connectToLocalHost(); // für regtest notwendig } System.out.println("Das Wallet wurde geladen: " + filenameWallet); System.out.println("\nDas Wallet aktualisiert die Blockchain in der Datei " + filenameWallet + ".spvchain"); System.out.println("Bitte haben Sie eine bis drei Minuten Geduld"); kit.startAsync(); kit.awaitRunning(); while (!kit.isRunning()) { try { wait(1000); } catch (InterruptedException e) { e.printStackTrace(); } } // kit is running progressBarWait.setVisible(false); progressBarWait.setIndeterminate(false); kit.wallet().allowSpendingUnconfirmedTransactions(); // nur eigene gelder, daher erlaube ich das mal System.out.println("Das aktuell verfuegbare Guthaben ist: " + kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); tfBalance.setText(kit.wallet().getBalance().toFriendlyString() + (" = ") + kit.wallet().getBalance() + " Satoshi"); balance = kit.wallet().getBalance(); System.out.println("Aktuelle Empfangsadresse : " + kit.wallet().currentReceiveAddress()); System.out.println("Das Programm ist betriebsbereit und wartet auf den Einsatz"); kitIsRunning = true; tfStatus.setText("Das WalletAppKit laeuft"); btnSendOpReturn.setEnabled(true); } }; thread.start(); } }); tfOpReturn.addKeyListener(new KeyAdapter() { @Override public void keyReleased(KeyEvent e) { super.keyTyped(e); tfOpReturnRestrictLength(); } }); cbxExtendedOpReturn.addActionListener(new ActionListener() { @Override public void actionPerformed(ActionEvent actionEvent) { tfOpReturnRestrictLength(); } }); lblLink.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); String labelLinkText = lblLink.getText(); if (!labelLinkText.equals(labelLinkPreset)) { try { Desktop.getDesktop().browse(new URI("https://tbtc.bitaps.com/" + tfTxId.getText())); } catch (IOException ex) { ex.printStackTrace(); } catch (URISyntaxException ex) { ex.printStackTrace(); } } } }); } private void tfOpReturnRestrictLength() { // check if tfOpReturn has more characters than allowed // 1234567890123456789012345678901234567890 String str = tfOpReturn.getText(); int strLengthAllowed = 40; if (cbxExtendedOpReturn.isSelected() == true) { strLengthAllowed = 80; } if (str.length() > strLengthAllowed) { str = str.substring(0, strLengthAllowed); } tfOpReturn.setText(str); } private String bytesToHex(byte[] bytes) { StringBuffer result = new StringBuffer(); for (byte b : bytes) result.append(Integer.toString((b & 0xff) + 0x100, 16).substring(1)); return result.toString(); } private static String getActualDateReverse() { // provides the actual date and time in this format yyyy-MM-dd_HH-mm-ss e.g. 2020-03-16_10-27-15 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd_HH-mm-ss"); LocalDateTime today = LocalDateTime.now(); return formatter.format(today); } public static void main(String[] args) throws IOException, InterruptedException { JFrame frame = new JFrame("Erzeuge eine OP_RETURN-Transaktion in der Bitcoin Blockchain"); RedirectedFrame outputFrameErrors = new RedirectedFrame("Log Frame", true, false, true, "BitcoinJ_CreateOpReturn_Logfile_" + getActualDateReverse() + ".txt", 750, 650, JFrame.DO_NOTHING_ON_CLOSE); RedirectedFrame outputFrameOutput = new RedirectedFrame("Output Frame", false, true, true, "BitcoinJ_CreateOpReturn_Output_" + getActualDateReverse() + ".txt", 700, 600, JFrame.DO_NOTHING_ON_CLOSE); frame.setContentPane(new BitcoinJCreateAnOp_Return().mainPanel); frame.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); frame.pack(); frame.setSize(730, 380); frame.setVisible(true); } private JPanel mainPanel; private JButton btnSendOpReturn; private JTextField tfBalance; private JTextField tfTxId; private JTextField tfStatus; private JButton btnClose; private JButton btnStartKit; private JProgressBar progressBarWait; private JTextField tfOpReturn; private JCheckBox cbxExtendedOpReturn; private JLabel lblLink; } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 |
<?xml version="1.0" encoding="UTF-8"?> <form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="BitcoinJCreateAnOp_Return"> <grid id="27dc6" binding="mainPanel" layout-manager="GridLayoutManager" row-count="17" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1"> <margin top="10" left="10" bottom="10" right="10"/> <constraints> <xy x="20" y="20" width="376" height="613"/> </constraints> <properties/> <border type="none"/> <children> <component id="e0fd9" class="javax.swing.JSeparator"> <constraints> <grid row="2" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="f1a03" class="javax.swing.JTextField" binding="tfOpReturn"> <constraints> <grid row="6" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="true"/> </properties> </component> <component id="4d2b1" class="javax.swing.JLabel"> <constraints> <grid row="6" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="OP_RETURN:"/> </properties> </component> <component id="93929" class="javax.swing.JSeparator"> <constraints> <grid row="7" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="c2ef" class="javax.swing.JSeparator"> <constraints> <grid row="9" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="f9349" class="javax.swing.JTextField" binding="tfTxId"> <constraints> <grid row="10" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> <enabled value="true"/> </properties> </component> <component id="d1077" class="javax.swing.JLabel"> <constraints> <grid row="10" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="TxId:"/> </properties> </component> <component id="49fa" class="javax.swing.JSeparator"> <constraints> <grid row="11" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="999d5" class="javax.swing.JLabel"> <constraints> <grid row="14" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Status:"/> </properties> </component> <component id="82258" class="javax.swing.JButton" binding="btnClose"> <constraints> <grid row="16" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Ende des Programms"/> </properties> </component> <component id="7b715" class="javax.swing.JButton" binding="btnStartKit"> <constraints> <grid row="0" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="starte das Wallet"/> </properties> </component> <component id="f1b5f" class="javax.swing.JTextField" binding="tfBalance"> <constraints> <grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="9855f" class="javax.swing.JLabel"> <constraints> <grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Guthaben:"/> </properties> </component> <component id="6516f" class="javax.swing.JSeparator"> <constraints> <grid row="4" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="18a4f" class="javax.swing.JSeparator"> <constraints> <grid row="15" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> <component id="e8ac2" class="javax.swing.JTextField" binding="tfStatus"> <constraints> <grid row="14" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="8" fill="1" indent="0" use-parent-layout="false"> <preferred-size width="150" height="-1"/> </grid> </constraints> <properties> <editable value="false"/> </properties> </component> <component id="e9f88" class="javax.swing.JProgressBar" binding="progressBarWait"> <constraints> <grid row="1" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"> <minimum-size width="-1" height="20"/> </grid> </constraints> <properties/> </component> <component id="6a45a" class="javax.swing.JButton" binding="btnSendOpReturn"> <constraints> <grid row="8" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/> </constraints> <properties> <enabled value="false"/> <text value="senden einer OP-Return-Transaktion"/> </properties> </component> <component id="98ce0" class="javax.swing.JCheckBox" binding="cbxExtendedOpReturn"> <constraints> <grid row="5" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="OP_RETURN mit 80 statt 40 Zeichen erlauben"/> </properties> </component> <component id="cb406" class="javax.swing.JLabel" binding="lblLink"> <constraints> <grid row="12" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="noch kein Link vorhanden"/> </properties> </component> <component id="141f" class="javax.swing.JLabel"> <constraints> <grid row="12" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/> </constraints> <properties> <text value="Link:"/> </properties> </component> <component id="ceeee" class="javax.swing.JSeparator"> <constraints> <grid row="13" column="1" row-span="1" col-span="1" vsize-policy="6" hsize-policy="6" anchor="0" fill="3" indent="0" use-parent-layout="false"/> </constraints> <properties/> </component> </children> </grid> </form> |