<commit_before>function getMajorVerison(){
	var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
	return raw ? parseInt(raw[2], 10) : false;
}

function displayContent(){
	var divContent = document.getElementById('content');
	var divNew = document.getElementById('new');
	var divLegacy = document.getElementById('legacy');
	var divFail = document.getElementById('fail');
	var divApply = document.getElementById('applyButton');

	if(getMajorVerison() > 47){
		divLegacy.style.display = 'none';
		divFail.style.display = 'none';
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		divNew.style.display = 'none';
		divFail.style.display = 'none';
	}
	else{
		divContent.style.display = 'none';
		divApply.style.display = 'none';
	}
}

chrome.extension.isAllowedIncognitoAccess(function(isAllowedAccess){
	var incognitoAllowed = document.getElementById('incognitoAllowed');
	var incognitoDisallowed = document.getElementById('incognitoDisallowed');

    if(isAllowedAccess == true){
		incognitoDisallowed.style.display = 'none';
	}
	else{
		incognitoAllowed.style.display = 'none';
	}
});

function save_options(){
	if(getMajorVerison() > 47){
		var policy = document.getElementById('policy').value;
		chrome.storage.local.set({
			rtcIPHandling: policy
		}, function(){
			var status = document.getElementById('status');
			status.textContent = 'Options saved.';
			chrome.storage.local.get('rtcIPHandling', function(items){
				chrome.privacy.network.webRTCIPHandlingPolicy.set({
					value: items.rtcIPHandling
				});
			});
			setTimeout(function(){
				status.textContent = '';
			}, 750);
		});
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		var nonProxiedUDP = document.getElementById('proxy').checked;
		var rtcMultipleRoutes = document.getElementById('multipleroutes').checked;
		chrome.storage.local.set({
			nonProxiedUDP: nonProxiedUDP,
			rtcMultipleRoutes: rtcMultipleRoutes
		}, function(){
			var status = document.getElementById('status');
			status.textContent = 'Options saved.';
			chrome.storage.local.get('rtcMultipleRoutes', function(items){
				chrome.privacy.network.webRTCMultipleRoutesEnabled.set({
					value: !items.rtcMultipleRoutes,
					scope: 'regular'
				});
			});
			chrome.storage.local.get('nonProxiedUDP', function(items){
				chrome.privacy.network.webRTCNonProxiedUdpEnabled.set({
					value: !items.nonProxiedUDP,
					scope: 'regular'
				});
			});
			setTimeout(function(){
				status.textContent = '';
			}, 750);
		});
	}
}

function restore_options(){
	if(getMajorVerison() > 47){
		chrome.storage.local.get({
			rtcIPHandling: 'default_public_interface_only'
		}, function(items){
			document.getElementById('policy').value = items.rtcIPHandling;
		});
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		chrome.storage.local.get({
			nonProxiedUDP: false,
			rtcMultipleRoutes: true
		}, function(items){
			document.getElementById('proxy').checked = items.nonProxiedUDP;
			document.getElementById('multipleroutes').checked = items.rtcMultipleRoutes;
		});
	}
}

document.addEventListener('DOMContentLoaded', displayContent);
document.addEventListener('DOMContentLoaded', restore_options);
document.addEventListener('DOMContentLoaded', chrome.extension.isAllowedIncognitoAccess);
document.getElementById('save').addEventListener('click', save_options);
<commit_msg>Very minor formatting change<commit_after>function getMajorVerison(){
	var raw = navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
	return raw ? parseInt(raw[2], 10) : false;
}

function displayContent(){
	var divContent = document.getElementById('content');
	var divNew = document.getElementById('new');
	var divLegacy = document.getElementById('legacy');
	var divFail = document.getElementById('fail');
	var divApply = document.getElementById('applyButton');

	if(getMajorVerison() > 47){
		divLegacy.style.display = 'none';
		divFail.style.display = 'none';
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		divNew.style.display = 'none';
		divFail.style.display = 'none';
	}
	else{
		divContent.style.display = 'none';
		divApply.style.display = 'none';
	}
}

chrome.extension.isAllowedIncognitoAccess(function(isAllowedAccess){
	var incognitoAllowed = document.getElementById('incognitoAllowed');
	var incognitoDisallowed = document.getElementById('incognitoDisallowed');

	if(isAllowedAccess == true){
		incognitoDisallowed.style.display = 'none';
	}
	else{
		incognitoAllowed.style.display = 'none';
	}
});

function save_options(){
	if(getMajorVerison() > 47){
		var policy = document.getElementById('policy').value;
		chrome.storage.local.set({
			rtcIPHandling: policy
		}, function(){
			var status = document.getElementById('status');
			status.textContent = 'Options saved.';
			chrome.storage.local.get('rtcIPHandling', function(items){
				chrome.privacy.network.webRTCIPHandlingPolicy.set({
					value: items.rtcIPHandling
				});
			});
			setTimeout(function(){
				status.textContent = '';
			}, 750);
		});
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		var nonProxiedUDP = document.getElementById('proxy').checked;
		var rtcMultipleRoutes = document.getElementById('multipleroutes').checked;
		chrome.storage.local.set({
			nonProxiedUDP: nonProxiedUDP,
			rtcMultipleRoutes: rtcMultipleRoutes
		}, function(){
			var status = document.getElementById('status');
			status.textContent = 'Options saved.';
			chrome.storage.local.get('rtcMultipleRoutes', function(items){
				chrome.privacy.network.webRTCMultipleRoutesEnabled.set({
					value: !items.rtcMultipleRoutes,
					scope: 'regular'
				});
			});
			chrome.storage.local.get('nonProxiedUDP', function(items){
				chrome.privacy.network.webRTCNonProxiedUdpEnabled.set({
					value: !items.nonProxiedUDP,
					scope: 'regular'
				});
			});
			setTimeout(function(){
				status.textContent = '';
			}, 750);
		});
	}
}

function restore_options(){
	if(getMajorVerison() > 47){
		chrome.storage.local.get({
			rtcIPHandling: 'default_public_interface_only'
		}, function(items){
			document.getElementById('policy').value = items.rtcIPHandling;
		});
	}
	else if(getMajorVerison() > 41 && getMajorVerison() < 48){
		chrome.storage.local.get({
			nonProxiedUDP: false,
			rtcMultipleRoutes: true
		}, function(items){
			document.getElementById('proxy').checked = items.nonProxiedUDP;
			document.getElementById('multipleroutes').checked = items.rtcMultipleRoutes;
		});
	}
}

document.addEventListener('DOMContentLoaded', displayContent);
document.addEventListener('DOMContentLoaded', restore_options);
document.addEventListener('DOMContentLoaded', chrome.extension.isAllowedIncognitoAccess);
document.getElementById('save').addEventListener('click', save_options);
<|endoftext|>


<commit_before>/**
 *
 * @author C.Vaes
 */

/**
* Check if url ends with a /
*/
function checkUrl(url) {

  if(url.substr(-1) !== '/' && url.length > 7)
    url = url + '/';

  if(url.indexOf("http://") == -1 && url.indexOf("https://") == -1)
    url = "http://" + url;

  return url;
}

//empty sonarrConfig object
var sonarrConfig = {};

/**
 * Test connection to sonarr server with api key. api/system/status call is used
 */
function test_connection() {
  var apiKey = document.getElementById('apiKey').value;
  var url = checkUrl(document.getElementById('url').value);
  document.getElementById('url').value = url;
  var status = document.getElementById('connectionStatus');

  status.textContent = 'Connecting to ' + url;
  $.ajax({
    url: url + 'api/system/status?apiKey=' + apiKey,
    statusCode: {
      401: function() {
        status.textContent = 'Credentials or url are not correct';
      },
      404: function() {
        status.textContent = 'Sonarr is not running on this address';
      }
    },
    complete : function(data){
      if(typeof(data.responseJSON) != "undefined"){
        status.textContent = 'Connection succesfull!';
        getInstallationInformation(data.responseJSON);
        sonarrConfig = data.responseJSON;
      } else {
        status.textContent = 'Credentials or url are not correct';
      }
    }

  });
}

function getInstallationInformation(data) {
  document.getElementById('version').textContent = data.version;
  document.getElementById('branch').textContent = data.branch;
}

/**
 * Save settings to chrome storage
 */
