PHP WebShell

Текущая директория: /usr/lib/node_modules/bitgo-express/node_modules/ripple-lib/test/integration

Просмотр файла: integration-test.js

/* eslint-disable max-nested-callbacks */
/* eslint-disable max-params */
'use strict';
const _ = require('lodash');
const assert = require('assert');
const errors = require('../../src/common/errors');
const wallet = require('./wallet');
const requests = require('../fixtures/requests');
const RippleAPI = require('ripple-api').RippleAPI;
const {isValidAddress} = require('ripple-address-codec');
const {isValidSecret} = require('../../src/common');
const {payTo, ledgerAccept} = require('./utils');


// how long before each test case times out
const TIMEOUT = process.browser ? 25000 : 10000;
const INTERVAL = 1000;   // how long to wait between checks for validated ledger

const serverUrl = 'ws://127.0.0.1:6006';

function acceptLedger(api) {
  return api.connection.request({command: 'ledger_accept'});
}

function verifyTransaction(testcase, hash, type, options, txData, address) {
  console.log('VERIFY...');
  return testcase.api.getTransaction(hash, options).then(data => {
    assert(data && data.outcome);
    assert.strictEqual(data.type, type);
    assert.strictEqual(data.address, address);
    assert.strictEqual(data.outcome.result, 'tesSUCCESS');
    if (testcase.transactions !== undefined) {
      testcase.transactions.push(hash);
    }
    return {txJSON: JSON.stringify(txData), id: hash, tx: data};
  }).catch(error => {
    if (error instanceof errors.PendingLedgerVersionError) {
      console.log('NOT VALIDATED YET...');
      return new Promise((resolve, reject) => {
        setTimeout(() => verifyTransaction(testcase, hash, type,
          options, txData, address).then(resolve, reject), INTERVAL);
      });
    }
    console.log(error.stack);
    assert(false, 'Transaction not successful: ' + error.message);
  });
}

function testTransaction(testcase, type, lastClosedLedgerVersion, prepared,
    address = wallet.getAddress(), secret = wallet.getSecret()) {
  const txJSON = prepared.txJSON;
  assert(txJSON, 'missing txJSON');
  const txData = JSON.parse(txJSON);
  assert.strictEqual(txData.Account, address);
  const signedData = testcase.api.sign(txJSON, secret);
  console.log('PREPARED...');
  return testcase.api.submit(signedData.signedTransaction)
  .then(data => testcase.test.title.indexOf('multisign') !== -1 ?
  acceptLedger(testcase.api).then(() => data) : data).then(data => {
    console.log('SUBMITTED...');
    assert.strictEqual(data.resultCode, 'tesSUCCESS');
    const options = {
      minLedgerVersion: lastClosedLedgerVersion,
      maxLedgerVersion: txData.LastLedgerSequence
    };
    ledgerAccept(testcase.api);
    return new Promise((resolve, reject) => {
      setTimeout(() => verifyTransaction(testcase, signedData.id, type,
        options, txData, address).then(resolve, reject), INTERVAL);
    });
  });
}

function setup(server = 'wss://s1.ripple.com') {
  this.api = new RippleAPI({server});
  console.log('CONNECTING...');
  return this.api.connect().then(() => {
    console.log('CONNECTED...');
  }, error => {
    console.log('ERROR:', error);
    throw error;
  });
}

const masterAccount = 'rHb9CJAWyB4rj91VRWn96DkukG4bwdtyTh';
const masterSecret = 'snoPBrXtMeMyMHUVTgbuqAfg1SUTb';

function makeTrustLine(testcase, address, secret) {
  const api = testcase.api;
  const specification = {
    currency: 'USD',
    counterparty: masterAccount,
    limit: '1341.1',
    ripplingDisabled: true
  };
  const trust = api.prepareTrustline(address, specification, {})
    .then(data => {
      const signed = api.sign(data.txJSON, secret);
      if (address === wallet.getAddress()) {
        testcase.transactions.push(signed.id);
      }
      return api.submit(signed.signedTransaction);
    })
    .then(() => ledgerAccept(api));
  return trust;
}

