github.com/igggame/nebulas-go@v2.1.0+incompatible/nebtestkit/cases/binary/value.test.js (about)

     1  'use strict';
     2  
     3  var expect = require('chai').expect;
     4  var BigNumber = require('bignumber.js');
     5  var HttpRequest = require("../../node-request");
     6  var TestNetConfig = require("../testnet_config.js");
     7  var Wallet;
     8  try {
     9      Wallet = require("../../neb.js");
    10  } catch (e) {
    11      Wallet = require("nebulas");
    12  }
    13  var utils = Wallet.Utils;
    14  var Neb = Wallet.Neb;
    15  var Account = Wallet.Account;
    16  var Transaction = Wallet.Transaction;
    17  var Unit = Wallet.Unit;
    18  
    19  // mocha cases/contract/xxx testneb2 -t 2000000
    20  
    21  var args = process.argv.splice(2);
    22  var env = args[1];
    23  var testNetConfig = new TestNetConfig(env);
    24  
    25  // global vars.
    26  var neb = new Neb();
    27  var ChainID = testNetConfig.ChainId;
    28  var sourceAccount = testNetConfig.sourceAccount;
    29  var coinbase = testNetConfig.coinbase;
    30  var apiEndPoint = testNetConfig.apiEndPoint;
    31  neb.setRequest(new HttpRequest(apiEndPoint));
    32  
    33  
    34  var coinState;
    35  
    36  
    37  var from;
    38  var fromState;
    39  var initFromBalance = 10;
    40  
    41  /*
    42   * set this value according to the status of your testnet.
    43   * the smaller the value, the faster the test, with the risk of causing error
    44   */
    45  
    46  var maxCheckTime = 40;
    47  var checkTimes = 0;
    48  
    49  function checkTransaction(hash, callback) {
    50      checkTimes += 1;
    51  
    52      if (checkTimes > maxCheckTime) {
    53          console.log("check tx receipt timeout:" + hash);
    54          checkTimes = 0;
    55          callback();
    56          return;
    57      }
    58      neb.api.getTransactionReceipt(hash).then(function (resp) {
    59          console.log("0. tx receipt status:" + resp.status);
    60          if (resp.status === 2) {
    61              setTimeout(function () {
    62                  checkTransaction(hash, callback);
    63              }, 2000);
    64          } else {
    65              checkTimes = 0;
    66              callback(resp);
    67          }
    68      }).catch(function (err) {
    69          console.log("1. fail to get tx receipt hash: " + hash);
    70          console.log("2. it may because the tx is being packing, we are going on to check it!");
    71          console.log("3. " + JSON.stringify(err));
    72          setTimeout(function () {
    73              checkTransaction(hash, callback);
    74          }, 2000);
    75      });
    76  }
    77  
    78  function testTransfer(testInput, testExpect, done) {
    79      neb.api.getAccountState(from.getAddressString()).then(function (state) {
    80  
    81          fromState = state;
    82          console.log("from state:" + JSON.stringify(state));
    83          return neb.api.getAccountState(coinbase);
    84      }).then(function (resp) {
    85  
    86          var toAddr = Account.NewAccount();
    87          if (testInput.isSameAddr === true) {
    88              toAddr = from;
    89          }
    90  
    91          coinState = resp;
    92          console.log("get coinbase state before tx:" + JSON.stringify(resp));
    93  
    94  
    95          var tx;
    96  
    97          if (!testInput.hasOwnProperty("payloadLength")) {
    98              tx = new Transaction(ChainID, from, toAddr, Unit.nasToBasic(testInput.transferValue), parseInt(fromState.nonce) + testInput.nonceIncrement, testInput.gasPrice, testInput.gasLimit);
    99          } else {
   100              var payloadContent = new Array(testInput.payloadLength + 1).join("s");
   101              console.log("payloadcontent:" + payloadContent)
   102              tx = new Transaction(ChainID, from, toAddr, Unit.nasToBasic(testInput.transferValue), parseInt(fromState.nonce) + testInput.nonceIncrement, testInput.gasPrice, testInput.gasLimit, payloadContent);
   103          }
   104  
   105          if (testInput.hasOwnProperty("overrideFromAddr")) {
   106              tx.from.address = Wallet.CryptoUtils.bufferToHex(testInput.overrideFromAddr);
   107              console.log("--> override tx.from.address with: " + testInput.overrideFromAddr);
   108          }
   109  
   110          if (testInput.hasOwnProperty("overrideToAddr")) {
   111              tx.to.address = Wallet.CryptoUtils.bufferToHex(testInput.overrideToAddr);
   112              console.log("--> override tx.to.address with: " + testInput.overrideToAddr);
   113          }
   114  
   115          if (testInput.hasOwnProperty("overrideGasLimit")) {
   116              tx.gasLimit = utils.toBigNumber(testInput.overrideGasLimit);
   117              console.log("--> override tx.gasLimit: " + tx.gasLimit);
   118          }
   119  
   120          if (testInput.hasOwnProperty("overrideGasPrice")) {
   121              tx.gasPrice = utils.toBigNumber(testInput.overrideGasPrice);
   122              console.log("--> override tx.gasPrice: " + tx.gasPrice);
   123          }
   124  
   125          tx.signTransaction();
   126  
   127          if (testInput.hasOwnProperty("overrideSignature")) {
   128              tx.sign = testInput.overrideSignature;
   129          } else if (testInput.fakeSign) {
   130              //repalce the privkey to sign
   131              console.log("this is the right signature:" + tx.sign.toString('hex'));
   132              console.log("repalce the privkey and sign another signatrue...")
   133              var newAccount = new Wallet.Account("a6e5eb222e4538fce79f5cb8774a72621637c2c9654c8b2525ed1d7e4e73653f");
   134              var privKey = tx.from.privKey
   135              tx.from.privKey = newAccount.privKey
   136              tx.signTransaction();
   137              console.log("now signatrue is: " + tx.sign.toString('hex'));
   138              tx.from.privKey = privKey;
   139          }
   140  
   141          console.log("tx to be sent: " + tx.toString());
   142          //console.log("tx to be send: " + JSON.stringify(JSON.parse(tx.toString()),null,'\t')); //json format output
   143          return neb.api.sendRawTransaction(tx.toProtoString());
   144  
   145      }).catch(function (err) {
   146          if (true === testExpect.canSendTx) {
   147              done(err);
   148          } else {
   149              console.log("cannot send tx, err: ", err);
   150              if (testExpect.hasOwnProperty("errMsg")) {
   151                  expect(err.error.error).to.be.equal(testExpect.errMsg);
   152                  // expect(testExpect.errMsg).to.be.equal(err);
   153              }
   154              done();
   155          }
   156      }).then(function (resp) {
   157  
   158          console.log("resp11:" + JSON.stringify(resp));
   159  
   160          if (true === testExpect.canSendTx) {
   161              console.log("send Raw Tx:" + JSON.stringify(resp));
   162              expect(resp).to.be.have.property('txhash');
   163              checkTransaction(resp.txhash, function (receipt) {
   164  
   165                  try {
   166                      if (true === testExpect.canSubmitTx) {
   167                          expect(receipt).to.not.be.a('undefined');
   168                          if (true === testExpect.canExcuteTx) {
   169                              expect(receipt).to.be.have.property('status').equal(1);
   170                          } else {
   171                              expect(receipt).to.be.have.property('status').equal(0);
   172                          }
   173                          console.log("tx receipt : " + JSON.stringify(receipt));
   174                          neb.api.getAccountState(receipt.from).then(function (state) {
   175  
   176                              console.log("get from account state :" + JSON.stringify(state));
   177                              expect(state.balance).to.equal(testExpect.fromBalanceAfterTx);
   178                              return neb.api.getAccountState(receipt.to);
   179                          }).then(function (state) {
   180  
   181                              console.log("get to account state :" + JSON.stringify(state));
   182                              expect(state.balance).to.equal(testExpect.toBalanceAfterTx);
   183                              return neb.api.getAccountState(coinbase);
   184                          }).then(function (state) {
   185  
   186                              console.log("get coinbase account state after tx:" + JSON.stringify(state));
   187                              var reward = new BigNumber(state.balance).sub(coinState.balance);
   188                              reward = reward.mod(new BigNumber(1.42694).mul(new BigNumber(10).pow(18)));
   189                              // The transaction should be only
   190                              expect(reward.toString()).to.equal(testExpect.transferReward);
   191                              return neb.api.getEventsByHash(resp.txhash);
   192                          }).then(function (eventResult) {
   193                              console.log("[eventCheck] event[0] topic: " + JSON.stringify(eventResult.events[0].topic));
   194                              if (ChainID !== 100) {
   195                                  expect(eventResult.events[0].topic).to.equal("chain.transactionResult");
   196                              }
   197                              if (eventResult.hasOwnProperty('eventError')) {
   198                                  expect(eventResult.events[0].error).to.equal(eventResult.eventError);
   199                              }
   200                              done();
   201                          }).catch(function (err) {
   202                              console.log(JSON.stringify(err));
   203                              done(err);
   204                          });
   205                      } else {
   206                          expect(receipt).to.be.a('undefined');
   207                          console.log("transaction can send but submit failed");
   208                          done();
   209                      }
   210                  } catch (err) {
   211                      console.log(JSON.stringify(err));
   212                      done(err);
   213                  }
   214              });
   215          } else {
   216              console.log(JSON.stringify(resp))
   217              expect(resp).to.be.a('undefined');
   218          }
   219      }).catch(function (err) {
   220          //TODO test case should fail: a tx which is expected "canNotSendTX" is send
   221          console.log(JSON.stringify(err));
   222          done(err);
   223      });
   224  }
   225  
   226  
   227  function prepare(done) {
   228      from = Account.NewAccount();
   229      neb.api.getAccountState(sourceAccount.getAddressString()).then(function (resp) {
   230          console.log("source state:" + JSON.stringify(resp));
   231          var tx = new Transaction(ChainID, sourceAccount, from, Unit.nasToBasic(initFromBalance), parseInt(resp.nonce) + 1);
   232          tx.signTransaction();
   233          // console.log("source tx:" + tx.toString());
   234          return neb.api.sendRawTransaction(tx.toProtoString());
   235      }).then(function (resp) {
   236          console.log("prepare: ", resp);
   237          checkTransaction(resp.txhash, function (resp) {
   238              try {
   239                  expect(resp).to.be.have.property('status').equal(1);
   240                  console.log("complete from address claim.");
   241                  done();
   242              } catch (err) {
   243                  done(err);
   244              }
   245          });
   246      }).catch(function (err) {
   247          console.log("claim token failed:" + JSON.stringify(err));
   248          done(err);
   249      });
   250  };
   251  
   252  describe('normal transaction', function () {
   253      it('normal transfer11', function (done) {
   254          var testInput = {
   255              transferValue: 1,
   256              isSameAddr: false,
   257              gasLimit: -1,
   258              gasPrice: -1,
   259              nonceIncrement: 1
   260          };
   261          //can calc value by previous params
   262          var testExpect = {
   263              canSendTx: true,
   264              canSubmitTx: true,
   265              canExcuteTx: true,
   266              fromBalanceAfterTx: '8999999980000000000',
   267              toBalanceAfterTx: '1000000000000000000',
   268              transferReward: '20000000000'
   269          };
   270  
   271          prepare(function (err) {
   272              if (err instanceof Error) {
   273                  done(err);
   274              } else {
   275                  testTransfer(testInput, testExpect, done);
   276              }
   277          });
   278      });
   279  
   280      it('[address invalid] invalid fromAddr (length is odd)', function (done) {
   281          var testInput = {
   282              transferValue: 1,
   283              isSameAddr: false,
   284              gasLimit: -1,
   285              gasPrice: -1,
   286              nonceIncrement: 1,
   287              overrideFromAddr: "01239120abdcde01239120abdcde"
   288          };
   289          //can calc value by previous params
   290          var testExpect = {
   291              canSendTx: false,
   292              canSubmitTx: false,
   293              canExcuteTx: false,
   294              fromBalanceAfterTx: '8999999980000000000',
   295              toBalanceAfterTx: '1000000000000000000',
   296              transferReward: '20000000000',
   297              errMsg: 'address: invalid address format'
   298          };
   299          prepare(function (err) {
   300              if (err instanceof Error) {
   301                  done(err);
   302              } else {
   303                  testTransfer(testInput, testExpect, done);
   304              }
   305          });
   306      });
   307  
   308      it('[address invalid] invalid fromAddr (length is even)', function (done) {
   309          var testInput = {
   310              transferValue: 1,
   311              isSameAddr: false,
   312              gasLimit: -1,
   313              gasPrice: -1,
   314              nonceIncrement: 1,
   315              overrideFromAddr: "01239120abdcde01239120abdcde1"
   316          };
   317          //can calc value by previous params
   318          var testExpect = {
   319              canSendTx: false,
   320              canSubmitTx: false,
   321              canExcuteTx: false,
   322              fromBalanceAfterTx: '8999999980000000000',
   323              toBalanceAfterTx: '1000000000000000000',
   324              transferReward: '20000000000',
   325              errMsg: 'address: invalid address format'
   326          };
   327          prepare(function (err) {
   328              if (err instanceof Error) {
   329                  done(err);
   330              } else {
   331                  testTransfer(testInput, testExpect, done);
   332              }
   333          });
   334      });
   335  
   336      it('[address invalid] invalid fromAddr (length exceed limits)', function (done) {
   337          var testInput = {
   338              transferValue: 1,
   339              isSameAddr: false,
   340              gasLimit: -1,
   341              gasPrice: -1,
   342              nonceIncrement: 1,
   343              overrideFromAddr: "01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde"
   344          };
   345          //can calc value by previous params
   346          var testExpect = {
   347              canSendTx: false,
   348              canSubmitTx: false,
   349              canExcuteTx: false,
   350              fromBalanceAfterTx: '8999999980000000000',
   351              toBalanceAfterTx: '1000000000000000000',
   352              transferReward: '20000000000',
   353              errMsg: 'address: invalid address format'
   354          };
   355          prepare(function (err) {
   356              if (err instanceof Error) {
   357                  done(err);
   358              } else {
   359                  testTransfer(testInput, testExpect, done);
   360              }
   361          });
   362      });
   363  
   364      it('[address invalid] invalid toAddr (length is odd)', function (done) {
   365          var testInput = {
   366              transferValue: 1,
   367              isSameAddr: false,
   368              gasLimit: -1,
   369              gasPrice: -1,
   370              nonceIncrement: 1,
   371              overrideToAddr: "01239120abdcde01239120abdcde"
   372          };
   373          //can calc value by previous params
   374          var testExpect = {
   375              canSendTx: false,
   376              canSubmitTx: false,
   377              canExcuteTx: false,
   378              fromBalanceAfterTx: '8999999980000000000',
   379              toBalanceAfterTx: '1000000000000000000',
   380              transferReward: '20000000000',
   381              errMsg: 'address: invalid address format'
   382          };
   383          prepare(function (err) {
   384              if (err instanceof Error) {
   385                  done(err);
   386              } else {
   387                  testTransfer(testInput, testExpect, done);
   388              }
   389          });
   390      });
   391  
   392      it('[address invalid] invalid toAddr (length is even)', function (done) {
   393          var testInput = {
   394              transferValue: 1,
   395              isSameAddr: false,
   396              gasLimit: -1,
   397              gasPrice: -1,
   398              nonceIncrement: 1,
   399              overrideToAddr: "01239120abdcde01239120abdcde1"
   400          };
   401          //can calc value by previous params
   402          var testExpect = {
   403              canSendTx: false,
   404              canSubmitTx: false,
   405              canExcuteTx: false,
   406              fromBalanceAfterTx: '8999999980000000000',
   407              toBalanceAfterTx: '1000000000000000000',
   408              transferReward: '20000000000',
   409              errMsg: 'address: invalid address format'
   410          };
   411          prepare(function (err) {
   412              if (err instanceof Error) {
   413                  done(err);
   414              } else {
   415                  testTransfer(testInput, testExpect, done);
   416              }
   417          });
   418      });
   419  
   420      it('[address invalid] invalid toAddr (length exceed limits)', function (done) {
   421          var testInput = {
   422              transferValue: 1,
   423              isSameAddr: false,
   424              gasLimit: -1,
   425              gasPrice: -1,
   426              nonceIncrement: 1,
   427              overrideToAddr: "01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde01239120abdcde"
   428          };
   429          //can calc value by previous params
   430          var testExpect = {
   431              canSendTx: false,
   432              canSubmitTx: false,
   433              canExcuteTx: false,
   434              fromBalanceAfterTx: '8999999980000000000',
   435              toBalanceAfterTx: '1000000000000000000',
   436              transferReward: '20000000000',
   437              errMsg: 'address: invalid address format'
   438          };
   439          prepare(function (err) {
   440              if (err instanceof Error) {
   441                  done(err);
   442              } else {
   443                  testTransfer(testInput, testExpect, done);
   444              }
   445          });
   446      });
   447  
   448      it('[address invalid] from addr empty', function (done) {
   449          var testInput = {
   450              transferValue: 1,
   451              isSameAddr: false,
   452              gasLimit: -1,
   453              gasPrice: -1,
   454              nonceIncrement: 1,
   455              overrideFromAddr: ""
   456          };
   457          //can calc value by previous params
   458          var testExpect = {
   459              canSendTx: false,
   460              canSubmitTx: false,
   461              canExcuteTx: false,
   462              fromBalanceAfterTx: '8999999980000000000',
   463              toBalanceAfterTx: '1000000000000000000',
   464              transferReward: '20000000000',
   465              errMsg: 'address: invalid address format'
   466          };
   467          prepare(function (err) {
   468              if (err instanceof Error) {
   469                  done(err);
   470              } else {
   471                  testTransfer(testInput, testExpect, done);
   472              }
   473          });
   474      });
   475  
   476      it('[address invalid] to addr empty', function (done) {
   477          var testInput = {
   478              transferValue: 1,
   479              isSameAddr: false,
   480              gasLimit: -1,
   481              gasPrice: -1,
   482              nonceIncrement: 1,
   483              overrideToAddr: ""
   484          };
   485          //can calc value by previous params
   486          var testExpect = {
   487              canSendTx: false,
   488              canSubmitTx: false,
   489              canExcuteTx: false,
   490              fromBalanceAfterTx: '8999999980000000000',
   491              toBalanceAfterTx: '1000000000000000000',
   492              transferReward: '20000000000',
   493              errMsg: 'address: invalid address format'
   494          };
   495          prepare(function (err) {
   496              if (err instanceof Error) {
   497                  done(err);
   498              } else {
   499                  testTransfer(testInput, testExpect, done);
   500              }
   501          });
   502      });
   503  
   504      it('[address] from & to are same', function (done) {
   505          var testInput = {
   506              transferValue: 1,
   507              isSameAddr: true,
   508              gasLimit: -1,
   509              gasPrice: -1,
   510              nonceIncrement: 1
   511          };
   512          //can calc value by previous params
   513          var testExpect = {
   514              canSendTx: true,
   515              canSubmitTx: true,
   516              canExcuteTx: true,
   517              fromBalanceAfterTx: '9999999980000000000',
   518              toBalanceAfterTx: '9999999980000000000',
   519              transferReward: '20000000000'
   520          };
   521          prepare(function (err) {
   522              if (err instanceof Error) {
   523                  done(err);
   524              } else {
   525                  testTransfer(testInput, testExpect, done);
   526              }
   527          });
   528      });
   529  
   530      it('[signature] invalid signature (wrong sig)', function (done) {
   531          var testInput = {
   532              transferValue: 1,
   533              isSameAddr: false,
   534              gasLimit: -1,
   535              gasPrice: -1,
   536              nonceIncrement: 1,
   537              overrideSignature: "some_wrong_sig"
   538          };
   539          //can calc value by previous params
   540          var testExpect = {
   541              canSendTx: false,
   542              canSubmitTx: false,
   543              canExcuteTx: true,
   544              fromBalanceAfterTx: '8999999980000000000',
   545              toBalanceAfterTx: '1000000000000000000',
   546              transferReward: '20000000000',
   547              errMsg: 'invalid signature'
   548          };
   549          prepare(function (err) {
   550              if (err instanceof Error) {
   551                  done(err);
   552              } else {
   553                  testTransfer(testInput, testExpect, done);
   554              }
   555          });
   556      });
   557  
   558      it('[signature] invalid signature (empty sig)', function (done) {
   559          var testInput = {
   560              transferValue: 1,
   561              isSameAddr: false,
   562              gasLimit: -1,
   563              gasPrice: -1,
   564              nonceIncrement: 1,
   565              overrideSignature: ""
   566          };
   567          //can calc value by previous params
   568          var testExpect = {
   569              canSendTx: false,
   570              canSubmitTx: false,
   571              canExcuteTx: true,
   572              fromBalanceAfterTx: '8999999980000000000',
   573              toBalanceAfterTx: '1000000000000000000',
   574              transferReward: '20000000000',
   575              errMsg: 'invalid signature'
   576          };
   577          prepare(function (err) {
   578              if (err instanceof Error) {
   579                  done(err);
   580              } else {
   581                  testTransfer(testInput, testExpect, done);
   582              }
   583          });
   584      });
   585  
   586      it('[signature] invalid signature (fake sig)', function (done) {
   587          var testInput = {
   588              transferValue: 1,
   589              isSameAddr: false,
   590              gasLimit: -1,
   591              gasPrice: -1,
   592              nonceIncrement: 1,
   593              fakeSign: true
   594          };
   595          //can calc value by previous params
   596          var testExpect = {
   597              canSendTx: false,
   598              canSubmitTx: false,
   599              canExcuteTx: false,
   600              fromBalanceAfterTx: '',
   601              toBalanceAfterTx: '',
   602              transferReward: '',
   603              errMsg: 'invalid transaction signer'
   604          };
   605          prepare(function (err) {
   606              if (err instanceof Error) {
   607                  done(err);
   608              } else {
   609                  testTransfer(testInput, testExpect, done);
   610              }
   611          });
   612      });
   613  
   614      it('[gasLimit insufficient] 0 < gasLimit = TxBaseGasCount-1', function (done) {
   615  
   616          var testInput = {
   617              transferValue: 1,
   618              isSameAddr: false,
   619              gasLimit: 19999,
   620              gasPrice: -1,
   621              nonceIncrement: 1
   622          };
   623  
   624          var testExpect = {
   625              canSendTx: true,
   626              canSubmitTx: false,
   627              canExcuteTx: true,
   628              fromBalanceAfterTx: '8999999980000000000',
   629              toBalanceAfterTx: '1000000000000000000',
   630              transferReward: '20000000000'
   631          };
   632          prepare(function (err) {
   633              if (err instanceof Error) {
   634                  done(err);
   635              } else {
   636                  testTransfer(testInput, testExpect, done);
   637              }
   638          });
   639      });
   640  
   641      it('[gasLimit insufficient] 1 = gasLimit < TxBaseGasCount', function (done) {
   642  
   643          var testInput = {
   644              transferValue: 1,
   645              isSameAddr: false,
   646              gasLimit: 1,
   647              gasPrice: -1,
   648              nonceIncrement: 1
   649          };
   650          //can calc value by previous params
   651          var testExpect = {
   652              canSendTx: true,
   653              canSubmitTx: false,
   654              canExcuteTx: false,
   655              fromBalanceAfterTx: '-1',
   656              toBalanceAfterTx: '-1',
   657              transferReward: '-1'
   658          };
   659          prepare(function (err) {
   660              if (err instanceof Error) {
   661                  done(err);
   662              } else {
   663                  testTransfer(testInput, testExpect, done);
   664              }
   665          });
   666      });
   667  
   668  
   669      it('[gasLimit sufficient] gasLimit<0', function (done) {
   670          var testInput = {
   671              transferValue: 1,
   672              isSameAddr: false,
   673              gasLimit: 0,
   674              overrideGasLimit: -100,
   675              gasPrice: -1,
   676              nonceIncrement: 1
   677          };
   678          //can calc value by previous params
   679          var testExpect = {
   680              canSendTx: false,
   681              canSubmitTx: false,
   682              canExcuteTx: false,
   683              fromBalanceAfterTx: '8999999980000000000',
   684              toBalanceAfterTx: '1000000000000000000',
   685              transferReward: '20000000000',
   686              errMsg: 'invalid gas limit, should be in (0, 5*10^10]'
   687          };
   688          prepare(function (err) {
   689              if (err instanceof Error) {
   690                  done(err);
   691              } else {
   692                  testTransfer(testInput, testExpect, done);
   693              }
   694          });
   695      });
   696  
   697      it('[gasLimit sufficient] gasLimit=0', function (done) {
   698          var testInput = {
   699              transferValue: 1,
   700              isSameAddr: false,
   701              gasLimit: 0,
   702              overrideGasLimit: 0,
   703              gasPrice: -1,
   704              nonceIncrement: 1
   705          };
   706          //can calc value by previous params
   707          var testExpect = {
   708              canSendTx: false,
   709              canSubmitTx: false,
   710              canExcuteTx: false,
   711              fromBalanceAfterTx: '8999999980000000000',
   712              toBalanceAfterTx: '1000000000000000000',
   713              transferReward: '20000000000',
   714              errMsg: 'invalid gas limit, should be in (0, 5*10^10]'
   715          };
   716          prepare(function (err) {
   717              if (err instanceof Error) {
   718                  done(err);
   719              } else {
   720                  testTransfer(testInput, testExpect, done);
   721              }
   722          });
   723      });
   724  
   725      it('[gasLimit sufficient] gasLimit > TransactionMaxGase', function (done) {
   726          var testInput = {
   727              transferValue: 1,
   728              isSameAddr: false,
   729              gasLimit: 50000000001,
   730              gasPrice: -1,
   731              nonceIncrement: 1
   732          };
   733          //can calc value by previous params
   734          var testExpect = {
   735              canSendTx: false,
   736              canSubmitTx: false,
   737              canExcuteTx: false,
   738              fromBalanceAfterTx: '10000000000000000000',
   739              toBalanceAfterTx: '0',
   740              transferReward: '0',
   741              errMsg: 'invalid gas limit, should be in (0, 5*10^10]'
   742          };
   743          prepare(function (err) {
   744              if (err instanceof Error) {
   745                  done(err);
   746              } else {
   747                  testTransfer(testInput, testExpect, done);
   748              }
   749          });
   750      });
   751  
   752      it('[gasLimit sufficient] gasLimit=TxBaseGasCount', function (done) {
   753          var testInput = {
   754              transferValue: 1,
   755              isSameAddr: false,
   756              gasLimit: 20000,
   757              gasPrice: -1,
   758              nonceIncrement: 1
   759          };
   760          //can calc value by previous params
   761          var testExpect = {
   762              canSendTx: true,
   763              canSubmitTx: true,
   764              canExcuteTx: true,
   765              fromBalanceAfterTx: '8999999980000000000',
   766              toBalanceAfterTx: '1000000000000000000',
   767              transferReward: '20000000000'
   768          };
   769          prepare(function (err) {
   770              if (err instanceof Error) {
   771                  done(err);
   772              } else {
   773                  testTransfer(testInput, testExpect, done);
   774              }
   775          });
   776      });
   777  
   778      it('[gasLimit sufficient] gasLimit>TxBaseGasCount', function (done) {
   779          var testInput = {
   780              transferValue: 1,
   781              isSameAddr: false,
   782              gasLimit: 20001,
   783              gasPrice: -1,
   784              nonceIncrement: 1
   785          };
   786          //can calc value by previous params
   787          var testExpect = {
   788              canSendTx: true,
   789              canSubmitTx: true,
   790              canExcuteTx: true,
   791              fromBalanceAfterTx: '8999999980000000000',
   792              toBalanceAfterTx: '1000000000000000000',
   793              transferReward: '20000000000'
   794          };
   795          prepare(function (err) {
   796              if (err instanceof Error) {
   797                  done(err);
   798              } else {
   799                  testTransfer(testInput, testExpect, done);
   800              }
   801          });
   802      });
   803  
   804      it('[gasPrice insufficient] gasPrice<0', function (done) {
   805          var testInput = {
   806              transferValue: 1,
   807              isSameAddr: false,
   808              gasLimit: -1,
   809              gasPrice: -1,
   810              overrideGasPrice: -1,
   811              nonceIncrement: 1
   812          };
   813          //can calc value by previous params
   814          var testExpect = {
   815              canSendTx: false,
   816              canSubmitTx: false,
   817              canExcuteTx: false,
   818              fromBalanceAfterTx: '8999999980000000000',
   819              toBalanceAfterTx: '1000000000000000000',
   820              transferReward: '20000000000',
   821              errMsg: 'invalid gas price, should be in (0, 10^12]'
   822          };
   823          prepare(function (err) {
   824              if (err instanceof Error) {
   825                  done(err);
   826              } else {
   827                  testTransfer(testInput, testExpect, done);
   828              }
   829          });
   830      });
   831  
   832      it('[gasPrice sufficient] gasPrice=0', function (done) {
   833          var testInput = {
   834              transferValue: 1,
   835              isSameAddr: false,
   836              gasLimit: 0,
   837              gasPrice: 0,
   838              overrideGasPrice: 0,
   839              nonceIncrement: 1
   840          };
   841          //can calc value by previous params
   842          var testExpect = {
   843              canSendTx: false,
   844              canSubmitTx: false,
   845              canExcuteTx: false,
   846              fromBalanceAfterTx: '8999999980000000000',
   847              toBalanceAfterTx: '1000000000000000000',
   848              transferReward: '20000000000',
   849              errMsg: 'invalid gas price, should be in (0, 10^12]'
   850          };
   851          prepare(function (err) {
   852              if (err instanceof Error) {
   853                  done(err);
   854              } else {
   855                  testTransfer(testInput, testExpect, done);
   856              }
   857          });
   858      });
   859  
   860      it('[gasPrice sufficient] gasPrice = txPool.gasPrice', function (done) {
   861          var testInput = {
   862              transferValue: 1,
   863              isSameAddr: false,
   864              gasLimit: 0,
   865              gasPrice: 1000000,
   866              nonceIncrement: 1
   867          };
   868          //can calc value by previous params
   869          var testExpect = {
   870              canSendTx: true,
   871              canSubmitTx: true,
   872              canExcuteTx: true,
   873              fromBalanceAfterTx: '8999999980000000000',
   874              toBalanceAfterTx: '1000000000000000000',
   875              transferReward: '20000000000'
   876          };
   877          prepare(function (err) {
   878              if (err instanceof Error) {
   879                  done(err);
   880              } else {
   881                  testTransfer(testInput, testExpect, done);
   882              }
   883          });
   884      });
   885      it('[gasPrice sufficient] gasPrice = 2 * txPool.baseGasPrice', function (done) {
   886          var testInput = {
   887              transferValue: 1,
   888              isSameAddr: false,
   889              gasLimit: -1,
   890              gasPrice: 2000000,
   891              nonceIncrement: 1
   892          };
   893          //can calc value by previous params
   894          var testExpect = {
   895              canSendTx: true,
   896              canSubmitTx: true,
   897              canExcuteTx: true,
   898              fromBalanceAfterTx: '8999999960000000000',
   899              toBalanceAfterTx: '1000000000000000000',
   900              transferReward: '40000000000'
   901          };
   902          prepare(function (err) {
   903              if (err instanceof Error) {
   904                  done(err);
   905              } else {
   906                  testTransfer(testInput, testExpect, done);
   907              }
   908          });
   909      });
   910  
   911      it('gas price is too small', function (done) {
   912  
   913          var testInput = {
   914              transferValue: 1,
   915              isSameAddr: false,
   916              gasLimit: -1,
   917              gasPrice: 1,
   918              nonceIncrement: 1
   919          };
   920          //can calc value by previous params
   921          var testExpect = {
   922              canSendTx: false,
   923              canSubmitTx: false,
   924              canExcuteTx: false,
   925              fromBalanceAfterTx: '-1',
   926              toBalanceAfterTx: '-1',
   927              transferReward: '-1',
   928              errMsg: 'below the gas price'
   929          };
   930          prepare(function (err) {
   931              if (err instanceof Error) {
   932                  done(err);
   933              } else {
   934                  testTransfer(testInput, testExpect, done);
   935              }
   936          });
   937      });
   938  
   939      it('[gasPrice insufficient] gasPrice < txPool.gasPrice', function (done) {
   940          var testInput = {
   941              transferValue: 1,
   942              isSameAddr: false,
   943              gasLimit: 0,
   944              gasPrice: 99999,
   945              nonceIncrement: 1
   946          };
   947          //can calc value by previous params
   948          var testExpect = {
   949              canSendTx: false,
   950              canSubmitTx: false,
   951              canExcuteTx: false,
   952              fromBalanceAfterTx: '',
   953              toBalanceAfterTx: '',
   954              transferReward: '',
   955              errMsg: 'below the gas price'
   956          };
   957          prepare(function (err) {
   958              if (err instanceof Error) {
   959                  done(err);
   960              } else {
   961                  testTransfer(testInput, testExpect, done);
   962              }
   963          });
   964      });
   965  
   966      it('[balanceOfFrom insufficient] gasPrice * gasLimit <= balanceOfFrom < valueOfTx ', function (done) {
   967  
   968          var testInput = {
   969              transferValue: 10.1,
   970              isSameAddr: false,
   971              gasLimit: -1,
   972              gasPrice: -1,
   973              nonceIncrement: 1
   974          };
   975          //can calc value by previous params
   976          var testExpect = {
   977              canSendTx: true,
   978              canSubmitTx: true,
   979              canExcuteTx: false,
   980              fromBalanceAfterTx: '9999999980000000000',
   981              toBalanceAfterTx: '0',
   982              transferReward: '20000000000',
   983              eventError: 'insufficient balance'
   984          };
   985          prepare(function (err) {
   986              if (err instanceof Error) {
   987                  done(err);
   988              } else {
   989                  testTransfer(testInput, testExpect, done);
   990              }
   991          });
   992      });
   993  
   994      it('[balanceOfFrom insufficient] balanceOfFrom < TxBaseGasCount * gasPrice + valueOfTx', function (done) {
   995  
   996          var testInput = {
   997              transferValue: 9.999999999999,
   998              isSameAddr: false,
   999              gasLimit: -1,
  1000              gasPrice: -1,
  1001              nonceIncrement: 1
  1002          };
  1003          //can calc value by previous params
  1004          var testExpect = {
  1005              canSendTx: true,
  1006              canSubmitTx: true,
  1007              canExcuteTx: false,
  1008              fromBalanceAfterTx: '9999999980000000000',
  1009              toBalanceAfterTx: '0',
  1010              transferReward: '20000000000'
  1011          };
  1012          prepare(function (err) {
  1013              if (err instanceof Error) {
  1014                  done(err);
  1015              } else {
  1016                  testTransfer(testInput, testExpect, done);
  1017              }
  1018          });
  1019      });
  1020  
  1021  
  1022  
  1023      it('[balanceOfFrom insufficient] balanceOfFrom < gasPrice * gasLimit', function (done) {
  1024  
  1025          var testInput = {
  1026              transferValue: 1,
  1027              isSameAddr: false,
  1028              gasLimit: 50000000000,
  1029              gasPrice: 210000000,
  1030              nonceIncrement: 1
  1031          };
  1032          //can calc value by previous params
  1033          var testExpect = {
  1034              canSendTx: true,
  1035              canSubmitTx: false,
  1036              canExcuteTx: false,
  1037              fromBalanceAfterTx: '-1',
  1038              toBalanceAfterTx: '-1',
  1039              transferReward: '-1'
  1040          };
  1041          prepare(function (err) {
  1042              if (err instanceof Error) {
  1043                  done(err);
  1044              } else {
  1045                  testTransfer(testInput, testExpect, done);
  1046              }
  1047          });
  1048      });
  1049  
  1050      it('[balanceOfFrom insufficient] from = to && balanceOfFrom < valueOfTx', function (done) {
  1051  
  1052          var testInput = {
  1053              transferValue: 15,
  1054              isSameAddr: true,
  1055              gasLimit: -1,
  1056              gasPrice: -1,
  1057              nonceIncrement: 1
  1058          };
  1059          //can calc value by previous params
  1060          var testExpect = {
  1061              canSendTx: true,
  1062              canSubmitTx: true,
  1063              canExcuteTx: false,
  1064              fromBalanceAfterTx: '9999999980000000000',
  1065              toBalanceAfterTx: '9999999980000000000',
  1066              transferReward: '20000000000',
  1067              eventError: 'insufficient balance'
  1068          };
  1069          prepare(function (err) {
  1070              if (err instanceof Error) {
  1071                  done(err);
  1072              } else {
  1073                  testTransfer(testInput, testExpect, done);
  1074              }
  1075          });
  1076  
  1077      });
  1078  
  1079  
  1080  
  1081      it('[nonce check] nonce < from.nonce + 1', function (done) {
  1082  
  1083          var testInput = {
  1084              transferValue: 1,
  1085              isSameAddr: false,
  1086              gasLimit: -1,
  1087              gasPrice: -1,
  1088              nonceIncrement: 0
  1089          };
  1090          //can calc value by previous params
  1091          var testExpect = {
  1092              canSendTx: false,
  1093              canSubmitTx: false,
  1094              canExcuteTx: false,
  1095              fromBalanceAfterTx: '-1',
  1096              toBalanceAfterTx: '-1',
  1097              transferReward: '-1',
  1098              errMsg: 'transaction\'s nonce is invalid, should bigger than the from\'s nonce'
  1099          };
  1100          prepare(function (err) {
  1101              if (err instanceof Error) {
  1102                  done(err);
  1103              } else {
  1104                  testTransfer(testInput, testExpect, done);
  1105              }
  1106          });
  1107      });
  1108  
  1109  
  1110      it('[nonce check] nonce > from.nonce + 1', function (done) {
  1111  
  1112          var testInput = {
  1113              transferValue: 1,
  1114              isSameAddr: false,
  1115              gasLimit: -1,
  1116              gasPrice: -1,
  1117              nonceIncrement: 2
  1118          };
  1119          //can calc value by previous params
  1120          var testExpect = {
  1121              canSendTx: true,
  1122              canSubmitTx: false,
  1123              canExcuteTx: false,
  1124              fromBalanceAfterTx: '-1',
  1125              toBalanceAfterTx: '-1',
  1126              transferReward: '-1'
  1127          };
  1128          prepare(function (err) {
  1129              if (err instanceof Error) {
  1130                  done(err);
  1131              } else {
  1132                  testTransfer(testInput, testExpect, done);
  1133              }
  1134          });
  1135      });
  1136  
  1137  
  1138      it('[nonce check] nonce < 0', function (done) {
  1139  
  1140          var testInput = {
  1141              transferValue: 1,
  1142              isSameAddr: false,
  1143              gasLimit: -1,
  1144              gasPrice: -1,
  1145              nonceIncrement: -10000000000
  1146          };
  1147          //can calc value by previous params
  1148          var testExpect = {
  1149              canSendTx: false,
  1150              canSubmitTx: false,
  1151              canExcuteTx: false,
  1152              fromBalanceAfterTx: '-1',
  1153              toBalanceAfterTx: '-1',
  1154              transferReward: '-1',
  1155              //errMsg: 'transaction\'s nonce is invalid, should bigger than the from\'s nonce'
  1156              errMsg: 'invalid transaction hash' //TODO is this error right?
  1157          };
  1158          prepare(function (err) {
  1159              if (err instanceof Error) {
  1160                  done(err);
  1161              } else {
  1162                  testTransfer(testInput, testExpect, done);
  1163              }
  1164          });
  1165      });
  1166  
  1167  
  1168      it('[balanceOfFrom sufficient] balanceOfFrom = GasLimit * GasPrice + valueOfTx ', function (done) {
  1169  
  1170          var testInput = {
  1171              transferValue: 9.99999998,
  1172              isSameAddr: false,
  1173              gasLimit: 20000,
  1174              gasPrice: 1000000,
  1175              nonceIncrement: 1
  1176          };
  1177          //can calc value by previous params
  1178          var testExpect = {
  1179              canSendTx: true,
  1180              canSubmitTx: true,
  1181              canExcuteTx: true,
  1182              fromBalanceAfterTx: '0',
  1183              toBalanceAfterTx: '9999999980000000000',
  1184              transferReward: '20000000000'
  1185          };
  1186          prepare(function (err) {
  1187              if (err instanceof Error) {
  1188                  done(err);
  1189              } else {
  1190                  testTransfer(testInput, testExpect, done);
  1191              }
  1192          });
  1193      });
  1194  
  1195  
  1196      it('[balanceOfFrom sufficient] (GasLimit * GasPrice + valueOfTx) > balanceOfFrom ' +
  1197          '&& balanceOfFrom = TxBaseGasCount * GasPrice + valueOfTx  ', function (done) {
  1198  
  1199          var testInput = {
  1200              transferValue: 9.99999998,
  1201              isSameAddr: false,
  1202              gasLimit: 400000,
  1203              gasPrice: 1000000,
  1204              nonceIncrement: 1
  1205          };
  1206  
  1207          // The TxBaseGasCount in neb is 20000
  1208  
  1209          var testExpect = {
  1210              canSendTx: true,
  1211              canSubmitTx: true,
  1212              canExcuteTx: false,
  1213              fromBalanceAfterTx: '9999999980000000000',
  1214              toBalanceAfterTx: '0',
  1215              transferReward: '20000000000'
  1216          };
  1217          prepare(function (err) {
  1218              if (err instanceof Error) {
  1219                  done(err);
  1220              } else {
  1221                  testTransfer(testInput, testExpect, done);
  1222              }
  1223          });
  1224      });
  1225  
  1226  
  1227      it('[ payload > 0 ] normal transfer', function (done) {
  1228          var testInput = {
  1229              transferValue: 1,
  1230              isSameAddr: false,
  1231              gasLimit: 30000,
  1232              gasPrice: -1,
  1233              nonceIncrement: 1,
  1234              payloadLength: 99
  1235          };
  1236          //can calc value by previous params
  1237          var testExpect = {
  1238              canSendTx: true,
  1239              canSubmitTx: true,
  1240              canExcuteTx: true,
  1241              fromBalanceAfterTx: '8999999979964000000',
  1242              toBalanceAfterTx: '1000000000000000000',
  1243              transferReward: '20036000000'
  1244          };
  1245          prepare(function (err) {
  1246              if (err instanceof Error) {
  1247                  done(err);
  1248              } else {
  1249                  testTransfer(testInput, testExpect, done);
  1250              }
  1251          });
  1252      });
  1253  
  1254      it('[ payload > 0 gaslimit ] TxBaseGasCount > gasLimit = minGasPerTransaction ', function (done) {
  1255          var testInput = {
  1256              transferValue: 1,
  1257              isSameAddr: false,
  1258              gasLimit: 20001,
  1259              gasPrice: -1,
  1260              nonceIncrement: 1,
  1261              payloadLength: 99
  1262          };
  1263          //can calc value by previous params
  1264          var testExpect = {
  1265              canSendTx: true,
  1266              canSubmitTx: false,
  1267              canExcuteTx: false,
  1268              fromBalanceAfterTx: '8999999979964000000',
  1269              toBalanceAfterTx: '1000000000000000000',
  1270              transferReward: '20036000000'
  1271          };
  1272          prepare(function (err) {
  1273              if (err instanceof Error) {
  1274                  done(err);
  1275              } else {
  1276                  testTransfer(testInput, testExpect, done);
  1277              }
  1278          });
  1279      });
  1280  
  1281      it('[ payload > 0 gaslimit ] TxBaseGasCount > gasLimit = TxBaseGasCount-1 ', function (done) {
  1282          var testInput = {
  1283              transferValue: 1,
  1284              isSameAddr: false,
  1285              gasLimit: 20035,
  1286              gasPrice: -1,
  1287              nonceIncrement: 1,
  1288              payloadLength: 99
  1289          };
  1290          //can calc value by previous params
  1291          var testExpect = {
  1292              canSendTx: true,
  1293              canSubmitTx: false,
  1294              canExcuteTx: false,
  1295              fromBalanceAfterTx: '8999999979964000000',
  1296              toBalanceAfterTx: '1000000000000000000',
  1297              transferReward: '20036000000'
  1298          };
  1299          prepare(function (err) {
  1300              if (err instanceof Error) {
  1301                  done(err);
  1302              } else {
  1303                  testTransfer(testInput, testExpect, done);
  1304              }
  1305          });
  1306      });
  1307  
  1308  
  1309  
  1310      it('[ payload > 0 ] TxBaseGasCount = gasLimit ', function (done) {
  1311          var testInput = {
  1312              transferValue: 1,
  1313              isSameAddr: false,
  1314              gasLimit: 20036,
  1315              gasPrice: -1,
  1316              nonceIncrement: 1,
  1317              payloadLength: 99
  1318          };
  1319          //can calc value by previous params
  1320          var testExpect = {
  1321              canSendTx: true,
  1322              canSubmitTx: true,
  1323              canExcuteTx: true,
  1324              fromBalanceAfterTx: '8999999979964000000',
  1325              toBalanceAfterTx: '1000000000000000000',
  1326              transferReward: '20036000000'
  1327          };
  1328          prepare(function (err) {
  1329              if (err instanceof Error) {
  1330                  done(err);
  1331              } else {
  1332                  testTransfer(testInput, testExpect, done);
  1333              }
  1334          });
  1335      });
  1336  
  1337      // TxBaseGasCount = min + data.length
  1338      it('[ data.length > 0 && balance ] balanceOfFrom = TxBaseGasCount * GasPrice + valueOfTx ', function (done) {
  1339          var testInput = {
  1340              transferValue: 9.999999979964,
  1341              isSameAddr: false,
  1342              gasLimit: 20036,
  1343              gasPrice: -1,
  1344              nonceIncrement: 1,
  1345              payloadLength: 99
  1346          };
  1347          //can calc value by previous params
  1348          var testExpect = {
  1349              canSendTx: true,
  1350              canSubmitTx: true,
  1351              canExcuteTx: true,
  1352              fromBalanceAfterTx: '0',
  1353              toBalanceAfterTx: '9999999979964000000',
  1354              transferReward: '20036000000'
  1355          };
  1356          prepare(function (err) {
  1357              if (err instanceof Error) {
  1358                  done(err);
  1359              } else {
  1360                  testTransfer(testInput, testExpect, done);
  1361              }
  1362          });
  1363      });
  1364  
  1365  
  1366  
  1367      it('[ data.length > 0 ] balanceOfFrom < GasLimit * GasPrice ', function (done) {
  1368          var testInput = {
  1369              transferValue: 1,
  1370              isSameAddr: false,
  1371              gasLimit: 50000000001,
  1372              gasPrice: 10000000,
  1373              nonceIncrement: 1,
  1374              payloadLength: 99
  1375          };
  1376          //can calc value by previous params
  1377          var testExpect = {
  1378              canSendTx: false,
  1379              canSubmitTx: false,
  1380              canExcuteTx: false,
  1381              fromBalanceAfterTx: '8999999979964000000',
  1382              toBalanceAfterTx: '1000000000000000000',
  1383              transferReward: '20036000000',
  1384              errMsg: 'invalid gas limit, should be in (0, 5*10^10]'
  1385          };
  1386          prepare(function (err) {
  1387              if (err instanceof Error) {
  1388                  done(err);
  1389              } else {
  1390                  testTransfer(testInput, testExpect, done);
  1391              }
  1392          });
  1393      });
  1394  
  1395  
  1396      it('[ payload > 0 ] (GasLimit * GasPrice + valueOfTx) > balanceOfFrom ' +
  1397          '&& balanceOfFrom = ( TxBaseGasCount + GasCountOfPayload )* gasPrice + valueOfTx', function (done) {
  1398          var testInput = {
  1399              transferValue: 9.999999979964,
  1400              isSameAddr: false,
  1401              gasLimit: 30000,
  1402              gasPrice: -1,
  1403              nonceIncrement: 1,
  1404              payloadLength: 99
  1405          };
  1406          //can calc value by previous params
  1407          var testExpect = {
  1408              canSendTx: true,
  1409              canSubmitTx: true,
  1410              canExcuteTx: false,
  1411              fromBalanceAfterTx: '9999999979964000000',
  1412              toBalanceAfterTx: '0',
  1413              transferReward: '20036000000'
  1414          };
  1415          prepare(function (err) {
  1416              if (err instanceof Error) {
  1417                  done(err);
  1418              } else {
  1419                  testTransfer(testInput, testExpect, done);
  1420              }
  1421          });
  1422      });
  1423  
  1424      it('[ payload > 0 ] gasPrice * gasLimit <= balanceOfFrom  ' +
  1425          '&& balanceOfFrom < valueOfTx + (TxBaseGasCount  + GasCountOfPayload)* gasPrice', function (done) {
  1426          var testInput = {
  1427              transferValue: 9.999999999,
  1428              isSameAddr: false,
  1429              gasLimit: 30000,
  1430              gasPrice: -1,
  1431              nonceIncrement: 1,
  1432              payloadLength: 99
  1433          };
  1434          //can calc value by previous params
  1435          var testExpect = {
  1436              canSendTx: true,
  1437              canSubmitTx: true,
  1438              canExcuteTx: false,
  1439              fromBalanceAfterTx: '9999999979964000000',
  1440              toBalanceAfterTx: '0',
  1441              transferReward: '20036000000'
  1442          };
  1443          prepare(function (err) {
  1444              if (err instanceof Error) {
  1445                  done(err);
  1446              } else {
  1447                  testTransfer(testInput, testExpect, done);
  1448              }
  1449          });
  1450      });
  1451  });