NEM-SDK Initiate transaction error

Hello, I’m trying to initiate transaction using nem-sdk. following is my code

    // Using sdk data
const endpoint = nem.model.objects.create("endpoint")(nem.model.nodes.defaultTestnet, nem.model.nodes.defaultPort);

const privateKey = walletService.decryptPrivateKey(password, wallet);
logger.info(`privateKey----> ${privateKey}`);

// transaction common data initialisation
const common = nem.model.objects.get("common");
common.privateKey = privateKey;

const transferTransaction = nem.model.objects.create("transferTransaction")(recipient, 5, "test transaction");
logger.info(`Transfer Transaction----> ${JSON.stringify(transferTransaction)}`);

const transactionEntity = nem.model.transactions.prepare("transferTransaction")(common, transferTransaction, nem.model.network.data.testnet.id)
logger.info(`Transaction Entity----> ${JSON.stringify(transactionEntity)}`);

// temporary nem-sdk fix
transactionEntity.fee=6000000

// Serialize transfer transaction and announce
const transaction = await nem.model.transactions.send(common, transactionEntity, endpoint);
logger.info(`Response----> ${JSON.stringify(transaction)}`);

But all time i am getting an error of FAILURE_TIMESTAMP_TOO_FAR_IN_FUTURE

stuck with this issue. please help me to get out from here

Please read explanation here:

This is bug in nem-sdk which uses local time instead of time from node.

As a workaround you can use this node: https://nistest.opening-line.jp:7891/
Explained here: 技術・開発向け参考ソースコードや資料リンク

1 Like

@CryptoBeliever
It worked. this “https://nistest.opening-line.jp:7891/” node worked for me. Thanks

@CryptoBeliever
The issue currently i faced got resolved by updating the node details. But what when i go for mainnet?

As you said it is an nem-sdk error, any solution for this?

Also what is the most standard way for initiating the transaction? The way i code or some other way?

I’m not familiar with nem-sdk. You should be able to override timestamp and use node time instead local time.
It should use time from endpoint /time-sync/network-time (sendTimeStamp)
Some people have same issue with nem-sdk. Try ask on @nemprojects Telegram channel.

@CryptoBeliever Ok going for that thanks

Let me show you how to implement a workaround using nem-sdk.

This code is for Node.js:

const express = require('express');
const app = express();
require('dotenv').config({ path: '.env.' + app.get('env') });
const nem = require('nem-sdk').default;
let common = nem.model.objects.create('common')('', process.env.TEST_NEM_PRIVATE_KEY);
const testEndpoint = nem.model.objects.create('endpoint')(
  nem.model.nodes.defaultTestnet,
  nem.model.nodes.defaultPort
);
const recipient = "TA4YBG2NAB53POXPDQQI7APINXK74XLXL3YIADUM";
const amount=1;
const message=null;

let transferTx = nem.model.objects.create('transferTransaction')(recipient, amount, message);

let txEntity = nem.model.transactions.prepare('transferTransaction')(common, transferTx, nem.model.network.data.testnet.id);

//workaround
nem.com.requests.chain.time(testEndpoint).then(function(time){
   let ts=Math.floor(time.receiveTimeStamp/1000);
   console.log(time);
   console.log(txEntity);  //print timestamp in entity using local time
   txEntity.timeStamp=ts;
   let due = 60;
   txEntity.deadline=ts + due * 60;
   console.log(txEntity); //print timestamp in entity with the network time
   return nem.model.transactions.send(common, txEntity, testEndpoint).then(function(ret) {
        console.log(ret);
   });
}).catch(function(err) {
   console.error(err);
});

I hope it help you.

2 Likes

@ccastromar Working. Excellent one. Thanks a ton :+1::+1:

@ccastromar

Prepared transaction is the standard way for sending the transaction or to sign the transaction self if the correct one?

I use this way to send transactions.

Internally nem-sdk serializes the data and uses your private key to sign data.

It creates an object that has the “serialized data” and the “signed data” and then sends all this to the NIS Server.
Your private key is not exposed to the nodes.

As in API doc

A RequestAnnounce object is used to transfer the transaction data and the signature to NIS in order to initiate and broadcast a transaction.

JSON structure by example:
{
        "data": "010100000100000000000000200000002b76078fa709bbe675
                 2222b215abc7ec0152ffe831fb4f9aed3e7749a425900a0009
                 3d0000000000000000002800000054444e46555946584f5353
                 334e4e4c4f35465a5348535a49354c33374b4e514945485055
                 4d584c54c0d45407000000000b00000001000000030000000c
                 3215",
        "signature": "db2473513c7f0ce9f8de6345f0fbe773
                      dc687eb571123d08eab4d98f96849eae
                      b63fa8756fb6c59d9b9d0e551537c1cd
                      ad4a564747ff9291db4a88b65c97c10d"
}
Description of the fields:
data:	The transaction data as string. The string is created by first creating the corresponding byte array (see chapter 6.7) and then converting the byte array to a hexadecimal string.
signature:	The signature for the transaction as hexadecimal string.

You mean in this way,

const express = require('express');
const app = express();
require('dotenv').config({ path: '.env.' + app.get('env') });
const nem = require('nem-sdk').default;
let common = nem.model.objects.create('common')('', process.env.TEST_NEM_PRIVATE_KEY);
const testEndpoint = nem.model.objects.create('endpoint')(
  nem.model.nodes.defaultTestnet,
  nem.model.nodes.defaultPort
);
const recipient = "TA4YBG2NAB53POXPDQQI7APINXK74XLXL3YIADUM";
const amount=1;
const message=null;

let transferTx = nem.model.objects.create('transferTransaction')(recipient, amount, message);

let txEntity = nem.model.transactions.prepare('transferTransaction')(common, transferTx, nem.model.network.data.testnet.id);

//workaround
nem.com.requests.chain.time(testEndpoint).then(function(time){
   let ts=Math.floor(time.receiveTimeStamp/1000);
   console.log(time);
   console.log(txEntity);  //print timestamp in entity using local time
   txEntity.timeStamp=ts;
   let due = 60;
   txEntity.deadline=ts + due * 60;
   console.log(txEntity); //print timestamp in entity with the network time
   return nem.model.transactions.send(common, txEntity, testEndpoint).then(function(ret) {
        console.log(ret);
   });
}).catch(function(err) {
   console.error(err);
});

does not expose my private key and it will keep only on client side?

Yeah, that way will send a json object that has “data” and “signature” properties.
You could watch it yourself.
Execute that program with:

NODE_DEBUG=request node yourapp.js

Then you’ll see what json data has been sent.

How can i check that, i have fully working service for the same in my local in node js. Now how can i check this

You could execute your node js local app with:

NODE_DEBUG=request node yournodeapp.js

(set a variable in your environment with NODE_DEBUG=request) so that you will see debug messages with GET and POST headers and json.