function makeOrder(api, address, specification, secret) {
  return api.prepareOrder(address, specification)
    .then(data => api.sign(data.txJSON, secret))
    .then(signed => api.submit(signed.signedTransaction))
    .then(() => ledgerAccept(api));
}

function setupAccounts(testcase) {
  const api = testcase.api;

  const promise = payTo(api, 'rMH4UxPrbuMa1spCBR98hLLyNJp4d8p4tM')
    .then(() => payTo(api, wallet.getAddress()))
    .then(() => payTo(api, testcase.newWallet.address))
    .then(() => payTo(api, 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc'))
    .then(() => payTo(api, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'))
    .then(() => {
      return api.prepareSettings(masterAccount, {defaultRipple: true})
      .then(data => api.sign(data.txJSON, masterSecret))
      .then(signed => api.submit(signed.signedTransaction))
      .then(() => ledgerAccept(api));
    })
    .then(() => makeTrustLine(testcase, wallet.getAddress(),
      wallet.getSecret()))
    .then(() => makeTrustLine(testcase, testcase.newWallet.address,
      testcase.newWallet.secret))
    .then(() => payTo(api, wallet.getAddress(), '123', 'USD', masterAccount))
    .then(() => payTo(api, 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'))
    .then(() => {
      const orderSpecification = {
        direction: 'buy',
        quantity: {
          currency: 'USD',
          value: '432',
          counterparty: masterAccount
        },
        totalPrice: {
          currency: 'XRP',
          value: '432'
        }
      };
      return makeOrder(testcase.api, testcase.newWallet.address,
        orderSpecification, testcase.newWallet.secret);
    })
    .then(() => {
      const orderSpecification = {
        direction: 'buy',
        quantity: {
          currency: 'XRP',
          value: '1741'
        },
        totalPrice: {
          currency: 'USD',
          value: '171',
          counterparty: masterAccount
        }
      };
      return makeOrder(testcase.api, masterAccount, orderSpecification,
        masterSecret);
    });
  return promise;
}

function teardown() {
  return this.api.disconnect();
}

function suiteSetup() {
  this.transactions = [];

  return setup.bind(this)(serverUrl)
    .then(() => ledgerAccept(this.api))
    .then(() => this.newWallet = this.api.generateAddress())
    // two times to give time to server to send `ledgerClosed` event
    // so getLedgerVersion will return right value
    .then(() => ledgerAccept(this.api))
    .then(() => this.api.getLedgerVersion())
    .then(ledgerVersion => {
      this.startLedgerVersion = ledgerVersion;
    })
    .then(() => setupAccounts(this))
    .then(() => teardown.bind(this)());
}

describe('integration tests', function() {
  const address = wallet.getAddress();
  const instructions = {maxLedgerVersionOffset: 10};
  this.timeout(TIMEOUT);

  before(suiteSetup);
  beforeEach(_.partial(setup, serverUrl));
  afterEach(teardown);


  it('settings', function() {
    return this.api.getLedgerVersion().then(ledgerVersion => {
      return this.api.prepareSettings(address,
        requests.prepareSettings.domain, instructions).then(prepared =>
          testTransaction(this, 'settings', ledgerVersion, prepared));
    });
  });


  it('trustline', function() {
    return this.api.getLedgerVersion().then(ledgerVersion => {
      return this.api.prepareTrustline(address,
        requests.prepareTrustline.simple, instructions).then(prepared =>
          testTransaction(this, 'trustline', ledgerVersion, prepared));
    });
  });


  it('payment', function() {
    const amount = {currency: 'XRP', value: '0.000001'};
    const paymentSpecification = {
      source: {
        address: address,
        maxAmount: amount
      },
      destination: {
        address: 'rKmBGxocj9Abgy25J51Mk1iqFzW9aVF9Tc',
        amount: amount
      }
    };
    return this.api.getLedgerVersion().then(ledgerVersion => {
      return this.api.preparePayment(address,
        paymentSpecification, instructions).then(prepared =>
          testTransaction(this, 'payment', ledgerVersion, prepared));
    });
  });


  it('order', function() {
    const orderSpecification = {
      direction: 'buy',
      quantity: {
        currency: 'USD',
        value: '237',
        counterparty: 'rMwjYedjc7qqtKYVLiAccJSmCwih4LnE2q'
      },
      totalPrice: {
        currency: 'XRP',
        value: '0.0002'
      }
    };
    return this.api.getLedgerVersion().then(ledgerVersion => {
      return this.api.prepareOrder(address, orderSpecification, instructions)
        .then(prepared =>
          testTransaction(this, 'order', ledgerVersion, prepared))
        .then(result => {
          const txData = JSON.parse(result.txJSON);
          return this.api.getOrders(address).then(orders => {
            assert(orders && orders.length > 0);
            const createdOrder = _.first(_.filter(orders, order => {
              return order.properties.sequence === txData.Sequence;
            }));
            assert(createdOrder);
            assert.strictEqual(createdOrder.properties.maker, address);
            assert.deepEqual(createdOrder.specification, orderSpecification);
            return txData;
          });
        })
        .then(txData => this.api.prepareOrderCancellation(
          address, {orderSequence: txData.Sequence}, instructions)
            .then(prepared => testTransaction(this, 'orderCancellation',
              ledgerVersion, prepared))
        );
    });
  });


  it('isConnected', function() {
    assert(this.api.isConnected());
  });


  it('getServerInfo', function() {
    return this.api.getServerInfo().then(data => {
      assert(data && data.pubkeyNode);
    });
  });


  it('getFee', function() {
    return this.api.getFee().then(fee => {
      assert.strictEqual(typeof fee, 'string');
      assert(!isNaN(Number(fee)));
      assert(parseFloat(fee) === Number(fee));
    });
  });


  it('getLedgerVersion', function() {
    return this.api.getLedgerVersion().then(ledgerVersion => {
      assert.strictEqual(typeof ledgerVersion, 'number');
      assert(ledgerVersion >= this.startLedgerVersion);
    });
  });


  it('getTransactions', function() {
    const options = {
      initiated: true,
      minLedgerVersion: this.startLedgerVersion
    };
    return this.api.getTransactions(address, options).then(transactionsData => {
      assert(transactionsData);
      assert.strictEqual(transactionsData.length, this.transactions.length);
    });
  });


  it('getTrustlines', function() {
    const fixture = requests.prepareTrustline.simple;
    const options = _.pick(fixture, ['currency', 'counterparty']);
    return this.api.getTrustlines(address, options).then(data => {
      assert(data && data.length > 0 && data[0] && data[0].specification);
      const specification = data[0].specification;
      assert.strictEqual(Number(specification.limit), Number(fixture.limit));
      assert.strictEqual(specification.currency, fixture.currency);
      assert.strictEqual(specification.counterparty, fixture.counterparty);
    });
  });


  it('getBalances', function() {
    const fixture = requests.prepareTrustline.simple;
    const options = _.pick(fixture, ['currency', 'counterparty']);
    return this.api.getBalances(address, options).then(data => {
      assert(data && data.length > 0 && data[0]);
      assert.strictEqual(data[0].currency, fixture.currency);
      assert.strictEqual(data[0].counterparty, fixture.counterparty);
    });
  });


  it('getSettings', function() {
    return this.api.getSettings(address).then(data => {
      assert(data);
      assert.strictEqual(data.domain, requests.prepareSettings.domain.domain);
    });
  });


  it('getOrderbook', function() {
    const orderbook = {
      base: {
        currency: 'XRP'
      },
      counter: {
        currency: 'USD',
        counterparty: masterAccount
      }
    };
    return this.api.getOrderbook(address, orderbook).then(book => {
      assert(book && book.bids && book.bids.length > 0);
      assert(book.asks && book.asks.length > 0);
      const bid = book.bids[0];
      assert(bid && bid.specification && bid.specification.quantity);
      assert(bid.specification.totalPrice);
      assert.strictEqual(bid.specification.direction, 'buy');
      assert.strictEqual(bid.specification.quantity.currency, 'XRP');
      assert.strictEqual(bid.specification.totalPrice.currency, 'USD');
      const ask = book.asks[0];
      assert(ask && ask.specification && ask.specification.quantity);
      assert(ask.specification.totalPrice);
      assert.strictEqual(ask.specification.direction, 'sell');
      assert.strictEqual(ask.specification.quantity.currency, 'XRP');
      assert.strictEqual(ask.specification.totalPrice.currency, 'USD');
    });
  });


  it('getPaths', function() {
    const pathfind = {
      source: {
        address: address
      },
      destination: {
        address: this.newWallet.address,
        amount: {
          value: '1',
          currency: 'USD',
          counterparty: masterAccount
        }
      }
    };
    return this.api.getPaths(pathfind).then(data => {
      assert(data && data.length > 0);
      const path = data[0];
      assert(path && path.source);
      assert.strictEqual(path.source.address, address);
      assert(path.paths && path.paths.length > 0);
    });
  });


  it('getPaths - send all', function() {
    const pathfind = {
      source: {
        address: address,
        amount: {
          currency: 'USD',
          value: '0.005'
        }
      },
      destination: {
        address: this.newWallet.address,
        amount: {
          currency: 'USD'
        }
      }
    };

    return this.api.getPaths(pathfind).then(data => {
      assert(data && data.length > 0);
      assert(_.every(data, path => {
        return parseFloat(path.source.amount.value)
        <= parseFloat(pathfind.source.amount.value);
      }));
      const path = data[0];
      assert(path && path.source);
      assert.strictEqual(path.source.address, pathfind.source.address);
      assert(path.paths && path.paths.length > 0);
    });
  });


  it('generateWallet', function() {
    const newWallet = this.api.generateAddress();
    assert(newWallet && newWallet.address && newWallet.secret);
    assert(isValidAddress(newWallet.address));
    assert(isValidSecret(newWallet.secret));
  });

});

describe('integration tests - standalone rippled', function() {
  const instructions = {maxLedgerVersionOffset: 10};
  this.timeout(TIMEOUT);

  beforeEach(_.partial(setup, serverUrl));
  afterEach(teardown);
  const address = 'r5nx8ZkwEbFztnc8Qyi22DE9JYjRzNmvs';
  const secret = 'ss6F8381Br6wwpy9p582H8sBt19J3';
  const signer1address = 'rQDhz2ZNXmhxzCYwxU6qAbdxsHA4HV45Y2';
  const signer1secret = 'shK6YXzwYfnFVn3YZSaMh5zuAddKx';
  const signer2address = 'r3RtUvGw9nMoJ5FuHxuoVJvcENhKtuF9ud';
  const signer2secret = 'shUHQnL4EH27V4EiBrj6EfhWvZngF';

  it('submit multisigned transaction', function() {
    const signers = {
      threshold: 2,
      weights: [
        {address: signer1address, weight: 1},
        {address: signer2address, weight: 1}
      ]
    };
    let minLedgerVersion = null;
    return payTo(this.api, address).then(() => {
      return this.api.getLedgerVersion().then(ledgerVersion => {
        minLedgerVersion = ledgerVersion;
        return this.api.prepareSettings(address, {signers}, instructions)
        .then(prepared => {
          return testTransaction(this, 'settings', ledgerVersion, prepared,
            address, secret);
        });
      });
    }).then(() => {
      const multisignInstructions =
        _.assign({}, instructions, {signersCount: 2});
      return this.api.prepareSettings(
        address, {domain: 'example.com'}, multisignInstructions)
      .then(prepared => {
        const signed1 = this.api.sign(
          prepared.txJSON, signer1secret, {signAs: signer1address});
        const signed2 = this.api.sign(
          prepared.txJSON, signer2secret, {signAs: signer2address});
        const combined = this.api.combine([
          signed1.signedTransaction, signed2.signedTransaction
        ]);
        return this.api.submit(combined.signedTransaction)
        .then(response => acceptLedger(this.api).then(() => response))
        .then(response => {
          assert.strictEqual(response.resultCode, 'tesSUCCESS');
          const options = {minLedgerVersion};
          return verifyTransaction(this, combined.id, 'settings',
            options, {}, address);
        }).catch(error => {
          console.log(error.message);
          throw error;
        });
      });
    });
  });
});

Выполнить команду


Для локальной разработки. Не используйте в интернете!