PHP WebShell

Текущая директория: /opt/bitgo-express/node_modules/bitgo/test

Просмотр файла: bitgoExpress.js

if (process.browser) {
  // Bitgo Express tests not supported in browser
  return;
}

var assert = require('assert');
var should = require('should');
var request = require("supertest-as-promised");
var _ = require('lodash');

var BitGoJS = require('../src/index');
var expressApp = require('../src/expressApp');
var TestBitGo = require('./lib/test_bitgo');
var testUtil = require('./testutil');

describe('Bitgo Express', function() {
  var agent;

  before(function() {
    var args = {
      debug: false,
      env: 'test',
      logfile: '/dev/null'
    };
    bitgo = new TestBitGo();
    bitgo.initializeTestVars();
    var app = expressApp(args);
    agent = request.agent(app);
  });

  describe('proxied calls', function() {

    it('error - not authed', function() {
      return agent.get('/api/v1/wallet')
      .send()
      .then(function(res) {
        res.should.have.status(401);
      });
    });

    it('error - proxied calls disabled', function() {
      var app = expressApp(_.extend(
        {},
        {
          debug: false,
          env: 'test',
          logfile: '/dev/null'
        },
        { disableproxy: true })
      );
      var disabledProxyAgent = request.agent(app);
      return disabledProxyAgent.get('/api/v1/market/latest')
      .send()
      .then(function(res) {
        res.should.have.status(404);
      });
    });

    it('market data', function() {
      return agent.get('/api/v1/market/latest')
      .send()
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('latest');
        res.body.latest.should.have.property('currencies');
        res.body.latest.currencies.should.have.property('USD');

        var usdMarketData = res.body.latest.currencies.USD;
        usdMarketData.should.have.property('last');
        usdMarketData.should.have.property('bid');
        usdMarketData.should.have.property('ask');
      });
    });

    it('get wallet list (authed)', function() {
      return agent.get('/api/v1/wallet')
      .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
      .send()
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('wallets');
        res.body.wallets.length.should.not.equal(0);
        res.body.wallets[0].should.have.property('label');
      });
    });

    it('post unlock (authed)', function() {
      return agent.post('/api/v1/user/unlock')
      .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
      .send({ otp: bitgo.testUserOTP(), duration: 3 })
      .then(function(res) {
        res.body.should.have.property('session');
        res.body.session.should.have.property('client');
        res.body.session.client.should.equal('test');
      });
    });

    it('put label set (authed)', function() {
      var walletId = '2MvfC3e6njdTXqWDfGvNUqDs5kwimfaTGjK';
      return agent.put('/api/v1/labels/' + walletId + '/msj42CCGruhRsFrGATiUuh25dtxYtnpbTx')
      .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
      .send({ label: 'testLabel_bitgoExpressSDK' })
      .then(function(res) {
        res.body.should.have.property('walletId');
        res.body.should.have.property('address');
        res.body.should.have.property('label');
        res.body.label.should.equal('testLabel_bitgoExpressSDK');
        res.body.walletId.should.equal(walletId);
      });
    });
  });

  describe('handled calls', function() {

    it('error - not authed', function() {
      return agent.post('/api/v1/wallets/simplecreate')
      .send({ passphrase:'abc', label: 'helloworld' })
      .then(function(res) {
        res.should.have.status(401);
      });
    });

    it('error - not authed (eth)', function() {
      return agent.post('/api/v1/eth/wallet/generate')
      .send({ passphrase:'abc', label: 'helloworld' })
      .then(function(res) {
        res.should.have.status(401);
      });
    });

    it('new keychain', function() {
      return agent.post('/api/v1/keychain/local')
      .send()
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('xpub');
        res.body.should.have.property('xprv');
      });
    });

    it('derive BIP32 private keychain', function() {
      return agent.post('/api/v1/keychain/derive')
      .send({
        path: 'm/1/2/3/4',
        xprv: 'xprv9s21ZrQH143K3o5A54b28GYVnDAa7gdPSxjWGz9ARzbxqYax8gbds5yGiU4D56GgSRwp7t9T8p54xh6MN19h8n6HJyR5FCkQopoUxC34EV3'
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('xpub');
        res.body.should.have.property('xprv');
        res.body.xprv.should.eql('xprvA1yY6N1A6aT3B9VUb2mhnLpNyPwAguPY3sibAXYXiEUVjT62TZNHTy13LhrdJ4BcGmt2hnRdgGQFLDowBqANkysSRw6KXri2MpGjkPAbGrS');
        res.body.xpub.should.eql('xpub6ExtVsY3vx1LPdZwh4Ji9Um7XRmf6N7PR6eBxux9Ga1UcFRB16gY1mKXBzVPcGZVpnDPYboEPYdPxfsrnq1Yec49RN4usyB5ba8NNtVbHeG');
        res.body.path.should.eql('m/1/2/3/4');
      });
    });

    it('derive BIP32 public keychain', function() {
      return agent.post('/api/v1/keychain/derive')
      .send({
        path: 'm/3/4/5/6',
        xpub: 'xpub6ExtVsY3vx1LPdZwh4Ji9Um7XRmf6N7PR6eBxux9Ga1UcFRB16gY1mKXBzVPcGZVpnDPYboEPYdPxfsrnq1Yec49RN4usyB5ba8NNtVbHeG'
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('xpub');
        res.body.should.not.have.property('xprv');
        res.body.xpub.should.eql('xpub6N5Svn29v8op8f6VgHeM9FXvmpoFx7535qW4HKFHeM7HqJDD2dWQq92MKduYZjuWi4FWZQsGDtHwRtLpmCRWMxy3d3r77jcsxDpYNAGpbuY');
        res.body.path.should.eql('m/3/4/5/6');
      });
    });

    it('decrypt', function() {
      var encryptedString = '{"iv":"n4zHXVTi/Go/riCP8fNs/A==","v":1,"iter":10000,"ks":256,"ts":64,"mode":"ccm","adata":"","cipher":"aes","salt":"zvLyve+4AJU=","ct":"gNMqheicMoD8ZmNzRwuQfWGAh+HA933l"}';
      return agent.post('/api/v1/decrypt')
      .send({input: encryptedString, password: 'password'})
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('decrypted');
        res.body.decrypted.should.equal('this is a secret');
      });
    });

    it('create wallet', function() {
      var backupXpub = "xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU";
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallets/simplecreate')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ passphrase: "chamchatka", label: "kokoko", backupXpub: backupXpub });
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('wallet');
        res.body.should.have.property('backupKeychain');
        res.body.backupKeychain.should.have.property('xpub');
        res.body.backupKeychain.xpub.should.equal(backupXpub);
      });
    });

    it('create eth wallet', function() {
      var backupXpub = "xpub6AHA9hZDN11k2ijHMeS5QqHx2KP9aMBRhTDqANMnwVtdyw2TDYRmF8PjpvwUFcL1Et8Hj59S3gTSMcUQ5gAqTz3Wd8EsMTmF3DChhqPQBnU";
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/eth/wallet/generate')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ passphrase: "chamchatka", label: "kokoko", backupXpub: backupXpub });
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('wallet');
        res.body.should.have.property('backupKeychain');
        res.body.backupKeychain.should.have.property('xpub');
        res.body.backupKeychain.should.have.property('ethAddress');
        res.body.backupKeychain.xpub.should.equal(backupXpub);
        res.body.backupKeychain.ethAddress.should.eql('0x467fecd39726a0245b6a72dcd0ad234849410cf1');
        res.body.wallet.private.should.have.property('addresses');
        res.body.wallet.private.addresses[1].address.should.eql('0x467fecd39726a0245b6a72dcd0ad234849410cf1');
        res.body.wallet.private.deployTxHash.should.startWith('0x');
      });
    });

    it('send eth transaction', function() {
      var amount = '36000';
      var destination = TestBitGo.TEST_ETH_WALLET2_ADDRESS;
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/eth/wallet/' + TestBitGo.TEST_ETH_WALLET1_ADDRESS + '/sendtransaction')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ recipients: [{ toAddress: destination, value: amount }], walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE });
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.should.have.property('tx');
        res.body.should.have.property('hash');
        return agent.get('/api/v1/eth/wallet/' + TestBitGo.TEST_ETH_WALLET1_ADDRESS + '/transfer/' + res.body.hash)
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send();
      })
      .then(function(res) {
        res.should.have.status(200);
        var transfer = res.body.transfer;
        transfer.from.should.eql(TestBitGo.TEST_ETH_WALLET1_ADDRESS);
        transfer.outputs.length.should.eql(1);
        transfer.outputs[0].to.should.eql(destination);
        transfer.outputs[0].value.should.eql(amount);
        transfer.creator.should.eql(TestBitGo.TEST_USERID);
      })
    });

    it('create transaction - wallet1 to wallet3', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/createtransaction')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ recipients: [{ address: TestBitGo.TEST_WALLET3_ADDRESS, amount: 2 * 1e8 }], walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE });
      })
      .then(function(res) {
        res.status.should.eql(200);
        var txInfo = res.body.txInfo;
        txInfo.nP2SHInputs.should.be.greaterThan(0);
        txInfo.nP2PKHInputs.should.eql(0);
        txInfo.nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination
      });
    });

    it('send coins - wallet1 to wallet3', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET1_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ address: TestBitGo.TEST_WALLET3_ADDRESS, amount: 0.002 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET1_PASSCODE });
      })
      .then(function(res) {
        res.status.should.equal(200);
        res.body.should.have.property('tx');
        res.body.should.have.property('hash');
        res.body.should.have.property('fee');
        res.body.should.have.property('feeRate');
      });
    });

    it('create transaction - wallet3 to wallet1 with insufficient amount', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/createtransaction')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ recipients: [{ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 10000 * 1e8 }], walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE });
      })
      .then(function(res) {
        res.status.should.eql(400);
        res.body.should.have.property('message');
        res.body.result.should.have.property('fee');
        res.body.result.should.have.property('available');
        res.body.message.should.equal("Insufficient funds");
        res.body.result.fee.should.be.greaterThan(546);
        res.body.result.available.should.be.greaterThan(546);
        var txInfo = res.body.result.txInfo;
        txInfo.nP2SHInputs.should.be.greaterThan(0);
        txInfo.nP2PKHInputs.should.eql(0);
        txInfo.nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination
      });
    });

    it('send coins - wallet3 to wallet1 with insufficient amount', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 10000 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, fee: 0.0003 * 1e8 });
      })
      .then(function(res) {
        res.status.should.equal(400);
        res.body.result.should.have.property('fee');
        res.body.result.should.have.property('available');
        res.body.message.should.equal("Insufficient funds");
        var result = res.body.result;
        result.should.have.property('fee');
        result.fee.should.equal(0.0003 * 1e8);
        var txInfo = res.body.result.txInfo;
        txInfo.nP2SHInputs.should.be.greaterThan(0);
        txInfo.nP2PKHInputs.should.eql(0);
        txInfo.nOutputs.should.be.greaterThan(2); // change + bitgo fee + destination
      });
    });

    it('send coins - wallet3 to wallet1 with fee', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_WALLET3_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_WALLET3_PASSCODE, fee: 0.0003 * 1e8 });
      })
      .then(function(res) {
        res.status.should.equal(200);
        res.body.should.have.property('tx');
        res.body.should.have.property('hash');
        res.body.should.have.property('fee');
        res.body.fee.should.equal(0.0003 * 1e8);
      });
    });

    it('create and reject a pending approval', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15);
      })
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({
          address: TestBitGo.TEST_WALLET1_ADDRESS,
          amount: 0.001 * 1e8,
          walletPassphrase: TestBitGo.TEST_PASSWORD,
          otp : bitgo.testUserOTP()
        });
      })
      .then(function(res) {
        res.status.should.equal(202);
        res.body.should.have.property('pendingApproval');
        res.body.status.should.eql('pendingApproval');
        var pendingApprovalId = res.body.pendingApproval;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER)
        .send({ walletPassphrase: TestBitGo.TEST_PASSWORD, state: 'rejected' });
      })
      .then(function(res) {
        res.body.state.should.eql('rejected');
      });
    });

    it('create a transaction and then reconstruct a tx to approve (with original fee)', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15)
      .then(function() {
        return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15);
      })
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({
          address: TestBitGo.TEST_WALLET1_ADDRESS,
          amount: 0.001 * 1e8,
          walletPassphrase: TestBitGo.TEST_PASSWORD,
          fee: 12345
        });
      })
      .then(function(res) {
        res.status.should.equal(202);
        res.body.should.have.property('pendingApproval');
        res.body.status.should.eql('pendingApproval');
        var pendingApprovalId = res.body.pendingApproval;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({walletPassphrase: TestBitGo.TEST_PASSWORD, useOriginalFee: true});
      })
      .then(function(res) {
        res.body.should.have.property('tx');
        res.body.tx.should.not.eql('');
        res.body.fee.should.eql(12345);
      });
    });

    it('calculate tx size from parameters', function() {
      return agent.post('/api/v1/calculateminerfeeinfo')
      .send({
        feeRate: 20000,
        nP2SHInputs: 2,
        nP2PKHInputs: 1,
        nOutputs: 4
      })
      .then(function(res) {
        res.should.have.status(200);
        res.body.size.should.eql(886);
        res.body.fee.should.eql(17720);
      });
    });

    it('create and accept a pending approval', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function() {
        return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15);
      })
      .then(function() {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, otp: bitgo.testUserOTP() });
      })
      .then(function(res) {
        res.status.should.equal(202);
        res.body.should.have.property('pendingApproval');
        res.body.status.should.eql('pendingApproval');
        var pendingApprovalId = res.body.pendingApproval;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER)
        .send({ walletPassphrase: TestBitGo.TEST_PASSWORD, state: 'approved', otp: bitgo.testUserOTP() });
      })
      .then(function(res) {
        res.body.state.should.eql('approved');
      });
    });

    it('create and accept a pending approval using the xprv', function() {
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function(res) {
        return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15)
      })
      .then(function(res) {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, otp: bitgo.testUserOTP() });
      })
      .then(function(res) {
        res.status.should.equal(202);
        res.body.should.have.property('pendingApproval');
        res.body.status.should.eql('pendingApproval');
        var pendingApprovalId = res.body.pendingApproval;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/express')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER)
        .send({ xprv: 'xprv9s21ZrQH143K3GisDvcsLyQZ88CrgtHziPuQ4ZZU6x3v8AZxEYEBZ7ANwfAPVz9mqraSjREVaCdFgv1u7mHvjuDRZ25J4wGJ73yooYhDoJ4',
                state: 'approved',
                otp: bitgo.testUserOTP()
	});
      })
      .then(function(res) {
        res.body.state.should.eql('approved');
      })
    });

    it('create and accept a pending approval (2 step accept by constructing tx with original user)', function() {
      var pendingApprovalId;
      return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN, 15)
      .then(function(res) {
        return testUtil.unlockToken(agent, TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER, 15)
      })
      .then(function(res) {
        return agent.post('/api/v1/wallet/' + TestBitGo.TEST_SHARED_WALLET_ADDRESS + '/sendcoins')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({ address: TestBitGo.TEST_WALLET1_ADDRESS, amount: 0.001 * 1e8, walletPassphrase: TestBitGo.TEST_PASSWORD, fee: 12345, otp: bitgo.testUserOTP() });;
      })
      .then(function(res) {
        res.status.should.equal(202);
        res.body.should.have.property('pendingApproval');
        res.body.status.should.eql('pendingApproval');
        pendingApprovalId = res.body.pendingApproval;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId + '/constructTx')
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN)
        .send({walletPassphrase: TestBitGo.TEST_PASSWORD});
      })
      .then(function(res) {
        res.body.should.have.property('tx');
        res.body.tx.should.not.eql('');
        res.body.fee.should.not.eql(12345); // fee should be recalculated dynamically
        var txHex = res.body.tx;
        return agent.put('/api/v1/pendingapprovals/' + pendingApprovalId)
        .set('Authorization', 'Bearer ' + TestBitGo.TEST_ACCESSTOKEN_SHAREDUSER)
        .send({ tx: txHex, state: 'approved', otp: bitgo.testUserOTP() });
      })
      .then(function(res) {
        res.body.state.should.eql('approved');
      });
    });
  });
});

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


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