function save_options() {
  var apiKey = document.getElementById('apiKey').value;
  var url = checkUrl(document.getElementById('url').value);
  var numberOfDaysCalendar = document.getElementById('numberOfDaysCalendar').value;
  var wantedItems = document.getElementById('wantedItems').value;
  var historyItems = document.getElementById('historyItems').value;
  var backgroundInterval = document.getElementById('backgroundInterval').value;
  chrome.storage.sync.set({
    apiKey: apiKey,
    url: url,
    numberOfDaysCalendar : numberOfDaysCalendar,
    wantedItems : wantedItems,
    historyItems : historyItems,
    backgroundInterval : backgroundInterval,
    sonarrConfig : sonarrConfig,
  }, function() {
    // Update status to let user know options were saved.
    var status = document.getElementById('status');
    status.textContent = 'Options saved.';
    setTimeout(function() {
      status.textContent = '';
    }, 750);
  });
}

/**
 * Restore settings from chrome storage
 */
function restore_options() {
  // Use default value apiKey = '' and url = https://localhost.
  chrome.storage.sync.get({
    apiKey: '',
    url: 'http://localhost:8989',
    numberOfDaysCalendar : 7,
    wantedItems: 15,
    historyItems: 15,
    backgroundInterval : 5
  }, function(items) {
    document.getElementById('apiKey').value = items.apiKey;
    document.getElementById('url').value = items.url;
    document.getElementById('numberOfDaysCalendar').value = items.numberOfDaysCalendar;

    document.getElementById('wantedItems').value = items.wantedItems;
    document.getElementById('historyItems').value = items.historyItems;
    document.getElementById('backgroundInterval').value = items.backgroundInterval;
  });

  	document.getElementById('versionNumber').appendChild(document.createTextNode(chrome.runtime.getManifest().version));
}

// add listeners to buttons
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click',save_options);
document.getElementById('testConnection').addEventListener('click',test_connection);<commit_msg>fix typo in options<commit_after>/**
 *
 * @author C.Vaes
 */

/**
* Check if url ends with a /
*/
function checkUrl(url) {

  if(url.substr(-1) !== '/' && url.length > 7)
    url = url + '/';

  if(url.indexOf("http://") == -1 && url.indexOf("https://") == -1)
    url = "http://" + url;

  return url;
}

//empty sonarrConfig object
var sonarrConfig = {};

/**
 * Test connection to sonarr server with api key. api/system/status call is used
 */
function test_connection() {
  var apiKey = document.getElementById('apiKey').value;
  var url = checkUrl(document.getElementById('url').value);
  document.getElementById('url').value = url;
  var status = document.getElementById('connectionStatus');

  status.textContent = 'Connecting to ' + url;
  $.ajax({
    url: url + 'api/system/status?apiKey=' + apiKey,
    statusCode: {
      401: function() {
        status.textContent = 'Credentials or url are not correct';
      },
      404: function() {
        status.textContent = 'Sonarr is not running on this address';
      }
    },
    complete : function(data){
      if(typeof(data.responseJSON) != "undefined"){
        status.textContent = 'Connection successful!';
        getInstallationInformation(data.responseJSON);
        sonarrConfig = data.responseJSON;
      } else {
        status.textContent = 'Credentials or url are not correct';
      }
    }

  });
}

function getInstallationInformation(data) {
  document.getElementById('version').textContent = data.version;
  document.getElementById('branch').textContent = data.branch;
}

/**
 * Save settings to chrome storage
 */
function save_options() {
  var apiKey = document.getElementById('apiKey').value;
  var url = checkUrl(document.getElementById('url').value);
  var numberOfDaysCalendar = document.getElementById('numberOfDaysCalendar').value;
  var wantedItems = document.getElementById('wantedItems').value;
  var historyItems = document.getElementById('historyItems').value;
  var backgroundInterval = document.getElementById('backgroundInterval').value;
  chrome.storage.sync.set({
    apiKey: apiKey,
    url: url,
    numberOfDaysCalendar : numberOfDaysCalendar,
    wantedItems : wantedItems,
    historyItems : historyItems,
    backgroundInterval : backgroundInterval,
    sonarrConfig : sonarrConfig,
  }, function() {
    // Update status to let user know options were saved.
    var status = document.getElementById('status');
    status.textContent = 'Options saved.';
    setTimeout(function() {
      status.textContent = '';
    }, 750);
  });
}

/**
 * Restore settings from chrome storage
 */
function restore_options() {
  // Use default value apiKey = '' and url = https://localhost.
  chrome.storage.sync.get({
    apiKey: '',
    url: 'http://localhost:8989',
    numberOfDaysCalendar : 7,
    wantedItems: 15,
    historyItems: 15,
    backgroundInterval : 5
  }, function(items) {
    document.getElementById('apiKey').value = items.apiKey;
    document.getElementById('url').value = items.url;
    document.getElementById('numberOfDaysCalendar').value = items.numberOfDaysCalendar;

    document.getElementById('wantedItems').value = items.wantedItems;
    document.getElementById('historyItems').value = items.historyItems;
    document.getElementById('backgroundInterval').value = items.backgroundInterval;
  });

  	document.getElementById('versionNumber').appendChild(document.createTextNode(chrome.runtime.getManifest().version));
}

// add listeners to buttons
document.addEventListener('DOMContentLoaded', restore_options);
document.getElementById('save').addEventListener('click',save_options);
document.getElementById('testConnection').addEventListener('click',test_connection);<|endoftext|>


<commit_before>// Engine Settings.

// Do not modify the ones marked with a *

// Unless you know what you are doing

var engine = {

    // Initial Label *
    "Label": "Start",

    // Number of Save Slots
    "Slots": 10,

    // Current Media *.
    "Song": "",
    "Sound": "",
    "Scene": "",

    // Javascript saved from the $ command *.
    "JS": "",

    // Current Statement *.
    "Step": 0,

    // History for the previous function *.
    "MusicHistory":[],
    "SoundHistory":[],
    "ImageHistory":[],
    "CharacterHistory":[],
    "SceneHistory":[],

    // Change to true for a MultiLanguage Game.
    "MultiLanguage": false,

    // Music for the Main Menu.
    "MenuMusic": "",

    // Prefix for the Save Slots in Local Storage.
    "SaveLabel": "Save_",
    "AutoSaveLabel": "AutoSave_",

    // Turn main menu on/off; Default: true *
    "ShowMenu": true,

    // Time interval between autosaves (In Minutes). Default: 0 (Off)
    "AutoSave": 0
}

// Initial Settings
var settings = {

    // Initial Language for Multilanguage Games.
    "Language": "English",

    // Initial Volumes from 0.0 to 1.
    "Volume":{
		"Music": 1,
		"Voice": 1,
		"Sound": 1
    }
}
<commit_msg>Add storage variable<commit_after>// Engine Settings.

// Do not modify the ones marked with a *

// Unless you know what you are doing

var engine = {

    // Initial Label *
    "Label": "Start",

    // Number of Save Slots
    "Slots": 10,

    // Current Media *.
    "Song": "",
    "Sound": "",
    "Scene": "",

    // Javascript saved from the $ command *.
    "JS": "",

    // Current Statement *.
    "Step": 0,

    // History for the previous function *.
    "MusicHistory":[],
    "SoundHistory":[],
    "ImageHistory":[],
    "CharacterHistory":[],
    "SceneHistory":[],

    // Change to true for a MultiLanguage Game.
    "MultiLanguage": false,

    // Music for the Main Menu.
    "MenuMusic": "",

    // Prefix for the Save Slots in Local Storage.
    "SaveLabel": "Save_",
    "AutoSaveLabel": "AutoSave_",

    // Turn main menu on/off; Default: true *
    "ShowMenu": true,

    // Time interval between autosaves (In Minutes). Default: 0 (Off)
    "AutoSave": 0
}

// Initial Settings
var settings = {

    // Initial Language for Multilanguage Games.
    "Language": "English",

    // Initial Volumes from 0.0 to 1.
    "Volume":{
		"Music": 1,
		"Voice": 1,
		"Sound": 1
    }
}

// Persistent Storage Variable
var storage = {
	player: {
		Name: ""
	}
}
<|endoftext|>


<commit_before>// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.
<commit_msg>TICKET-1234 - usefull commit message<commit_after>// Avoid `console` errors in browsers that lack a console.
(function() {
    var method;
    var noop = function () {};
    var methods = [
        'assert', 'clear', 'count', 'debug', 'dir', 'dirxml', 'error',
        'exception', 'group', 'groupCollapsed', 'groupEnd', 'info', 'log',
        'markTimeline', 'profile', 'profileEnd', 'table', 'time', 'timeEnd',
        'timeStamp', 'trace', 'warn'
    ];
    var length = methods.length;
    var console = (window.console = window.console || {});

    var test = 'foo';
    var bar = test
    console.log(bar);

    while (length--) {
        method = methods[length];

        // Only stub undefined methods.
        if (!console[method]) {
            console[method] = noop;
        }
    }
}());

