LiskArchive / lisk-ui

🖥️ Lisk user-interface submodule
https://lisk.io/
GNU General Public License v3.0
24 stars 35 forks source link

Unable to Send Lisk: Expected type string but found type null #75

Closed karmacoma closed 7 years ago

karmacoma commented 7 years ago

Moved from: https://github.com/LiskHQ/lisk/issues/293.

Hi,

I am attempting to send List from my address, but I keep getting an error of "Expected type string but found type null". If I try to send out from the Lisk Nano client, I get "Invalid transaction timestamp" error. Can you please tell me what I'm doing wrong and how to fix this?

vrlcrypt commented 7 years ago

I also can't vote.

screen shot 2016-10-17 at 9 59 36 am
Isabello commented 7 years ago

Can you provide some more detail about this? Are you using login.lisk.io for this or your own server? is it behind an nginx node? @vrlc92

Isabello commented 7 years ago

Root cause for this issue is related to the way we handle transactions and public keys

https://github.com/LiskHQ/lisk-ui/blob/29b37ac0aa43232cde93fe5b9178533558146b5b/js/controllers/passphraseController.js

        $http.post("/api/accounts/open/", { secret: pass })
            .then(function (resp) {
                if (resp.data.success) {
                    userService.setData(resp.data.account.address, resp.data.account.publicKey, resp.data.account.balance, resp.data.account.unconfirmedBalance, resp.data.account.effectiveBalance); <<<<<<<<<< We assign publicKey based on the return of /api/accounts/open - This is null on every new account
                    userService.setForging(resp.data.account.forging);
                    userService.setSecondPassphrase(resp.data.account.secondSignature || resp.data.account.unconfirmedSignature);
                    userService.unconfirmedPassphrase = resp.data.account.unconfirmedSignature;
                    if (remember) {
                        userService.setSessionPassphrase(pass);
                    }
                    $state.go('main.dashboard');
                } else {
                    $scope.errorMessage = resp.data.error;
                }
            });

Wallets without a publickey assigned to them will have a null publickey

lisk_main=# select address,"publicKey", balance from mem_accounts where address = '10776522510235196105L';
        address        | publicKey |  balance
-----------------------+-----------+-----------
 10776522510235196105L |           | 100000000

In order for these wallets to get a publickey a transaction needs to be signed and broadcast out to the block chain. The U_TX will cause a public key to be inserted into mem_accounts.

Now when logging in the wallet will have a public key after any transaction is made

lisk_main=# select address,"publicKey", balance from mem_accounts where address = '10776522510235196105L';
        address        |                             publicKey                              | balance
-----------------------+--------------------------------------------------------------------+----------
 10776522510235196105L | \x0dc13eafe5c2d3e46c14faad4de8533a24ba9438afe404902bcfc812760e322b | 90000000
(1 row)

The roadblock comes in when all of our transations rely on having this data

evidence is on this line of publicKey requirement:

https://github.com/LiskHQ/lisk-ui/blob/29b37ac0aa43232cde93fe5b9178533558146b5b/js/controllers/modals/sendTransactionController.js#L214

     $scope.sendTransaction = function (secretPhrase, withSecond) {
        if ($scope.secondPassphrase && !withSecond) {
            $scope.checkSecondPass = true;
            $scope.focus = 'secondPhrase';
            return;
        }

        $scope.errorMessage = {};

        var data = {
            secret: secretPhrase,
            amount: $scope.convertLISK($scope.amount),
            recipientId: $scope.to,
            publicKey: userService.publicKey <<<<<<<<<< Heres where we ask the userService for the public key that was assigned on login.
        };

        if ($scope.secondPassphrase) {
            data.secondSecret = $scope.secondPhrase;
            if ($scope.rememberedPassphrase) {
                data.secret = $scope.rememberedPassphrase;
            }
        }

        if (!$scope.sending) {
            $scope.sending = true;

            $http.put('/api/transactions', data).then(function (resp) { <<<<<<<<< Heres the troublesome API end point that relies on public key
                $scope.sending = false;

                if (resp.data.error) {
                    Materialize.toast('Transaction error', 3000, 'red white-text');
                    $scope.errorMessage.fromServer = resp.data.error;
                } else {
                    if ($scope.destroy) {
                        $scope.destroy();
                    }
                    Materialize.toast('Transaction sent', 3000, 'green white-text');
                    sendTransactionModal.deactivate();
                }
            });
        }
    }

the reason being we have null data and our type checking is only looking for strings. We have a few options here:

  1. Create a new api endpoint for registering a publicKey without sending LSK
  2. Automatically insert publicKey into the database upon login of any wallet that also has lisk present if there isnt one.
  3. Continue using the same schema but adjust the logic to generate the publicKey and insert it locally if its a null value.
vrlcrypt commented 7 years ago

@Isabello:

  1. I created this account from login.lisk.io. https://explorer.lisk.io/address/16933982283740439749L
  2. Then Joel sent me 2500 LSK: https://explorer.lisk.io/tx/11369152799282331186
  3. I couldn't vote and withdraw lisks.
  4. I called: https://login.lisk.io/api/accounts/getPublicKey?address=16933982283740439749L {"success":false,"error":"Account not found"}
  5. After I withdraw lisks from m.lisk.io, then I called again: https://login.lisk.io/api/accounts/getPublicKey?address=16933982283740439749L {"success":true,"publicKey":"97fb4f1d17eb2d86d7eefca5d848a572551637607031b90ab517ba3010569854"}

As the public key is an optional parameter, perhaps the best solution is just to remove it when it has a null value.

Lisk nano for example doesn't send the publicKey, so the same problem does not occur. https://github.com/LiskHQ/lisk-nano/blob/development/src/app/services/peers/peer.js#L122

vrlcrypt commented 7 years ago

@Isabello

My guess

An account is registered in blockchain when its address is the sender or recipient of a transaction.

When its address is: Sender: the publicKey is recorded Recipient: the publicKey isn't recorded

Isabello commented 7 years ago

Publickeys are generated upon the first transaction sent by a secret key. The root cause is the way we pull data from api and the null value publickey has until this first sending transaction.

On Oct 27, 2016 18:31, "Victor" notifications@github.com wrote:

@Isabello https://github.com/Isabello

My guess

An account is registered in blockchain when its address is the sender or recipient of a transaction.

When its address is: Sender: the publicKey is recorded Recipient: the publicKey isn't recorded

— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/LiskHQ/lisk-ui/issues/75#issuecomment-256798857, or mute the thread https://github.com/notifications/unsubscribe-auth/APzFsBBI49OJP_D7TBk9YhmXa7pmwKzQks5q4TRtgaJpZM4KVywG .

karmacoma commented 7 years ago

Thank you @Isabello. Closing here, and resolving in original issue: https://github.com/LiskHQ/lisk/issues/293, using your pull request.