├── .bowerrc
├── .gitignore
├── .jshintrc
├── LICENSE
├── README.md
├── app
├── address
│ ├── address.html
│ └── address.js
├── app.css
├── app.js
├── bitcore.js
├── components
│ ├── code.html
│ ├── console
│ │ ├── console.html
│ │ ├── console.js
│ │ └── jqconsole.js
│ ├── explanation.html
│ ├── loader.html
│ └── network.html
├── fonts
│ ├── icomoon
│ │ ├── Read Me.txt
│ │ ├── demo-files
│ │ │ ├── demo.css
│ │ │ └── demo.js
│ │ ├── demo.html
│ │ ├── fonts
│ │ │ ├── icomoon.eot
│ │ │ ├── icomoon.svg
│ │ │ ├── icomoon.ttf
│ │ │ └── icomoon.woff
│ │ ├── selection.json
│ │ └── style.css
│ ├── solid-icons
│ │ ├── Read Me.txt
│ │ ├── demo-files
│ │ │ ├── demo.css
│ │ │ └── demo.js
│ │ ├── demo.html
│ │ ├── fonts
│ │ │ ├── solid-icons.eot
│ │ │ ├── solid-icons.svg
│ │ │ ├── solid-icons.ttf
│ │ │ └── solid-icons.woff
│ │ ├── selection.json
│ │ └── style.css
│ ├── ubuntu-bold-italic.woff
│ ├── ubuntu-bold.woff
│ ├── ubuntu-light.woff
│ └── ubuntu.woff
├── hdkeys
│ ├── hdkeys.html
│ └── hdkeys.js
├── img
│ ├── add-user-icon.svg
│ ├── api-icon.svg
│ ├── arrow-down-info.svg
│ ├── arrow-down.svg
│ ├── arrow-right-small-single.svg
│ ├── arrow-right-small.svg
│ ├── arrow-right.svg
│ ├── arrow-up-info.svg
│ ├── arrows-nav.svg
│ ├── bitcore-logo-hd.svg
│ ├── bitcore-og-image.png
│ ├── btc-icon-address.svg
│ ├── btc-nav.svg
│ ├── close-icon.svg
│ ├── code-spot.svg
│ ├── dice-icon.svg
│ ├── doc-icon.svg
│ ├── favicon.png
│ ├── gear-icon-title.svg
│ ├── githubcat-icon.svg
│ ├── key-nav.svg
│ ├── keyring-nav.svg
│ ├── lava-ball-social.png
│ ├── learn-title.svg
│ ├── private-key-icon.svg
│ ├── public-key-icon.svg
│ ├── qr-nav.svg
│ ├── remove-icon.svg
│ ├── terminal-icon.svg
│ ├── transp-box.svg
│ └── user-icon.svg
├── index.html
├── multisig
│ ├── multisig.html
│ └── multisig.js
├── transaction
│ ├── transaction.html
│ └── transaction.js
├── units
│ ├── units.html
│ └── units.js
└── unspent
│ ├── unspent.html
│ └── unspent.js
├── bower.json
├── index.html
└── package.json
/.bowerrc:
--------------------------------------------------------------------------------
1 | {
2 | "directory": "app/bower_components"
3 | }
4 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | logs/*
2 | *.sw[a-z]
3 | !.gitkeep
4 | node_modules/
5 | bower_components/
6 | tmp
7 | .DS_Store
8 | .idea
9 | *.log
10 |
--------------------------------------------------------------------------------
/.jshintrc:
--------------------------------------------------------------------------------
1 | {
2 | "globalstrict": true,
3 | "globals": {
4 | "angular": false,
5 | "describe": false,
6 | "it": false,
7 | "expect": false,
8 | "beforeEach": false,
9 | "afterEach": false,
10 | "module": false,
11 | "inject": false
12 | }
13 | }
14 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Yemel Jardi
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Bitcore Playground
2 |
3 | **Note:** This project has become a part of the [bitcore-website](https://github.com/bitpay/bitcore-website) repository, and can be found at: https://github.com/bitpay/bitcore-website/tree/master/components/bitcore-playground
4 |
5 | Try it online at [bitcore.io/playground](http://bitcore.io/playground).
6 |
7 |
--------------------------------------------------------------------------------
/app/address/address.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Address
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Generate a bitcoin address from a private or public key.
11 |
12 |
13 |
14 |
15 |
16 |
17 | PRIVATE KEY
18 |
19 |
20 |
21 |
22 |
29 |
30 |
31 |
32 |
33 |
34 |
39 |
40 |
41 |
42 |
43 |
44 | PUBLIC KEY
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
58 |
59 |
60 |
61 |
62 |
63 | ADDRESS
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
--------------------------------------------------------------------------------
/app/address/address.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.address', ['ngRoute'])
4 |
5 | .config(['$routeProvider', function($routeProvider) {
6 | $routeProvider.when('/address', {
7 | templateUrl: 'address/address.html',
8 | controller: 'AddressCtrl'
9 | });
10 | }])
11 |
12 | .controller('AddressCtrl', function($scope, bitcore) {
13 |
14 | $scope.bitcoreURL = 'http://bitcore.io/guide/address.html';
15 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#term-address';
16 |
17 | $scope.$on('networkUpdate', function() {
18 | $scope.newKey();
19 | });
20 |
21 | $scope.newKey = function() {
22 | $scope.privateKey = new bitcore.PrivateKey();
23 | $scope.publicKey = $scope.privateKey.publicKey;
24 | setExampleCode();
25 | };
26 |
27 | $scope.privateUpdated = function(value) {
28 | if (bitcore.PrivateKey.isValid(value)) {
29 | $scope.privateKey = new bitcore.PrivateKey(value);
30 | $scope.publicKey = $scope.privateKey.publicKey;
31 | setExampleCode($scope.privateKey);
32 | } else {
33 | // mark as invalid
34 | }
35 | };
36 |
37 | $scope.publicUpdated = function(value) {
38 | if (bitcore.PublicKey.isValid(value)) {
39 | $scope.privateKey = '';
40 | $scope.publicKey = new bitcore.PublicKey(value);
41 | setExampleCode(null, $scope.publicKey);
42 | } else {
43 | // mark as invalid
44 | }
45 | };
46 |
47 | function setExampleCode(privkey, pubkey) {
48 | var template = "";
49 |
50 | if (!privkey && !pubkey) {
51 | template += "var privateKey = new bitcore.PrivateKey();\n";
52 | template += "var publicKey = privateKey.publicKey;\n";
53 | } else if (privkey) {
54 | template += "var privateKey = new bitcore.PrivateKey('"+ privkey.toString() + "');\n";
55 | template += "var publicKey = privateKey.publicKey;\n";
56 | } else {
57 | template += "var publicKey = new bitcore.PublicKey('"+ pubkey.toString()+ "');\n";
58 | }
59 | template += "var address = publicKey.toAddress();";
60 |
61 | $scope.exampleCode = template;
62 | };
63 |
64 | $scope.jumpConsole = function() {
65 | $('#terminaltab').click();
66 | window.REPL.console.SetPromptText($scope.exampleCode);
67 | window.REPL.scrollToBottom();
68 | };
69 |
70 | $scope.newKey();
71 |
72 | });
73 |
--------------------------------------------------------------------------------
/app/app.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | var app = angular.module('playApp', [
4 | 'ngRoute',
5 | 'playApp.units',
6 | 'playApp.address',
7 | 'playApp.hdkeys',
8 | 'playApp.transaction',
9 | 'playApp.unspent',
10 | 'playApp.multisig'
11 | ]);
12 |
13 | // Config
14 | app.config(['$routeProvider', function($routeProvider) {
15 | $routeProvider.otherwise({redirectTo: '/units'});
16 | }]);
17 |
18 | app.constant('bitcore', require('bitcore'));
19 |
20 | // Filters
21 | app.filter('btc', function(bitcore) {
22 | return function(satoshis) {
23 | return bitcore.Unit.fromSatoshis(satoshis).toBTC();
24 | };
25 | })
26 | .filter('permalink', function(bitcore) {
27 | return function(data, section) {
28 | var url = './#/' + section + '?data=' + encodeURI(data);
29 | if (url.length > 2083) throw new Error('URL too long')
30 | return url;
31 | };
32 | })
33 | .filter('ellipsify', function() {
34 | return function(data) {
35 | return data.substr(0, 4) + '...' + data.substr(data.length - 4, data.length);
36 | };
37 | });
38 |
39 | // Directives
40 | app.directive('exampleCode', function() {
41 | return {
42 | link: function(scope, element, attrs) {
43 | scope.$watch(attrs.exampleCode, function(value) {
44 | element.text(value);
45 | hljs.highlightBlock(element[0]);
46 | });
47 | }
48 | };
49 | })
50 | .directive('autoSelect', function() {
51 | return {
52 | link: function(scope, element, attrs) {
53 | $(element).focus(function(){
54 | $(this).select();
55 | });
56 | element.attr('spellcheck', false);
57 | }
58 | };
59 | })
60 | .directive('requireTooltip', function() {
61 | return {
62 | link: function(scope, element, attrs) {
63 | $(document).foundation();
64 | $(document).foundation('tooltip', 'reflow');
65 | }
66 | };
67 | })
68 | .directive('requireModal', function() {
69 | return {
70 | link: function(scope, element, attrs) {
71 | $(document).foundation();
72 | $(document).foundation('reveal', 'reflow');
73 | }
74 | };
75 | });
76 |
77 | // Filters
78 | function registerValidator(app, name, validator) {
79 | app.directive(name, function(bitcore) {
80 | return {
81 | require: 'ngModel',
82 | link: function(scope, elem, attr, ngModel) {
83 | function validate(value) {
84 | var valid = validator(bitcore, value, scope, attr);
85 | ngModel.$setValidity(null, valid);
86 | return value;
87 | }
88 | ngModel.$parsers.unshift(validate);
89 | ngModel.$formatters.unshift(validate);
90 | }
91 | };
92 | });
93 | }
94 |
95 | registerValidator(app, 'privateKey', function(bitcore, value) {
96 | return bitcore.PrivateKey.isValid(value);
97 | });
98 | registerValidator(app, 'publicKey', function(bitcore, value) {
99 | return bitcore.PublicKey.isValid(value);
100 | });
101 | registerValidator(app, 'xprivateKey', function(bitcore, value) {
102 | return bitcore.HDPrivateKey.isValidSerialized(value);
103 | });
104 | registerValidator(app, 'xpublicKey', function(bitcore, value) {
105 | return bitcore.HDPublicKey.isValidSerialized(value);
106 | });
107 | registerValidator(app, 'privateHdpath', function(bitcore, value, scope) {
108 | return !!(/^[mM][']?(\/[0-9]+[']?)*[/]?$/.exec(value));
109 | });
110 | registerValidator(app, 'publicHdpath', function(bitcore, value, scope) {
111 | return !!(/^[mM](\/[0-9]+)*[/]?$/.exec(value));
112 | });
113 | registerValidator(app, 'address', function(bitcore, value) {
114 | return bitcore.Address.isValid(value);
115 | });
116 |
117 | // Sidebar
118 | app.controller('SideBar', function($scope, $rootScope, $timeout, $location) {
119 | $timeout(function(){
120 | $rootScope.showFooter = true;
121 | $rootScope.$apply();
122 | }, 100);
123 |
124 | $scope.getClass = function(path) {
125 | return $location.path().substr(0, path.length) === path ? "current" : "";
126 | }
127 |
128 | })
129 | .controller('Network', function($scope, $rootScope, $timeout, bitcore) {
130 | var networks = bitcore.Networks;
131 | networks.defaultNetwork = networks.testnet;
132 | $rootScope.$broadcast('networkUpdate');
133 |
134 | $scope.setTestnet = function(value) {
135 | networks.defaultNetwork = value ? networks.livenet : networks.testnet;
136 | $rootScope.$broadcast('networkUpdate');
137 | };
138 | });
139 |
--------------------------------------------------------------------------------
/app/components/code.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/components/console/console.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
--------------------------------------------------------------------------------
/app/components/console/console.js:
--------------------------------------------------------------------------------
1 | $(function () {
2 |
3 | function REPL() {
4 |
5 | this.element = document.getElementById("console");
6 | this.console = $('#console').jqconsole(null, '>> ');
7 | this.console.$input_source.blur();
8 |
9 | setInterval(function(){
10 | $('.jqconsole-cursor').toggleClass("blink");
11 | }, 1000);
12 |
13 | $('#terminal-content').on('appear', function() {
14 | $('#terminaltab-sticky').addClass('hide');
15 | });
16 |
17 | $('#terminal-content').on('disappear', function() {
18 | $('#terminaltab-sticky').removeClass('hide');
19 | });
20 |
21 | $('.goto-repl').click(function() {
22 | $("html, body").animate({ scrollTop: $(document).height() }, "slow");
23 | self.console.$input_source.focus();
24 | });
25 |
26 | window.console._log = function() {
27 | var result = Array.prototype.slice.call(arguments);
28 | result = result.map(toConsoleString).join(' ') + '\n';
29 | self.console.Write(result, 'jqconsole-output');
30 | self.scrollToBottom();
31 | };
32 |
33 | var self = this;
34 | $(this.element).click(function(){
35 | self.console.$input_source.focus();
36 | });
37 |
38 | this.console.$input_source.blur(function() {
39 | self.scrollToBottom();
40 | });
41 |
42 | this.console.RegisterShortcut('U', function() {
43 | var col = self.console.GetColumn() - 3;
44 | var text = self.console.GetPromptText();
45 | self.console.SetPromptText(text.slice(col));
46 | self.console.MoveToStart();
47 | });
48 |
49 | this.console.RegisterShortcut('A', function() {
50 | self.console.MoveToStart();
51 | });
52 |
53 | this.console.RegisterShortcut('E', function() {
54 | self.console.MoveToEnd();
55 | });
56 |
57 | this.console.RegisterShortcut('L', function() {
58 | self.console.Clear();
59 | });
60 |
61 | // Autocomplete hack
62 | this.console._Indent = function() {
63 | var tokens = this.GetPromptText().split(' ');
64 | var token = tokens[tokens.length-1];
65 |
66 | if (!isSafeToken(token)) return;
67 |
68 | // get context
69 | var context = getContext(token);
70 | var prefix = token.split(".").slice(-1)[0];
71 |
72 | // get completition alternatives
73 | var alternatives = filterPrefix(prefix, context);
74 | alternatives = alternatives.sort(function(a, b) {
75 | if(a < b) return -1;
76 | if(a > b) return 1;
77 | return 0;
78 | });
79 |
80 | // get extended prefix
81 | var newPrefix = extendPrefix(prefix, alternatives);
82 | var contextName = token.split('.').slice(0,-1).join('.');
83 |
84 | // set new token
85 | var extendedToken = (contextName.length > 0 ? contextName + '.' : '') + newPrefix;
86 | tokens[tokens.length-1] = extendedToken;
87 |
88 | // print new token
89 | this.SetPromptText(tokens.join(" "));
90 |
91 | if (alternatives.length > 1) {
92 | this._PrintAlternatives(alternatives);
93 | self.scrollToBottom();
94 | }
95 | };
96 |
97 | this.console._PrintAlternatives = function(alternatives) {
98 | this.Write(this.GetPromptText(true) + '\n', 'jqconsole-old-prompt');
99 | var all = alternatives.join(" ");
100 | this.Write(all + '\n\n', 'jqconsole-output');
101 | };
102 |
103 | this.console._Unindent = function() {};
104 | }
105 |
106 | function getContext(token) {
107 | if (token.indexOf('.') === -1) {
108 | return Object.keys(window);
109 | }
110 |
111 | var context = token.split('.').slice(0, -1).join('.');
112 |
113 | var element;
114 | try {
115 | element = window.eval(context);
116 | } catch (err) {
117 | return [];
118 | }
119 |
120 | var options;
121 | if (Array.isArray(element)) {
122 | options = Object.getOwnPropertyNames(Array.prototype);
123 | } else {
124 | options = $.map(element, function(value, key) { return key; });
125 | }
126 |
127 | // filter and sort
128 | options = options.filter(function(key) {
129 | return key && key.indexOf('_') !== 0;
130 | }).sort(function(a, b) {
131 | if(a < b) return -1;
132 | if(a > b) return 1;
133 | return 0;
134 | });
135 |
136 | return options;
137 | }
138 |
139 | function isSafeToken(token) {
140 | var unsafe = "()[];=".split('');
141 | return !!token && unsafe.reduce(function(prev, c) {
142 | return prev && !$.contains(token, c);
143 | });
144 | }
145 |
146 | function filterPrefix(prefix, alternatives) {
147 | return alternatives.filter(function(opt) {
148 | return opt.indexOf(prefix) === 0;
149 | });
150 | }
151 |
152 | function extendPrefix(prefix, alternatives) {
153 | if (!prefix) return '';
154 | if (alternatives.length === 0) return prefix;
155 | if (alternatives.length === 1) return alternatives;
156 |
157 | var newPrefix = prefix + alternatives[0][prefix.length];
158 | var filtered = filterPrefix(newPrefix, alternatives);
159 |
160 | if (filtered.length != alternatives.length) return prefix;
161 | return extendPrefix(newPrefix, alternatives);
162 | }
163 |
164 | REPL.prototype.prompt = function() {
165 | var self = this;
166 | this.console.Prompt(true, function(line) {
167 | try {
168 | var line = line.replace(/(\n| |^|;)var /g, "$1"); // show assignment on console
169 | var line = line.replace(/(\n| |^|;)console.log\(/g, "$1console._log("); // show assignment on console
170 |
171 | var result = window.eval(line);
172 | } catch (err) {
173 | return self.errorCallback(err);
174 | }
175 | self.resultCallback(result);
176 | });
177 | this.scrollToBottom();
178 | }
179 |
180 | REPL.prototype.outputCallback = function(output) {
181 | this.console.Write(output, 'jqconsole-output');
182 | }
183 |
184 | REPL.prototype.scrollToBottom = function() {
185 | this.element.scrollTop = this.element.scrollHeight;
186 | }
187 |
188 | REPL.prototype.resultCallback = function(result) {
189 | if (typeof result === 'undefined') {
190 | this.console.Write('undefined\n', 'jqconsole-undefined');
191 | return this.prompt();
192 | }
193 |
194 | window._ = result;
195 |
196 | this.console.Write('' + toConsoleString(result) + '\n', 'jqconsole-output');
197 | this.prompt();
198 | }
199 |
200 | function toConsoleString(obj) {
201 | if (obj instanceof Array) {
202 | return obj = '[' + obj.map(toConsoleString).join(', ') + ']';
203 | }
204 |
205 | if (obj instanceof Object && obj.inspect) {
206 | return obj.inspect();
207 | }
208 |
209 | return String(obj);
210 | }
211 |
212 | REPL.prototype.errorCallback = function(error) {
213 | this.console.Write('' + error + '\n', 'jqconsole-error');
214 | this.prompt();
215 | }
216 |
217 | window.REPL = new REPL();
218 | window.REPL.prompt();
219 | window.REPL.console.SetPromptText("var priv = new bitcore.PrivateKey();");
220 | window.bitcore = require('bitcore');
221 |
222 | });
--------------------------------------------------------------------------------
/app/components/explanation.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Under the hood
5 |
6 |
7 |
8 |
9 |
10 |
19 |
20 |
--------------------------------------------------------------------------------
/app/components/loader.html:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/app/components/network.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | TESTNET
5 |
6 |
12 |
13 | LIVENET
14 |
15 |
16 |
--------------------------------------------------------------------------------
/app/fonts/icomoon/Read Me.txt:
--------------------------------------------------------------------------------
1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures.
2 |
3 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects.
4 |
5 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu > Manage Projects) to retrieve your icon selection.
6 |
--------------------------------------------------------------------------------
/app/fonts/icomoon/demo-files/demo.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | font-family: sans-serif;
5 | font-size: 1em;
6 | line-height: 1.5;
7 | color: #555;
8 | background: #fff;
9 | }
10 | h1 {
11 | font-size: 1.5em;
12 | font-weight: normal;
13 | }
14 | small {
15 | font-size: .66666667em;
16 | }
17 | a {
18 | color: #e74c3c;
19 | text-decoration: none;
20 | }
21 | a:hover, a:focus {
22 | box-shadow: 0 1px #e74c3c;
23 | }
24 | .bshadow0, input {
25 | box-shadow: inset 0 -2px #e7e7e7;
26 | }
27 | input:hover {
28 | box-shadow: inset 0 -2px #ccc;
29 | }
30 | input, fieldset {
31 | font-size: 1em;
32 | margin: 0;
33 | padding: 0;
34 | border: 0;
35 | }
36 | input {
37 | color: inherit;
38 | line-height: 1.5;
39 | height: 1.5em;
40 | padding: .25em 0;
41 | }
42 | input:focus {
43 | outline: none;
44 | box-shadow: inset 0 -2px #449fdb;
45 | }
46 | .glyph {
47 | font-size: 16px;
48 | width: 15em;
49 | padding-bottom: 1em;
50 | margin-right: 4em;
51 | margin-bottom: 1em;
52 | float: left;
53 | overflow: hidden;
54 | }
55 | .liga {
56 | width: 80%;
57 | width: calc(100% - 2.5em);
58 | }
59 | .talign-right {
60 | text-align: right;
61 | }
62 | .talign-center {
63 | text-align: center;
64 | }
65 | .bgc1 {
66 | background: #f1f1f1;
67 | }
68 | .fgc1 {
69 | color: #999;
70 | }
71 | .fgc0 {
72 | color: #000;
73 | }
74 | p {
75 | margin-top: 1em;
76 | margin-bottom: 1em;
77 | }
78 | .mvm {
79 | margin-top: .75em;
80 | margin-bottom: .75em;
81 | }
82 | .mtn {
83 | margin-top: 0;
84 | }
85 | .mtl, .mal {
86 | margin-top: 1.5em;
87 | }
88 | .mbl, .mal {
89 | margin-bottom: 1.5em;
90 | }
91 | .mal, .mhl {
92 | margin-left: 1.5em;
93 | margin-right: 1.5em;
94 | }
95 | .mhmm {
96 | margin-left: 1em;
97 | margin-right: 1em;
98 | }
99 | .mls {
100 | margin-left: .25em;
101 | }
102 | .ptl {
103 | padding-top: 1.5em;
104 | }
105 | .pbs, .pvs {
106 | padding-bottom: .25em;
107 | }
108 | .pvs, .pts {
109 | padding-top: .25em;
110 | }
111 | .unit {
112 | float: left;
113 | }
114 | .unitRight {
115 | float: right;
116 | }
117 | .size1of2 {
118 | width: 50%;
119 | }
120 | .size1of1 {
121 | width: 100%;
122 | }
123 | .clearfix:before, .clearfix:after {
124 | content: " ";
125 | display: table;
126 | }
127 | .clearfix:after {
128 | clear: both;
129 | }
130 | .hidden-true {
131 | display: none;
132 | }
133 | .textbox0 {
134 | width: 3em;
135 | background: #f1f1f1;
136 | padding: .25em .5em;
137 | line-height: 1.5;
138 | height: 1.5em;
139 | }
140 | #testDrive {
141 | display: block;
142 | padding-top: 24px;
143 | line-height: 1.5;
144 | }
145 | .fs0 {
146 | font-size: 16px;
147 | }
148 | .fs1 {
149 | font-size: 32px;
150 | }
151 |
--------------------------------------------------------------------------------
/app/fonts/icomoon/demo-files/demo.js:
--------------------------------------------------------------------------------
1 | if (!('boxShadow' in document.body.style)) {
2 | document.body.setAttribute('class', 'noBoxShadow');
3 | }
4 |
5 | document.body.addEventListener("click", function(e) {
6 | var target = e.target;
7 | if (target.tagName === "INPUT" &&
8 | target.getAttribute('class').indexOf('liga') === -1) {
9 | target.select();
10 | }
11 | });
12 |
13 | (function() {
14 | var fontSize = document.getElementById('fontSize'),
15 | testDrive = document.getElementById('testDrive'),
16 | testText = document.getElementById('testText');
17 | function updateTest() {
18 | testDrive.innerHTML = testText.value || String.fromCharCode(160);
19 | if (window.icomoonLiga) {
20 | window.icomoonLiga(testDrive);
21 | }
22 | }
23 | function updateSize() {
24 | testDrive.style.fontSize = fontSize.value + 'px';
25 | }
26 | fontSize.addEventListener('change', updateSize, false);
27 | testText.addEventListener('input', updateTest, false);
28 | testText.addEventListener('change', updateTest, false);
29 | updateSize();
30 | }());
31 |
--------------------------------------------------------------------------------
/app/fonts/icomoon/fonts/icomoon.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/icomoon/fonts/icomoon.eot
--------------------------------------------------------------------------------
/app/fonts/icomoon/fonts/icomoon.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/icomoon/fonts/icomoon.ttf
--------------------------------------------------------------------------------
/app/fonts/icomoon/fonts/icomoon.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/icomoon/fonts/icomoon.woff
--------------------------------------------------------------------------------
/app/fonts/icomoon/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'icomoon';
3 | src:url('fonts/icomoon.eot?10xkm6');
4 | src:url('fonts/icomoon.eot?#iefix10xkm6') format('embedded-opentype'),
5 | url('fonts/icomoon.woff?10xkm6') format('woff'),
6 | url('fonts/icomoon.ttf?10xkm6') format('truetype'),
7 | url('fonts/icomoon.svg?10xkm6#icomoon') format('svg');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | [class^="icon-"], [class*=" icon-"] {
13 | font-family: 'icomoon';
14 | speak: none;
15 | font-style: normal;
16 | font-weight: normal;
17 | font-variant: normal;
18 | text-transform: none;
19 | line-height: 1;
20 |
21 | /* Better Font Rendering =========== */
22 | -webkit-font-smoothing: antialiased;
23 | -moz-osx-font-smoothing: grayscale;
24 | }
25 |
26 | .icon-forum:before {
27 | content: "\e61a";
28 | }
29 |
30 | .icon-ball:before {
31 | content: "\e61b";
32 | }
33 |
34 | .icon-btc-solid:before {
35 | content: "\e605";
36 | }
37 |
38 | .icon-lab-solid:before {
39 | content: "\e60f";
40 | }
41 |
42 | .icon-github:before {
43 | content: "\e60d";
44 | }
45 |
46 | .icon-api:before {
47 | content: "\e600";
48 | }
49 |
50 | .icon-arrow-down:before {
51 | content: "\e601";
52 | }
53 |
54 | .icon-arrow-left:before {
55 | content: "\e602";
56 | }
57 |
58 | .icon-arrow-right:before {
59 | content: "\e603";
60 | }
61 |
62 | .icon-arrow-up:before {
63 | content: "\e604";
64 | }
65 |
66 | .icon-checked:before {
67 | content: "\e606";
68 | }
69 |
70 | .icon-close:before {
71 | content: "\e607";
72 | }
73 |
74 | .icon-coin:before {
75 | content: "\e608";
76 | }
77 |
78 | .icon-docs:before {
79 | content: "\e609";
80 | }
81 |
82 | .icon-double-arrow-solid:before {
83 | content: "\e60a";
84 | }
85 |
86 | .icon-double-arrow:before {
87 | content: "\e60b";
88 | }
89 |
90 | .icon-gear:before {
91 | content: "\e60c";
92 | }
93 |
94 | .icon-keyring-solid:before {
95 | content: "\e60e";
96 | }
97 |
98 | .icon-plus:before {
99 | content: "\e610";
100 | }
101 |
102 | .icon-private-key:before {
103 | content: "\e611";
104 | }
105 |
106 | .icon-public-key-solid:before {
107 | content: "\e612";
108 | }
109 |
110 | .icon-public-key:before {
111 | content: "\e613";
112 | }
113 |
114 | .icon-qr-solid:before {
115 | content: "\e614";
116 | }
117 |
118 | .icon-qr:before {
119 | content: "\e615";
120 | }
121 |
122 | .icon-terminal:before {
123 | content: "\e616";
124 | }
125 |
126 | .icon-tree-solid:before {
127 | content: "\e617";
128 | }
129 |
130 | .icon-user-plus:before {
131 | content: "\e618";
132 | }
133 |
134 | .icon-user:before {
135 | content: "\e619";
136 | }
137 |
138 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/Read Me.txt:
--------------------------------------------------------------------------------
1 | Open *demo.html* to see a list of all the glyphs in your font along with their codes/ligatures.
2 |
3 | You won't need any of the files located under the *demo-files* directory when including the generated font in your own projects.
4 |
5 | You can import *selection.json* back to the IcoMoon app using the *Import Icons* button (or via Main Menu > Manage Projects) to retrieve your icon selection.
6 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/demo-files/demo.css:
--------------------------------------------------------------------------------
1 | body {
2 | padding: 0;
3 | margin: 0;
4 | font-family: sans-serif;
5 | font-size: 1em;
6 | line-height: 1.5;
7 | color: #555;
8 | background: #fff;
9 | }
10 | h1 {
11 | font-size: 1.5em;
12 | font-weight: normal;
13 | }
14 | small {
15 | font-size: .66666667em;
16 | }
17 | a {
18 | color: #e74c3c;
19 | text-decoration: none;
20 | }
21 | a:hover, a:focus {
22 | box-shadow: 0 1px #e74c3c;
23 | }
24 | .bshadow0, input {
25 | box-shadow: inset 0 -2px #e7e7e7;
26 | }
27 | input:hover {
28 | box-shadow: inset 0 -2px #ccc;
29 | }
30 | input, fieldset {
31 | font-size: 1em;
32 | margin: 0;
33 | padding: 0;
34 | border: 0;
35 | }
36 | input {
37 | color: inherit;
38 | line-height: 1.5;
39 | height: 1.5em;
40 | padding: .25em 0;
41 | }
42 | input:focus {
43 | outline: none;
44 | box-shadow: inset 0 -2px #449fdb;
45 | }
46 | .glyph {
47 | font-size: 16px;
48 | width: 15em;
49 | padding-bottom: 1em;
50 | margin-right: 4em;
51 | margin-bottom: 1em;
52 | float: left;
53 | overflow: hidden;
54 | }
55 | .liga {
56 | width: 80%;
57 | width: calc(100% - 2.5em);
58 | }
59 | .talign-right {
60 | text-align: right;
61 | }
62 | .talign-center {
63 | text-align: center;
64 | }
65 | .bgc1 {
66 | background: #f1f1f1;
67 | }
68 | .fgc1 {
69 | color: #999;
70 | }
71 | .fgc0 {
72 | color: #000;
73 | }
74 | p {
75 | margin-top: 1em;
76 | margin-bottom: 1em;
77 | }
78 | .mvm {
79 | margin-top: .75em;
80 | margin-bottom: .75em;
81 | }
82 | .mtn {
83 | margin-top: 0;
84 | }
85 | .mtl, .mal {
86 | margin-top: 1.5em;
87 | }
88 | .mbl, .mal {
89 | margin-bottom: 1.5em;
90 | }
91 | .mal, .mhl {
92 | margin-left: 1.5em;
93 | margin-right: 1.5em;
94 | }
95 | .mhmm {
96 | margin-left: 1em;
97 | margin-right: 1em;
98 | }
99 | .mls {
100 | margin-left: .25em;
101 | }
102 | .ptl {
103 | padding-top: 1.5em;
104 | }
105 | .pbs, .pvs {
106 | padding-bottom: .25em;
107 | }
108 | .pvs, .pts {
109 | padding-top: .25em;
110 | }
111 | .unit {
112 | float: left;
113 | }
114 | .unitRight {
115 | float: right;
116 | }
117 | .size1of2 {
118 | width: 50%;
119 | }
120 | .size1of1 {
121 | width: 100%;
122 | }
123 | .clearfix:before, .clearfix:after {
124 | content: " ";
125 | display: table;
126 | }
127 | .clearfix:after {
128 | clear: both;
129 | }
130 | .hidden-true {
131 | display: none;
132 | }
133 | .textbox0 {
134 | width: 3em;
135 | background: #f1f1f1;
136 | padding: .25em .5em;
137 | line-height: 1.5;
138 | height: 1.5em;
139 | }
140 | #testDrive {
141 | display: block;
142 | padding-top: 24px;
143 | line-height: 1.5;
144 | }
145 | .fs0 {
146 | font-size: 16px;
147 | }
148 | .fs1 {
149 | font-size: 32px;
150 | }
151 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/demo-files/demo.js:
--------------------------------------------------------------------------------
1 | if (!('boxShadow' in document.body.style)) {
2 | document.body.setAttribute('class', 'noBoxShadow');
3 | }
4 |
5 | document.body.addEventListener("click", function(e) {
6 | var target = e.target;
7 | if (target.tagName === "INPUT" &&
8 | target.getAttribute('class').indexOf('liga') === -1) {
9 | target.select();
10 | }
11 | });
12 |
13 | (function() {
14 | var fontSize = document.getElementById('fontSize'),
15 | testDrive = document.getElementById('testDrive'),
16 | testText = document.getElementById('testText');
17 | function updateTest() {
18 | testDrive.innerHTML = testText.value || String.fromCharCode(160);
19 | if (window.icomoonLiga) {
20 | window.icomoonLiga(testDrive);
21 | }
22 | }
23 | function updateSize() {
24 | testDrive.style.fontSize = fontSize.value + 'px';
25 | }
26 | fontSize.addEventListener('change', updateSize, false);
27 | testText.addEventListener('input', updateTest, false);
28 | testText.addEventListener('change', updateTest, false);
29 | updateSize();
30 | }());
31 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/demo.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IcoMoon Demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
Font Name: icomoon (Glyphs: 11)
13 |
14 |
15 |
Grid Size: Unknown
16 |
32 |
48 |
64 |
80 |
96 |
112 |
128 |
144 |
160 |
176 |
192 |
193 |
194 |
195 |
196 |
Font Test Drive
197 |
202 |
204 |
205 |
206 |
207 |
208 |
209 |
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/fonts/solid-icons.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/solid-icons/fonts/solid-icons.eot
--------------------------------------------------------------------------------
/app/fonts/solid-icons/fonts/solid-icons.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
--------------------------------------------------------------------------------
/app/fonts/solid-icons/fonts/solid-icons.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/solid-icons/fonts/solid-icons.ttf
--------------------------------------------------------------------------------
/app/fonts/solid-icons/fonts/solid-icons.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/solid-icons/fonts/solid-icons.woff
--------------------------------------------------------------------------------
/app/fonts/solid-icons/selection.json:
--------------------------------------------------------------------------------
1 | {
2 | "IcoMoonType": "selection",
3 | "icons": [
4 | {
5 | "icon": {
6 | "paths": [
7 | "M894.8 810.8l3.2-808.8h-670.2c-121.2 0-221.8 96-221.8 216.6v613.8c0 80.6 51.2 150.2 122 178.6 20.2 9 43.2 15 66.8 15h649.2v-2.4h51.4l-0.8-105h-42.6v-108.6l42.8 0.8zM200 919.4c-4.4 0-8.2-0.6-12.4-1.4-3-0.4-5.8-1-8.6-1.8s-5.4-1.6-8.2-2.6c-18.8-8.8-32-27.6-32-49.8 0-30.6 24-55.4 54.6-55.4l552.6 1.2v32.4h-540v50h540v26.8l-546 0.6zM790 704.8l-597.4-1.2c-29.6 0-56.6 8.4-80.6 22.4v-507.4c0-62.6 52.8-110.6 115.8-110.6h562.2v596.8z"
8 | ],
9 | "attrs": [
10 | {
11 | "fill": "rgb(68, 68, 68)"
12 | }
13 | ],
14 | "isMulticolor": false,
15 | "grid": 0,
16 | "tags": [
17 | "api"
18 | ],
19 | "colorPermutations": {
20 | "6868681": [
21 | 0
22 | ]
23 | }
24 | },
25 | "attrs": [
26 | {
27 | "fill": "rgb(68, 68, 68)"
28 | }
29 | ],
30 | "properties": {
31 | "order": 93,
32 | "id": 23,
33 | "prevSize": 32,
34 | "code": 58880,
35 | "name": "api"
36 | },
37 | "setIdx": 0,
38 | "iconIdx": 0
39 | },
40 | {
41 | "icon": {
42 | "paths": [
43 | "M640.2 700h-180.4v-156.8h180.4c49.8 0 90.2 35.2 90.2 78.4-0 43.4-40.4 78.4-90.2 78.4zM459.8 308h135.2c49.8 0 90.2 35.2 90.2 78.4 0 43.4-40.4 78.4-90.2 78.4h-135.2v-156.8zM821.8 487.8c27-27.2 44-62.4 44-101.4 0-122.6-84.6-196-225.4-196v0-147c0-5.4-5-9.8-11.4-9.8h-67.6c-6 0-11 4.2-11.2 9.4v147.4h-90.2v-147c0-5.4-5-9.8-11.4-9.8h-67.6c-6 0-11 4.2-11.2 9.4v147.4h-191.8c-6.2 0-11.2 4.4-11.2 9.8v58.8c0.2 5.2 5.2 9.8 11.4 9.8h11.4c49.8 0 90.2 35.2 90.2 78.4v313.8c0 41-36.2 74.6-82.2 78.2-4.8 0.4-8.8 3.4-10 7.4l-17.6 59c-0.8 3 0 6 2 8.4s5.4 3.8 9 3.8h188.6v147.4c0.2 5.2 5.2 9.4 11.2 9.4h67.6c6.2 0 11.4-4.4 11.4-9.8v-147h90.2v147.4c0.2 5.2 5.2 9.4 11.2 9.4h67.6c6.2 0 11.4-4.4 11.4-9.8v-147h45c141 0 225.6-73.6 225.6-196-0-57.6-36-107-89-134z"
44 | ],
45 | "attrs": [
46 | {
47 | "fill": "rgb(68, 68, 68)"
48 | }
49 | ],
50 | "isMulticolor": false,
51 | "grid": 0,
52 | "tags": [
53 | "btc-solid"
54 | ],
55 | "colorPermutations": {
56 | "6868681": [
57 | 0
58 | ]
59 | }
60 | },
61 | "attrs": [
62 | {
63 | "fill": "rgb(68, 68, 68)"
64 | }
65 | ],
66 | "properties": {
67 | "order": 78,
68 | "id": 18,
69 | "prevSize": 32,
70 | "code": 58881,
71 | "name": "btc-solid"
72 | },
73 | "setIdx": 0,
74 | "iconIdx": 5
75 | },
76 | {
77 | "icon": {
78 | "paths": [
79 | "M596.2 401c0-18.2-22.4-33-50.2-33h-76v66h76c27.6 0 50.2-14.8 50.2-33z",
80 | "M621.2 501c0-18.2-22.4-33-50.2-33h-101v66h101c27.8 0 50.2-14.8 50.2-33z",
81 | "M1010 439v-7h0.2c-12.8-198-229.4-358.2-495.6-358.2s-483 160.2-495.8 358.2h-0.8v7.2c0 4-0.8 7.8-0.8 11.8s0.8 8 0.8 11.8v113.8c0 211.2 223.8 383.6 498.4 383.6 104.8 0 202.2-26.6 282.4-68.6h5.2v-4.4c54-30 99.6-67.6 134-111.6v0-0.8c46-58 72-125.6 72-198.2v-113.6c0-4 0.8-8 0.8-12.2 0-3.8-0.8-7.6-0.8-11.8zM308 323c0-2.2 2.2-4.2 5.8-4.2h106.2v-62.2c0-2.2 3.4-4.6 6.8-4.6h37.6c3.4 0 6.2 1.8 6.2 4v62h49.4v-61.4c2-2.2 3.8-4.6 7.2-4.6h37.6c3.4 0 6.2 1.8 6.2 4v62c78.4 0 125.6 31.4 125.6 83.2 0 16.4-9.4 31.4-24.4 43 29.6 11.4 49.6 32.6 49.6 56.8 0 51.8-47 83-125.6 83h-25v62c0 2.2-2.8 4-6.2 4h-37.6c-3.4 0-5.2-2-7.2-4.2v-61.8h-49.4v62c0 2.2-2.8 4-6.2 4h-37.6c-3.4 0-6.8-2-6.8-4.2v-61.8h-104.4c-2 0-3.8-0.8-5-1.8s-1.6-2.4-1.2-3.6l9.6-25c0.6-1.8 2.8-3 5.6-3.2 25.6-1.4 45.8-15.6 45.8-33v-132.4c0-18.2-22.4-33-50.2-33h-6.2c-3.4 0-5.8-2-5.8-4.2v-24.8zM626 904.8c-28 5.4-58 8.8-90 9.8v-86.6h-44v86.4c-224-8.8-404.2-138.4-426.8-302.8 79.6 127.8 250.4 216.4 449.2 216.4 38.4 0 75.6-3.6 111.6-9.8v86.6zM760 861c-28 13.6-58 24.8-90 33.4v-85.8c32-7.8 62-18 90-30.2v82.6zM894 760.2c-24 28.6-54 54.4-90 76.2v-79.8c34-18 64-38.8 90-62.4v66zM938 692.4v-45.6c10-11.4 17.6-23.2 25.2-35.4-3.8 28.4-13.2 55.4-25.2 81z"
82 | ],
83 | "attrs": [
84 | {
85 | "fill": "rgb(68, 68, 68)"
86 | },
87 | {
88 | "fill": "rgb(68, 68, 68)"
89 | },
90 | {
91 | "fill": "rgb(68, 68, 68)"
92 | }
93 | ],
94 | "isMulticolor": false,
95 | "grid": 0,
96 | "tags": [
97 | "coin"
98 | ],
99 | "colorPermutations": {
100 | "6868681": [
101 | 0,
102 | 0,
103 | 0
104 | ]
105 | }
106 | },
107 | "attrs": [
108 | {
109 | "fill": "rgb(68, 68, 68)"
110 | },
111 | {
112 | "fill": "rgb(68, 68, 68)"
113 | },
114 | {
115 | "fill": "rgb(68, 68, 68)"
116 | }
117 | ],
118 | "properties": {
119 | "order": 81,
120 | "id": 15,
121 | "prevSize": 32,
122 | "code": 58882,
123 | "name": "coin"
124 | },
125 | "setIdx": 0,
126 | "iconIdx": 8
127 | },
128 | {
129 | "icon": {
130 | "paths": [
131 | "M662.6 1.4h-516.6v1020.6h799.8v-738.4l-283.2-282.2zM691.2 159l96.6 96.4h-96.6v-96.4zM237.8 92.8h361.6v254h254.6v583.6h-616.2v-837.6z",
132 | "M676.2 425v91.4h-357v-91.4h357z",
133 | "M319.2 573.6h357.2v91.4h-357.2v-91.4z",
134 | "M319.2 722.2h245.4v91.4h-245.4v-91.4z"
135 | ],
136 | "attrs": [
137 | {
138 | "fill": "rgb(68, 68, 68)"
139 | },
140 | {
141 | "fill": "rgb(68, 68, 68)"
142 | },
143 | {
144 | "fill": "rgb(68, 68, 68)"
145 | },
146 | {
147 | "fill": "rgb(68, 68, 68)"
148 | }
149 | ],
150 | "isMulticolor": false,
151 | "grid": 0,
152 | "tags": [
153 | "docs"
154 | ],
155 | "colorPermutations": {
156 | "6868681": [
157 | 0,
158 | 0,
159 | 0,
160 | 0
161 | ]
162 | }
163 | },
164 | "attrs": [
165 | {
166 | "fill": "rgb(68, 68, 68)"
167 | },
168 | {
169 | "fill": "rgb(68, 68, 68)"
170 | },
171 | {
172 | "fill": "rgb(68, 68, 68)"
173 | },
174 | {
175 | "fill": "rgb(68, 68, 68)"
176 | }
177 | ],
178 | "properties": {
179 | "order": 82,
180 | "id": 14,
181 | "prevSize": 32,
182 | "code": 58883,
183 | "name": "docs"
184 | },
185 | "setIdx": 0,
186 | "iconIdx": 9
187 | },
188 | {
189 | "icon": {
190 | "paths": [
191 | "M367.6 79.4l-252.8 234.8 252.8 226.4v-105.6h541.6v-225.6h-541.6z",
192 | "M909.2 713.8l-252.8-226.4v128.2h-541.6v225.6h541.6v107.4l252.8-234.8z"
193 | ],
194 | "attrs": [
195 | {
196 | "fill": "rgb(68, 68, 68)"
197 | },
198 | {
199 | "fill": "rgb(68, 68, 68)"
200 | }
201 | ],
202 | "isMulticolor": false,
203 | "grid": 0,
204 | "tags": [
205 | "double-arrow-solid"
206 | ],
207 | "colorPermutations": {
208 | "6868681": [
209 | 0,
210 | 0
211 | ]
212 | }
213 | },
214 | "attrs": [
215 | {
216 | "fill": "rgb(68, 68, 68)"
217 | },
218 | {
219 | "fill": "rgb(68, 68, 68)"
220 | }
221 | ],
222 | "properties": {
223 | "order": 94,
224 | "id": 13,
225 | "prevSize": 32,
226 | "code": 58884,
227 | "name": "double-arrow-solid"
228 | },
229 | "setIdx": 0,
230 | "iconIdx": 10
231 | },
232 | {
233 | "icon": {
234 | "paths": [
235 | "M504.2 922.4c-55.6 0-103.6-2.8-131.6-7.6-126.8-22-363-63-363-394.4 0-76.6 23.6-144.8 70.2-202.4-10.4-37.4-20.6-108.6 14.4-197l6.4-16.4 16.8-5.4c3.2-1 12.4-3.4 27.6-3.4 36 0 97.8 13 190.8 72.8 55.8-14 114.8-21.2 175.6-21.4 61 0.2 120.2 7.4 176 21.4 93-60 154.8-72.8 190.6-72.8 15.2 0 24.4 2.4 27.6 3.4l16.8 5.4 6.4 16.4c35.2 88.4 25 159.6 14.6 197 46.6 57.6 70.2 125.6 70.2 202.6 0 295.2-184 364.8-364.2 393.8-30.2 4.8-86.2 8-145.2 8v0 0zM160.8 175c-23 75.4-3.8 128.8 0.6 139.6l8.8 21.6-15.8 17.2c-42.8 46.2-64.4 102.4-64.4 166.8 0 245.6 134.6 288.8 297.2 317 23.2 4 67 6.4 117.2 6.4 53.8 0 105.6-2.8 132.2-7 150.4-24.2 297.4-68.8 297.4-316.4 0-64.6-21.6-120.8-64.4-167l-15.6-17.2 8.8-21.6c4.4-10.8 23.6-64.2 0.6-139.6-23.8 2.8-72.6 15.4-150.4 68l-14 9.4-16.4-4.6c-53-14.6-112-22.4-170.6-22.8-58.2 0.2-117 8.2-170 22.8l-16.4 4.6-14.2-9.4c-78-52.4-126.8-65.2-150.6-67.8v0 0z",
236 | "M385.2 622.4c0 38-20.6 68.8-45.8 68.8s-45.8-30.8-45.8-68.8 20.4-68.8 45.8-68.8c25.4 0 45.8 30.8 45.8 68.8z",
237 | "M730.2 622.4c0 38-20.4 68.8-45.8 68.8-25.2 0-45.8-30.8-45.8-68.8s20.4-68.8 45.8-68.8c25.4 0 45.8 30.8 45.8 68.8z"
238 | ],
239 | "attrs": [
240 | {
241 | "fill": "rgb(68, 68, 68)"
242 | },
243 | {
244 | "fill": "rgb(68, 68, 68)"
245 | },
246 | {
247 | "fill": "rgb(68, 68, 68)"
248 | }
249 | ],
250 | "isMulticolor": false,
251 | "grid": 0,
252 | "tags": [
253 | "github"
254 | ],
255 | "colorPermutations": {
256 | "6868681": [
257 | 0,
258 | 0,
259 | 0
260 | ]
261 | }
262 | },
263 | "attrs": [
264 | {
265 | "fill": "rgb(68, 68, 68)"
266 | },
267 | {
268 | "fill": "rgb(68, 68, 68)"
269 | },
270 | {
271 | "fill": "rgb(68, 68, 68)"
272 | }
273 | ],
274 | "properties": {
275 | "order": 95,
276 | "id": 10,
277 | "prevSize": 32,
278 | "code": 58885,
279 | "name": "github"
280 | },
281 | "setIdx": 0,
282 | "iconIdx": 13
283 | },
284 | {
285 | "icon": {
286 | "paths": [
287 | "M795.4 847.8l33.8-73-86.4-18.8 25.4-87.6-82.4-14.8c-19.6 18.4-42.2 33.6-67 45.2l148.8 258.6 98.8 7 20.2-89.2-91.2-27.4z",
288 | "M540.8 478.4c-1.6 0.2-3.4 0.4-5 0.4-0.2 0-0.2 0-0.4 0v0c-9.2 0.2-18.8-1.8-27.4-6.6-25.8-14.4-35-47-20.6-72.8s47-35 72.8-20.6c19.2 10.8 29.2 31.6 27 52.2 37.4-10.8 70.2-31.8 95.6-59.8-17.2-30.8-42.4-57.8-75.4-76.4-95.4-53.6-216.2-19.6-269.6 76-43 76.8-29.4 170.2 27.4 231.4l-167.2 299.4 44.8 88.4 86.8-28.4-23.2-92.6 80-8.6-28.4-83.6 88.2-23.2-30.2-80 56.4-11.6c81.8 16 168-20.8 211-97.4 27.4-49 31.6-104.6 16.4-154.4-41.6 40-97.4 65.6-159 68.2z",
289 | "M363 257.6c-1.2-8.4-2.2-16.8-2.2-25.6 0-93.2 75.8-169.2 169.2-169.2s169.2 75.8 169.2 169.2-75.8 169.2-169.2 169.2c-7.2 0-14.2-1.2-21.2-2.2-5 8.2-8.6 17.4-8.6 27.6 0 3.6 1.2 7 1.8 10.4 9.2 1.2 18.4 2.8 28 2.8 114.6 0 207.8-93.2 207.8-207.8 0-114.8-93.2-208-207.8-208s-208 93.2-208 207.8c0 18.6 3.2 36.4 7.8 53.4 10.2-10 21.4-19.2 33.2-27.6z"
290 | ],
291 | "attrs": [
292 | {
293 | "fill": "rgb(68, 68, 68)"
294 | },
295 | {
296 | "fill": "rgb(68, 68, 68)"
297 | },
298 | {
299 | "fill": "rgb(68, 68, 68)"
300 | }
301 | ],
302 | "isMulticolor": false,
303 | "grid": 0,
304 | "tags": [
305 | "keyring-solid"
306 | ],
307 | "colorPermutations": {
308 | "6868681": [
309 | 0,
310 | 0,
311 | 0
312 | ]
313 | }
314 | },
315 | "attrs": [
316 | {
317 | "fill": "rgb(68, 68, 68)"
318 | },
319 | {
320 | "fill": "rgb(68, 68, 68)"
321 | },
322 | {
323 | "fill": "rgb(68, 68, 68)"
324 | }
325 | ],
326 | "properties": {
327 | "order": 87,
328 | "id": 9,
329 | "prevSize": 32,
330 | "code": 58886,
331 | "name": "keyring-solid"
332 | },
333 | "setIdx": 0,
334 | "iconIdx": 14
335 | },
336 | {
337 | "icon": {
338 | "paths": [
339 | "M526.4 152.8c0 14.912-12.088 27-27 27s-27-12.088-27-27c0-14.912 12.088-27 27-27s27 12.088 27 27z",
340 | "M591.4 99c0 19.551-15.849 35.4-35.4 35.4s-35.4-15.849-35.4-35.4c0-19.551 15.849-35.4 35.4-35.4s35.4 15.849 35.4 35.4z",
341 | "M532 39.4c0 8.616-6.984 15.6-15.6 15.6s-15.6-6.984-15.6-15.6c0-8.616 6.984-15.6 15.6-15.6s15.6 6.984 15.6 15.6z",
342 | "M736.4 603.2c16.6-24 26.2-53 26.2-84.4 0-82.6-67.2-149.6-150.2-149.6h-35.6v-94.8c0-5.2 4.6-9.2 10.2-9.4 7.6-0.2 13.6-6.2 13.6-13.4-0.2-7.2-7-13-14.6-13h-152.4c-7.6 0-14.4 5.6-14.6 13-0.2 7.2 6 13.2 13.6 13.4 5.6 0.2 10.2 4 10.2 9.4v75.2c0 0 0 0 0 0h30c5.4 0 9.6 4.4 9.6 9.6s-4.4 9.6-9.6 9.6h-30c0 0 0 0 0 0v0.2h-152c-17.4 0-31.6 14.2-31.6 31.6s14.2 31.6 31.6 31.6h8c29.4 0 53.4 23.8 53.4 53.4v272.6c0 29.4-23.8 53.4-53.4 53.4h-8c-17.4 0-31.6 14.2-31.6 31.6s14.2 31.6 31.6 31.6h152v0.2c0 0 0 0 0 0h30c5.4 0 9.6 4.4 9.6 9.6 0 5.4-4.4 9.6-9.6 9.6h-30c0 0 0 0 0 0v52.8c0 35.2 30.2 63.8 67.2 63.8s67.2-28.8 67.2-63.8v-72.4h61.2c85 0 154-68.8 154-153.4-0.2-47.4-22-89.8-56-118zM476.2 454.2h92.8c34.8 0 63.2 28.4 63.2 63.2s-28.4 63.2-63.2 63.2h-92.8v-126.4zM600.6 790h-128.4v-126.4h128.4c34.8 0 63.2 28.4 63.2 63.2-0 34.6-28.4 63.2-63.2 63.2z"
343 | ],
344 | "attrs": [
345 | {
346 | "fill": "rgb(68, 68, 68)"
347 | },
348 | {
349 | "fill": "rgb(68, 68, 68)"
350 | },
351 | {
352 | "fill": "rgb(68, 68, 68)"
353 | },
354 | {
355 | "fill": "rgb(68, 68, 68)"
356 | }
357 | ],
358 | "isMulticolor": false,
359 | "grid": 0,
360 | "tags": [
361 | "lab-solid"
362 | ],
363 | "colorPermutations": {
364 | "6868681": [
365 | 0,
366 | 0,
367 | 0,
368 | 0
369 | ]
370 | }
371 | },
372 | "attrs": [
373 | {
374 | "fill": "rgb(68, 68, 68)"
375 | },
376 | {
377 | "fill": "rgb(68, 68, 68)"
378 | },
379 | {
380 | "fill": "rgb(68, 68, 68)"
381 | },
382 | {
383 | "fill": "rgb(68, 68, 68)"
384 | }
385 | ],
386 | "properties": {
387 | "order": 88,
388 | "id": 8,
389 | "prevSize": 32,
390 | "code": 58887,
391 | "name": "lab-solid"
392 | },
393 | "setIdx": 0,
394 | "iconIdx": 15
395 | },
396 | {
397 | "icon": {
398 | "paths": [
399 | "M766.2 267.8c-0.8-69-28.4-133.6-77.4-182s-114-75-182.8-75c-1 0-2.2 0-3.2 0-69.4 0.8-134.4 28.6-183 78.4-48.6 49.6-74.8 115.4-74 184.8 1.4 111.4 72.6 208.4 177.6 243.6l5.8 435 115 75.2 85.4-95.6-35.6-88.8 33.8-59.8-35.4-75.6 33.2-81.2-35.6-70.6 4.8-40.8c104-37.8 172.8-136.6 171.4-247.6zM559.8 262.6c-14.2 14.6-33.2 22.6-53.6 23h-1c-41.4 0-75.6-33.8-76.2-75.2-0.2-20.4 7.4-39.6 21.6-54 14.2-14.6 33.2-22.6 53.6-23h1c41.4 0 75.6 33.8 76.2 75.2 0.2 20.4-7.4 39.6-21.6 54z"
400 | ],
401 | "attrs": [
402 | {
403 | "fill": "rgb(68, 68, 68)"
404 | }
405 | ],
406 | "isMulticolor": false,
407 | "grid": 0,
408 | "tags": [
409 | "public-key-solid"
410 | ],
411 | "colorPermutations": {
412 | "6868681": [
413 | 0
414 | ]
415 | }
416 | },
417 | "attrs": [
418 | {
419 | "fill": "rgb(68, 68, 68)"
420 | }
421 | ],
422 | "properties": {
423 | "order": 91,
424 | "id": 5,
425 | "prevSize": 32,
426 | "code": 58888,
427 | "name": "public-key-solid"
428 | },
429 | "setIdx": 0,
430 | "iconIdx": 18
431 | },
432 | {
433 | "icon": {
434 | "paths": [
435 | "M820 526h136v90h-136v-90z",
436 | "M254.6 695.4h81.6v81.6h-81.6v-81.6z",
437 | "M92 532v408h408v-408h-408zM410 848h-226v-226h226v226z",
438 | "M254.6 239.2h81.6v81.6h-81.6v-81.6z",
439 | "M92 76v408h408v-408h-408zM410 394h-226v-224h226v224z",
440 | "M710.6 239.2h81.6v81.6h-81.6v-81.6z",
441 | "M548 76v408h408v-408h-408zM862 394h-224v-224h224v224z",
442 | "M548 526h90v408h-90v-408z",
443 | "M953.4 660h-81.4v102h-74v80h-68v92h226v-275.4z"
444 | ],
445 | "attrs": [
446 | {
447 | "fill": "rgb(68, 68, 68)"
448 | },
449 | {
450 | "fill": "rgb(68, 68, 68)"
451 | },
452 | {
453 | "fill": "rgb(68, 68, 68)"
454 | },
455 | {
456 | "fill": "rgb(68, 68, 68)"
457 | },
458 | {
459 | "fill": "rgb(68, 68, 68)"
460 | },
461 | {
462 | "fill": "rgb(68, 68, 68)"
463 | },
464 | {
465 | "fill": "rgb(68, 68, 68)"
466 | },
467 | {
468 | "fill": "rgb(68, 68, 68)"
469 | },
470 | {
471 | "fill": "rgb(68, 68, 68)"
472 | }
473 | ],
474 | "isMulticolor": false,
475 | "grid": 0,
476 | "tags": [
477 | "qr-solid"
478 | ],
479 | "colorPermutations": {
480 | "6868681": [
481 | 0,
482 | 0,
483 | 0,
484 | 0,
485 | 0,
486 | 0,
487 | 0,
488 | 0,
489 | 0
490 | ]
491 | }
492 | },
493 | "attrs": [
494 | {
495 | "fill": "rgb(68, 68, 68)"
496 | },
497 | {
498 | "fill": "rgb(68, 68, 68)"
499 | },
500 | {
501 | "fill": "rgb(68, 68, 68)"
502 | },
503 | {
504 | "fill": "rgb(68, 68, 68)"
505 | },
506 | {
507 | "fill": "rgb(68, 68, 68)"
508 | },
509 | {
510 | "fill": "rgb(68, 68, 68)"
511 | },
512 | {
513 | "fill": "rgb(68, 68, 68)"
514 | },
515 | {
516 | "fill": "rgb(68, 68, 68)"
517 | },
518 | {
519 | "fill": "rgb(68, 68, 68)"
520 | }
521 | ],
522 | "properties": {
523 | "order": 73,
524 | "id": 3,
525 | "prevSize": 32,
526 | "code": 58889,
527 | "name": "qr-solid"
528 | },
529 | "setIdx": 0,
530 | "iconIdx": 20
531 | }
532 | ],
533 | "height": 1024,
534 | "metadata": {
535 | "name": "icomoon"
536 | },
537 | "preferences": {
538 | "showGlyphs": true,
539 | "showQuickUse": true,
540 | "showQuickUse2": true,
541 | "showSVGs": true,
542 | "fontPref": {
543 | "prefix": "icon-",
544 | "metadata": {
545 | "fontFamily": "icomoon"
546 | },
547 | "metrics": {
548 | "emSize": 1024,
549 | "baseline": 6.25,
550 | "whitespace": 50
551 | },
552 | "autoHost": false,
553 | "resetPoint": 58880
554 | },
555 | "imagePref": {
556 | "prefix": "icon-",
557 | "png": true,
558 | "useClassSelector": true,
559 | "color": 4473924,
560 | "bgColor": 16777215,
561 | "classSelector": ".icon"
562 | },
563 | "historySize": 100,
564 | "showCodes": true,
565 | "quickUsageToken": {
566 | "UntitledProject": "NzAzZmU3Y2EzZjNkMjMxMjMzMDUzMDI2YWE5MWZmYjgjMSMxNDIyODk1MjI3IyMj"
567 | }
568 | }
569 | }
--------------------------------------------------------------------------------
/app/fonts/solid-icons/style.css:
--------------------------------------------------------------------------------
1 | @font-face {
2 | font-family: 'solid-icons';
3 | src:url('fonts/solid-icons.eot?-e02rc4');
4 | src:url('fonts/solid-icons.eot?#iefix-e02rc4') format('embedded-opentype'),
5 | url('fonts/solid-icons.woff?-e02rc4') format('woff'),
6 | url('fonts/solid-icons.ttf?-e02rc4') format('truetype'),
7 | url('fonts/solid-icons.svg?-e02rc4#icomoon') format('svg');
8 | font-weight: normal;
9 | font-style: normal;
10 | }
11 |
12 | [class^="icon-"], [class*=" icon-"] {
13 | font-family: 'solid-icons';
14 | speak: none;
15 | font-style: normal;
16 | font-weight: normal;
17 | font-variant: normal;
18 | text-transform: none;
19 | line-height: 1;
20 |
21 | /* Better Font Rendering =========== */
22 | -webkit-font-smoothing: antialiased;
23 | -moz-osx-font-smoothing: grayscale;
24 | }
25 |
26 | .icon-tree-solid:before {
27 | content: "\e60a";
28 | }
29 |
30 | .icon-api:before {
31 | content: "\e600";
32 | }
33 |
34 | .icon-btc-solid:before {
35 | content: "\e601";
36 | }
37 |
38 | .icon-coin:before {
39 | content: "\e602";
40 | }
41 |
42 | .icon-docs:before {
43 | content: "\e603";
44 | }
45 |
46 | .icon-double-arrow-solid:before {
47 | content: "\e604";
48 | }
49 |
50 | .icon-github:before {
51 | content: "\e605";
52 | }
53 |
54 | .icon-keyring-solid:before {
55 | content: "\e606";
56 | }
57 |
58 | .icon-lab-solid:before {
59 | content: "\e607";
60 | }
61 |
62 | .icon-public-key-solid:before {
63 | content: "\e608";
64 | }
65 |
66 | .icon-qr-solid:before {
67 | content: "\e609";
68 | }
69 |
70 |
--------------------------------------------------------------------------------
/app/fonts/ubuntu-bold-italic.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/ubuntu-bold-italic.woff
--------------------------------------------------------------------------------
/app/fonts/ubuntu-bold.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/ubuntu-bold.woff
--------------------------------------------------------------------------------
/app/fonts/ubuntu-light.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/ubuntu-light.woff
--------------------------------------------------------------------------------
/app/fonts/ubuntu.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/fonts/ubuntu.woff
--------------------------------------------------------------------------------
/app/hdkeys/hdkeys.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Hierarchical Deterministic Keys
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Derive HD keys from a private or public extended key and a path.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
Master Keys
19 |
20 |
21 |
22 |
23 | Root HD Private Key
24 |
25 |
26 |
27 |
28 |
35 |
36 |
37 |
38 | Root HD Public Key
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
Derived Keys
56 |
57 |
58 |
59 |
60 |
61 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | Path: {{node.path}}
77 |
78 |
86 |
87 |
88 |
89 |
90 |
98 |
99 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
HD Public Key
109 |
110 |
111 |
112 |
113 |
114 |
115 |
118 |
119 |
120 |
121 |
122 |
123 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
--------------------------------------------------------------------------------
/app/hdkeys/hdkeys.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.hdkeys', ['ngRoute'])
4 |
5 | .config(['$routeProvider', function($routeProvider) {
6 | $routeProvider.when('/hdkeys', {
7 | templateUrl: 'hdkeys/hdkeys.html',
8 | controller: 'HDKeysCtrl'
9 | });
10 | }])
11 |
12 | .controller('HDKeysCtrl', function($scope, bitcore) {
13 |
14 | $scope.bitcoreURL = 'http://bitcore.io/guide/hierarchical.html';
15 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#hierarchical-deterministic-key-creation';
16 | var privateValidPath = function(path) {
17 | return !!(/^[mM][']?(\/[0-9]+[']?)*[/]?$/.exec(path));
18 | };
19 | var publicValidPath = function(path) {
20 | return !!(/^[mM](\/[0-9]+)*[/]?$/.exec(path));
21 | };
22 | $scope.path = "m/44'/0'/0'/0/1337";
23 | $scope.keys = [];
24 |
25 | $scope.$on('networkUpdate', function() {
26 | $scope.newKey();
27 | });
28 |
29 | $scope.newKey = function() {
30 | $scope.updatePrivate(new bitcore.HDPrivateKey().toString());
31 | };
32 |
33 | $scope.updatePrivate = function(value) {
34 | if (!bitcore.HDPrivateKey.isValidSerialized(value)) return; // mark as invalid
35 |
36 | $scope.xpriv = new bitcore.HDPrivateKey(value);
37 | $scope.xpub = $scope.xpriv.hdPublicKey;
38 | $scope.keys = $scope.deriveKeys($scope.xpriv, $scope.path);
39 | setExampleCode($scope.xpriv, $scope.path);
40 | };
41 |
42 | $scope.updatePublic = function(value) {
43 | if (!bitcore.HDPublicKey.isValidSerialized(value)) return; // mark as invalid
44 |
45 | $scope.xpriv = '';
46 | $scope.xpub = new bitcore.HDPublicKey(value);
47 | $scope.keys = $scope.deriveKeys($scope.xpub, $scope.path);
48 | setExampleCode($scope.xpub, $scope.path);
49 | };
50 |
51 | $scope.updatePath = function(value) {
52 | if ($scope.xpriv) {
53 | if (!privateValidPath(value)) return;
54 | } else {
55 | if (!publicValidPath(value)) return;
56 | }
57 |
58 | $scope.keys = $scope.deriveKeys($scope.xpriv || $scope.xpub, value);
59 | setExampleCode($scope.xpriv || $scope.xpub, value);
60 | };
61 |
62 | $scope.deriveKeys = function(key, path) {
63 | var xpriv, xpub;
64 | if (key instanceof bitcore.HDPrivateKey) {
65 | xpriv = key;
66 | xpub = key.hdPublicKey;
67 | } else if (key instanceof bitcore.HDPublicKey) {
68 | xpriv = null;
69 | xpub = key;
70 | } else {
71 | return;
72 | }
73 |
74 | if (path[path.length-1] === '/') {
75 | path = path.substr(0, path.length - 1);
76 | }
77 |
78 | if (xpriv) {
79 | if (!privateValidPath(path)) return;
80 | } else {
81 | if (!publicValidPath(path)) return;
82 | }
83 |
84 | var indexes = bitcore.HDPrivateKey._getDerivationIndexes(path);
85 | var MAX = 2147483647;
86 | var paths = indexes.map(function(m, i) {
87 | return 'm/' + indexes.slice(0, i+1).map(function(index) {
88 | if (index >= MAX) {
89 | return (index - MAX - 1) + "'";
90 | }
91 | return '' + index;
92 | }).join('/');
93 | });
94 | paths = ['m'].concat(paths);
95 |
96 | var nodes = paths.map(function(p) {
97 | return {
98 | path: p,
99 | xpriv: xpriv && key.derive(p),
100 | xpub: (key instanceof bitcore.HDPublicKey) ? key.derive(p) : key.derive(p).hdPublicKey
101 | };
102 | });
103 |
104 | nodes[nodes.length-1].visible = true;
105 | nodes.reverse();
106 | return nodes;
107 | };
108 |
109 | function setExampleCode(hdKey, path, isNew) {
110 | var template = "";
111 |
112 | if (hdKey instanceof bitcore.HDPublicKey) {
113 | template += "var hdPublicKey = new bitcore.HDPrivateKey();\n";
114 | template += "var derivedHdPublicKey = hdPublicKey.derive('" + path + "');\n"
115 |
116 | } else if (hdKey instanceof bitcore.HDPrivateKey) {
117 | template += "var hdPrivateKey = new bitcore.HDPrivateKey();\n";
118 |
119 | template += "\n// private key derivation\n";
120 | template += "var derivedHdPrivateKey = hdPrivateKey.derive(\"" + path + "\");\n"
121 | template += "var derivedPrivateKey = hdPrivateKey.privateKey;\n"
122 |
123 | template += "\n// public key derivation\n";
124 | template += "var derivedHdPublicKey = derivedHdPrivateKey.hdPublicKey;\n"
125 | }
126 |
127 | template += "var derivedPublicKey = derivedHdPublicKey.publicKey;\n"
128 | template += "var address = derivedPublicKey.toAddress();"
129 |
130 | $scope.exampleCode = template;
131 | };
132 |
133 | $scope.jumpConsole = function() {
134 | $('#terminaltab').click();
135 | window.REPL.console.SetPromptText($scope.exampleCode);
136 | window.REPL.scrollToBottom();
137 | };
138 |
139 | $scope.newKey();
140 | });
141 |
--------------------------------------------------------------------------------
/app/img/add-user-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/api-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-down-info.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-right-small-single.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-right-small.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrow-up-info.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/arrows-nav.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/bitcore-logo-hd.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/bitcore-og-image.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/img/bitcore-og-image.png
--------------------------------------------------------------------------------
/app/img/btc-icon-address.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/btc-nav.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/close-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/code-spot.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/dice-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/doc-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/img/favicon.png
--------------------------------------------------------------------------------
/app/img/gear-icon-title.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/githubcat-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/key-nav.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/keyring-nav.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/lava-ball-social.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/bitpay/bitcore-playground/a84081f762a58ec1ff1bde90125cdd225cfc749c/app/img/lava-ball-social.png
--------------------------------------------------------------------------------
/app/img/learn-title.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
16 |
--------------------------------------------------------------------------------
/app/img/private-key-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/public-key-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/qr-nav.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/remove-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/terminal-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/transp-box.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/img/user-icon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 | Bitcore Playground
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
123 |
124 |
125 |
126 |
127 |
128 |
145 |
146 |
147 |
148 |
149 |
175 |
176 |
177 |
178 |
181 |
182 |
185 |
186 |
187 |
188 |
189 |
190 |
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
--------------------------------------------------------------------------------
/app/multisig/multisig.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Multi-signature Address
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 | Derive a bitcoin address that requires several signatures to spend its funds.
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | Number of Keys:
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 | Required Signatures:
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
47 |
50 |
51 |
52 |
53 |
54 |
Private Key
55 |
56 |
57 |
58 |
59 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
Public Key
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
98 |
99 |
100 |
101 |
102 |
103 |
{{threshold}}-of-{{totalKeys}} Bitcoin Address
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
--------------------------------------------------------------------------------
/app/multisig/multisig.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.multisig', ['ngRoute'])
4 |
5 | .config(['$routeProvider', function($routeProvider) {
6 | $routeProvider.when('/multisig', {
7 | templateUrl: 'multisig/multisig.html',
8 | controller: 'MultisigCtrl'
9 | });
10 | }])
11 |
12 | .controller('MultisigCtrl', function($scope, bitcore) {
13 |
14 | $scope.bitcoreURL = 'http://bitcore.io/guide/transaction.html#Multisig_Transactions';
15 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#term-multisig';
16 |
17 | $scope.$on('networkUpdate', function() {
18 | $scope.keys = $scope.keys.map(getRandomKey);
19 | });
20 |
21 | $scope.totalKeysRange = function() {
22 | var size = Math.max($scope.keys.length, 7);
23 | return Range(size);
24 | };
25 |
26 | $scope.signaturesRange = function() {
27 | return Range($scope.keys.length);
28 | };
29 |
30 | function Range(size) {
31 | var result = [];
32 | for (var i = 1; i <= size; i++) {
33 | result.push(i);
34 | }
35 | return result;
36 | }
37 |
38 | function setupKeys() {
39 | $scope.keys = [1,2,3].map(getRandomKey);
40 | $scope.totalKeys = $scope.keys.length;
41 | $scope.threshold = 2;
42 | }
43 |
44 | $scope.setKeyAmount = function(amount) {
45 | var delta = amount - $scope.keys.length;
46 | if (delta > 0) {
47 | for (var i = 0; i < delta; i++) $scope.add();
48 | } else {
49 | for (var i = 0; i > delta; i--) $scope.keys = $scope.keys.slice(0, -1);
50 | }
51 |
52 | if ($scope.threshold > amount) {
53 | $scope.threshold = amount;
54 | }
55 | };
56 |
57 | // Initial Setup
58 | setupKeys();
59 |
60 | function getRandomKey() {
61 | var priv = new bitcore.PrivateKey();
62 | return {
63 | privKey: priv.toString(),
64 | pubKey: priv.publicKey.toString()
65 | };
66 | }
67 |
68 | $scope.add = function() {
69 | $scope.keys.push(getRandomKey());
70 | $scope.totalKeys = $scope.keys.length;
71 | };
72 |
73 | $scope.remove = function(index) {
74 | var newKeys = [];
75 | for (var key in $scope.keys) {
76 | if (key != index) {
77 | newKeys.push($scope.keys[key]);
78 | }
79 | }
80 | $scope.keys = newKeys;
81 | $scope.totalKeys = $scope.keys.length;
82 | $scope.threshold = Math.min($scope.threshold, $scope.totalKeys);
83 | };
84 |
85 | $scope.updatePriv = function(index) {
86 | var privKey = new bitcore.PrivateKey($scope.keys[index].privKey);
87 | $scope.keys[index].privKey = privKey.toBuffer().toString('hex');
88 | $scope.keys[index].pubKey = privKey.publicKey.toString();
89 | setAddress();
90 | };
91 |
92 | $scope.randPriv = function(index) {
93 | $scope.keys[index] = getRandomKey();
94 | $scope.updatePriv(index);
95 | };
96 |
97 | $scope.updatePub = function(index) {
98 | $scope.keys[index].privKey = '';
99 | $scope.keys[index].pubKey = new bitcore.PublicKey($scope.keys[index].pubKey).toString();
100 | setAddress();
101 | };
102 |
103 | var setAddress = function() {
104 | var pubkeys = [];
105 | for (var key in $scope.keys) {
106 | pubkeys.push($scope.keys[key].pubKey);
107 | }
108 | var address = new bitcore.Address(pubkeys, $scope.threshold);
109 |
110 | $scope.address = address.toString();
111 | setExampleCode(pubkeys, $scope.threshold);
112 | };
113 |
114 | function setExampleCode(pubkeys, threshold) {
115 | var template = "var publicKeys = [\n";
116 |
117 | pubkeys.forEach(function(key, index) {
118 | template += " new bitcore.PublicKey('" + key.toString() + "')";
119 | template += (index < pubkeys.length - 1) ? ',\n' : '\n';
120 | });
121 |
122 | template += "];\n";
123 | template += "var requiredSignatures = " + threshold + ";\n";
124 | template += "var address = new bitcore.Address(publicKeys, requiredSignatures);";
125 |
126 | $scope.exampleCode = template;
127 | };
128 |
129 | $scope.jumpConsole = function() {
130 | $('#terminaltab').click();
131 | window.REPL.console.SetPromptText($scope.exampleCode);
132 | window.REPL.scrollToBottom();
133 | };
134 |
135 | setAddress();
136 | $scope.$watchCollection('keys', setAddress);
137 | $scope.$watch('threshold', setAddress);
138 | });
139 |
--------------------------------------------------------------------------------
/app/transaction/transaction.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Transaction
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Build, sign and broadcast a transaction.
11 |
12 |
13 |
14 |
15 |
16 |
Input Selection
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
Outputs for Address: {{currentAddress}}
39 |
40 |
41 |
42 |
43 |
44 |
No outputs found
45 |
46 |
47 |
48 |
49 |
50 |
51 |
54 |
55 |
56 |
{{utxo.satoshis|btc}} BTC
57 |
58 |
63 |
64 |
65 |
66 |
67 |
70 |
71 |
72 |
{{utxo.satoshis|btc}} BTC
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
Transaction
92 |
93 |
94 | TX ID:
95 | {{transaction.id}}
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 | Total Inputs: {{transaction._inputAmount | btc}}
104 |
105 |
106 |
107 |
108 |
109 |
110 | Total Outputs: {{transaction._outputAmount | btc}}
111 |
112 |
113 | Fee: {{transaction._getUnspentValue() | btc}}
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
Inputs
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
{{input.output.satoshis|btc}} BTC
141 |
142 |
154 |
155 |
156 |
157 |
160 |
161 |
162 |
163 |
164 |
165 | TX ID:
166 | {{input.prevTxId.toString('hex')}}
167 |
168 |
169 | OUT #:
170 | {{input.outputIndex}}
171 |
172 |
173 | Script:
174 | {{input.output.script.toString()}}
175 |
176 |
177 |
178 |
179 |
180 |
181 |
182 |
183 |
184 |
185 |
186 |
187 |
188 |
189 |
190 |
Outputs
191 |
192 |
193 |
194 |
195 |
196 |
197 |
198 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 | {{output.satoshis|btc}} BTC to {{getAddress(output) | ellipsify}}
214 |
215 |
216 | Data
217 |
218 |
219 | {{output.satoshis|btc}} BTC to an unrecognized script
220 |
221 |
222 |
234 |
237 |
238 |
239 |
240 |
241 | Data:
242 | 0x{{output.script.getData().toString('hex')}}
243 |
244 |
245 | Script:
246 | {{output.script.toString()}}
247 |
248 |
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
261 |
262 |
263 |
Serialized transaction:
264 |
265 |
266 |
271 |
272 |
273 |
279 |
280 |
281 |
282 |
283 |
284 |
285 |
286 |
287 |
288 |
289 |
290 |
Add a Pay to Address
291 |
312 |
313 |
314 |
315 |
316 |
317 |
318 |
319 |
320 |
Add a OP_RETURN Output
321 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
362 |
363 |
364 |
365 |
Could not sign any inputs.
366 |
Please check that the private key provided corresponds to a input of this transaction.
367 |
×
368 |
369 |
370 |
371 |
Transaction Rejected by Insight
372 |
Make sure the outputs where not spent already, that all inputs where signed, and no outputs are dust amounts (less than 5600 satoshis).
373 |
×
374 |
375 |
376 |
Transaction Broadcasted
377 |
See the transaction on insight: {{transaction.id}}
378 | ×
379 |
380 |
--------------------------------------------------------------------------------
/app/transaction/transaction.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.transaction', ['ngRoute'])
4 |
5 | .config(['$routeProvider', function($routeProvider) {
6 | $routeProvider.when('/transaction', {
7 | templateUrl: 'transaction/transaction.html',
8 | controller: 'TransactionCtrl'
9 | });
10 | }])
11 |
12 | .controller('TransactionCtrl', function($scope, $rootScope, $http, bitcore) {
13 |
14 | $scope.bitcoreURL = 'http://bitcore.io/guide/transaction.html';
15 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#transactions';
16 | var explorers = require('bitcore-explorers');
17 | var defaultLivenetAddress = '1PPQ2anP7DVWmeScdo8fCSTeWCpfBDFAhy';
18 | var defaultTestnetAddress = 'mfnUxBP3JjS4pU1kddzUshF8bcU7wF99mx';
19 |
20 | $scope.$on('networkUpdate', function() {
21 | reset();
22 | });
23 |
24 | var reset = function() {
25 | if (bitcore.Networks.defaultNetwork.name === 'testnet') {
26 | $scope.utxoAddress = defaultTestnetAddress;
27 | } else {
28 | $scope.utxoAddress = defaultLivenetAddress;
29 | }
30 | $scope.utxos = [];
31 | $scope.loading = false;
32 | $scope.currentAddress = '';
33 | $rootScope.transaction = new bitcore.Transaction();
34 | $scope.privateKey = '';
35 |
36 | $scope.fromAddresses = [];
37 | $rootScope.toAddresses = {};
38 | $rootScope.addData = [];
39 | $rootScope.privateKeys = [];
40 | $scope.change = '';
41 | $scope.loading = false;
42 | setExampleCode();
43 | };
44 | reset();
45 |
46 | $scope.privateKey = '';
47 |
48 | $scope.fromAddresses = [];
49 | $rootScope.toAddresses = {};
50 | $rootScope.addData = [];
51 | $rootScope.privateKeys = [];
52 | $scope.change = '';
53 | $scope.nLockTime = undefined;
54 | $scope.loading = false;
55 |
56 | $scope.$watch('nLockTime', function(newValue) {
57 | if (!newValue) {
58 | $scope.currentAddress = undefined;
59 | } else {
60 | $rootScope.transaction.nLockTime = newValue;
61 | }
62 | setExampleCode();
63 | });
64 |
65 | $scope.utxos = [];
66 |
67 | $scope.fetchUTXO = function(address) {
68 | var client = new explorers.Insight();
69 | if (!bitcore.Address.isValid(address)) return; // mark as invalid
70 |
71 | $scope.loading = true;
72 | client.getUnspentUtxos(address, onUTXOs);
73 | $scope.fromAddresses.push(address);
74 |
75 | function onUTXOs(err, utxos) {
76 | $scope.loading = false;
77 | if (err) throw err;
78 |
79 | if (!utxos.length) {
80 | $scope.utxos = [];
81 | $scope.notFound = address;
82 | $scope.currentAddress = '';
83 | $scope.$apply();
84 | return;
85 | }
86 |
87 | $scope.utxos = utxos;
88 | $scope.currentAddress = address;
89 | $scope.$apply();
90 | console.log(utxos);
91 | }
92 | };
93 |
94 | $scope.signWith = function(privKey) {
95 | try {
96 | $('#addSignatureModal').foundation('reveal', 'close');
97 | if (!privKey) {
98 | return;
99 | }
100 | var privateKey = new bitcore.PrivateKey(privKey);
101 | $rootScope.privateKeys.push(privateKey);
102 | var signatures = $rootScope.transaction.getSignatures(privateKey);
103 | if (!signatures.length) {
104 | $('#noSignatures').foundation('reveal', 'open');
105 | } else {
106 | $rootScope.transaction.sign(privateKey);
107 | }
108 | setExampleCode();
109 | } catch (e) {
110 | console.log('Error', e);
111 | }
112 | };
113 |
114 | $scope.addUTXO = function(utxo) {
115 | utxo.used = true;
116 | $rootScope.transaction.from(utxo);
117 | setExampleCode();
118 | };
119 |
120 | $scope.removeUtxo = function(utxo) {
121 | var txId = utxo.txId.toString('hex');
122 | $rootScope.transaction.removeInput(txId, utxo.outputIndex);
123 | for (var i in $scope.utxos) {
124 | if ($scope.utxos[i].txId.toString('hex') === txId && $scope.utxos[i].outputIndex === utxo.outputIndex) {
125 | $scope.utxos[i].used = false;
126 | }
127 | }
128 | setExampleCode();
129 | };
130 | $scope.removeInput = function(input) {
131 | $scope.removeUtxo({txId: input.prevTxId, outputIndex: input.outputIndex});
132 | };
133 | $scope.removeOutput = function(index) {
134 | $rootScope.transaction.removeOutput(index);
135 | setExampleCode();
136 | $scope.$apply();
137 | };
138 |
139 | $scope.addAddressOutput = function(address, amount) {
140 | console.log(address, amount);
141 | $('#addAddressModal').foundation('reveal', 'close');
142 | if (!amount && amount !== 0) {
143 | return;
144 | }
145 | amount = bitcore.Unit.fromBTC(amount).toSatoshis();
146 | $rootScope.toAddresses[address] = amount;
147 | $rootScope.transaction.to(address, amount);
148 | setExampleCode();
149 | };
150 |
151 | $rootScope.addDataOutput = function(info) {
152 | $('#addDataModal').foundation('reveal', 'close');
153 | $rootScope.addData.push(info);
154 | $rootScope.transaction.addData(info);
155 | setExampleCode();
156 | };
157 |
158 | $scope.addPrivateKey = function(privKey) {
159 | $rootScope.privateKeys.push(privKey);
160 | setExampleCode();
161 | };
162 |
163 | $scope.canSerialize = function() {
164 | try {
165 | $rootScope.transaction.serialize();
166 | } catch (err) {
167 | return false;
168 | }
169 | return $rootScope.transaction.inputs.length > 0;
170 | }
171 |
172 | $scope.broadcast = function() {
173 | var serialized = $rootScope.transaction.serialize();
174 | var client = new explorers.Insight();
175 | $scope.broadcasting = true;
176 | client.broadcast(serialized, function(err, id) {
177 | $scope.broadcasting = false;
178 | if (err) {
179 | $('#broadcastError').foundation('reveal', 'open');
180 | } else {
181 | $rootScope.transactionUrl = client.url + '/tx/' + $rootScope.transaction.id;
182 | $scope.$apply();
183 | $('#broadcastSuccess').foundation('reveal', 'open');
184 | }
185 | });
186 | };
187 |
188 | function setExampleCode() {
189 | var template = "";
190 | var i;
191 |
192 | template += "var transaction = new bitcore.Transaction()\n";
193 | for (i in $scope.utxos) {
194 | if ($scope.utxos[i].used) {
195 | template += " .from(" + $scope.utxos[i].toJSON() + ")\n";
196 | }
197 | }
198 | for (i in $rootScope.toAddresses) {
199 | template += " .to('" + i + "', " + $rootScope.toAddresses[i] + ")\n";
200 | }
201 | for (i in $rootScope.addData) {
202 | template += " .addData('" + $rootScope.addData[i] + "')\n";
203 | }
204 | for (i in $rootScope.privateKeys) {
205 | template += " .sign('" + $rootScope.privateKeys[i] + "')\n";
206 | }
207 | if ($scope.change) {
208 | template += " .change('" + $scope.change + "')\n";
209 | }
210 | if (!_.isUndefined($scope.nLockTime)) {
211 | template += "transaction.nLockTime = " + $scope.nLockTime + ";\n";
212 | }
213 |
214 | $scope.exampleCode = template;
215 | }
216 |
217 | $scope.jumpConsole = function() {
218 | $('#terminaltab').click();
219 | window.REPL.console.SetPromptText($scope.exampleCode);
220 | window.REPL.scrollToBottom();
221 | };
222 |
223 | $scope.getAddress = function(output) {
224 | return output.script.isScriptHashOut() || output.script.isPublicKeyHashOut()
225 | ? output.script.toAddress().toString()
226 | : '';
227 | }
228 |
229 | function initialExample() {
230 | var template = "";
231 |
232 | template += "var transaction = new bitcore.Transaction()\n";
233 | template += " .from(utxos)\n";
234 | template += " .to('1bitcoinAddress...', 10000)\n";
235 | template += " .to('2bitcoinAddress...', 10000)\n";
236 | template += " .change('3bitcoinAddress...', 20000);";
237 |
238 | $scope.exampleCode = template;
239 | }
240 |
241 | initialExample();
242 |
243 | // Monkey patching until next bitcore version is released
244 | bitcore.Transaction.prototype.removeInput = function(txId, outputIndex) {
245 | var index;
246 | if (!outputIndex && _.isNumber(txId)) {
247 | index = txId;
248 | } else {
249 | index = _.findIndex(this.inputs, function(input) {
250 | return input.prevTxId.toString('hex') === txId && input.outputIndex === outputIndex;
251 | });
252 | }
253 | if (index < 0 || index >= this.inputs.length) {
254 | throw new errors.Transaction.InvalidIndex(index, this.inputs.length);
255 | }
256 | var input = this.inputs[index];
257 | this._inputAmount -= input.output.satoshis;
258 | this.inputs = _.without(this.inputs, input);
259 | this._updateChangeOutput();
260 | };
261 | });
262 |
--------------------------------------------------------------------------------
/app/units/units.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Bitcoin Units
4 |
5 |
6 |
7 |
8 |
9 |
Convert between the most frequent bitcoin units and fiat currencies.
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
Bitcoin
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
Fiat
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 | 1 BTC = {{currency.rate.toFixed(2)}} {{currency.code}}
115 |
116 | Exchange rates from bitpay.com/api/rates
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
--------------------------------------------------------------------------------
/app/units/units.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.units', ['ngRoute'])
4 |
5 | .config(['$routeProvider',
6 | function($routeProvider) {
7 | $routeProvider.when('/units', {
8 | templateUrl: 'units/units.html',
9 | controller: 'UnitsCtrl'
10 | });
11 | }
12 | ])
13 |
14 | .controller('UnitsCtrl', function($scope, $http, bitcore) {
15 | $scope.unit = {};
16 | $scope.currencies = [];
17 | $scope.currency = null;
18 | $scope.exampleCode = '';
19 | $scope.bitcoreURL = 'http://bitcore.io/guide/unit.html';
20 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#plain-text';
21 |
22 | function setExampleCode(value, code, fiat) {
23 | var template;
24 | var templates = {
25 | BTC: 'var unit = new bitcore.Unit.fromBTC(@value);',
26 | mBTC: 'var unit = new bitcore.Unit.fromMilis(@value);',
27 | bits: 'var unit = new bitcore.Unit.fromBits(@value);',
28 | satoshis: 'var unit = new bitcore.Unit.fromSatoshis(@value);',
29 | };
30 |
31 | if (templates[code]) {
32 | template = templates[code].replace('@value', value);
33 | template += '\nvar rate = @rate; // @fiat/BTC exchange rate';
34 | } else {
35 | template = 'var rate = @rate; // @fiat/BTC exchange rate\n';
36 | template += 'var unit = new bitcore.Unit.fromFiat(@value, rate);';
37 | }
38 | template = template.replace('@value', value);
39 | template = template.replace('@rate', fiat && fiat.rate);
40 | template = template.replace('@fiat', fiat && fiat.code);
41 |
42 | var rate = $scope.currency ? $scope.currency.rate : 0;
43 | template += "\nconsole.log('Units', unit.BTC, unit.mBTC, unit.bits, unit.satoshis, unit.atRate(rate));";
44 | $scope.exampleCode = template;
45 | }
46 |
47 | $scope.jumpConsole = function() {
48 | $('#terminaltab').click();
49 | window.REPL.console.SetPromptText($scope.exampleCode);
50 | window.REPL.scrollToBottom();
51 | };
52 |
53 | $scope.updateUnit = function(value, code) {
54 | var unit = new bitcore.Unit(value, code);
55 |
56 | if (value === '' || isNaN(unit.satoshis)) {
57 | return; // TODO: mark as invalid
58 | }
59 |
60 | $scope.unit.BTC = unit.BTC;
61 | $scope.unit.mBTC = unit.mBTC;
62 | $scope.unit.bits = unit.bits;
63 | $scope.unit.satoshis = unit.satoshis;
64 |
65 | if (angular.isString(code)) {
66 | $scope.unit[code] = value;
67 | $scope.unit.fiat = $scope.currency ? unit.atRate($scope.currency.rate) : 0;
68 | }
69 |
70 | setExampleCode(value, code, $scope.currency);
71 | };
72 |
73 | $scope.updateFiat = function(value, rate) {
74 | $scope.updateUnit(value, rate.rate);
75 | };
76 |
77 | $scope.updateUnit(1, 'BTC');
78 |
79 | $http.get('https://bitpay.com/api/rates').
80 | success(function(rates) {
81 | $scope.currencies = rates.filter(function(rate) {
82 | return rate.code === 'USD' ||
83 | rate.code === 'EUR' ||
84 | rate.code === 'ARS' ||
85 | rate.code === 'GBP' ||
86 | rate.code === 'JPY' ||
87 | rate.code === 'CAD' ||
88 | rate.code === 'BRL' ||
89 | rate.code === 'CLP';
90 |
91 | });
92 | $scope.currency = rates[0];
93 | $scope.updateUnit(1, 'BTC');
94 | }).
95 | error(function() {
96 | console.log('Error while fetching exchange rates');
97 | });
98 | });
99 |
--------------------------------------------------------------------------------
/app/unspent/unspent.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
Unspent Transaction Outputs
4 |
5 |
6 |
7 |
8 |
9 |
10 |
Retrieve all the UTXOs associated with a bitcoin address.
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
Outputs for Address: {{currentAddress}}
35 |
36 |
37 |
38 |
39 |
40 |
No unspent transaction outputs found in address.
41 |
42 |
43 |
44 |
45 |
46 |
49 |
{{utxo.satoshis|btc}} BTC
50 |
51 | TX ID:
52 | {{utxo.txId}}
53 |
54 |
55 | OUT #:
56 | {{utxo.outputIndex}}
57 |
58 |
59 | Script:
60 | {{utxo.script.toString()}}
61 |
62 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
--------------------------------------------------------------------------------
/app/unspent/unspent.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | angular.module('playApp.unspent', ['ngRoute'])
4 |
5 | .config(['$routeProvider', function($routeProvider) {
6 | $routeProvider.when('/unspent', {
7 | templateUrl: 'unspent/unspent.html',
8 | controller: 'UnspentCtrl'
9 | });
10 | }])
11 |
12 | .controller('UnspentCtrl', function($scope, $http, bitcore) {
13 |
14 | var explorers = require('bitcore-explorers');
15 |
16 | var defaultLivenetAddress = '1PPQ2anP7DVWmeScdo8fCSTeWCpfBDFAhy';
17 | var defaultTestnetAddress = 'mfnUxBP3JjS4pU1kddzUshF8bcU7wF99mx';
18 | $scope.bitcoreURL = 'http://bitcore.io/guide/module/explorers/index.html';
19 | $scope.bitcoinURL = 'https://bitcoin.org/en/developer-guide#term-output';
20 |
21 | $scope.$on('networkUpdate', function() {
22 | reset();
23 | });
24 |
25 | var reset = function() {
26 | if (bitcore.Networks.defaultNetwork.name === 'testnet') {
27 | $scope.utxoAddress = defaultTestnetAddress;
28 | } else {
29 | $scope.utxoAddress = defaultLivenetAddress;
30 | }
31 | $scope.utxos = [];
32 | $scope.loading = false;
33 | $scope.currentAddress = '';
34 | setExampleCode();
35 | };
36 | reset();
37 |
38 | $scope.addressUpdated = function(address) {
39 | setExampleCode();
40 | };
41 |
42 | $scope.$watch('utxoAddress', function() {
43 | $scope.notFound = '';
44 | });
45 |
46 | $scope.fetchUTXO = function(address) {
47 | var client = new explorers.Insight();
48 |
49 | if (!bitcore.Address.isValid(address)) {
50 | return; // mark as invalid
51 | }
52 |
53 | $scope.loading = true;
54 | $scope.notFound = false;
55 | client.getUnspentUtxos(address, onUTXOs);
56 |
57 | function onUTXOs(err, utxos) {
58 | $scope.loading = false;
59 | if (err) throw err;
60 |
61 | if (!utxos.length) {
62 | $scope.utxos = [];
63 | $scope.notFound = true;
64 | $scope.currentAddress = '';
65 | $scope.$apply();
66 | return;
67 | }
68 |
69 | $scope.currentAddress = address;
70 | $scope.utxos = utxos;
71 | for (var utxo in utxos) {
72 | utxos[utxo].url = client.url + '/tx/' + utxos[utxo].txId;
73 | utxos[utxo].txUrl = 'transaction/';
74 | }
75 | $scope.$apply();
76 | }
77 | };
78 |
79 | function setExampleCode() {
80 | var template = "";
81 | var address = $scope.utxoAddress || '1BitcoinEaterAddressDontSendf59kuE';
82 |
83 | template += "var explorers = require('bitcore-explorers');\n";
84 | template += "var client = new explorers.Insight();\n";
85 | template += "client.getUnspentUtxos('" + address + "', function(err, utxos) {\n";
86 | template += " UTXOs = utxos;\n";
87 | template += " console.log('UTXOs:', utxos);\n";
88 | template += "});";
89 |
90 | $scope.exampleCode = template;
91 | }
92 |
93 | $scope.jumpConsole = function() {
94 | $('#terminaltab').click();
95 | window.REPL.console.SetPromptText($scope.exampleCode);
96 | window.REPL.scrollToBottom();
97 | };
98 |
99 | setExampleCode();
100 |
101 | });
102 |
--------------------------------------------------------------------------------
/bower.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bitcore-playground",
3 | "version": "0.0.2",
4 | "description": "A bitcoin playground powered by bitcore",
5 | "homepage": "https://github.com/bitpay/bitcore-playground",
6 | "authors": [
7 | "Yemel Jardi "
8 | ],
9 | "license": "MIT",
10 | "private": true,
11 | "dependencies": {
12 | "angular": "~1.3.9",
13 | "html5-boilerplate": "~4.3.0",
14 | "angular-route": "~1.3.9",
15 | "foundation": "~5.5.0",
16 | "highlightjs": "~8.4.0",
17 | "lodash": "~3.0.0",
18 | "foundation-icon-fonts": "zurb/foundation-icon-fonts",
19 | "jquery-appear": "~0.2.2",
20 | "bitcore": "~0.10.2",
21 | "bitcore-explorers": "~0.10.0",
22 | "angular-animate": "~1.3.12"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Bitcore Playground
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "bitcore-playground",
3 | "version": "0.0.4",
4 | "description": "A bitcoin playground powered by bitcore",
5 | "repository": "https://github.com/bitpay/bitcore-playground",
6 | "license": "MIT",
7 | "devDependencies": {
8 | "http-server": "^0.6.1"
9 | },
10 | "scripts": {
11 | "start": "http-server -a localhost -p 8000 -c-1"
12 | }
13 | }
14 |
--------------------------------------------------------------------------------