diff --git a/react/src/actions/actions/cli.js b/react/src/actions/actions/cli.js index c770295..1591b74 100644 --- a/react/src/actions/actions/cli.js +++ b/react/src/actions/actions/cli.js @@ -3,14 +3,18 @@ import { CLI } from '../storeType'; import Config from '../../config'; import Store from '../../store'; -export function shepherdCliPromise(mode, chain, cmd) { - const _payload = { +export function shepherdCliPromise(mode, chain, cmd, params) { + let _payload = { mode, chain, cmd, token: Config.token, }; + if (params) { + _payload.params = params; + } + return new Promise((resolve, reject) => { fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`, { method: 'POST', diff --git a/react/src/actions/actions/electrum.js b/react/src/actions/actions/electrum.js index 580c72c..584392c 100644 --- a/react/src/actions/actions/electrum.js +++ b/react/src/actions/actions/electrum.js @@ -334,4 +334,36 @@ export function shepherdElectrumBip39Keys(seed, match, addressdepth, accounts) { resolve(json); }); }); +} + +// split test +export function shepherdElectrumSplitUtxoPromise(payload) { + console.warn(payload); + + return new Promise((resolve, reject) => { + return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/electrum/createrawtx-test`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + payload, + token: Config.token, + }), + }) + .catch((error) => { + console.log(error); + Store.dispatch( + triggerToaster( + 'shepherdElectrumSendPromise', + 'Error', + 'error' + ) + ); + }) + .then(response => response.json()) + .then(json => { + resolve(json); + }); + }); } \ No newline at end of file diff --git a/react/src/components/dashboard/tools/tools.js b/react/src/components/dashboard/tools/tools.js index ee1090b..7d36ddf 100644 --- a/react/src/components/dashboard/tools/tools.js +++ b/react/src/components/dashboard/tools/tools.js @@ -11,6 +11,8 @@ import { shepherdToolsSeedToWif, shepherdToolsWifToKP, shepherdElectrumListunspent, + shepherdCliPromise, + shepherdElectrumSplitUtxoPromise, } from '../../../actions/actionCreators'; import Store from '../../../store'; import QRCode from 'qrcode.react'; @@ -43,6 +45,12 @@ class Tools extends React.Component { balanceAddr: '', balanceCoin: '', balanceResult: null, + utxoSplitCoin: 'BEER', + utxoSplitList: null, + utxoSplitPairsCount: 1, + utxoSplitPairs: '10,0.002', + utxoSplitRawtx: null, + utxoSplitPushResult: null, }; this.updateInput = this.updateInput.bind(this); this.updateSelectedCoin = this.updateSelectedCoin.bind(this); @@ -56,6 +64,114 @@ class Tools extends React.Component { this.getBalanceAlt = this.getBalanceAlt.bind(this); this.getUtxos = this.getUtxos.bind(this); this.toggleS2wIsIguana = this.toggleS2wIsIguana.bind(this); + this.getUtxoSplit = this.getUtxoSplit.bind(this); + this.splitUtxo = this.splitUtxo.bind(this); + } + + splitUtxo() { + let largestUTXO = { amount: 0 }; + + for (let i = 0; i < this.state.utxoSplitList.length; i++) { + if (Number(this.state.utxoSplitList[i].amount) > Number(largestUTXO.amount)) { + largestUTXO = this.state.utxoSplitList[i]; + } + } + + console.warn(`largest utxo ${largestUTXO.amount}`); + console.warn(`largest utxo ${largestUTXO.amount}`); + + const utxoSize = largestUTXO.amount; + const targetSizes = this.state.utxoSplitPairs.split(','); + const wif = ''; + const address = ''; + let totalOutSize = 0; + let _targets = []; + + console.warn(`total utxos ${this.state.utxoSplitPairsCount * targetSizes.length}`); + console.warn(`total pairs ${this.state.utxoSplitPairsCount}`); + console.warn(`utxo size ${utxoSize}`); + console.warn(`utxo sizes`); + console.warn(targetSizes); + + for (let i = 0; i < this.state.utxoSplitPairsCount; i++) { + console.warn(`vout ${i} ${targetSizes[0]}`); + console.warn(`vout ${i + 1} ${targetSizes[1]}`); + _targets.push(Number(targetSizes[0]) * 100000000); + _targets.push(Number(targetSizes[1]) * 100000000); + totalOutSize += Number(targetSizes[0]) + Number(targetSizes[1]); + } + + console.warn(`total out size ${totalOutSize}`); + console.warn(`change ${utxoSize - totalOutSize}`); + + const payload = { + wif, + network: 'komodo', + targets: _targets, + utxo: [largestUTXO], + changeAddress: address, + outputAddress: address, + change: Math.floor(Number(utxoSize - totalOutSize) * 100000000) - 10000, // 10k sat fee + }; + + shepherdElectrumSplitUtxoPromise(payload) + .then((res) => { + console.warn(res); + + if (res.msg === 'success') { + //this.setState({ + // utxoSplitRawtx: res.result, + //}); + + shepherdCliPromise(null, this.state.utxoSplitCoin, 'sendrawtransaction', [res.result]) + .then((res) => { + console.warn(res); + + if (!res.error) { + this.setState({ + utxoSplitPushResult: res.result, + }); + } else { + Store.dispatch( + triggerToaster( + res.result, + 'Split UTXO error', + 'error' + ) + ); + } + }); + } else { + Store.dispatch( + triggerToaster( + res.result, + 'Split UTXO error', + 'error' + ) + ); + } + }); + } + + getUtxoSplit() { + shepherdCliPromise(null, this.state.utxoSplitCoin, 'listunspent') + .then((res) => { + console.warn(res); + + if (!res.error) { + this.setState({ + utxoSplitList: res.result, + }); + } else { + Store.dispatch( + triggerToaster( + res.result, + 'Get UTXO error', + 'error' + ) + ); + } + }); } getUtxos() { @@ -325,6 +441,53 @@ class Tools extends React.Component { ); } + renderUTXOSplitResponse() { + const _utxos = this.state.utxoSplitList; + let _items = []; + console.warn(_utxos); + + if (_utxos && + _utxos.length) { + for (let i = 0; i < _utxos.length; i++) { + _items.push( + + { _utxos[i].amount } + { _utxos[i].address } + { _utxos[i].confirmations } + { _utxos[i].vout } + { _utxos[i].txid } + + ); + } + } + + return ( + + + + + + + + + + + + { _items } + + + + + + + + + + +
AmountAddressConfirmationsVoutTxID
AmountAddressConfirmationsVoutTxID
+ ); + } + render() { return (
@@ -368,6 +531,11 @@ class Tools extends React.Component { onClick={ () => this.setActiveSection('utxo') }> UTXO * +
* Electrum

@@ -758,6 +926,85 @@ class Tools extends React.Component { } } + { this.state.activeSection === 'utxo-split' && +
+
+ + +
+
+ +
+
+
+ + +
+
+ + +
+
+ +
+ { this.state.utxoSplitList && +
+ { /*this.renderUTXOSplitResponse()*/ } + Total UTXO: { this.state.utxoSplitList.length } +
+ } + { this.state.utxoSplitRawtx && +
+ Rawtx:
{ this.state.utxoSplitRawtx }
+
+ } + { this.state.utxoSplitPushResult && +
+ TXID:
{ this.state.utxoSplitPushResult }
+
+ } +
+ }