oipwg / oip-hdmw

BIP44 Lite Wallet - Powerful Open Source Javascript library to easily manage any BIP44 Wallet with multi-coin support
https://oipwg.github.io/oip-hdmw/
MIT License
26 stars 19 forks source link

Error Sending Transaction #6

Open werewolfe opened 5 years ago

werewolfe commented 5 years ago

I'm having trouble sending a transaction. I've been following the errors, but not sure where the problem is.

Here is the current error in the console:

Unable to send Transaction! Error: Unable to build Transaction 
Error: No Inputs or Outputs selected! Fail! at TransactionBuilder.sendTX (TransactionBuilder.js:642)

Here is my current transaction code:

sendPayment(){
    let address = new HDMW.Address(this.digibyte.seed, HDMW.Networks.digibyte, false);
    this.myWallet.sendPayment({
      from: address,
      to: { "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa": 1 },
      coin: "digibyte",
    }).then(function(txid){
      this.txid = txid;
      console.log("Successfully sent Transaction! " + this.txid);
    }).catch(function(error){
      console.error("Unable to send Transaction!", error)
    })
 }

I've tried different versions of this with the same error:

sendPayment(){
    this.myWallet.sendPayment({
      to: { "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa": 1 },
      coin: "digibyte",
    }).then(function(txid){
      this.txid = txid;
      console.log("Successfully sent Transaction! " + this.txid);
    }).catch(function(error){
      console.error("Unable to send Transaction!", error)
    })
  }

I guess I'm not sure how to pass the options details correctly.

orpheus commented 5 years ago

