diff --git a/web/cashtab/src/components/Send/SendToken.js b/web/cashtab/src/components/Send/SendToken.js
--- a/web/cashtab/src/components/Send/SendToken.js
+++ b/web/cashtab/src/components/Send/SendToken.js
@@ -1,10 +1,10 @@
import React, { useState, useEffect } from 'react';
import { WalletContext } from '../../utils/context';
-import { Alert, Form, notification, message } from 'antd';
+import { Form, notification, message } from 'antd';
import { CashSpin, CashSpinIcon } from '../Common/CustomSpinner';
import { Row, Col } from 'antd';
import Paragraph from 'antd/lib/typography/Paragraph';
-import { SecondaryButton } from '../Common/PrimaryButton';
+import PrimaryButton, { SecondaryButton } from '../Common/PrimaryButton';
import { CashLoader } from '../Common/CustomIcons';
import {
FormItemWithMaxAddon,
@@ -285,9 +285,11 @@
{apiError && }
>
) : (
-
+ submit()}
+ >
Send {token.info.tokenName}
-
+
)}
{apiError && (
@@ -299,14 +301,6 @@
)}
-
diff --git a/web/cashtab/src/hooks/useBCH.js b/web/cashtab/src/hooks/useBCH.js
--- a/web/cashtab/src/hooks/useBCH.js
+++ b/web/cashtab/src/hooks/useBCH.js
@@ -128,50 +128,50 @@
// Examples of slpUtxo
/*
- Genesis transaction:
- {
- address: "bitcoincash:qrhzv5t79e2afc3rdutcu0d3q20gl7ul3ue58whah6"
- decimals: 9
- height: 617564
- isValid: true
- satoshis: 546
- tokenDocumentHash: ""
- tokenDocumentUrl: "developer.bitcoin.com"
- tokenId: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
- tokenName: "PiticoLaunch"
- tokenTicker: "PTCL"
- tokenType: 1
- tx_hash: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
- tx_pos: 2
- txid: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
- utxoType: "minting-baton"
- value: 546
- vout: 2
- }
+ Genesis transaction:
+ {
+ address: "bitcoincash:qrhzv5t79e2afc3rdutcu0d3q20gl7ul3ue58whah6"
+ decimals: 9
+ height: 617564
+ isValid: true
+ satoshis: 546
+ tokenDocumentHash: ""
+ tokenDocumentUrl: "developer.bitcoin.com"
+ tokenId: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
+ tokenName: "PiticoLaunch"
+ tokenTicker: "PTCL"
+ tokenType: 1
+ tx_hash: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
+ tx_pos: 2
+ txid: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
+ utxoType: "minting-baton"
+ value: 546
+ vout: 2
+ }
- Send transaction:
- {
- address: "bitcoincash:qrhzv5t79e2afc3rdutcu0d3q20gl7ul3ue58whah6"
- decimals: 9
- height: 655115
- isValid: true
- satoshis: 546
- tokenDocumentHash: ""
- tokenDocumentUrl: "developer.bitcoin.com"
- tokenId: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
- tokenName: "PiticoLaunch"
- tokenQty: 1.123456789
- tokenTicker: "PTCL"
- tokenType: 1
- transactionType: "send"
- tx_hash: "dea400f963bc9f51e010f88533010f8d1f82fc2bcc485ff8500c3a82b25abd9e"
- tx_pos: 1
- txid: "dea400f963bc9f51e010f88533010f8d1f82fc2bcc485ff8500c3a82b25abd9e"
- utxoType: "token"
- value: 546
- vout: 1
- }
- */
+ Send transaction:
+ {
+ address: "bitcoincash:qrhzv5t79e2afc3rdutcu0d3q20gl7ul3ue58whah6"
+ decimals: 9
+ height: 655115
+ isValid: true
+ satoshis: 546
+ tokenDocumentHash: ""
+ tokenDocumentUrl: "developer.bitcoin.com"
+ tokenId: "6c41f244676ecfcbe3b4fabee2c72c2dadf8d74f8849afabc8a549157db69199"
+ tokenName: "PiticoLaunch"
+ tokenQty: 1.123456789
+ tokenTicker: "PTCL"
+ tokenType: 1
+ transactionType: "send"
+ tx_hash: "dea400f963bc9f51e010f88533010f8d1f82fc2bcc485ff8500c3a82b25abd9e"
+ tx_pos: 1
+ txid: "dea400f963bc9f51e010f88533010f8d1f82fc2bcc485ff8500c3a82b25abd9e"
+ utxoType: "token"
+ value: 546
+ vout: 1
+ }
+ */
} else {
token = {};
token.info = slpUtxo;
@@ -220,27 +220,17 @@
slpBalancesAndUtxos,
{ tokenId, amount, tokenReceiverAddress },
) => {
+ // Handle error of user having no BCH
+ if (slpBalancesAndUtxos.nonSlpUtxos.length === 0) {
+ throw new Error(
+ `You need some ${currency.ticker} to send ${currency.tokenTicker}`,
+ );
+ }
const largestBchUtxo = slpBalancesAndUtxos.nonSlpUtxos.reduce(
(previous, current) =>
previous.satoshis > current.satoshis ? previous : current,
);
- // console.log(`largestBchUtxo`, largestBchUtxo);
- // this is big enough? might need to combine utxos
- // TODO improve utxo selection
- /*
- {
- address: "bitcoincash:qrcl220pxeec78vnchwyh6fsdyf60uv9tcynw3u2ev"
- height: 0
- isValid: false
- satoshis: 1510
- tx_hash: "faef4d8bf56353702e29c22f2aace970ddbac617144456d509e23e1192b320a8"
- tx_pos: 0
- txid: "faef4d8bf56353702e29c22f2aace970ddbac617144456d509e23e1192b320a8"
- value: 1510
- vout: 0
- wif: "removed for git potential"
- }
- */
+
const bchECPair = BCH.ECPair.fromWIF(largestBchUtxo.wif);
const tokenUtxos = slpBalancesAndUtxos.slpUtxos.filter(
(utxo, index) => {
@@ -277,19 +267,11 @@
let finalTokenAmountSent = new BigNumber(0);
let tokenAmountBeingSentToAddress = new BigNumber(amount);
- /*
- console.log(`tokenAmountBeingSentToAddress`, tokenAmountBeingSentToAddress);
- console.log(
- `tokenAmountBeingSentToAddress.toString()`,
- tokenAmountBeingSentToAddress.toString()
- );
- */
+
let tokenUtxosBeingSpent = [];
for (let i = 0; i < tokenUtxos.length; i++) {
finalTokenAmountSent = finalTokenAmountSent.plus(
- new BigNumber(tokenUtxos[i].tokenQty).div(
- Math.pow(10, tokenUtxos[i].decimals),
- ),
+ new BigNumber(tokenUtxos[i].tokenQty),
);
transactionBuilder.addInput(
tokenUtxos[i].tx_hash,
@@ -301,16 +283,6 @@
}
}
- // Run a test function to mock the outputs generated by BCH.SLP.TokenType1.generateSendOpReturn below
- slpDebug(
- tokenUtxosBeingSpent,
- tokenAmountBeingSentToAddress.toString(),
- );
-
- // Generate the OP_RETURN code.
- console.log(`Debug output`);
- console.log(`tokenUtxos`, tokenUtxosBeingSpent);
- console.log(`sendQty`, tokenAmountBeingSentToAddress.toString());
const slpSendObj = BCH.SLP.TokenType1.generateSendOpReturn(
tokenUtxosBeingSpent,
tokenAmountBeingSentToAddress.toString(),
@@ -395,8 +367,6 @@
// END transaction construction.
- // Broadcast transaction to the network
-
const txidStr = await BCH.RawTransactions.sendRawTransaction([hex]);
if (txidStr && txidStr[0]) {
console.log(`${currency.tokenTicker} txid`, txidStr[0]);
@@ -408,143 +378,12 @@
} else {
link = `${currency.blockExplorerUrlTestnet}/tx/${txidStr}`;
}
+
//console.log(`link`, link);
return link;
};
- const slpDebug = (tokenUtxos, sendQty) => {
- console.log(`slpDebug test called with`);
- console.log(`tokenUtxos`, tokenUtxos);
- console.log(`sendQty`, sendQty);
- try {
- //const tokenId = tokenUtxos[0].tokenId;
- const decimals = tokenUtxos[0].decimals;
-
- // Joey patch to do
- // totalTokens must be a big number accounting for decimals
- // sendQty must be the same
- /* From slp-sdk
-
- amount = new BigNumber(amount).times(10 ** tokenDecimals) // Don't forget to account for token precision
-
-
- This is analagous to sendQty here
- */
- const sendQtyBig = new BigNumber(sendQty).times(10 ** decimals);
-
- // Calculate the total amount of tokens owned by the wallet.
- //let totalTokens = 0;
- //for (let i = 0; i < tokenUtxos.length; i++) totalTokens += tokenUtxos[i].tokenQty;
-
- // Calculate total amount of tokens using Big Number throughout
- /*
- let totalTokens = new BigNumber(0);
- for (let i = 0; i < tokenUtxos.length; i++) {
- console.log(`tokenQty normal`, tokenUtxos[i].tokenQty);
- const thisTokenQty = new BigNumber(tokenUtxos[i].tokenQty);
- totalTokens.plus(thisTokenQty);
- }
- totalTokens.times(10 ** decimals);
- */
- let totalTokens = tokenUtxos.reduce((tot, txo) => {
- return tot.plus(
- new BigNumber(txo.tokenQty).times(10 ** decimals),
- );
- }, new BigNumber(0));
-
- console.log(`totalTokens`, totalTokens);
- //test
- //totalTokens = new BigNumber(totalTokens).times(10 ** decimals);
-
- console.log(`sendQtyBig`, sendQtyBig);
- const change = totalTokens.minus(sendQtyBig);
- console.log(`change`, change);
-
- //let script;
- //let outputs = 1;
-
- // The normal case, when there is token change to return to sender.
- if (change > 0) {
- //outputs = 2;
-
- // Convert the send quantity to the format expected by slp-mdm.
-
- //let baseQty = new BigNumber(sendQty).times(10 ** decimals);
- // Update: you've done this earlier, so don't do it now
- let baseQty = sendQtyBig.toString();
- console.log(`baseQty: `, baseQty);
-
- // Convert the change quantity to the format expected by slp-mdm.
- //let baseChange = new BigNumber(change).times(10 ** decimals);
- // Update: you've done this earlier, so don't do it now
- let baseChange = change.toString();
- console.log(`baseChange: `, baseChange);
-
- const outputQty = new BigNumber(baseChange).plus(
- new BigNumber(baseQty),
- );
- const inputQty = new BigNumber(totalTokens);
- console.log(
- `new BigNumber(baseChange)`,
- new BigNumber(baseChange),
- );
- console.log(`new BigNumber(baseQty)`, new BigNumber(baseQty));
- console.log(`outputQty:`, outputQty);
- console.log(`inputQty:`, inputQty);
- console.log(
- `outputQty.minus(inputQty).toString():`,
- outputQty.minus(inputQty).toString(),
- );
- console.log(
- `outputQty.minus(inputQty).toString():`,
- outputQty.minus(inputQty).toString() === '0',
- );
-
- const tokenOutputDelta =
- outputQty.minus(inputQty).toString() !== '0';
- if (tokenOutputDelta)
- console.log(
- 'Token transaction inputs do not match outputs, cannot send transaction',
- );
- // Generate the OP_RETURN as a Buffer.
- /*
- script = slpMdm.TokenType1.send(tokenId, [
- new slpMdm.BN(baseQty),
- new slpMdm.BN(baseChange)
- ]);
- */
- //
-
- // Corner case, when there is no token change to send back.
- } else {
- console.log(`No change case:`);
- let baseQty = sendQtyBig.toString();
- console.log(`baseQty: `, baseQty);
-
- // Check for potential burns
- const noChangeOutputQty = new BigNumber(baseQty);
- const noChangeInputQty = new BigNumber(totalTokens);
- console.log(`noChangeOutputQty`, noChangeOutputQty);
- console.log(`noChangeInputQty`, noChangeInputQty);
-
- const tokenSingleOutputError =
- noChangeOutputQty.minus(noChangeInputQty).toString() !==
- '0';
- if (tokenSingleOutputError)
- console.log(
- 'Token transaction inputs do not match outputs, cannot send transaction',
- );
-
- // Generate the OP_RETURN as a Buffer.
- //script = slpMdm.TokenType1.send(tokenId, [new slpMdm.BN(baseQty)]);
- }
- } catch (err) {
- console.log(`Error in generateSendOpReturn()`);
- throw err;
- }
- };
-
const sendBch = async (
BCH,
wallet,
@@ -553,16 +392,7 @@
callbackTxId,
) => {
// Note: callbackTxId is a callback function that accepts a txid as its only parameter
- /* Debug logs
- console.log(`sendBch called with`);
- console.log("BCH", BCH);
- console.log("wallet", wallet);
- console.log("utxos", utxos);
- console.log("addresses", addresses);
- console.log("values", values);
- console.log("encodedOpReturn", encodedOpReturn);
- console.log("callbackTxid", callbackTxId);
- */
+
try {
if (!values || values.length === 0) {
return null;
diff --git a/web/cashtab/src/hooks/useWallet.js b/web/cashtab/src/hooks/useWallet.js
--- a/web/cashtab/src/hooks/useWallet.js
+++ b/web/cashtab/src/hooks/useWallet.js
@@ -664,25 +664,29 @@
tokens[receivedTokenObjectIndex].info.tokenName;
//console.log(`receivedSlpQty`, receivedSlpQty);
- // Notification
- notification.success({
- message: `SLP Transaction received: ${receivedSlpTicker}`,
- description: (
-
- You received {receivedSlpQty} {receivedSlpName}
-
- ),
- duration: 5,
- });
+ // Notification if you received SLP
+ if (receivedSlpQty > 0) {
+ notification.success({
+ message: `${currency.tokenTicker} Transaction received: ${receivedSlpTicker}`,
+ description: (
+
+ You received {receivedSlpQty} {receivedSlpName}
+
+ ),
+ duration: 5,
+ });
+ }
//
} else {
// If tokens[i].balance > previousTokens[i].balance, a new SLP tx of an existing token has been received
+ // Note that tokens[i].balance is of type BigNumber
for (let i = 0; i < tokens.length; i += 1) {
- if (tokens[i].balance > previousTokens[i].balance) {
+ if (tokens[i].balance.gt(previousTokens[i].balance)) {
// Received this token
// console.log(`previousTokenId`, previousTokens[i].tokenId);
// console.log(`currentTokenId`, tokens[i].tokenId);
+
if (previousTokens[i].tokenId !== tokens[i].tokenId) {
console.log(
`TokenIds do not match, breaking from SLP notifications`,
@@ -691,10 +695,10 @@
// Also don't 'continue' ; this means you have sent a token, just stop iterating through
break;
}
- const receivedSlpDecimals = tokens[i].info.decimals;
- const receivedSlpQty = (
- tokens[i].balance - previousTokens[i].balance
- ).toFixed(receivedSlpDecimals);
+ const receivedSlpQty = tokens[i].balance.minus(
+ previousTokens[i].balance,
+ );
+
const receivedSlpTicker = tokens[i].info.tokenTicker;
const receivedSlpName = tokens[i].info.tokenName;
@@ -702,7 +706,8 @@
message: `SLP Transaction received: ${receivedSlpTicker}`,
description: (
- You received {receivedSlpQty} {receivedSlpName}
+ You received {receivedSlpQty.toString()}{' '}
+ {receivedSlpName}
),
duration: 5,