Skip to content
This repository has been archived by the owner on Nov 6, 2020. It is now read-only.

fund account via ShapeShift #2099

Merged
merged 37 commits into from
Sep 15, 2016
Merged
Show file tree
Hide file tree
Changes from 29 commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
21c135f
initial import before tweaking starts
jacogr Sep 13, 2016
fc304c0
GPL header
jacogr Sep 13, 2016
6faff8f
es6-ify library & flatten
jacogr Sep 13, 2016
1a6daa8
fix tests with new structure, proper naming
jacogr Sep 13, 2016
cab8a6b
define functions explicitly withing closure
jacogr Sep 13, 2016
186baff
call is not needed within closure
jacogr Sep 13, 2016
ea5e54a
Merge branch 'js-3rdparty-shapeshift' into jg-fund-account
jacogr Sep 14, 2016
b2771fe
allow className in Select
jacogr Sep 14, 2016
cc87e5e
add missing provider logos
jacogr Sep 14, 2016
24fff44
actually export the newError action
jacogr Sep 14, 2016
be99b09
add support for buttons
jacogr Sep 14, 2016
bfebf03
coin retrieval available
jacogr Sep 14, 2016
39f736a
allow subscriptions to statusses
jacogr Sep 14, 2016
3cca307
simplify subscription state handling
jacogr Sep 14, 2016
0b71fc8
fatal error indicator
jacogr Sep 14, 2016
b09c7c9
render modal titles correctly in the case where there are no steps
jacogr Sep 14, 2016
03b3a36
fix children propType
jacogr Sep 14, 2016
937f3d2
allow intermediate progress bar to be displayed on top on modals
jacogr Sep 14, 2016
3e5c8df
UI looks reasonably presentable, testing with network next
jacogr Sep 14, 2016
62c4fc7
remove testing price info as well
jacogr Sep 14, 2016
581efd8
3 decimal places, display is unwieldly
jacogr Sep 14, 2016
7698927
remove debug for no coins available
jacogr Sep 15, 2016
81c8eed
update coin message slightly
jacogr Sep 15, 2016
885d321
treat coin changes properly
jacogr Sep 15, 2016
ab7faf2
busy shifting flag
jacogr Sep 15, 2016
8b6b07c
pass correct result through to callback
jacogr Sep 15, 2016
902c8ac
fix PropTypes as received
jacogr Sep 15, 2016
38e2e42
slightly more presentable UI...
jacogr Sep 15, 2016
26d7b27
removed etherscan logo, doesn't belong in this branch
jacogr Sep 15, 2016
5adc791
fix typo
jacogr Sep 15, 2016
a3bea1f
use shapeshift ison & name
jacogr Sep 15, 2016
9703f4b
rename fundAccount to shapeshift
jacogr Sep 15, 2016
369334c
fix wording
jacogr Sep 15, 2016
f1fac42
.map -> .forEach
jacogr Sep 15, 2016
268f4ef
array for classlist
jacogr Sep 15, 2016
2981c87
check response.ok, throw Error
jacogr Sep 15, 2016
001d888
Merge branch 'js' into jg-fund-account
jacogr Sep 15, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
71 changes: 71 additions & 0 deletions js/src/3rdparty/shapeshift/helpers.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import chai from 'chai';
import nock from 'nock';

global.expect = chai.expect; // eslint-disable-line no-undef

import 'isomorphic-fetch';
import es6Promise from 'es6-promise';
es6Promise.polyfill();

import initShapeshift from './';
import initRpc from './rpc';

const APIKEY = '0x123454321';

const shapeshift = initShapeshift(APIKEY);
const rpc = initRpc(APIKEY);

function mockget (requests) {
let scope = nock(rpc.ENDPOINT);

requests.forEach((request) => {
scope = scope
.get(`/${request.path}`)
.reply(request.code || 200, () => {
return request.reply;
});
});

return scope;
}

function mockpost (requests) {
let scope = nock(rpc.ENDPOINT);

requests.forEach((request) => {
scope = scope
.post(`/${request.path}`)
.reply(request.code || 200, (uri, body) => {
scope.body = scope.body || {};
scope.body[request.path] = body;

return request.reply;
});
});

return scope;
}

export {
APIKEY,
mockget,
mockpost,
shapeshift,
rpc
};
22 changes: 22 additions & 0 deletions js/src/3rdparty/shapeshift/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import initRpc from './rpc';
import initShapeshift from './shapeshift';