So it looks like it's not able to find the inputs it needs to build the transaction. This could be caused by a couple of things, but I don't think it's your code. Because I cannot test can you do this for me? Go into your node_modules/oip-hdmw/lib/TransactionBuilder.js at line 495 and log a few variables for me please. The code should look like this:

}, {
        key: 'buildTX',
        value: async function buildTX(manual_selected) {
            var _this2 = this;

            var selected = manual_selected;

            if (!selected) {
                try {
                    selected = await this.buildInputsAndOutputs();
                } catch (e) {
                    throw new Error("Unable to select inputs and outputs \n" + e);
                }
            }

            this.selected = selected;

            var inputs = selected.inputs;
            var outputs = selected.outputs;
            var fee = selected.fee;

            // inputs and outputs will be undefined if no solution was found
            if (!inputs || !outputs) {
                throw new Error("No Inputs or Outputs selected! Fail!");
            }

Log selected before and after the if statement Then log inputs, outputs, and fee and we'll go from there!

werewolfe commented 5 years ago

Here are the logs:

console.log(selected) before if: -> TransactionBuilder.js:500 undefined      
console.log(selected) after if: -> TransactionBuilder.js:508 {fee: 18816} fee: 18816__proto__: Object
console.log(inputs) -> TransactionBuilder.js:512 undefined
console.log(outputs) -> TransactionBuilder.js:514 undefined
console.log(fee) -> TransactionBuilder.js:516 18816
orpheus commented 5 years ago

okay, now at line 388 under this function:

if (!utxos) {
    try {
        utxos = await this.getUnspents();
    } catch (e) {
        throw new Error("Unable to get Unspents for Addresses \n" + e);
    }
}

log utxos

Pretty much going to have to keep going back until we find which variable isn't returning correctly. Or if you want to publish your repo, I can clone and take a look at it myself.

But under utxos, look at the major variables being declared and see which one returns null/undefined. When we do, I can make a change and add better error handling.

werewolfe commented 5 years ago

Here is the utxos log. I think we're getting somewhere.

[{…}]
0:
address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
amount: 1
confirmations: 6
confirmationsFromCache: true
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
ts: 1552630412
txid: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
vout: 0
__proto__: Object
length: 1
__proto__: Array(0)

I did send 1 DGB to the address to test, so it looks like it is there.

orpheus commented 5 years ago

alright, now log selected under this line: var selected = (0, _coinselect2.default)(utxosNoUnconfirmed, targets, Math.ceil(this.coin.feePerByte), extraBytesLength);

werewolfe commented 5 years ago

Got the fee

TransactionBuilder.js:427 console.log(selected); -> {fee: 18816} fee: 18816__proto__: Object 

logs

orpheus commented 5 years ago

log these variables utxosNoUnconfirmed, targets, Math.ceil(this.coin.feePerByte), extraBytesLength before var selected = ...

Wondering if it's a problem with the coinselect function

werewolfe commented 5 years ago

console.log(utxosNoUnconfirmed); 425

[{…}]
0:
address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
confirmations: 6
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
txId: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
value: undefined
vout: 0

console.log(targets); 426

[{…}]0: {address: "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa", value: 100000000}length: 1__proto__: Array(0)

console.log(Math.ceil(this.coin.feePerByte)); 427

98

console.log(extraBytesLength); 428

0

At least they each have a value.

bitspill commented 5 years ago

value: undefined seems highly suspect and should refer to the 1 DGB that's contained within d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396:0

werewolfe commented 5 years ago

value: undefined seems highly suspect and should refer to the 1 DGB that's contained within d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396:0

I didn't catch that, interesting.

orpheus commented 5 years ago

I think I might have an idea. When you logged utxos it was this:

[{…}]
0:
address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
amount: 1
confirmations: 6
confirmationsFromCache: true
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
ts: 1552630412
txid: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
vout: 0
__proto__: Object
length: 1
__proto__: Array(0)

but then right after it gets back the utxos, it tries to format them like this:

var formattedUtxos = utxos.map((utxo) => {
            return {
                address: utxo.address,
                txId: utxo.txid,
                vout: utxo.vout,
                scriptPubKey: utxo.scriptPubKey,
                value: utxo.satoshis,
                confirmations: utxo.confirmations
            }
        })

value is looking for utxo.satoshis but in the utxos, there's no satoshiskey.

Can you verify this?

orpheus commented 5 years ago

if you look at the documentation here, there is both amount and satoshis. So did satoshis come back undefined or was it not returned at all?

bitspill commented 5 years ago

Looks like https://digiexplorer.info is running Insight API v0.2.12 whereas FLO is currently running Insight API v5.0.0-beta.72

The DGB API doesn't return a satoshi value https://digiexplorer.info/api/addr/DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm/utxo

Compared to FLO https://livenet.flocha.in/api/addr/F77pykX5Dq2ju9sxdJC4a4cYZk7xNNegH5/utxo

Seems it will be necessary to add a check for that and calculate satoshis from value if satoshis doesn't exist or to update the Explorer to a more recent API version

EDIT: Or switch the api url in digibyte.js to this other explorer that seems to be running a newer version and does return satoshis https://digibyteblockexplorer.com/api/addr/DEoWetricML2TJE37wEPxQqjZzYWXvvkKW/utxo

werewolfe commented 5 years ago

I switched to a different explorer that returns satoshis. There is still an issue. The value is now present, but the inputs and outputs are still undefined.

When I log utxos:

address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
amount: 1
confirmations: 37685
height: 8367532
satoshis: 100000000
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
txid: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
vout: 0

When I log formattedUtxos:

address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
confirmations: 37685
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
txId: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
value: 100000000
vout: 0
var inputs = selected.inputs;
            console.log(inputs); // undefined
            var outputs = selected.outputs;
            console.log(outputs); // undefined

Unable to send Transaction! Error: Unable to build Transaction 
Error: No Inputs or Outputs selected! Fail!
werewolfe commented 5 years ago

In TransactionBuilder.js I logged coin and account as below. Variable account is returned as undefined. I think this is the issue. coin provides all of the detail about the coin and the explorer.

function TransactionBuilder(coin, options, account) {
        _classCallCheck(this, TransactionBuilder);
        console.log(coin); //Line 110
        console.log(account); //Line 111
        this.coin = coin;
        this.account = account;

        // Addresses we are sending from
        this.from = [];
        // Addresses we want to send to & amounts
        this.to = [];

        this.passedOptions = {};

        this.parseOptions(options);
    }
orpheus commented 5 years ago

line 425 can you log this again? var selected = coinselect(utxosNoUnconfirmed, targets, Math.ceil(this.coin.feePerByte), extraBytesLength) and every var in it? selected, utxosNounconfirmed, targets, Math.ceil(this.coin.feePerByte), and extraBytes.length; just want an updated version with the new api in one place

And then, can you show me how you're initializing the HDMW?

sendPayment(){
    let address = new HDMW.Address(this.digibyte.seed, HDMW.Networks.digibyte, false);
    this.myWallet.sendPayment({
      from: address,
      to: { "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa": 1 },
      coin: "digibyte",
    }).then(function(txid){
      this.txid = txid;
      console.log("Successfully sent Transaction! " + this.txid);
    }).catch(function(error){
      console.error("Unable to send Transaction!", error)
    })
 }

I see here, you're creating a new instance of HDMW for new HDMW.Address but how did you init this.myWallet?

Also log this.accounts in lib/Coin.js in the constructor under (make sure discover: true)

if (this.discover){
    this.discoverAccounts()
        // log here
}
werewolfe commented 5 years ago

console.log(utxosNoUnconfirmed);

address: "DNf2iFGDwfUPnSbcY8KRZBjHdTgzgrrAYm"
confirmations: 44622
scriptPubKey: "76a914c0236c01b74bd84a8a269696f74d67b179c904cd88ac"
txId: "d59b065a32ffccfed897b1fd9b5a42366b1471022213c66d82da486e2c797396"
value: 100000000

console.log(targets);

address: "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa"
value: 100000000

console.log(Math.ceil(this.coin.feePerByte)); 98

console.log(extraBytesLength); 0

console.log(selected); {fee: 18816}

This is Angular/TypeScript: Initializing wallet.

import * as HDMW from 'oip-hdmw';

export class HomePage {

  Wallet: any = HDMW.Wallet;
  myWallet: any;
  digibyte: any;
  digibyteAddress: any;
  digibyteAddressPub: any;

  constructor(){
    this.myWallet = new this.Wallet('My Mnemonic');
    this.myWallet.addCoin('digibyte', {});
    this.show = this.myWallet.getCoins();
  }
}
sendPayment(){
    this.myWallet.sendPayment({
      to: { "DU22gCjXbV8R43PPJXb8ichDfEVQdHJsaa": 1 },
      coin: "digibyte",
    }).then(function(txid){
      this.txid = txid;
      console.log("Successfully sent Transaction! " + this.txid);
    }).catch(function(error){
      console.error("Unable to send Transaction!", error)
    })
  }

Logging this.accounts in Coin.js line 89: This provided a large amount of data, about 100 DigiByte addresses, API info and everything appears okay.

orpheus commented 5 years ago

Would you be willing to send me the Digibytes network information and send me the smallest amount of Digitbyte to an address so I can test locally?

werewolfe commented 5 years ago

Would you be willing to send me the Digibytes network information and send me the smallest amount of Digitbyte to an address so I can test locally?

oip-hdmw/lib/digibyte.js

'use strict';

var _insightExplorer = require('insight-explorer');

var _coininfo = require('coininfo');

var _coininfo2 = _interopRequireDefault(_coininfo);

var _bip44Constants = require('bip44-constants');

//var _bip44Constants2 = _interopRequireDefault(_bip44Constants);

var _config = require('./config');

var _config2 = _interopRequireDefault(_config);

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

var digibyteFeePerKb = 100000;

var n = _coininfo2.default.digibyte.main.toBitcoinJS();

module.exports = {
    name: 'digibyte',
    displayName: 'DigiByte',
    ticker: 'DGB',
    satPerCoin: 1e8,
    feePerKb: digibyteFeePerKb,
    feePerByte: digibyteFeePerKb / 1024,
    maxFeePerByte: 100,
    minFee: digibyteFeePerKb,
    dust: 54600,

    txVersion: 1,

    explorer: new _insightExplorer.Insight(_config2.default.defaultApiUrls.digibyte),

    getExtraBytes: function getExtraBytes(options) {
        return;
    },

    network: {
        bip32: {
            public: 0x0488B21E,
            private: 0x0488ADE4
        },
        slip44: 20, //_bip44constants2.default.DGB,
        messagePrefix: '\x18DigiByte Signed Message:\n',
        pubKeyHash: n.pubKeyHash,
        scriptHash: n.scriptHash,
        wif: n.wif
    }
};

Paste your DigiByte address and I'll send it over. Thanks for the help! Also, I can email you the explorer URL. I don't want it easily accessible to the public.

orpheus commented 5 years ago

ryanachacon@gmail.com

orpheus commented 5 years ago

I'm having trouble getting the network info from coininfo cannot do: coininfo.digibyte.main.toBitcoinJS()

coininfo.digibyte.main returns fine. this happen at all?

  ● Test suite failed to run

    TypeError: Cannot read property 'public' of undefined

       5 | var digibyteFeePerKb = 100000;
       6 | 
    >  7 | console.log(coininfo.digibyte.main.toBitcoinJS(), typeof coininfo.digibyte.main.toBitcoinJS)
         |                                    ^
       8 | 
       9 | module.exports = {
      10 |  name: 'digibyte',
werewolfe commented 5 years ago

I'm having trouble getting the network info from coininfo cannot do: coininfo.digibyte.main.toBitcoinJS()

coininfo.digibyte.main returns fine. this happen at all?

  ● Test suite failed to run

    TypeError: Cannot read property 'public' of undefined

       5 | var digibyteFeePerKb = 100000;
       6 | 
    >  7 | console.log(coininfo.digibyte.main.toBitcoinJS(), typeof coininfo.digibyte.main.toBitcoinJS)
         |                                    ^
       8 | 
       9 | module.exports = {
      10 |    name: 'digibyte',

I have not experienced that error. Possible to test toBitcore()?

bip32: {
        public: 0x0488B21E,
            private: 0x0488ADE4
orpheus commented 5 years ago

outdated dependency my b

pubAddr: DDtbnXL2qToMLBYgKUiT2P1XaB6xEnvC9t

werewolfe commented 5 years ago

outdated dependency my b

pubAddr: DDtbnXL2qToMLBYgKUiT2P1XaB6xEnvC9t

Sent some DGB to that address. Hopefully that's what you intended, if not then they're probably burned🙃

orpheus commented 5 years ago

haha yeah that's what I intended. It'll take me a while to get through this and get back to you. But for now, can you add the discover option to your wallet initilizatoin and tell me if you receive any errors?

constructor(){
    this.myWallet = new this.Wallet('My Mnemonic', {discover: true}); // make changes here
werewolfe commented 5 years ago

Added {discover: true}, still get the same error:

home.page.ts:55 Unable to send Transaction! Error: Unable to build Transaction 
Error: No Inputs or Outputs selected! Fail!
    at TransactionBuilder.sendTX (TransactionBuilder.js:651)

Also, when I add this the transaction takes about 35 seconds to process and show error. Seems like a long time. Is there a way to operate this as a single coin wallet?