// Place any jQuery/helper plugins in here.
<|endoftext|>


<commit_before>var app = angular.module("poolApp", []);
app.controller("MainController", function($scope) {
    $scope.poolbase = [ {
        title: "Google",
        tags: "googling tips",
        links: [ {
            name: "Google efficiently",
            href: "http://www.makeuseof.com/tag/google-power-user/"
        } ]
    },{
        title: "Technical Interview Q&A",
        tags: "interviews questions tr technical awesome",
        links: [ {
            name: "Awesome Interviews",
            href: "https://github.com/MaximAbramchuck/awesome-interviews"
        } ]
    }, {
        title: "Html/Html5",
        tags: "markup",
        links: [ {
            name: "Introduction to HTML",
            href: "https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Introduction#History_of_HTML"
        }, {
            name: "Learn HTML",
            href: "http://learn.shayhowe.com/html-css/getting-to-know-html/"
        }, {
            name: "HTML5 in 5 mins",
            href: "https://msdn.microsoft.com/en-us/hh549253.aspx"
        }, {
            name: "More about HTML5",
            href: "https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5"
        }, {
            name: "HTML5-Canvas tutorial",
            href: "http://www.html5canvastutorials.com/"
        }, {
            name: "HTML5 + your browser compatibility",
            href: "https://html5test.com/"
        } ]
    }, {
        title: "Free Responsive Web Templates",
        tags: "website webpage",
        links: [ {
            name: "HTML5UP",
            href: "http://html5up.net/"
        }, {
            name: "Get Template",
            href: "http://www.gettemplate.com/"
        }, {
            name: "Foundation Templates",
            href: "http://foundation.zurb.com/templates.html"
        }, {
            name: "Bootstrap Templates",
            href: "http://startbootstrap.com/template-categories/all/"
        } ]
    }, {
        title: "Css/Css3",
        tags: "flex,styling,layout",
        links: [ {
            name: "Learn CSS",
            href: "http://learn.shayhowe.com/html-css/getting-to-know-css/"
        }, {
            name: "Learn Layout",
            href: "http://learnlayout.com/"
        }, {
            name: "CSS Properties",
            href: "http://www.cssportal.com/css-properties/index.php"
        }, {
            name: "30 CSS selectors to remember",
            href: "http://code.tutsplus.com/tutorials/the-30-css-selectors-you-must-memorize--net-16048"
        }, {
            name: "Game on CSS selectors",
            href: "http://flukeout.github.io/"
        }, {
            name: "Game on CSS3 Flexbox",
            href: "http://flexboxfroggy.com/"
        }, {
            name: "Link vs Import",
            href: "https://www.stevesouders.com/blog/2009/04/09/dont-use-import/"
        } ]
    }, {
        title: "Choosing color for text",
        tags: "colors",
        links: [ {
            name: "Choose right color",
            href: "http://colorsafe.co/"
        }, {
            name: "Pick color online",
            href: "http://colourco.de/"
        } ]
    }, {
        title: "Css Generators",
        tags: "generator",
        links: [ {
            name: "Online CSS3 generator",
            href: "http://enjoycss.com/"
        }, {
            name: "CSS Matic",
            href: "http://www.cssmatic.com/"
        }, {
            name: "Generate CSS arrow",
            href: "http://cssarrowplease.com/"
        }, {
            name: "CSS Shapes",
            href: "https://css-tricks.com/examples/ShapesOfCSS/"
        }, {
            name: "CSS gradient generator",
            href: "http://www.colorzilla.com/gradient-editor/"
        } ]
    }, {
        title: "Css Frameworks",
        tags: "frameworks",
        links: [ {
            name: "Bootstrap",
            href: "http://getbootstrap.com/"
        }, {
            name: "Foundation",
            href: "http://foundation.zurb.com/"
        }, {
            name: "Metro UI",
            href: "http://metroui.org.ua/"
        }, {
            name: "Furtive-CSS micro framework",
            href: "http://furtive.co/"
        } ]
    }, {
        title: "JavaScript",
        tags: "js,ecmascript,es5",
        links: [ {
            name: "All about JavaScript",
            href: "http://jstherightway.org/"
        }, {
            name: "JavaScript Standards",
            href: "http://bguiz.github.io/js-standards/intro/"
        }, {
            name: "Interactive way to learn JS",
            href: "http://www.codecademy.com/en/tracks/javascript"
        }, {
            name: "JavaScript Styleguide",
            href: "https://github.com/airbnb/javascript"
        }, {
            name: "Learn Object oriented JavaScript",
            href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript"
        }, {
            name: "Javascript Design Patterns",
            href: "https://scotch.io/bar-talk/4-javascript-design-patterns-you-should-know"
        }, {
            name: "Javascript Char codes",
            href: "http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes"
        }, {
            name: "jsPerf - compare js snippets ",
            href: "https://jsperf.com/"
        } ]
    }, {
        title: "Javascript Libraries",
        tags: "js jquery",
        links: [ {
            name: "Interactive way to learn jQuery",
            href: "http://try.jquery.com/"
        } ]
    }, {
        title: "AngularJS",
        tags: "js,javascript frameworks,ajs",
        links: [ {
            name: "AngularJS Guidelines",
            href: "http://bguiz.github.io/js-standards/angularjs/single-responsibility/"
        }, {
            name: "Angular StyleGuide",
            href: "https://github.com/johnpapa/angular-styleguide/tree/master/a1"
        }, {
            name: "AngularJS in 60minutes",
            href: "http://fastandfluid.com/publicdownloads/AngularJSIn60MinutesIsh_DanWahlin_May2013.pdf"
        }, {
            name: "AngularJS examples",
            href: "http://tutorialzine.com/2013/08/learn-angularjs-5-examples/"
        } ]
    }, {
        title: "Regular Expressions",
        tags: "regex",
        links: [ {
            name: "Regexone - learn interactively",
            href: "http://regexone.com/"
        }, {
            name: "Online Regex builder",
            href: "http://regexr.com/"
        } ]
    }, {
        title: "Learn Command Line Interface",
        tags: "cli cmd",
        links: [ {
            name: "Learn CLI the hard way",
            href: "http://cli.learncodethehardway.org/book/"
        } ]
    }, {
        title: "Introduction to programming",
        tags: "beginner coding",
        links: [ {
            name: "Lets Play the game",
            href: "http://learn.code.org/hoc/1"
        } ]
    }, {
        title: "One stop for programming",
        tags: "code learn api",
        links: [ {
            name: "Learn X in Y minutes",
            href: "http://learnxinyminutes.com/"
        }, {
            name: "Api hub",
            href: "http://overapi.com/"
        } ]
    }, {
        title: "C",
        tags: "compiled",
        links: [ {
            name: "Learn C the hard way",
            href: "http://c.learncodethehardway.org/book/"
        }, {
            name: "Basic c programs",
            href: "http://www.programiz.com/c-programming/examples"
        } ]
    }, {
        title: "Python",
        tags: "interpreted",
        links: [ {
            name: "Learn python the hard way",
            href: "http://learnpythonthehardway.org/book/"
        }, {
            name: "Basic python programs",
            href: "http://www.programiz.com/python-programming/examples"
        } ]
    }, {
        title: "Ruby",
        tags: "interpreted",
        links: [ {
            name: "Learn ruby the hard way",
            href: "http://learnrubythehardway.org/book/"
        }, {
            name: "Interactive way to learn ruby",
            href: "http://tryruby.org/levels/1/challenges/0"
        } ]
    }, {
        title: "Git",
        tags: "version control system vcs",
        links: [ {
            name: "Git in 15mins",
            href: "https://try.github.io"
        } ]
    }, {
        title: "Online Tutorials",
        tags: "free online all science technology",
        links: [ {
            name: "Scotch",
            href: "https://scotch.io/"
        }, {
            name: "Codecademy",
            href: "http://codecademy.com/"
        }, {
            name: "khanacademy",
            href: "https://www.khanacademy.org/"
        }, {
            name: "Codeschool",
            href: "https://www.codeschool.com/"
        }, {
            name: "Tutorials point",
            href: "http://tutorialspoint.com/"
        } ]
    }, {
        title: "Magazines for Web-development",
        tags: "web magazines smashing alistapart",
        links: [ {
            name: "Smashing magazine",
            href: "http://www.smashingmagazine.com/"
        }, {
            name: "Alistapart",
            href: "http://alistapart.com/topics"
        } ]
    }, {
        title: "Website Building",
        tags: "websites",
        links: [ {
            name: "Website creation guidelines by Google",
            href: "https://support.google.com/webmasters/answer/6001102"
        } ]
    }, {
        title: "Miscellaneous",
        tags: "grunt",
        links: [ {
            name: "Can I Use",
            href: "http://caniuse.com/"
        },{
            name: "Getting started with Grunt",
            href: "https://scotch.io/tutorials/a-simple-guide-to-getting-started-with-grunt"
        }, {
            name: "Grunt-Smashing Magazine",
            href: "http://www.smashingmagazine.com/2013/10/get-up-running-grunt/"
        }, {
            name: "Free e-books",
            href: "https://www.syncfusion.com/resources/techportal/ebooks"
        } ]
    } ];
    $scope.searchFilter = function(obj) {
        var re = new RegExp($scope.search, "i");
        return !$scope.search || re.test(obj.title) || re.test(obj.tags);
    };
});
<commit_msg>Js link added<commit_after>var app = angular.module("poolApp", []);
app.controller("MainController", function($scope) {
    $scope.poolbase = [ {
        title: "Google",
        tags: "googling tips",
        links: [ {
            name: "Google efficiently",
            href: "http://www.makeuseof.com/tag/google-power-user/"
        } ]
    },{
        title: "Technical Interview Q&A",
        tags: "interviews questions tr technical awesome",
        links: [ {
            name: "Awesome Interviews",
            href: "https://github.com/MaximAbramchuck/awesome-interviews"
        } ]
    }, {
        title: "Html/Html5",
        tags: "markup",
        links: [ {
            name: "Introduction to HTML",
            href: "https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Introduction#History_of_HTML"
        }, {
            name: "Learn HTML",
            href: "http://learn.shayhowe.com/html-css/getting-to-know-html/"
        }, {
            name: "HTML5 in 5 mins",
            href: "https://msdn.microsoft.com/en-us/hh549253.aspx"
        }, {
            name: "More about HTML5",
            href: "https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/HTML5"
        }, {
            name: "HTML5-Canvas tutorial",
            href: "http://www.html5canvastutorials.com/"
        }, {
            name: "HTML5 + your browser compatibility",
            href: "https://html5test.com/"
        } ]
    }, {
        title: "Free Responsive Web Templates",
        tags: "website webpage",
        links: [ {
            name: "HTML5UP",
            href: "http://html5up.net/"
        }, {
            name: "Get Template",
            href: "http://www.gettemplate.com/"
        }, {
            name: "Foundation Templates",
            href: "http://foundation.zurb.com/templates.html"
        }, {
            name: "Bootstrap Templates",
            href: "http://startbootstrap.com/template-categories/all/"
        } ]
    }, {
        title: "Css/Css3",
        tags: "flex,styling,layout",
        links: [ {
            name: "Learn CSS",
            href: "http://learn.shayhowe.com/html-css/getting-to-know-css/"
        }, {
            name: "Learn Layout",
            href: "http://learnlayout.com/"
        }, {
            name: "CSS Properties",
            href: "http://www.cssportal.com/css-properties/index.php"
        }, {
            name: "30 CSS selectors to remember",
            href: "http://code.tutsplus.com/tutorials/the-30-css-selectors-you-must-memorize--net-16048"
        }, {
            name: "Game on CSS selectors",
            href: "http://flukeout.github.io/"
        }, {
            name: "Game on CSS3 Flexbox",
            href: "http://flexboxfroggy.com/"
        }, {
            name: "Link vs Import",
            href: "https://www.stevesouders.com/blog/2009/04/09/dont-use-import/"
        } ]
    }, {
        title: "Choosing color for text",
        tags: "colors",
        links: [ {
            name: "Choose right color",
            href: "http://colorsafe.co/"
        }, {
            name: "Pick color online",
            href: "http://colourco.de/"
        } ]
    }, {
        title: "Css Generators",
        tags: "generator",
        links: [ {
            name: "Online CSS3 generator",
            href: "http://enjoycss.com/"
        }, {
            name: "CSS Matic",
            href: "http://www.cssmatic.com/"
        }, {
            name: "Generate CSS arrow",
            href: "http://cssarrowplease.com/"
        }, {
            name: "CSS Shapes",
            href: "https://css-tricks.com/examples/ShapesOfCSS/"
        }, {
            name: "CSS gradient generator",
            href: "http://www.colorzilla.com/gradient-editor/"
        } ]
    }, {
        title: "Css Frameworks",
        tags: "frameworks",
        links: [ {
            name: "Bootstrap",
            href: "http://getbootstrap.com/"
        }, {
            name: "Foundation",
            href: "http://foundation.zurb.com/"
        }, {
            name: "Metro UI",
            href: "http://metroui.org.ua/"
        }, {
            name: "Furtive-CSS micro framework",
            href: "http://furtive.co/"
        } ]
    }, {
        title: "JavaScript",
        tags: "js,ecmascript,es5",
        links: [ {
            name: "Essential JavaScript",
            href: "http://javascript.info/"
        }, {
            name: "All about JavaScript",
            href: "http://jstherightway.org/"
        }, {
            name: "JavaScript Standards",
            href: "http://bguiz.github.io/js-standards/intro/"
        }, {
            name: "Interactive way to learn JS",
            href: "http://www.codecademy.com/en/tracks/javascript"
        }, {
            name: "JavaScript Styleguide",
            href: "https://github.com/airbnb/javascript"
        }, {
            name: "Learn Object oriented JavaScript",
            href: "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript"
        }, {
            name: "Javascript Design Patterns",
            href: "https://scotch.io/bar-talk/4-javascript-design-patterns-you-should-know"
        }, {
            name: "Javascript Char codes",
            href: "http://www.cambiaresearch.com/articles/15/javascript-char-codes-key-codes"
        }, {
            name: "jsPerf - compare js snippets ",
            href: "https://jsperf.com/"
        } ]
    }, {
        title: "Javascript Libraries",
        tags: "js jquery",
        links: [ {
            name: "Interactive way to learn jQuery",
            href: "http://try.jquery.com/"
        } ]
    }, {
        title: "AngularJS",
        tags: "js,javascript frameworks,ajs",
        links: [ {
            name: "AngularJS Guidelines",
            href: "http://bguiz.github.io/js-standards/angularjs/single-responsibility/"
        }, {
            name: "Angular StyleGuide",
            href: "https://github.com/johnpapa/angular-styleguide/tree/master/a1"
        }, {
            name: "AngularJS in 60minutes",
            href: "http://fastandfluid.com/publicdownloads/AngularJSIn60MinutesIsh_DanWahlin_May2013.pdf"
        }, {
            name: "AngularJS examples",
            href: "http://tutorialzine.com/2013/08/learn-angularjs-5-examples/"
        } ]
    }, {
        title: "Regular Expressions",
        tags: "regex",
        links: [ {
            name: "Regexone - learn interactively",
            href: "http://regexone.com/"
        }, {
            name: "Online Regex builder",
            href: "http://regexr.com/"
        } ]
    }, {
        title: "Learn Command Line Interface",
        tags: "cli cmd",
        links: [ {
            name: "Learn CLI the hard way",
            href: "http://cli.learncodethehardway.org/book/"
        } ]
    }, {
        title: "Introduction to programming",
        tags: "beginner coding",
        links: [ {
            name: "Lets Play the game",
            href: "http://learn.code.org/hoc/1"
        } ]
    }, {
        title: "One stop for programming",
        tags: "code learn api",
        links: [ {
            name: "Learn X in Y minutes",
            href: "http://learnxinyminutes.com/"
        }, {
            name: "Api hub",
            href: "http://overapi.com/"
        } ]
    }, {
        title: "C",
        tags: "compiled",
        links: [ {
            name: "Learn C the hard way",
            href: "http://c.learncodethehardway.org/book/"
        }, {
            name: "Basic c programs",
            href: "http://www.programiz.com/c-programming/examples"
        } ]
    }, {
        title: "Python",
        tags: "interpreted",
        links: [ {
            name: "Learn python the hard way",
            href: "http://learnpythonthehardway.org/book/"
        }, {
            name: "Basic python programs",
            href: "http://www.programiz.com/python-programming/examples"
        } ]
    }, {
        title: "Ruby",
        tags: "interpreted",
        links: [ {
            name: "Learn ruby the hard way",
            href: "http://learnrubythehardway.org/book/"
        }, {
            name: "Interactive way to learn ruby",
            href: "http://tryruby.org/levels/1/challenges/0"
        } ]
    }, {
        title: "Git",
        tags: "version control system vcs",
        links: [ {
            name: "Git in 15mins",
            href: "https://try.github.io"
        } ]
    }, {
        title: "Online Tutorials",
        tags: "free online all science technology",
        links: [ {
            name: "Scotch",
            href: "https://scotch.io/"
        }, {
            name: "Codecademy",
            href: "http://codecademy.com/"
        }, {
            name: "khanacademy",
            href: "https://www.khanacademy.org/"
        }, {
            name: "Codeschool",
            href: "https://www.codeschool.com/"
        }, {
            name: "Tutorials point",
            href: "http://tutorialspoint.com/"
        } ]
    }, {
        title: "Magazines for Web-development",
        tags: "web magazines smashing alistapart",
        links: [ {
            name: "Smashing magazine",
            href: "http://www.smashingmagazine.com/"
        }, {
            name: "Alistapart",
            href: "http://alistapart.com/topics"
        } ]
    }, {
        title: "Website Building",
        tags: "websites",
        links: [ {
            name: "Website creation guidelines by Google",
            href: "https://support.google.com/webmasters/answer/6001102"
        } ]
    }, {
        title: "Miscellaneous",
        tags: "grunt",
        links: [ {
            name: "Can I Use",
            href: "http://caniuse.com/"
        },{
            name: "Getting started with Grunt",
            href: "https://scotch.io/tutorials/a-simple-guide-to-getting-started-with-grunt"
        }, {
            name: "Grunt-Smashing Magazine",
            href: "http://www.smashingmagazine.com/2013/10/get-up-running-grunt/"
        }, {
            name: "Free e-books",
            href: "https://www.syncfusion.com/resources/techportal/ebooks"
        } ]
    } ];
    $scope.searchFilter = function(obj) {
        var re = new RegExp($scope.search, "i");
        return !$scope.search || re.test(obj.title) || re.test(obj.tags);
    };
});
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class qryptos extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'qryptos',
            'name': 'QRYPTOS',
            'countries': [ 'CN', 'TW' ],
            'version': '2',
            'rateLimit': 1000,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/30953915-b1611dc0-a436-11e7-8947-c95bd5a42086.jpg',
                'api': 'https://api.qryptos.com',
                'www': 'https://www.qryptos.com',
                'doc': [
                    'https://developers.quoine.com',
                    'https://developers.quoine.com/v2',
                ],
                'fees': 'https://qryptos.zendesk.com/hc/en-us/articles/115007858167-Fees',
            },
            'api': {
                'public': {
                    'get': [
                        'products',
                        'products/{id}',
                        'products/{id}/price_levels',
                        'executions',
                        'ir_ladders/{currency}',
                    ],
                },
                'private': {
                    'get': [
                        'accounts/balance',
                        'accounts/main_asset',
                        'crypto_accounts',
                        'executions/me',
                        'fiat_accounts',
                        'loan_bids',
                        'loans',
                        'orders',
                        'orders/{id}',
                        'orders/{id}/trades',
                        'orders/{id}/executions',
                        'trades',
                        'trades/{id}/loans',
                        'trading_accounts',
                        'trading_accounts/{id}',
                    ],
                    'post': [
                        'fiat_accounts',
                        'loan_bids',
                        'orders',
                    ],
                    'put': [
                        'loan_bids/{id}/close',
                        'loans/{id}',
                        'orders/{id}',
                        'orders/{id}/cancel',
                        'trades/{id}',
                        'trades/{id}/close',
                        'trades/close_all',
                        'trading_accounts/{id}',
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'].toString ();
            let base = market['base_currency'];
            let quote = market['quoted_currency'];
            let symbol = base + '/' + quote;
            let maker = this.safeFloat (market, 'maker_fee');
            let taker = this.safeFloat (market, 'taker_fee');
            let active = !market['disabled'];
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'maker': maker,
                'taker': taker,
                'active': active,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccountsBalance ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let total = parseFloat (balance['balance']);
            let account = {
                'free': total,
                'used': 0.0,
                'total': total,
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdPriceLevels (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'buy_price_levels', 'sell_price_levels');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let last = undefined;
        if ('last_traded_price' in ticker) {
            if (ticker['last_traded_price']) {
                let length = ticker['last_traded_price'].length;
                if (length > 0)
                    last = parseFloat (ticker['last_traded_price']);
            }
        }
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high_market_ask'),
            'low': this.safeFloat (ticker, 'low_market_bid'),
            'bid': this.safeFloat (ticker, 'market_bid'),
            'ask': this.safeFloat (ticker, 'market_ask'),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_24h'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetProducts (params);
        let result = {};
        for (let t = 0; t < tickers.length; t++) {
            let ticker = tickers[t];
            let base = ticker['base_currency'];
            let quote = ticker['quoted_currency'];
            let symbol = base + '/' + quote;
            let market = this.markets[symbol];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.publicGetProductsId (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['created_at'] * 1000;
        return {
            'info': trade,
            'id': trade['id'].toString (),
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['taker_side'],
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['quantity']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_id': market['id'],
        };
        if (limit)
            request['limit'] = limit;
        let response = await this.publicGetExecutions (this.extend (request, params));
        return this.parseTrades (response['models'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'order_type': type,
            'product_id': this.marketId (symbol),
            'side': side,
            'quantity': amount,
        };
        if (type === 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend ({
            'order': order,
        }, params));
        return this.parseOrder(response);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePutOrdersIdCancel (this.extend ({
            'id': id,
        }, params));
        let order = this.parseOrder (result);
        if (order['status'] === 'closed')
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        return order;
    }

    parseOrder (order) {
        let timestamp = order['created_at'] * 1000;
        let marketId = order['product_id'].toString ();
        let market = this.marketsById[marketId];
        let status = undefined;
        if ('status' in order) {
            if (order['status'] === 'live') {
                status = 'open';
            } else if (order['status'] === 'filled') {
                status = 'closed';
            } else if (order['status'] === 'cancelled') { // 'll' intended
                status = 'canceled';
            }
        }
        let amount = parseFloat (order['quantity']);
        let filled = parseFloat (order['filled_quantity']);
        let symbol = undefined;
        if (market) {
            symbol = market['symbol'];
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'type': order['order_type'],
            'status': status,
            'symbol': symbol,
            'side': order['side'],
            'price': order['price'],
            'amount': amount,
            'filled': filled,
            'remaining': amount - filled,
            'trades': undefined,
            'fee': {
                'currency': undefined,
                'cost': parseFloat (order['order_fee']),
            },
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params={}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let status = params['status'];
        if (status === 'open') {
            request['status'] = 'live';
        } else if (status === 'closed') {
            request['status'] = 'filled';
        } else if (status === 'canceled') {
            request['status'] = 'cancelled';
        }
        let result = await this.privateGetOrders (request);
        let orders = result['models'];
        return this.parseOrders (orders, market, since, limit);
    }

    fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'open' }, params));
    }

    fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'closed' }, params));
    }

    handleErrors (code, reason, url, method, headers, body) {
        let response = undefined;
        if (code === 200 || code === 404 || code === 422) {
            if ((body[0] === '{') || (body[0] === '[')) {
                response = JSON.parse (body);
            } else {
                // if not a JSON response
                throw new ExchangeError (this.id + ' returned a non-JSON reply: ' + body);
            }
        }
        if (code === 401) {
            if (body === 'API Authentication failed') {
                throw new AuthenticationError (body);
            }
        }
        if (code === 404) {
            if ('message' in response) {
                if (response['message'] === 'Order not found') {
                    throw new OrderNotFound (this.id + ' ' + body);
                }
            }
        } else if (code === 422) {
            if ('errors' in response) {
                let errors = response['errors'];
                if ('user' in errors) {
                    let messages = errors['user'];
                    if (messages.indexOf ('not_enough_free_balance') >= 0) {
                        throw new InsufficientFunds (this.id + ' ' + body);
                    }
                } else if ('quantity' in errors) {
                    let messages = errors['quantity'];
                    if (messages.indexOf ('less_than_order_size') >= 0) {
                        throw new InvalidOrder (this.id + ' ' + body);
                    }
                }
            }
        }
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = {
            'X-Quoine-API-Version': this.version,
            'Content-Type': 'application/json',
        };
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            if (method === 'GET') {
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            } else if (Object.keys (query).length) {
                body = this.json (query);
            }
            let nonce = this.nonce ();
            let request = {
                'path': url,
                'nonce': nonce,
                'token_id': this.apiKey,
                'iat': Math.floor (nonce / 1000), // issued at
            };
            headers['X-Quoine-Auth'] = this.jwt (request, this.secret);
        }
        url = this.urls['api'] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>qryptos edits to order status in fetchOrders for python safety<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class qryptos extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'qryptos',
            'name': 'QRYPTOS',
            'countries': [ 'CN', 'TW' ],
            'version': '2',
            'rateLimit': 1000,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/30953915-b1611dc0-a436-11e7-8947-c95bd5a42086.jpg',
                'api': 'https://api.qryptos.com',
                'www': 'https://www.qryptos.com',
                'doc': [
                    'https://developers.quoine.com',
                    'https://developers.quoine.com/v2',
                ],
                'fees': 'https://qryptos.zendesk.com/hc/en-us/articles/115007858167-Fees',
            },
            'api': {
                'public': {
                    'get': [
                        'products',
                        'products/{id}',
                        'products/{id}/price_levels',
                        'executions',
                        'ir_ladders/{currency}',
                    ],
                },
                'private': {
                    'get': [
                        'accounts/balance',
                        'accounts/main_asset',
                        'crypto_accounts',
                        'executions/me',
                        'fiat_accounts',
                        'loan_bids',
                        'loans',
                        'orders',
                        'orders/{id}',
                        'orders/{id}/trades',
                        'orders/{id}/executions',
                        'trades',
                        'trades/{id}/loans',
                        'trading_accounts',
                        'trading_accounts/{id}',
                    ],
                    'post': [
                        'fiat_accounts',
                        'loan_bids',
                        'orders',
                    ],
                    'put': [
                        'loan_bids/{id}/close',
                        'loans/{id}',
                        'orders/{id}',
                        'orders/{id}/cancel',
                        'trades/{id}',
                        'trades/{id}/close',
                        'trades/close_all',
                        'trading_accounts/{id}',
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'].toString ();
            let base = market['base_currency'];
            let quote = market['quoted_currency'];
            let symbol = base + '/' + quote;
            let maker = this.safeFloat (market, 'maker_fee');
            let taker = this.safeFloat (market, 'taker_fee');
            let active = !market['disabled'];
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'maker': maker,
                'taker': taker,
                'active': active,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccountsBalance ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let total = parseFloat (balance['balance']);
            let account = {
                'free': total,
                'used': 0.0,
                'total': total,
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdPriceLevels (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'buy_price_levels', 'sell_price_levels');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let last = undefined;
        if ('last_traded_price' in ticker) {
            if (ticker['last_traded_price']) {
                let length = ticker['last_traded_price'].length;
                if (length > 0)
                    last = parseFloat (ticker['last_traded_price']);
            }
        }
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high_market_ask'),
            'low': this.safeFloat (ticker, 'low_market_bid'),
            'bid': this.safeFloat (ticker, 'market_bid'),
            'ask': this.safeFloat (ticker, 'market_ask'),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_24h'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetProducts (params);
        let result = {};
        for (let t = 0; t < tickers.length; t++) {
            let ticker = tickers[t];
            let base = ticker['base_currency'];
            let quote = ticker['quoted_currency'];
            let symbol = base + '/' + quote;
            let market = this.markets[symbol];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.publicGetProductsId (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['created_at'] * 1000;
        return {
            'info': trade,
            'id': trade['id'].toString (),
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['taker_side'],
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['quantity']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_id': market['id'],
        };
        if (limit)
            request['limit'] = limit;
        let response = await this.publicGetExecutions (this.extend (request, params));
        return this.parseTrades (response['models'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'order_type': type,
            'product_id': this.marketId (symbol),
            'side': side,
            'quantity': amount,
        };
        if (type === 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend ({
            'order': order,
        }, params));
        return this.parseOrder(response);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePutOrdersIdCancel (this.extend ({
            'id': id,
        }, params));
        let order = this.parseOrder (result);
        if (order['status'] === 'closed')
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        return order;
    }

    parseOrder (order) {
        let timestamp = order['created_at'] * 1000;
        let marketId = order['product_id'].toString ();
        let market = this.marketsById[marketId];
        let status = undefined;
        if ('status' in order) {
            if (order['status'] === 'live') {
                status = 'open';
            } else if (order['status'] === 'filled') {
                status = 'closed';
            } else if (order['status'] === 'cancelled') { // 'll' intended
                status = 'canceled';
            }
        }
        let amount = parseFloat (order['quantity']);
        let filled = parseFloat (order['filled_quantity']);
        let symbol = undefined;
        if (market) {
            symbol = market['symbol'];
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'type': order['order_type'],
            'status': status,
            'symbol': symbol,
            'side': order['side'],
            'price': order['price'],
            'amount': amount,
            'filled': filled,
            'remaining': amount - filled,
            'trades': undefined,
            'fee': {
                'currency': undefined,
                'cost': parseFloat (order['order_fee']),
            },
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params={}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let status = this.safeValue (params['status']);
        if (status) {
            params = this.omit (params, 'status');
            if (status === 'open') {
                request['status'] = 'live';
            } else if (status === 'closed') {
                request['status'] = 'filled';
            } else if (status === 'canceled') {
                request['status'] = 'cancelled';
            }
        }
        let result = await this.privateGetOrders (this.extend (request, params));
        let orders = result['models'];
        return this.parseOrders (orders, market, since, limit);
    }

    fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'open' }, params));
    }

    fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'closed' }, params));
    }

    handleErrors (code, reason, url, method, headers, body) {
        let response = undefined;
        if (code === 200 || code === 404 || code === 422) {
            if ((body[0] === '{') || (body[0] === '[')) {
                response = JSON.parse (body);
            } else {
                // if not a JSON response
                throw new ExchangeError (this.id + ' returned a non-JSON reply: ' + body);
            }
        }
        if (code === 401) {
            if (body === 'API Authentication failed') {
                throw new AuthenticationError (body);
            }
        }
        if (code === 404) {
            if ('message' in response) {
                if (response['message'] === 'Order not found') {
                    throw new OrderNotFound (this.id + ' ' + body);
                }
            }
        } else if (code === 422) {
            if ('errors' in response) {
                let errors = response['errors'];
                if ('user' in errors) {
                    let messages = errors['user'];
                    if (messages.indexOf ('not_enough_free_balance') >= 0) {
                        throw new InsufficientFunds (this.id + ' ' + body);
                    }
                } else if ('quantity' in errors) {
                    let messages = errors['quantity'];
                    if (messages.indexOf ('less_than_order_size') >= 0) {
                        throw new InvalidOrder (this.id + ' ' + body);
                    }
                }
            }
        }
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = {
            'X-Quoine-API-Version': this.version,
            'Content-Type': 'application/json',
        };
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            if (method === 'GET') {
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            } else if (Object.keys (query).length) {
                body = this.json (query);
            }
            let nonce = this.nonce ();
            let request = {
                'path': url,
                'nonce': nonce,
                'token_id': this.apiKey,
                'iat': Math.floor (nonce / 1000), // issued at
            };
            headers['X-Quoine-Auth'] = this.jwt (request, this.secret);
        }
        url = this.urls['api'] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>


