diff --git a/app.html b/app.html
index 198c4f7..f075cf0 100644
--- a/app.html
+++ b/app.html
@@ -58,6 +58,9 @@
Shamir's Secret Sharing
Scheme
+
+ Encoding/Decoding
+
diff --git a/app.js b/app.js
index d1bc18d..d3c1e9e 100644
--- a/app.js
+++ b/app.js
@@ -34,6 +34,7 @@ function routeConfig($locationProvider, $routeProvider) {
.when('/hd-wallet', {template: '', containerClass: 'container'})
.when('/bitcoin-block', {template: '', containerClass: 'container'})
.when('/shamir-secret-sharing', {template: '', containerClass: 'container'})
+ .when('/encoding-decoding', {template: '', containerClass: 'container'})
.when('/mu-sig', {template: '', containerClass: 'container'})
.when('/schnorr', {template: '', containerClass: 'container'})
.when('/transaction-creator', {template: '', containerClass: 'container'})
diff --git a/index.html b/index.html
index decf9f3..ec504d0 100644
--- a/index.html
+++ b/index.html
@@ -63,6 +63,7 @@
+
diff --git a/libs/templates.js b/libs/templates.js
index f5162ad..6b2cae9 100644
--- a/libs/templates.js
+++ b/libs/templates.js
@@ -62,6 +62,9 @@ angular.module('app').run(['$templateCache', function($templateCache) {
" Shamir's Secret Sharing\n" +
" Scheme\n" +
" \n" +
+ " \n" +
+ " Encoding/Decoding\n" +
+ " \n" +
" \n" +
" \n" +
" \n" +
@@ -145,6 +148,7 @@ angular.module('app').run(['$templateCache', function($templateCache) {
" \n" +
" \n" +
" \n" +
+ " \n" +
" \n" +
" \n" +
" \n" +
@@ -2549,6 +2553,128 @@ angular.module('app').run(['$templateCache', function($templateCache) {
);
+ $templateCache.put('pages/encoding-decoding/encoding-decoding.html',
+ "Encoding/Decoding
\n" +
+ "\n" +
+ "Hex
\n" +
+ "\n" +
+ "\n" +
+ "Base64
\n" +
+ "\n" +
+ "
\n" +
+ "
\n" +
+ "\n" +
+ "Bitcoin Outpoint
\n" +
+ "\n" +
+ "
\n" +
+ "
\n"
+ );
+
+
$templateCache.put('pages/hd-wallet/hd-wallet.html',
"Hierarchical Deterministic Wallet (BIP32/38/39/44/49/84)
\n" +
"\n" +
diff --git a/pages/encoding-decoding/encoding-decoding.html b/pages/encoding-decoding/encoding-decoding.html
new file mode 100644
index 0000000..d6264cd
--- /dev/null
+++ b/pages/encoding-decoding/encoding-decoding.html
@@ -0,0 +1,118 @@
+Encoding/Decoding
+
+Hex
+
+
+Base64
+
+
+Bitcoin Outpoint
+
diff --git a/pages/encoding-decoding/encoding-decoding.js b/pages/encoding-decoding/encoding-decoding.js
new file mode 100644
index 0000000..f6330fe
--- /dev/null
+++ b/pages/encoding-decoding/encoding-decoding.js
@@ -0,0 +1,113 @@
+angular
+ .module('app')
+ .component('encodingDecodingPage', {
+ templateUrl: 'pages/encoding-decoding/encoding-decoding.html',
+ controller: EncodingDecodingPageController,
+ controllerAs: 'vm',
+ bindings: {}
+ });
+
+function EncodingDecodingPageController() {
+ const vm = this;
+ const Buffer = bitcoin.Buffer;
+
+ vm.hexString = '68656c6c6f';
+ vm.hexDecodedString = '';
+ vm.base64String = 'aGVsbG8=';
+ vm.base64DecodedString = '';
+ vm.outpointString = '8f900c6414c5c27231080f46168105e9fec20f9fb2f11b25ee0312d89bc022c0:8';
+ vm.outpointEncodedString = '';
+ vm.error = null;
+ vm.error2 = null;
+
+ vm.$onInit = function () {
+ vm.parseHexString();
+ vm.parseBase64String();
+ vm.parseOutpointString();
+ };
+
+ vm.parseHexString = function () {
+ try {
+ vm.error = null;
+ vm.hexDecodedString = Buffer.from(vm.hexString, 'hex').toString('utf8');
+ } catch (e) {
+ vm.error = e.message;
+ }
+ };
+
+ vm.encodeHexString = function () {
+ try {
+ vm.error2 = null;
+ vm.hexString = Buffer.from(vm.hexDecodedString, 'utf8').toString('hex');
+ } catch (e) {
+ vm.error2 = e.message;
+ }
+ }
+
+ vm.parseBase64String = function () {
+ try {
+ vm.error3 = null;
+ vm.base64DecodedString = Buffer.from(vm.base64String, 'base64').toString('utf8');
+ } catch (e) {
+ vm.error3 = e.message;
+ }
+ };
+
+ vm.encodeBase64String = function () {
+ try {
+ vm.error4 = null;
+ vm.base64String = Buffer.from(vm.base64DecodedString, 'utf8').toString('base64');
+ } catch (e) {
+ vm.error4 = e.message;
+ }
+ }
+
+ vm.parseOutpointString = function () {
+ try {
+ vm.error5 = null;
+
+ const [txid, vout] = vm.outpointString.split(':');
+ if (txid === undefined || vout === undefined) {
+ throw new Error('Invalid outpoint string, must be in form :');
+ }
+
+ const txidBuffer = Buffer.from(txid, 'hex');
+ if (txidBuffer.length !== 32) {
+ throw new Error('Invalid txid, must be 32 bytes');
+ }
+
+ // A TXID is the reverse of the hash of the transaction.
+ txidBuffer.reverse();
+
+ const voutInt = parseInt(vout, 10);
+
+ const resultBuffer = Buffer.alloc(36);
+ txidBuffer.copy(resultBuffer);
+ resultBuffer.writeInt32LE(voutInt, 32);
+
+ vm.outpointEncodedString = resultBuffer.toString('hex');
+ } catch (e) {
+ vm.error5 = e.message;
+ }
+ };
+
+ vm.decodeEncodedOutpoint = function () {
+ try {
+ vm.error6 = null;
+ const parsedBuffer = Buffer.from(vm.outpointEncodedString, 'hex');
+
+ if (parsedBuffer.length !== 36) {
+ throw new Error('Invalid encoded outpoint, must be 36 bytes');
+ }
+
+ const txidBuffer = parsedBuffer.slice(0, 32);
+ txidBuffer.reverse();
+
+ const vout = parsedBuffer.readInt32LE(32);
+
+ vm.outpointString = `${txidBuffer.toString('hex')}:${vout}`;
+ } catch (e) {
+ vm.error6 = e.message;
+ }
+ }
+}