4

I've learned a lot today, and I couldn't have gotten this far so quickly without this StackExchange. I've almost got sending worked out, but I can't for the life of me figure out why this is failing at the point of injection with a "unrevealed_key" error.

I am aware that I should decode the forged transaction and reverify the values to ensure the remote node hasn't tried to change my transaction, but I removed that bit from this post for the sake of simplicity.

const send = (from, to, amount, sk) => {

sotez.rpc.getHead()
    .then(head => {
        const operation = {
            branch: head.hash,
            contents: [{
                kind: 'transaction',
                source: from,
                fee: '50000',
                counter: '31204',
                gas_limit: '10200',
                storage_limit: '0',
                amount: amount,
                destination: to,
            }],
        }

        sotez.tezos.forge(head, operation)
            .then(unsigned => {
                const binary = unsigned.opbytes

                sotez.crypto.sign(binary, sk, '0x03')
                    .then(signed => {
                        operation.signature = signed.edsig

                        sotez.rpc.inject(operation, signed.sbytes)
                            .then(result => {
                                console.log(result)
                            })
                    })
            })
    })
}

send('tz1htPf3VPXrHBTX1E7y3tBteib6hA9Teosj', 'tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5', '1000000', 'edskS6KrT1G365PsuQiMVvPgZCS1CKTC5EFc7N...')

Returns: [{"kind":"branch","id":"proto.003-PsddFKi3.contract.unrevealed_key","contract":"tz1htPf3VPXrHBTX1E7y3tBteib6hA9Teosj"}]

Edit: So I need to reveal this account first. I modified my send method to check if the account has been revealed before, and if not then add the revealing to the list of operations. Now I get {"kind":"permanent","id":"proto.003-PsddFKi3.operation.invalid_signature"}.

const send = (from, to, amount, keys, revealed) => {

tezos.rpc.getHead()
    .then(head => {
        const operation = {
            branch: head.hash,
            contents: [{
                kind: 'transaction',
                source: from,
                fee: '50000',
                counter: '31205',
                gas_limit: '10200',
                storage_limit: '0',
                amount: amount,
                destination: to
            }],
        }

        if (!revealed) {
            operation.contents.unshift({
                kind: 'reveal',
                fee: '1269',
                counter: '31204',
                public_key: keys.pk,
                source: from,
                gas_limit: '10000',
                storage_limit: '0',
            })
        }

        tezos.tezos.forge(head, operation)
            .then(unsigned => {
                const binary = unsigned.opbytes

                tezos.crypto.sign(binary, keys.sk, '0x03')
                    .then(signed => {
                        operation.signature = signed.edsig

                        tezos.rpc.inject(operation, signed.sbytes)
                            .then(result => {
                                console.log(result)
                            })
                    })
            })
    })
}

send('tz1htPf3VPXrHBTX1E7y3tBteib6hA9Teosj', 'tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5', '1000000', keys, false)

Edit2: This worked, using sendOperation

const send = (from, to, amount, keys) => {

sotez.rpc.getHead()
    .then(head => {
        const operation = {
                kind: 'transaction',
                source: from,
                fee: '50000',
                gas_limit: '10200',
                storage_limit: '0',
                amount: amount,
                destination: to
        }

        const params = {
            from,
            operation,
            keys
        }

        sotez.rpc.sendOperation({from, operation, keys})
            .then(result => {
                console.log(result)
            })
    })
}

send('tz1htPf3VPXrHBTX1E7y3tBteib6hA9Teosj', 'tz3WXYtyDUNL91qfiCJtVUX746QpNv5i5ve5', '1000000', keys)
6

Before sending transactions from an account, a 'reveal' operation must be made for the account. It looks like this account may have been activated, but not yet revealed. To make this work we would need to include the reveal operation in the list of operations:

sotez.rpc.getHead()
  .then(head => {
    const operation = {
      branch: head.hash,
      contents: [
        {
          kind: 'reveal',
          fee: '1269',
          counter: '31204',
          public_key: keys.pk,
          source: from,
          gas_limit: '10000',
          storage_limit: '0',
        },
        {
          kind: 'transaction',
          source: from,
          fee: '50000',
          counter: '31205',
          gas_limit: '10200',
          storage_limit: '0',
          amount: amount,
          destination: to,
        }
      ],
    }
    ...
  })

After the account has been revealed, the reveal is not needed to be included in the operations thereafter.

SendOperation Answer:

const send = (from, to, amount, keys) => {
  const operation = {
    kind: 'transaction',
    source: from,
    fee: '50000',
    gas_limit: '10200',
    storage_limit: '0',
    amount: `${amount}`,
    destination: to,
  };

  rpc.sendOperation({ from, operation, keys })
    .then(result => console.log(result));
};
  • Thanks! I edited my question with the reveal operation added. When I run it now, it just hangs with no result or error. – Michael Rodriguez Mar 3 at 23:47
  • Ah nevermind, it was because of the counter increment. I noticed your edit and fixed it in my method. Oddly, though, now I'm getting this error: {"kind":"permanent","id":"proto.003-PsddFKi3.operation.invalid_signature"} – Michael Rodriguez Mar 3 at 23:57
  • Have you tried the same transfer using rpc.sendOperation? sendOperation should handle whether the transaction needs a reveal and all the counters for the operations. – AKISH Mar 4 at 0:06
  • 1
    I'll have to see what is making the responses hang, bit I think I tried one of your examples from earlier and noticed that the amount key wasn't being handled correctly in sotez (was supposed to be coerced into a string). If you try your sendOperation and make the amount a string, as well as adding a fee, gas_limit, and storage_limit that may work. – AKISH Mar 4 at 0:21
  • 1
    I just remembered that sendOperation takes a params object containing the from, the operation, and the keys. I've updated my question, and it worked! – Michael Rodriguez Mar 4 at 0:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.