<commit_before>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class qryptos extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'qryptos',
            'name': 'QRYPTOS',
            'countries': [ 'CN', 'TW' ],
            'version': '2',
            'rateLimit': 1000,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/30953915-b1611dc0-a436-11e7-8947-c95bd5a42086.jpg',
                'api': 'https://api.qryptos.com',
                'www': 'https://www.qryptos.com',
                'doc': [
                    'https://developers.quoine.com',
                    'https://developers.quoine.com/v2',
                ],
                'fees': 'https://qryptos.zendesk.com/hc/en-us/articles/115007858167-Fees',
            },
            'api': {
                'public': {
                    'get': [
                        'products',
                        'products/{id}',
                        'products/{id}/price_levels',
                        'executions',
                        'ir_ladders/{currency}',
                    ],
                },
                'private': {
                    'get': [
                        'accounts/balance',
                        'accounts/main_asset',
                        'crypto_accounts',
                        'executions/me',
                        'fiat_accounts',
                        'loan_bids',
                        'loans',
                        'orders',
                        'orders/{id}',
                        'orders/{id}/trades',
                        'orders/{id}/executions',
                        'trades',
                        'trades/{id}/loans',
                        'trading_accounts',
                        'trading_accounts/{id}',
                    ],
                    'post': [
                        'fiat_accounts',
                        'loan_bids',
                        'orders',
                    ],
                    'put': [
                        'loan_bids/{id}/close',
                        'loans/{id}',
                        'orders/{id}',
                        'orders/{id}/cancel',
                        'trades/{id}',
                        'trades/{id}/close',
                        'trades/close_all',
                        'trading_accounts/{id}',
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'].toString ();
            let base = market['base_currency'];
            let quote = market['quoted_currency'];
            let symbol = base + '/' + quote;
            let maker = this.safeFloat (market, 'maker_fee');
            let taker = this.safeFloat (market, 'taker_fee');
            let active = !market['disabled'];
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'maker': maker,
                'taker': taker,
                'active': active,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccountsBalance ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let total = parseFloat (balance['balance']);
            let account = {
                'free': total,
                'used': 0.0,
                'total': total,
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdPriceLevels (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'buy_price_levels', 'sell_price_levels');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let last = undefined;
        if ('last_traded_price' in ticker) {
            if (ticker['last_traded_price']) {
                let length = ticker['last_traded_price'].length;
                if (length > 0)
                    last = parseFloat (ticker['last_traded_price']);
            }
        }
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high_market_ask'),
            'low': this.safeFloat (ticker, 'low_market_bid'),
            'bid': this.safeFloat (ticker, 'market_bid'),
            'ask': this.safeFloat (ticker, 'market_ask'),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_24h'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetProducts (params);
        let result = {};
        for (let t = 0; t < tickers.length; t++) {
            let ticker = tickers[t];
            let base = ticker['base_currency'];
            let quote = ticker['quoted_currency'];
            let symbol = base + '/' + quote;
            let market = this.markets[symbol];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.publicGetProductsId (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['created_at'] * 1000;
        return {
            'info': trade,
            'id': trade['id'].toString (),
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['taker_side'],
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['quantity']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_id': market['id'],
        };
        if (typeof limit !== 'undefined')
            request['limit'] = limit;
        let response = await this.publicGetExecutions (this.extend (request, params));
        return this.parseTrades (response['models'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'order_type': type,
            'product_id': this.marketId (symbol),
            'side': side,
            'quantity': amount,
        };
        if (type === 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend ({
            'order': order,
        }, params));
        return this.parseOrder(response);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePutOrdersIdCancel (this.extend ({
            'id': id,
        }, params));
        let order = this.parseOrder (result);
        if (order['status'] === 'closed')
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        return order;
    }

    parseOrder (order) {
        let timestamp = order['created_at'] * 1000;
        let marketId = order['product_id'].toString ();
        let market = this.marketsById[marketId];
        let status = undefined;
        if ('status' in order) {
            if (order['status'] === 'live') {
                status = 'open';
            } else if (order['status'] === 'filled') {
                status = 'closed';
            } else if (order['status'] === 'cancelled') { // 'll' intended
                status = 'canceled';
            }
        }
        let amount = parseFloat (order['quantity']);
        let filled = parseFloat (order['filled_quantity']);
        let symbol = undefined;
        if (market) {
            symbol = market['symbol'];
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'type': order['order_type'],
            'status': status,
            'symbol': symbol,
            'side': order['side'],
            'price': order['price'],
            'amount': amount,
            'filled': filled,
            'remaining': amount - filled,
            'trades': undefined,
            'fee': {
                'currency': undefined,
                'cost': parseFloat (order['order_fee']),
            },
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params={}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let status = this.safeValue (params, 'status');
        if (status) {
            params = this.omit (params, 'status');
            if (status === 'open') {
                request['status'] = 'live';
            } else if (status === 'closed') {
                request['status'] = 'filled';
            } else if (status === 'canceled') {
                request['status'] = 'cancelled';
            }
        }
        let result = await this.privateGetOrders (this.extend (request, params));
        let orders = result['models'];
        return this.parseOrders (orders, market, since, limit);
    }

    fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'open' }, params));
    }

    fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'closed' }, params));
    }

    handleErrors (code, reason, url, method, headers, body) {
        let response = undefined;
        if (code === 200 || code === 404 || code === 422) {
            if ((body[0] === '{') || (body[0] === '[')) {
                response = JSON.parse (body);
            } else {
                // if not a JSON response
                throw new ExchangeError (this.id + ' returned a non-JSON reply: ' + body);
            }
        }
        if (code === 401) {
            if (body === 'API Authentication failed') {
                throw new AuthenticationError (body);
            }
        }
        if (code === 404) {
            if ('message' in response) {
                if (response['message'] === 'Order not found') {
                    throw new OrderNotFound (this.id + ' ' + body);
                }
            }
        } else if (code === 422) {
            if ('errors' in response) {
                let errors = response['errors'];
                if ('user' in errors) {
                    let messages = errors['user'];
                    if (messages.indexOf ('not_enough_free_balance') >= 0) {
                        throw new InsufficientFunds (this.id + ' ' + body);
                    }
                } else if ('quantity' in errors) {
                    let messages = errors['quantity'];
                    if (messages.indexOf ('less_than_order_size') >= 0) {
                        throw new InvalidOrder (this.id + ' ' + body);
                    }
                }
            }
        }
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = {
            'X-Quoine-API-Version': this.version,
            'Content-Type': 'application/json',
        };
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            if (method === 'GET') {
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            } else if (Object.keys (query).length) {
                body = this.json (query);
            }
            let nonce = this.nonce ();
            let request = {
                'path': url,
                'nonce': nonce,
                'token_id': this.apiKey,
                'iat': Math.floor (nonce / 1000), // issued at
            };
            headers['X-Quoine-Auth'] = this.jwt (request, this.secret);
        }
        url = this.urls['api'] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<commit_msg>Removed order property<commit_after>'use strict';

