|
250 | 250 | console.log('DEBUG Amount:', amount);
|
251 | 251 |
|
252 | 252 | let output = { satoshis, address };
|
| 253 | + let draft = await draftWalletTx(utxos, inputs, output); |
| 254 | + |
| 255 | + amount = output.satoshis / SATS; |
| 256 | + $('[data-id=send-dust]').textContent = draft.tx.feeTarget; |
| 257 | + $('[data-id=send-amount]').textContent = amount.toFixed(8); |
| 258 | + |
| 259 | + let signedTx = await dashTx.legacy.finalizePresorted(draft.tx); |
| 260 | + console.log('DEBUG signed tx', signedTx); |
| 261 | + { |
| 262 | + let amountStr = amount.toFixed(4); |
| 263 | + let confirmed = window.confirm(`Really send ${amountStr} to ${address}?`); |
| 264 | + if (!confirmed) { |
| 265 | + return; |
| 266 | + } |
| 267 | + } |
| 268 | + void (await rpc('sendrawtransaction', signedTx.transaction)); |
| 269 | + void (await commitWalletTx(signedTx)); |
| 270 | + }; |
| 271 | + |
| 272 | + async function draftWalletTx(utxos, inputs, output) { |
253 | 273 | let draftTx = dashTx.legacy.draftSingleOutput({ utxos, inputs, output });
|
254 | 274 | console.log('DEBUG draftTx', draftTx);
|
255 | 275 |
|
|
286 | 306 |
|
287 | 307 | draftTx.inputs.sort(DashTx.sortInputs);
|
288 | 308 | draftTx.outputs.sort(DashTx.sortOutputs);
|
289 |
| - amount = output.satoshis / SATS; |
290 |
| - |
291 |
| - $('[data-id=send-dust]').textContent = draftTx.feeTarget; |
292 |
| - $('[data-id=send-amount]').textContent = amount.toFixed(8); |
293 | 309 |
|
294 |
| - let tx = await dashTx.legacy.finalizePresorted(draftTx); |
295 |
| - console.log('DEBUG signed tx', tx); |
296 |
| - { |
297 |
| - let amountStr = amount.toFixed(4); |
298 |
| - let confirmed = window.confirm(`Really send ${amountStr} to ${address}?`); |
299 |
| - if (!confirmed) { |
300 |
| - return; |
301 |
| - } |
302 |
| - } |
303 |
| - void (await rpc('sendrawtransaction', tx.transaction)); |
| 310 | + return { |
| 311 | + tx: draftTx, |
| 312 | + change: changeOutput, |
| 313 | + }; |
| 314 | + } |
304 | 315 |
|
| 316 | + async function commitWalletTx(signedTx) { |
305 | 317 | let updatedAddrs = [];
|
306 |
| - for (let input of tx.inputs) { |
| 318 | + for (let input of signedTx.inputs) { |
307 | 319 | updatedAddrs.push(input.address);
|
308 | 320 | let knownSpent = spentAddrs.includes(input.address);
|
309 | 321 | if (!knownSpent) {
|
|
315 | 327 | delete deltasMap[input.address];
|
316 | 328 | dbSet(input.address, null);
|
317 | 329 | }
|
318 |
| - for (let output of tx.outputs) { |
| 330 | + for (let output of signedTx.outputs) { |
319 | 331 | updatedAddrs.push(output.address);
|
320 | 332 | removeElement(addresses, output.address);
|
321 | 333 | removeElement(receiveAddrs, output.address);
|
322 | 334 | removeElement(changeAddrs, output.address);
|
323 | 335 | delete deltasMap[output.address];
|
324 | 336 | dbSet(output.address, null);
|
325 | 337 | }
|
326 |
| - |
327 | 338 | await updateDeltas(updatedAddrs);
|
| 339 | + |
| 340 | + let txid = await DashTx.getId(signedTx.transaction); |
| 341 | + for (let input of signedTx.inputs) { |
| 342 | + let coin = selectCoin(input.address, input.txid, input.outputIndex); |
| 343 | + if (!coin) { |
| 344 | + continue; |
| 345 | + } |
| 346 | + coin.reserved = true; // mark as spent-ish |
| 347 | + } |
| 348 | + for (let i = 0; i < signedTx.outputs.length; i += 1) { |
| 349 | + let output = signedTx.outputs[i]; |
| 350 | + let info = deltasMap[output.address]; |
| 351 | + if (!info) { |
| 352 | + info = { balance: 0, deltas: [] }; |
| 353 | + deltasMap[output.address] = info; |
| 354 | + } |
| 355 | + let memCoin = selectCoin(output.address, txid, i); |
| 356 | + if (!memCoin) { |
| 357 | + memCoin = { |
| 358 | + address: output.address, |
| 359 | + satoshis: output.satoshis, |
| 360 | + txid: txid, |
| 361 | + index: i, |
| 362 | + }; |
| 363 | + info.deltas.push(memCoin); |
| 364 | + } |
| 365 | + } |
| 366 | + |
328 | 367 | renderAddresses();
|
329 | 368 | renderCoins();
|
330 |
| - }; |
| 369 | + } |
331 | 370 |
|
332 | 371 | function renderAddresses() {
|
333 | 372 | $('[data-id=spent-count]').textContent = spentAddrs.length;
|
|
580 | 619 | $('[data-id=cj-balance]').textContent = cjAmount.toFixed(8);
|
581 | 620 | }
|
582 | 621 |
|
583 |
| - App.denominateCoins = function (event) { |
| 622 | + App.denominateCoins = async function (event) { |
584 | 623 | console.log('DENOMINATE COINS');
|
585 | 624 | event.preventDefault();
|
586 | 625 |
|
|
636 | 675 | }
|
637 | 676 | slot.need -= 1;
|
638 | 677 |
|
639 |
| - // TODO DashTx. |
| 678 | + // TODO DashTx. |
640 | 679 | console.log('Found coins to make denom', slot.denom, coins);
|
| 680 | + let roundRobiner = createRoundRobin(slots, slot); |
| 681 | + // roundRobiner(); |
641 | 682 |
|
642 |
| - if (slot.need >= 1) { |
643 |
| - // round-robin same priority |
644 |
| - slots.push(slot); |
645 |
| - } |
| 683 | + let address = receiveAddrs.shift(); |
| 684 | + let satoshis = slot.denom; |
| 685 | + let output = { satoshis, address }; |
| 686 | + |
| 687 | + void (await confirmAndBroadcastAndCompleteTx(coins, output).then( |
| 688 | + roundRobiner, |
| 689 | + )); |
646 | 690 | }
|
647 | 691 | }
|
648 | 692 | };
|
649 | 693 |
|
| 694 | + function createRoundRobin(slots, slot) { |
| 695 | + return function () { |
| 696 | + if (slot.need >= 1) { |
| 697 | + // round-robin same priority |
| 698 | + slots.push(slot); |
| 699 | + } |
| 700 | + }; |
| 701 | + } |
| 702 | + |
| 703 | + async function confirmAndBroadcastAndCompleteTx(inputs, output) { |
| 704 | + let utxos = null; |
| 705 | + let draft = await draftWalletTx(utxos, inputs, output); |
| 706 | + |
| 707 | + let signedTx = await dashTx.legacy.finalizePresorted(draft.tx); |
| 708 | + { |
| 709 | + console.log('DEBUG confirming signed tx', signedTx); |
| 710 | + let amount = output.satoshis / SATS; |
| 711 | + let amountStr = amount.toFixed(4); |
| 712 | + let confirmed = window.confirm( |
| 713 | + `Really send ${amountStr} to ${output.address}?`, |
| 714 | + ); |
| 715 | + if (!confirmed) { |
| 716 | + return; |
| 717 | + } |
| 718 | + } |
| 719 | + void (await rpc('sendrawtransaction', signedTx.transaction)); |
| 720 | + void (await commitWalletTx(signedTx)); |
| 721 | + } |
| 722 | + |
650 | 723 | function groupSlotsByPriorityAndAmount(slots) {
|
651 | 724 | let priorityGroups = {};
|
652 | 725 | for (let slot of slots) {
|
|
796 | 869 | continue;
|
797 | 870 | }
|
798 | 871 |
|
| 872 | + console.log('DEBUG denom', denom, coin); |
799 | 873 | denomsMap[denom][coin.address] = coin;
|
800 | 874 | }
|
801 | 875 | }
|
|
812 | 886 | await init();
|
813 | 887 | siftDenoms();
|
814 | 888 | renderCashDrawer();
|
| 889 | + App.syncCashDrawer(); |
815 | 890 | }
|
816 | 891 |
|
817 | 892 | main().catch(function (err) {
|
|
0 commit comments