2018-05-16 18:25:05 +02:00
/ * *
* @ author tlwr [ toby @ toby . codes ]
* @ copyright Crown Copyright 2017
* @ license Apache - 2.0
* /
import Operation from "../Operation" ;
import Utils from "../Utils" ;
import OperationError from "../errors/OperationError" ;
import { ALPHABET _OPTIONS } from "../lib/Base58" ;
/ * *
* From Base58 operation
* /
class FromBase58 extends Operation {
/ * *
* FromBase58 constructor
* /
constructor ( ) {
super ( ) ;
this . name = "From Base58" ;
this . module = "Default" ;
this . description = "Base58 (similar to Base64) is a notation for encoding arbitrary byte data. It differs from Base64 by removing easily misread characters (i.e. l, I, 0 and O) to improve human readability.<br><br>This operation decodes data from an ASCII string (with an alphabet of your choosing, presets included) back into its raw form.<br><br>e.g. <code>StV1DL6CwTryKyV</code> becomes <code>hello world</code><br><br>Base58 is commonly used in cryptocurrencies (Bitcoin, Ripple, etc)." ;
2018-08-21 20:07:13 +02:00
this . infoURL = "https://wikipedia.org/wiki/Base58" ;
2018-05-16 18:25:05 +02:00
this . inputType = "string" ;
this . outputType = "byteArray" ;
this . args = [
{
"name" : "Alphabet" ,
"type" : "editableOption" ,
"value" : ALPHABET _OPTIONS
} ,
{
"name" : "Remove non-alphabet chars" ,
"type" : "boolean" ,
"value" : true
}
] ;
2018-05-20 17:49:42 +02:00
this . patterns = [
{
match : "^[1-9A-HJ-NP-Za-km-z]{20,}$" ,
flags : "" ,
args : [ "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz" , false ]
} ,
{
match : "^[1-9A-HJ-NP-Za-km-z]{20,}$" ,
flags : "" ,
args : [ "rpshnaf39wBUDNEGHJKLM4PQRST7VWXYZ2bcdeCg65jkm8oFqi1tuvAxyz" , false ]
} ,
] ;
2018-05-16 18:25:05 +02:00
}
/ * *
* @ param { string } input
* @ param { Object [ ] } args
* @ returns { byteArray }
* /
run ( input , args ) {
let alphabet = args [ 0 ] || ALPHABET _OPTIONS [ 0 ] . value ;
const removeNonAlphaChars = args [ 1 ] === undefined ? true : args [ 1 ] ,
result = [ 0 ] ;
alphabet = Utils . expandAlphRange ( alphabet ) . join ( "" ) ;
if ( alphabet . length !== 58 ||
[ ] . unique . call ( alphabet ) . length !== 58 ) {
throw new OperationError ( "Alphabet must be of length 58" ) ;
}
if ( input . length === 0 ) return [ ] ;
2018-10-22 03:10:49 +02:00
let zeroPrefix = 0 ;
for ( let i = 0 ; i < input . length && input [ i ] === alphabet [ 0 ] ; i ++ ) {
zeroPrefix ++ ;
}
2018-05-16 18:25:05 +02:00
[ ] . forEach . call ( input , function ( c , charIndex ) {
const index = alphabet . indexOf ( c ) ;
if ( index === - 1 ) {
if ( removeNonAlphaChars ) {
return ;
} else {
throw new OperationError ( ` Char ' ${ c } ' at position ${ charIndex } not in alphabet ` ) ;
}
}
let carry = result [ 0 ] * 58 + index ;
result [ 0 ] = carry & 0xFF ;
carry = carry >> 8 ;
for ( let i = 1 ; i < result . length ; i ++ ) {
carry += result [ i ] * 58 ;
result [ i ] = carry & 0xFF ;
carry = carry >> 8 ;
}
while ( carry > 0 ) {
result . push ( carry & 0xFF ) ;
carry = carry >> 8 ;
}
} ) ;
2018-10-22 03:10:49 +02:00
while ( zeroPrefix > 0 ) {
result . push ( 0 ) ;
zeroPrefix -- ;
}
2018-05-16 18:25:05 +02:00
return result . reverse ( ) ;
}
}
export default FromBase58 ;