Usando mi método de contrato para la transferencia de tokens ERC20 y configurando el propietario inicial

Sé que esto se ha preguntado antes en un par de lugares, pero no he progresado desde hace un día. Tengo el siguiente código para configurar el propietario inicial de mi token ERC20. Uso el siguiente código en un método POST, donde el usuario ingresaría su dirección y lo configuraría como propietario.

Implementé el contrato usando Metamask y la cuenta "desde" es la misma desde la que lo implementé. El testSendAccount es básicamente un marcador de posición que uso. ¿Hay algo más que debería haber agregado en el código?

El código es el siguiente:

'use strict';
/*
const config = require('../config');
var Web3 = require('web3');
var web3 = new Web3();
const infuraApi = require('infura')(config.infuraApiKey);
//Set a provider (HttpProvider)
if (typeof web3 !== 'undefined') {
  web3 = new Web3(web3.currentProvider);
} else {
  // set the provider you want from Web3.providers
  web3 = new Web3(new Web3.providers.HttpProvider('https://ropsten.infura.io/' + infuraApi));
}

const EthereumTx = require('ethereumjs-tx');
var accountAddressHex = require('metamaskAccount')(config.metamaskAccount.metamaskAddressHex);
var accountAddressPrivateKey  = require('metamaskAccount')(config.metamaskAccount.metamaskAddressPrivateKey);
var privateKey = new Buffer(accountAddressPrivateKey, 'hex')
var count = web3.eth.getTransactionCount(accountAddressHex);
var contractAddress = require('solidityContract')(config.solidityContract.contractAddress);
var contractAbiArray = require('solidityContract')(config.solidityContract.contractABI);
var contract = web3.eth.contract(contractAbiArray).at(contractAddress );

const testSendAccount= [Redacted];
const gasPrice = web3.eth.gasPrice;
const gasPriceHex = web3.toHex(gasPrice);
const gasLimitHex = web3.toHex(3000000);
//const tokenTransferAmount = 1;//EDIT 1

var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( {from: accountAddressHex}, function(err, hash){
        if(!err) { tokenIdToAssignHex = hash;
        console.log(tokenIdToAssignHex); }
        else { console.log("Error"); }
      });


 var tokenIdToAssign = contract.nextTokenIdToAssign.call(function(err, res){
          if(!err) { tokenIdToAssign = res;
            console.log(tokenIdToAssign.toNumber()); }
        else { console.log("Error"); }
      });

var rawTransaction = {
    "from": accountAddressHex,
    "nonce": web3.toHex(count),
    "gasPrice": gasPriceHex,
    "gasLimit": gasLimitHex,
    "to": contractAddress,
    "value": "0x0",
    "data": contract.setInitialOwner.getData(testSendAccount, tokenTransferAmount, {from: accountAddressHex}), //contract.transfer.getData("0xCb...", 10, {from: "0x26..."}),
    "chainId": 0x03 //Ropsten id is 3, replace with 1 for main
};
var tx = new EthereumTx(rawTransaction);
tx.sign(privateKey);
var serializedTx = tx.serialize();
web3.eth.sendRawTransaction('0x' + serializedTx.toString('hex'), function(err, hash) {
    if (!err) { console.log( 'contract creation tx: ' + hash); }
    else {
        console.log(err);
        return;
      }
});

EDIT 1 He cambiado, const tokenTransferAmount = 1;ya const tokenIdToAssign = contract.nextTokenIdToAssign.call();que esta es la variable que se ocupa de cuál debería ser el próximo token que se establecerá en el contrato.

EDITAR 2 Cambié el tokenToAssign y agregué el

var tokenIdToAssignHex = contract.nextTokenIdToAssign.sendTransaction( {from: accountAddressHex}, function(err, hash){ if(!err) { tokenIdToAssignHex = hash; console.log(tokenIdToAssignHex); } else { console.log("Error"); } });

EDITAR 3 EDITAR 1

Aquí está el código de contrato para setInitialOwner:

function setInitialOwner(address _to, uint256 _tokenId) public
    onlyOwner
    tokensRemainingToAssign
    tenKLimit (_tokenId)
    yesZeroAddressOwner (_tokenId) 
    notSelfSend (_to, _tokenId) {

        tokenIdToOwner[_tokenId] = _to;
        balanceOfAddress[_to] = balanceOfAddress[_to].add(1);
        emit Assign(_to, _tokenId);

        tokenIndexArray.push(_tokenId);

        uint256 length = balanceOf(msg.sender);
        ownedTokensIndexMapping[_tokenId] = length;
        addressToTokenIdByIndex[msg.sender][length] = _tokenId;

        nextTokenIdToAssign = nextTokenFunc(nextTokenIdToAssign);
       hypeKillsTokensRemainingToAssign = tokensRemainingToAssign.sub(1);
        }
¿Está funcionando tu código? Si no, ¿qué está yendo mal?
El código no funciona. Mi idea era que después de la ejecución del código, toAccount podría ver el token en la billetera Metamask, una vez que agregue el token en la interfaz de usuario. Pero este no parece ser el caso. También he editado, una línea en el código, para obtener el nextTokenId. Este ID lo deberíamos usar durante la transferencia para saber exactamente qué número estamos enviando, pero cuando paso a console.log() su valor, aparece "indefinido".
Entonces, una cosa que traté de hacer fue web3.eth.getCode(contractAddress);que arrojara un valor nulo. Esto es extraño, ya que implementé el contrato usando Metamask en la red ropsten.
¿Tiene una identificación de transacción? ¿La transacción se completa con un estado exitoso? ¿Tu ERC20 genera un evento Transfer?
Pude hacer una transacción. Pero no puedo actualizar el nextTokenToAssign con el tokenIdToAssignHexpara actualizar la siguiente identificación del token. Entonces termino con el token 1, que revertirá cualquier transacción adicional. He agregado tokenIdToAssignHex, pero arroja un error.
Hice una edición, agregando el código del contrato. Entonces, para actualizar mi nextTokenIdToAssigntuve que enviar una transacción sin procesar nuevamente a nextTokenIdToAssign, ya que infura no es compatible con sendTransaction. El problema en este punto es que todavía no se actualiza. ¿Podría deberse a la función setter nextTokenFunc(uint256 _tokenId), teniendo en cuenta que nextTokenIdToAssignse cambia esencialmente durante setInitialOwner con una función interna como nextTokenIdToAssign.

Respuestas (2)

Cambio de API web3 1.0.

let myContract = new web3.eth.Contract(abi, contractAddress);
let data = myContract.methods.transfer(toAddress, value).encodeABI();
let rawTx = {
    "nonce": web3.utils.toHex(nonce),
    "gasPrice": "0x3b9aca00",
    "gasLimit": web3.utils.toHex(gasLimit),
    "to": contractAddress,
    "value": "0x00",
    "data": data,
}
const tx = new Tx(rawTx)
tx.sign(privateKey)
let serializedTx = "0x" + tx.serialize().toString('hex');
web3.eth.sendSignedTransaction(serializedTx).on('transactionHash', function (txHash) {

}).on('receipt', function (receipt) {
    console.log("receipt:" + receipt);
}).on('confirmation', function (confirmationNumber, receipt) {
    //console.log("confirmationNumber:" + confirmationNumber + " receipt:" + receipt);
}).on('error', function (error) {

});

puede ver esto: Transferencia de tokens ERC20 de la cuenta usando web3 sobre Ropsten

Gracias por la sugerencia de cambio de API web3 1.0. Eventualmente tendré que actualizar a 1.0 también.

Dado que otros pueden encontrar este problema, publicaré la solución a la que llegué. El problema aquí era que mi nextTokenToAssignvariable no se actualizaba correctamente.

Usé [myetherwallet.com][1] para implementar el contrato y verificar su valor. Cuando implementé el contrato, si luego no llamaba a la función constructora, estableciendo el valor inicial de nextTokenToAssignen 1, no se actualizaría durante las sucesivas llamadas a la setInitialOwnerfunción. Entonces, la solución simplemente fue simplemente llamar a la función.