bigchaindb / js-bigchaindb-driver

Official BigchainDB JavaScript driver for Node.js and the browser
https://docs.bigchaindb.com/projects/js-driver/en/latest/usage.html
Apache License 2.0
216 stars 92 forks source link

Problem: Re-Assign Divisible Token get 400 BAD REQUEST and Tutorial guide #166

Closed DragonZelda closed 6 years ago

DragonZelda commented 6 years ago

This issue is on the bigchaindb test server. First, I created a UserA then create a Divisible Token. Then I create a UserB and assign some Token to UserB. After that if I want to assign the Token from UserB to UserC, I will face the following issue when using conn.postTransactionCommit:

{ message: 'HTTP Error: Requested page not reachable', status: '400 BAD REQUEST', requestURI: 'https://test.bigchaindb.com/api/v1/transactions?mode=commit' }

===

For the guide at url: https://www.bigchaindb.com/developers/guide/tutorial-token-launch/ The sample code of section section: Combination of different BigchainDB transactions seems not correct: const signedTransfer = BigchainDB.Transaction .signTransaction(combineTranfer, newUser.privateKey)

The transaction owner (tokenCreator or Alice) want to combine the transactions to a newUser. So it should be signed with tokenCreator or Alice privateKey, not newUser privateKey.

After test, the correct code is:

const signedTransfer = BigchainDB.Transaction .signTransaction(combineTranfer, alice.privateKey, alice.privateKey)

It should be the same for BigchainDB Javascript Driver Documents at url: https://docs.bigchaindb.com/projects/js-driver/en/latest/usage.html#divisible-assets last sample code.

Currently the sample code show that if Alice want to transfer Token to Bob and Carly is:

const txTransferDivisibleInputsSigned = driver.Transaction.signTransaction( txTransferDivisibleInputs, carly.privateKey, bob.privateKey)

Alice is the transaction owner. It not make sense when the owner want to transfer the token to his friend but need his friends privateKey. So these two privateKey should be Alice.privateKey.

tnguyen42 commented 6 years ago

Hi, It may be a bit late and it's kind of a random suggestion, but maybe try to add port 443 to your url: https://test.bigchaindb.com:443/api/v1/transactions?mode=commit

DragonZelda commented 6 years ago

It is still the same. The response is:

{ message: 'HTTP Error: Requested page not reachable', status: '400 BAD REQUEST', requestURI: 'https://test.bigchaindb.com:443/api/v1/transactions?mode=commit' }

when I try to assign the token at second tier.

future-is-present commented 6 years ago

That was problem with the connectivity to BigchainDB. At that moment the test network was not as stable as it is now.

sandip-j commented 6 years ago

I'm also facing the same issue. This issue still persist at their server. I think it's not problem of server. It's problem of code at their end or I think we are doing something wrong but they provide a much explained demo

DragonZelda commented 6 years ago

I'm also facing the same issue. This issue still persist at their server. I think it's not problem of server. It's problem of code at their end or I think we are doing something wrong but they provide a much explained demo

It is so sad to know that the issue still persist. I try my best to debug but it seems that they just ignore it.

future-is-present commented 6 years ago

The issue exists in the part where getting the create transaction before the transfering part. I will solve it asap.

The code below is working:

const BigchainDB = require('bigchaindb-driver')
var bip39 = require('bip39')

// TEST NETWORK
const API_PATH = 'https://test.bigchaindb.com/api/v1/'
const conn = new BigchainDB.Connection(API_PATH, 
    {
        app_id: 'valid_id',
        app_key: 'valid_key'
    }
)

// LOCAL

// const API_PATH = 'http://127.0.0.1:9984/api/v1/'
// const conn = new BigchainDB.Connection(API_PATH, {
//      app_id: '',
//     app_key: ''
// })

const nTokens = 10000
let tokensLeft
const tokenCreator = new BigchainDB
.Ed25519Keypair(bip39.mnemonicToSeed('seedPhrase').slice(0,32))

tokenLaunch()
function tokenLaunch() {
    // Construct a transaction payload
    const tx = BigchainDB.Transaction.makeCreateTransaction({
            token: 'TT (Tutorial Tokens)',
            number_tokens: nTokens
        },
        // Metadata field, contains information about the transaction itself
        // (can be `null` if not needed)
        {
            datetime: new Date().toString()
        },
        // Output: Divisible asset, include nTokens as parameter
        [BigchainDB.Transaction.makeOutput(BigchainDB.Transaction
          .makeEd25519Condition(tokenCreator.publicKey), nTokens.toString())],
        tokenCreator.publicKey
    )

    // Sign the transaction with the private key of the token creator
    const txSigned = BigchainDB.Transaction
      .signTransaction(tx, tokenCreator.privateKey)

    conn.postTransactionCommit(txSigned)
        .then(res => {
            tokensLeft = nTokens
            console.log(res.id)
            transferTokens(res.id)
        })
}

const amountToSend = 200

const newUser = new BigchainDB
    .Ed25519Keypair(bip39.mnemonicToSeed('newUserseedPhrase')
        .slice(0, 32))

async function transferTokens(txId) {
    // User who will receive the 200 tokens
    const newUser = new BigchainDB.Ed25519Keypair()
    // Search outputs of the transactions belonging the token creator
    // False argument to retrieve unspent outputs
    conn.getTransaction(txId)
        .then((txOutputs) => {
            // Create transfer transaction
            const createTranfer = BigchainDB.Transaction
                .makeTransferTransaction(
                    [{
                        tx: txOutputs,
                        output_index: 0
                    }],
                    // Transaction output: Two outputs, because the whole input
                    // must be spent
                    [BigchainDB.Transaction.makeOutput(
                            BigchainDB.Transaction
                            .makeEd25519Condition(tokenCreator.publicKey),
                            (tokensLeft - amountToSend).toString()),
                        BigchainDB.Transaction.makeOutput(
                            BigchainDB.Transaction
                            .makeEd25519Condition(newUser.publicKey),
                            amountToSend.toString())
                    ],
                    // Metadata (optional)
                    {
                        transfer_to: 'john',
                        tokens_left: tokensLeft.toString()
                    }
                )
            // Sign the transaction with the tokenCreator key
            const signedTransfer = BigchainDB.Transaction
                .signTransaction(createTranfer, tokenCreator.privateKey)

            return conn.postTransactionCommit(signedTransfer)
        })
        .then(res => {
            // Update tokensLeft
            tokensLeft -= amountToSend
            console.log('transfer', res.id)
        })

}
MuzammalRamzan commented 4 years ago

we use TxID when launching a token and this id is not changing thats why we can only send one time transaction jxt upadate the txID according to transaction it will work fine