export default function (apikey) {
return initShapeshift(initRpc(apikey));
}
67 changes: 67 additions & 0 deletions js/src/3rdparty/shapeshift/rpc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

const ENDPOINT = 'https://cors.shapeshift.io';

function call (method, options) {
return fetch(`${ENDPOINT}/${method}`, options)
.then((response) => {
if (response.status !== 200) {
Copy link
Contributor

@derhuerst derhuerst Sep 15, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think checking for 200 <= status && status < 300 is safer, as the HTTP RFC defines 2xx as "client's request was successfully received, understood, and accepted.".

Edit: Check for response.ok.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

response.ok :)

throw { code: response.status, message: response.statusText }; // eslint-disable-line
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As people often check for err instanceof Error, i'd consider using new Error(…) here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Actually needs to be done to align with the other APIs as well.

}

return response.json();
})
.then((result) => {
if (result.error) {
throw { code: -1, message: result.error }; // eslint-disable-line
}

return result;
});
}

export default function (apiKey) {
function get (method) {
return call(method, {
method: 'GET',
headers: {
'Accept': 'application/json'
}
});
}

function post (method, data) {
const params = Object.assign({}, { apiKey }, data);
const body = JSON.stringify(params);

return call(method, {
method: 'POST',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
'Content-Length': body.length
},
body
});
}

return {
ENDPOINT,
get,
post
};
}
77 changes: 77 additions & 0 deletions js/src/3rdparty/shapeshift/rpc.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

import { APIKEY, mockget, mockpost, rpc } from './helpers.spec.js';

describe('shapeshift/rpc', () => {
describe('GET', () => {
const REPLY = { test: 'this is some result' };

let scope;
let result;

beforeEach(() => {
scope = mockget([{ path: 'test', reply: REPLY }]);

return rpc
.get('test')
.then((_result) => {
result = _result;
});
});

it('does GET', () => {
expect(scope.isDone()).to.be.true;
});

it('retrieves the info', () => {
expect(result).to.deep.equal(REPLY);
});
});

describe('POST', () => {
const REPLY = { test: 'this is some result' };

let scope;
let result;

beforeEach(() => {
scope = mockpost([{ path: 'test', reply: REPLY }]);

return rpc
.post('test', { input: 'stuff' })
.then((_result) => {
result = _result;
});
});

it('does POST', () => {
expect(scope.isDone()).to.be.true;
});

it('retrieves the info', () => {
expect(result).to.deep.equal(REPLY);
});

it('passes the input object', () => {
expect(scope.body.test.input).to.equal('stuff');
});

it('passes the apikey specified', () => {
expect(scope.body.test.apiKey).to.equal(APIKEY);
});
});
});
93 changes: 93 additions & 0 deletions js/src/3rdparty/shapeshift/shapeshift.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
// Copyright 2015, 2016 Ethcore (UK) Ltd.
// This file is part of Parity.

// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.

export default function (rpc) {
const subscriptions = [];

function getCoins () {
return rpc.get('getcoins');
}

function getMarketInfo (pair) {
return rpc.get(`marketinfo/${pair}`);
}

function getStatus (depositAddress) {
return rpc.get(`txStat/${depositAddress}`);
}

function shift (toAddress, returnAddress, pair) {
return rpc.post('shift', {
withdrawal: toAddress,
pair: pair,
returnAddress: returnAddress
});
}

function subscribe (depositAddress, callback) {
const idx = subscriptions.length;

subscriptions.push({
depositAddress,
callback,
idx
});
}

function _getSubscriptionStatus (subscription) {
if (!subscription) {
return;
}

getStatus(subscription.depositAddress)
.then((result) => {
switch (result.status) {
case 'no_deposits':
case 'received':
subscription.callback(null, result);
return;

case 'complete':
subscription.callback(null, result);
subscriptions[subscription.idx] = null;
return;

case 'failed':
subscription.callback({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As above – using new Error(…) might be useful, because people tend to do err instanceof Error or err.toString().

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Only issue here is that there are 2 types of errors - recoverable and non-recoverable. The fatal flag indicates that. So not 100% sure how to handle that.

message: status.error,
fatal: true
});
subscriptions[subscription.idx] = null;
return;
}
})
.catch(subscription.callback);
}

function _pollStatus () {
subscriptions.map(_getSubscriptionStatus);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be .forEach.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch, fixed.

}

setInterval(_pollStatus, 2000);

return {
getCoins,
getMarketInfo,
getStatus,
shift,
subscribe
};
}
Loading