//  ---------------------------------------------------------------------------

const Exchange = require ('./base/Exchange');
const { ExchangeError, OrderNotFound, InvalidOrder, InsufficientFunds, AuthenticationError } = require ('./base/errors');

//  ---------------------------------------------------------------------------

module.exports = class qryptos extends Exchange {

    describe () {
        return this.deepExtend (super.describe (), {
            'id': 'qryptos',
            'name': 'QRYPTOS',
            'countries': [ 'CN', 'TW' ],
            'version': '2',
            'rateLimit': 1000,
            'has': {
                'CORS': false,
                'fetchTickers': true,
                'fetchOrder': true,
                'fetchOrders': true,
                'fetchOpenOrders': true,
                'fetchClosedOrders': true,
            },
            'urls': {
                'logo': 'https://user-images.githubusercontent.com/1294454/30953915-b1611dc0-a436-11e7-8947-c95bd5a42086.jpg',
                'api': 'https://api.qryptos.com',
                'www': 'https://www.qryptos.com',
                'doc': [
                    'https://developers.quoine.com',
                    'https://developers.quoine.com/v2',
                ],
                'fees': 'https://qryptos.zendesk.com/hc/en-us/articles/115007858167-Fees',
            },
            'api': {
                'public': {
                    'get': [
                        'products',
                        'products/{id}',
                        'products/{id}/price_levels',
                        'executions',
                        'ir_ladders/{currency}',
                    ],
                },
                'private': {
                    'get': [
                        'accounts/balance',
                        'accounts/main_asset',
                        'crypto_accounts',
                        'executions/me',
                        'fiat_accounts',
                        'loan_bids',
                        'loans',
                        'orders',
                        'orders/{id}',
                        'orders/{id}/trades',
                        'orders/{id}/executions',
                        'trades',
                        'trades/{id}/loans',
                        'trading_accounts',
                        'trading_accounts/{id}',
                    ],
                    'post': [
                        'fiat_accounts',
                        'loan_bids',
                        'orders',
                    ],
                    'put': [
                        'loan_bids/{id}/close',
                        'loans/{id}',
                        'orders/{id}',
                        'orders/{id}/cancel',
                        'trades/{id}',
                        'trades/{id}/close',
                        'trades/close_all',
                        'trading_accounts/{id}',
                    ],
                },
            },
        });
    }

    async fetchMarkets () {
        let markets = await this.publicGetProducts ();
        let result = [];
        for (let p = 0; p < markets.length; p++) {
            let market = markets[p];
            let id = market['id'].toString ();
            let base = market['base_currency'];
            let quote = market['quoted_currency'];
            let symbol = base + '/' + quote;
            let maker = this.safeFloat (market, 'maker_fee');
            let taker = this.safeFloat (market, 'taker_fee');
            let active = !market['disabled'];
            result.push ({
                'id': id,
                'symbol': symbol,
                'base': base,
                'quote': quote,
                'maker': maker,
                'taker': taker,
                'active': active,
                'info': market,
            });
        }
        return result;
    }

    async fetchBalance (params = {}) {
        await this.loadMarkets ();
        let balances = await this.privateGetAccountsBalance ();
        let result = { 'info': balances };
        for (let b = 0; b < balances.length; b++) {
            let balance = balances[b];
            let currency = balance['currency'];
            let total = parseFloat (balance['balance']);
            let account = {
                'free': total,
                'used': 0.0,
                'total': total,
            };
            result[currency] = account;
        }
        return this.parseBalance (result);
    }

    async fetchOrderBook (symbol, params = {}) {
        await this.loadMarkets ();
        let orderbook = await this.publicGetProductsIdPriceLevels (this.extend ({
            'id': this.marketId (symbol),
        }, params));
        return this.parseOrderBook (orderbook, undefined, 'buy_price_levels', 'sell_price_levels');
    }

    parseTicker (ticker, market = undefined) {
        let timestamp = this.milliseconds ();
        let last = undefined;
        if ('last_traded_price' in ticker) {
            if (ticker['last_traded_price']) {
                let length = ticker['last_traded_price'].length;
                if (length > 0)
                    last = parseFloat (ticker['last_traded_price']);
            }
        }
        let symbol = undefined;
        if (market)
            symbol = market['symbol'];
        return {
            'symbol': symbol,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'high': this.safeFloat (ticker, 'high_market_ask'),
            'low': this.safeFloat (ticker, 'low_market_bid'),
            'bid': this.safeFloat (ticker, 'market_bid'),
            'ask': this.safeFloat (ticker, 'market_ask'),
            'vwap': undefined,
            'open': undefined,
            'close': undefined,
            'first': undefined,
            'last': last,
            'change': undefined,
            'percentage': undefined,
            'average': undefined,
            'baseVolume': this.safeFloat (ticker, 'volume_24h'),
            'quoteVolume': undefined,
            'info': ticker,
        };
    }

    async fetchTickers (symbols = undefined, params = {}) {
        await this.loadMarkets ();
        let tickers = await this.publicGetProducts (params);
        let result = {};
        for (let t = 0; t < tickers.length; t++) {
            let ticker = tickers[t];
            let base = ticker['base_currency'];
            let quote = ticker['quoted_currency'];
            let symbol = base + '/' + quote;
            let market = this.markets[symbol];
            result[symbol] = this.parseTicker (ticker, market);
        }
        return result;
    }

    async fetchTicker (symbol, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let ticker = await this.publicGetProductsId (this.extend ({
            'id': market['id'],
        }, params));
        return this.parseTicker (ticker, market);
    }

    parseTrade (trade, market) {
        let timestamp = trade['created_at'] * 1000;
        return {
            'info': trade,
            'id': trade['id'].toString (),
            'order': undefined,
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'symbol': market['symbol'],
            'type': undefined,
            'side': trade['taker_side'],
            'price': parseFloat (trade['price']),
            'amount': parseFloat (trade['quantity']),
        };
    }

    async fetchTrades (symbol, since = undefined, limit = undefined, params = {}) {
        await this.loadMarkets ();
        let market = this.market (symbol);
        let request = {
            'product_id': market['id'],
        };
        if (typeof limit !== 'undefined')
            request['limit'] = limit;
        let response = await this.publicGetExecutions (this.extend (request, params));
        return this.parseTrades (response['models'], market, since, limit);
    }

    async createOrder (symbol, type, side, amount, price = undefined, params = {}) {
        await this.loadMarkets ();
        let order = {
            'order_type': type,
            'product_id': this.marketId (symbol),
            'side': side,
            'quantity': amount,
        };
        if (type === 'limit')
            order['price'] = price;
        let response = await this.privatePostOrders (this.extend (order, params));
        return this.parseOrder(response);
    }

    async cancelOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let result = await this.privatePutOrdersIdCancel (this.extend ({
            'id': id,
        }, params));
        let order = this.parseOrder (result);
        if (order['status'] === 'closed')
            throw new OrderNotFound (this.id + ' ' + this.json (order));
        return order;
    }

    parseOrder (order) {
        let timestamp = order['created_at'] * 1000;
        let marketId = order['product_id'].toString ();
        let market = this.marketsById[marketId];
        let status = undefined;
        if ('status' in order) {
            if (order['status'] === 'live') {
                status = 'open';
            } else if (order['status'] === 'filled') {
                status = 'closed';
            } else if (order['status'] === 'cancelled') { // 'll' intended
                status = 'canceled';
            }
        }
        let amount = parseFloat (order['quantity']);
        let filled = parseFloat (order['filled_quantity']);
        let symbol = undefined;
        if (market) {
            symbol = market['symbol'];
        }
        return {
            'id': order['id'].toString (),
            'timestamp': timestamp,
            'datetime': this.iso8601 (timestamp),
            'type': order['order_type'],
            'status': status,
            'symbol': symbol,
            'side': order['side'],
            'price': order['price'],
            'amount': amount,
            'filled': filled,
            'remaining': amount - filled,
            'trades': undefined,
            'fee': {
                'currency': undefined,
                'cost': parseFloat (order['order_fee']),
            },
            'info': order,
        };
    }

    async fetchOrder (id, symbol = undefined, params = {}) {
        await this.loadMarkets ();
        let order = await this.privateGetOrdersId (this.extend ({
            'id': id,
        }, params));
        return this.parseOrder (order);
    }

    async fetchOrders (symbol = undefined, since = undefined, limit = undefined, params={}) {
        await this.loadMarkets ();
        let market = undefined;
        let request = {};
        if (symbol) {
            market = this.market (symbol);
            request['product_id'] = market['id'];
        }
        let status = this.safeValue (params, 'status');
        if (status) {
            params = this.omit (params, 'status');
            if (status === 'open') {
                request['status'] = 'live';
            } else if (status === 'closed') {
                request['status'] = 'filled';
            } else if (status === 'canceled') {
                request['status'] = 'cancelled';
            }
        }
        let result = await this.privateGetOrders (this.extend (request, params));
        let orders = result['models'];
        return this.parseOrders (orders, market, since, limit);
    }

    fetchOpenOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'open' }, params));
    }

    fetchClosedOrders (symbol = undefined, since = undefined, limit = undefined, params = {}) {
        return this.fetchOrders (symbol, since, limit, this.extend ({ 'status': 'closed' }, params));
    }

    handleErrors (code, reason, url, method, headers, body) {
        let response = undefined;
        if (code === 200 || code === 404 || code === 422) {
            if ((body[0] === '{') || (body[0] === '[')) {
                response = JSON.parse (body);
            } else {
                // if not a JSON response
                throw new ExchangeError (this.id + ' returned a non-JSON reply: ' + body);
            }
        }
        if (code === 401) {
            if (body === 'API Authentication failed') {
                throw new AuthenticationError (body);
            }
        }
        if (code === 404) {
            if ('message' in response) {
                if (response['message'] === 'Order not found') {
                    throw new OrderNotFound (this.id + ' ' + body);
                }
            }
        } else if (code === 422) {
            if ('errors' in response) {
                let errors = response['errors'];
                if ('user' in errors) {
                    let messages = errors['user'];
                    if (messages.indexOf ('not_enough_free_balance') >= 0) {
                        throw new InsufficientFunds (this.id + ' ' + body);
                    }
                } else if ('quantity' in errors) {
                    let messages = errors['quantity'];
                    if (messages.indexOf ('less_than_order_size') >= 0) {
                        throw new InvalidOrder (this.id + ' ' + body);
                    }
                }
            }
        }
    }

    nonce () {
        return this.milliseconds ();
    }

    sign (path, api = 'public', method = 'GET', params = {}, headers = undefined, body = undefined) {
        let url = '/' + this.implodeParams (path, params);
        let query = this.omit (params, this.extractParams (path));
        headers = {
            'X-Quoine-API-Version': this.version,
            'Content-Type': 'application/json',
        };
        if (api === 'public') {
            if (Object.keys (query).length)
                url += '?' + this.urlencode (query);
        } else {
            this.checkRequiredCredentials ();
            if (method === 'GET') {
                if (Object.keys (query).length)
                    url += '?' + this.urlencode (query);
            } else if (Object.keys (query).length) {
                body = this.json (query);
            }
            let nonce = this.nonce ();
            let request = {
                'path': url,
                'nonce': nonce,
                'token_id': this.apiKey,
                'iat': Math.floor (nonce / 1000), // issued at
            };
            headers['X-Quoine-Auth'] = this.jwt (request, this.secret);
        }
        url = this.urls['api'] + url;
        return { 'url': url, 'method': method, 'body': body, 'headers': headers };
    }
};
<|endoftext|>