Changeset View
Changeset View
Standalone View
Standalone View
web/cashtab/src/hooks/useBCH.js
| Show First 20 Lines • Show All 378 Lines • ▼ Show 20 Lines | const getSlpBalancesAndUtxos = hydratedUtxoDetails => { | ||||
| } | } | ||||
| // Prevent app from treating slpUtxos as nonSlpUtxos | // Prevent app from treating slpUtxos as nonSlpUtxos | ||||
| // Must enforce === false as api will occasionally return utxo.isValid === null | // Must enforce === false as api will occasionally return utxo.isValid === null | ||||
| // Do not classify utxos with 546 satoshis as nonSlpUtxos as a precaution | // Do not classify utxos with 546 satoshis as nonSlpUtxos as a precaution | ||||
| // Do not classify any utxos that include token information as nonSlpUtxos | // Do not classify any utxos that include token information as nonSlpUtxos | ||||
| const nonSlpUtxos = hydratedUtxos.filter( | const nonSlpUtxos = hydratedUtxos.filter( | ||||
| utxo => | utxo => | ||||
| utxo.isValid === false && utxo.value !== 546 && !utxo.tokenName, | utxo.isValid === false && | ||||
| utxo.value !== currency.etokenSats && | |||||
| !utxo.tokenName, | |||||
| ); | ); | ||||
| // To be included in slpUtxos, the utxo must | // To be included in slpUtxos, the utxo must | ||||
| // have utxo.isValid = true | // have utxo.isValid = true | ||||
| // If utxo has a utxo.tokenQty field, i.e. not a minting baton, then utxo.tokenQty !== '0' | // If utxo has a utxo.tokenQty field, i.e. not a minting baton, then utxo.tokenQty !== '0' | ||||
| const slpUtxos = hydratedUtxos.filter( | const slpUtxos = hydratedUtxos.filter( | ||||
| utxo => utxo.isValid && !(utxo.tokenQty === '0'), | utxo => utxo.isValid && !(utxo.tokenQty === '0'), | ||||
| ); | ); | ||||
| ▲ Show 20 Lines • Show All 133 Lines • ▼ Show 20 Lines | const createToken = async (BCH, wallet, feeInSatsPerByte, configObj) => { | ||||
| // add input with txid and index of vout | // add input with txid and index of vout | ||||
| transactionBuilder.addInput(txid, vout); | transactionBuilder.addInput(txid, vout); | ||||
| inputUtxos.push(utxo); | inputUtxos.push(utxo); | ||||
| txFee = calcFee(BCH, inputUtxos, 3, feeInSatsPerByte); | txFee = calcFee(BCH, inputUtxos, 3, feeInSatsPerByte); | ||||
| if ( | if ( | ||||
| originalAmount | originalAmount | ||||
| .minus(new BigNumber(currency.dustSats)) | .minus(new BigNumber(currency.etokenSats)) | ||||
| .minus(new BigNumber(txFee)) | .minus(new BigNumber(txFee)) | ||||
| .gte(0) | .gte(0) | ||||
| ) { | ) { | ||||
| break; | break; | ||||
| } | } | ||||
| } | } | ||||
| // amount to send back to the remainder address. | // amount to send back to the remainder address. | ||||
| const remainder = originalAmount | const remainder = originalAmount | ||||
| .minus(new BigNumber(currency.dustSats)) | .minus(new BigNumber(currency.etokenSats)) | ||||
| .minus(new BigNumber(txFee)); | .minus(new BigNumber(txFee)); | ||||
| if (remainder.lt(0)) { | if (remainder.lt(0)) { | ||||
| const error = new Error(`Insufficient funds`); | const error = new Error(`Insufficient funds`); | ||||
| error.code = SEND_BCH_ERRORS.INSUFFICIENT_FUNDS; | error.code = SEND_BCH_ERRORS.INSUFFICIENT_FUNDS; | ||||
| throw error; | throw error; | ||||
| } | } | ||||
| // Generate the OP_RETURN entry for an SLP GENESIS transaction. | // Generate the OP_RETURN entry for an SLP GENESIS transaction. | ||||
| const script = BCH.SLP.TokenType1.generateGenesisOpReturn( | const script = BCH.SLP.TokenType1.generateGenesisOpReturn( | ||||
| configObj, | configObj, | ||||
| ); | ); | ||||
| // OP_RETURN needs to be the first output in the transaction. | // OP_RETURN needs to be the first output in the transaction. | ||||
| transactionBuilder.addOutput(script, 0); | transactionBuilder.addOutput(script, 0); | ||||
| // add output w/ address and amount to send | // add output w/ address and amount to send | ||||
| transactionBuilder.addOutput(CREATION_ADDR, currency.dustSats); | transactionBuilder.addOutput(CREATION_ADDR, currency.etokenSats); | ||||
| // Send change to own address | // Send change to own address | ||||
| if (remainder.gte(new BigNumber(currency.dustSats))) { | if (remainder.gte(new BigNumber(currency.etokenSats))) { | ||||
| transactionBuilder.addOutput( | transactionBuilder.addOutput( | ||||
| CREATION_ADDR, | CREATION_ADDR, | ||||
| parseInt(remainder), | parseInt(remainder), | ||||
| ); | ); | ||||
| } | } | ||||
| // Sign the transactions with the HD node. | // Sign the transactions with the HD node. | ||||
| for (let i = 0; i < inputUtxos.length; i++) { | for (let i = 0; i < inputUtxos.length; i++) { | ||||
| ▲ Show 20 Lines • Show All 139 Lines • ▼ Show 20 Lines | ) => { | ||||
| const slpData = slpSendObj.script; | const slpData = slpSendObj.script; | ||||
| // Add OP_RETURN as first output. | // Add OP_RETURN as first output. | ||||
| transactionBuilder.addOutput(slpData, 0); | transactionBuilder.addOutput(slpData, 0); | ||||
| // Send dust transaction representing tokens being sent. | // Send dust transaction representing tokens being sent. | ||||
| transactionBuilder.addOutput( | transactionBuilder.addOutput( | ||||
| BCH.SLP.Address.toLegacyAddress(tokenReceiverAddress), | BCH.SLP.Address.toLegacyAddress(tokenReceiverAddress), | ||||
| 546, | currency.etokenSats, | ||||
| ); | ); | ||||
| // Return any token change back to the sender. | // Return any token change back to the sender. | ||||
| if (slpSendObj.outputs > 1) { | if (slpSendObj.outputs > 1) { | ||||
| // Change goes back to where slp utxo came from | // Change goes back to where slp utxo came from | ||||
| transactionBuilder.addOutput( | transactionBuilder.addOutput( | ||||
| BCH.SLP.Address.toLegacyAddress( | BCH.SLP.Address.toLegacyAddress( | ||||
| tokenUtxosBeingSpent[0].address, | tokenUtxosBeingSpent[0].address, | ||||
| ), | ), | ||||
| 546, | currency.etokenSats, | ||||
| ); | ); | ||||
| } | } | ||||
| // get byte count to calculate fee. paying 1 sat | // get byte count to calculate fee. paying 1 sat | ||||
| // Note: This may not be totally accurate. Just guessing on the byteCount size. | // Note: This may not be totally accurate. Just guessing on the byteCount size. | ||||
| const txFee = calcFee( | const txFee = calcFee( | ||||
| BCH, | BCH, | ||||
| tokenUtxosBeingSpent, | tokenUtxosBeingSpent, | ||||
| 5, | 5, | ||||
| 1.1 * currency.defaultFee, | 1.1 * currency.defaultFee, | ||||
| ); | ); | ||||
| // amount to send back to the sending address. It's the original amount - 1 sat/byte for tx size | // amount to send back to the sending address. It's the original amount - 1 sat/byte for tx size | ||||
| const remainder = originalAmount - txFee - 546 * 2; | const remainder = originalAmount - txFee - currency.etokenSats * 2; | ||||
| if (remainder < 1) { | if (remainder < 1) { | ||||
| throw new Error('Selected UTXO does not have enough satoshis'); | throw new Error('Selected UTXO does not have enough satoshis'); | ||||
| } | } | ||||
| // Last output: send the BCH change back to the wallet. | // Last output: send the BCH change back to the wallet. | ||||
| // Send it back from whence it came | // Send it back from whence it came | ||||
| transactionBuilder.addOutput( | transactionBuilder.addOutput( | ||||
| ▲ Show 20 Lines • Show All 253 Lines • Show Last 20 Lines | |||||