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