Browse Source

resolved merge commits; hide unnecessary elements

all-modes
pbca26 8 years ago
parent
commit
1ef3850c4e
  1. 4
      react/change.log
  2. 10
      react/src/actions/actionCreators.js
  3. 14
      react/src/actions/actions/copyAddress.js
  4. 86
      react/src/actions/actions/interest.js
  5. 164
      react/src/actions/actions/jumblr.js
  6. 1
      react/src/actions/actions/log.js
  7. 37
      react/src/actions/actions/nativeNewAddress.js
  8. 46
      react/src/actions/actions/nativeSend.js
  9. 31
      react/src/actions/actions/nativeSyncInfo.js
  10. 6
      react/src/actions/actions/settings.js
  11. 1
      react/src/actions/storeType.js
  12. 0
      react/src/assets/images/cryptologo/aud.png
  13. 0
      react/src/assets/images/cryptologo/bet.png
  14. 0
      react/src/assets/images/cryptologo/bgn.png
  15. 0
      react/src/assets/images/cryptologo/bots.png
  16. 0
      react/src/assets/images/cryptologo/brl.png
  17. 0
      react/src/assets/images/cryptologo/cad.png
  18. 0
      react/src/assets/images/cryptologo/ceal.png
  19. 0
      react/src/assets/images/cryptologo/chf.png
  20. 0
      react/src/assets/images/cryptologo/cny.png
  21. BIN
      react/src/assets/images/cryptologo/coqui.png
  22. 0
      react/src/assets/images/cryptologo/crypto.png
  23. 0
      react/src/assets/images/cryptologo/czk.png
  24. 0
      react/src/assets/images/cryptologo/dkk.png
  25. 0
      react/src/assets/images/cryptologo/eur.png
  26. 0
      react/src/assets/images/cryptologo/game.png
  27. 0
      react/src/assets/images/cryptologo/gbp.png
  28. 0
      react/src/assets/images/cryptologo/hkd.png
  29. 0
      react/src/assets/images/cryptologo/hodl.png
  30. 0
      react/src/assets/images/cryptologo/hrk.png
  31. 0
      react/src/assets/images/cryptologo/huf.png
  32. 0
      react/src/assets/images/cryptologo/idr.png
  33. 0
      react/src/assets/images/cryptologo/ils.png
  34. 0
      react/src/assets/images/cryptologo/inr.png
  35. 0
      react/src/assets/images/cryptologo/jpy.png
  36. 0
      react/src/assets/images/cryptologo/jumblr.png
  37. 0
      react/src/assets/images/cryptologo/kmd.png
  38. 0
      react/src/assets/images/cryptologo/krw.png
  39. 0
      react/src/assets/images/cryptologo/kv.png
  40. 0
      react/src/assets/images/cryptologo/mesh.png
  41. 0
      react/src/assets/images/cryptologo/mgw.png
  42. 0
      react/src/assets/images/cryptologo/mvp.png
  43. 0
      react/src/assets/images/cryptologo/mxn.png
  44. 0
      react/src/assets/images/cryptologo/myr.png
  45. 0
      react/src/assets/images/cryptologo/nok.png
  46. 0
      react/src/assets/images/cryptologo/nzd.png
  47. 0
      react/src/assets/images/cryptologo/pangea.png
  48. 0
      react/src/assets/images/cryptologo/php.png
  49. 0
      react/src/assets/images/cryptologo/pln.png
  50. 0
      react/src/assets/images/cryptologo/revs.png
  51. 0
      react/src/assets/images/cryptologo/ron.png
  52. 0
      react/src/assets/images/cryptologo/rub.png
  53. 0
      react/src/assets/images/cryptologo/sek.png
  54. 0
      react/src/assets/images/cryptologo/sgd.png
  55. 0
      react/src/assets/images/cryptologo/shark.png
  56. 0
      react/src/assets/images/cryptologo/supernet.png
  57. 0
      react/src/assets/images/cryptologo/thb.png
  58. 0
      react/src/assets/images/cryptologo/try.png
  59. 0
      react/src/assets/images/cryptologo/wlc.png
  60. 0
      react/src/assets/images/cryptologo/zar.png
  61. 1
      react/src/components/addcoin/addcoinOptionsAC.js
  62. 31
      react/src/components/addcoin/payload.js
  63. 136
      react/src/components/dashboard/claimInterestModal/claimInterestModal.js
  64. 132
      react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js
  65. 7
      react/src/components/dashboard/coinTile/coinTileItem.js
  66. 2
      react/src/components/dashboard/coinTile/coinTileItem.render.js
  67. 2
      react/src/components/dashboard/coindDownModal/coindDownModal.render.js
  68. 387
      react/src/components/dashboard/jumblr/jumblr.js
  69. 543
      react/src/components/dashboard/jumblr/jumblr.render.js
  70. 6
      react/src/components/dashboard/navbar/navbar.js
  71. 4
      react/src/components/dashboard/navbar/navbar.render.js
  72. 16
      react/src/components/dashboard/receiveCoin/receiveCoin.js
  73. 98
      react/src/components/dashboard/receiveCoin/receiveCoin.render.js
  74. 2
      react/src/components/dashboard/walletsBalance/walletsBalance.js
  75. 23
      react/src/components/dashboard/walletsData/pagination.js
  76. 40
      react/src/components/dashboard/walletsData/pagination.render.js
  77. 30
      react/src/components/dashboard/walletsData/walletsData.js
  78. 35
      react/src/components/dashboard/walletsData/walletsData.render.js
  79. 28
      react/src/components/dashboard/walletsInfo/walletsInfo.js
  80. 14
      react/src/components/dashboard/walletsInfo/walletsInfo.render.js
  81. 25
      react/src/components/dashboard/walletsNative/walletsNative.js
  82. 14
      react/src/components/dashboard/walletsNative/walletsNative.render.js
  83. 21
      react/src/components/dashboard/walletsNativeInfo/walletsNativeInfo.js
  84. 11
      react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js
  85. 46
      react/src/components/dashboard/walletsNativeSend/walletsNativeSend.render.js
  86. 6
      react/src/components/dashboard/walletsNav/walletsNav.js
  87. 4
      react/src/components/dashboard/walletsNav/walletsNav.render.js
  88. 2
      react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js
  89. 16
      react/src/components/main/main.js
  90. 245
      react/src/components/overrides.scss
  91. 14
      react/src/reducers/activeCoin.js
  92. 9
      react/src/reducers/dashboard.js
  93. 4
      react/src/translate/en.js
  94. 91
      react/src/util/coinHelper.js
  95. 57
      react/src/util/crypto/gen/array.map.js
  96. 1271
      react/src/util/crypto/gen/biginteger.js
  97. 1974
      react/src/util/crypto/gen/bitcoin.js
  98. 295
      react/src/util/crypto/gen/crypto-scrypt.js
  99. 407
      react/src/util/crypto/gen/cryptojs.aes.js
  100. 410
      react/src/util/crypto/gen/cryptojs.blockmodes.js

4
react/change.log

@ -16,6 +16,10 @@ UI:
- qr code generator / scan
- basilisk send form reset fix
- added native wallet info button
- added coqui assetchain
- jumblr
- zcashparams folder check
- claim interest modal
v0.2.0.21a-beta
--------------

10
react/src/actions/actionCreators.js

@ -27,6 +27,7 @@ import {
DASHBOARD_ACTIVE_COIN_NATIVE_TXHISTORY,
DISPLAY_LOGIN_SETTINGS_MODAL,
DISPLAY_COIND_DOWN_MODAL,
DISPLAY_CLAIM_INTEREST_MODAL,
START_INTERVAL,
STOP_INTERVAL
} from './storeType';
@ -68,6 +69,8 @@ export * from './actions/basiliskTxHistory';
export * from './actions/iguanaHelpers';
export * from './actions/cli';
export * from './actions/update';
export * from './actions/jumblr';
export * from './actions/interest';
export function changeActiveAddress(address) {
return {
@ -367,3 +370,10 @@ export function toggleLoginSettingsModal(display) {
displayLoginSettingsModal: display,
}
}
export function toggleClaimInterestModal(display) {
return {
type: DISPLAY_CLAIM_INTEREST_MODAL,
displayClaimInterestModal: display,
}
}

14
react/src/actions/actions/copyAddress.js

@ -15,3 +15,17 @@ export function copyCoinAddress(address) {
);
}
}
export function copyString(string, message) {
const _result = copyToClipboard(string);
return dispatch => {
dispatch(
triggerToaster(
message,
translate('TOASTR.COIN_NOTIFICATION'),
_result ? 'success' : 'error'
)
);
}
}

86
react/src/actions/actions/interest.js

@ -0,0 +1,86 @@
import {
triggerToaster
} from '../actionCreators';
import {
logGuiHttp,
guiLogState
} from './log';
import Config from '../../config';
export function getListUnspent(coin) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'listunspent',
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'getListUnspent',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}
export function getRawTransaction(coin, txid) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'getrawtransaction',
params: [
txid,
1
],
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'getTransaction',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}

164
react/src/actions/actions/jumblr.js

@ -0,0 +1,164 @@
import {
triggerToaster,
getNewKMDAddresses
} from '../actionCreators';
import {
logGuiHttp,
guiLogState
} from './log';
import Config from '../../config';
function getNewAddress(coin) { // TODO: remove(?)
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'getnewaddress'
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'genJumblrAddress + getKMDAddressesNative',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}
export function setJumblrAddress(coin, type, address) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: type === 'deposit' ? 'jumblr_deposit' : 'jumblr_secret',
params: [address],
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'setJumblrAddress',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json);
});
});
}
function dumpPrivkey(coin, key) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'dumpprivkey',
params: [key],
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'dumpPrivkey ',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}
export function importPrivkey(coin, key) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'importprivkey',
params: [
key,
'',
false
],
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'importPrivkey ',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json.result ? json.result : json);
})
});
}

1
react/src/actions/actions/log.js

@ -41,7 +41,6 @@ export function getAgamaLog(type) {
);
})
.then(response => response.json())
.then()
}
}

37
react/src/actions/actions/nativeNewAddress.js

@ -10,21 +10,7 @@ import {
guiLogState
} from './log';
function handleGetNewKMDAddresses(pubpriv, coin, dispatch, json) {
dispatch(
triggerToaster(
json.result ? json.result : json,
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
'info',
false
)
);
dispatch(getKMDAddressesNative(coin));
return {};
}
export function getNewKMDAddresses(coin, pubpriv) {
export function getNewKMDAddresses(coin, pubpriv, mode) {
let payload;
let ajaxFunctionInput = pubpriv === 'public' ? 'getnewaddress' : 'z_getnewaddress';
@ -115,22 +101,25 @@ export function getNewKMDAddresses(coin, pubpriv) {
}));
}
dispatch(
handleGetNewKMDAddresses(
pubpriv,
coin,
dispatch,
json
triggerToaster(
json.result ? json.result : json,
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
'info',
false
)
);
dispatch(getKMDAddressesNative(coin, mode));
})
.catch(function(ex) {
dispatch(
handleGetNewKMDAddresses(
pubpriv,
coin,
dispatch
triggerToaster(
json.result ? json.result : json,
translate('KMD_NATIVE.NEW_ADDR_GENERATED'),
'info',
false
)
);
dispatch(getKMDAddressesNative(coin, mode));
});
}
}

46
react/src/actions/actions/nativeSend.js

@ -195,7 +195,7 @@ export function getKMDOPID(opid, coin) {
passthruAgent = getPassthruAgent(coin),
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
if (passthruAgent == 'iguana') {
if (passthruAgent === 'iguana') {
payload = {
'userpass': tmpIguanaRPCAuth,
'agent': passthruAgent,
@ -285,3 +285,47 @@ export function getKMDOPID(opid, coin) {
})
}
}
export function sendToAddressPromise(coin, address, amount) {
return new Promise((resolve, reject) => {
const payload = {
mode: null,
chain: coin,
cmd: 'sendtoaddress',
params: [
address,
amount,
'KMD interest claim request',
'KMD interest claim request',
true
]
};
const _fetchConfig = {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ 'payload': payload }),
};
fetch(
`http://127.0.0.1:${Config.agamaPort}/shepherd/cli`,
_fetchConfig
)
.catch(function(error) {
console.log(error);
dispatch(
triggerToaster(
'sendToAddress',
'Error',
'error'
)
);
})
.then(response => response.json())
.then(json => {
resolve(json);
})
});
}

31
react/src/actions/actions/nativeSyncInfo.js

@ -11,9 +11,9 @@ import {
} from './log';
import Config from '../../config';
export function getSyncInfoNativeKMD(skipDebug) {
export function getSyncInfoNativeKMD(skipDebug, json) {
const coin = 'KMD';
// https://www.kmd.host/
return dispatch => {
const _timestamp = Date.now();
if (Config.debug) {
@ -40,13 +40,15 @@ export function getSyncInfoNativeKMD(skipDebug) {
'response': error,
}));
}
dispatch(
/*dispatch(
triggerToaster(
'getSyncInfoNativeKMD',
'Error',
'error'
)
);
);*/
console.warn('remote kmd node fetch failed', true);
dispatch(getSyncInfoNativeState({ 'remoteKMDNode': null }));
})
.then(response => response.json())
.then(json => {
@ -72,7 +74,7 @@ function getSyncInfoNativeState(json, coin, skipDebug) {
json &&
json.error &&
json.error.message.indexOf('Activating best') === -1) {
return getSyncInfoNativeKMD(skipDebug);
return getSyncInfoNativeKMD(skipDebug, json);
} else {
if (json &&
json.error &&
@ -161,6 +163,15 @@ export function getSyncInfoNative(coin, skipDebug) {
return _response;
})
.then(json => {
if (json === 'Work queue depth exceeded') {
dispatch(
getSyncInfoNativeState(
{ result: 'daemon is busy', error: null, id: null },
coin,
skipDebug
)
);
} else {
if (!json &&
Config.cli.default) {
dispatch(
@ -171,7 +182,12 @@ export function getSyncInfoNative(coin, skipDebug) {
true
)
);
if (coin === 'KMD') {
dispatch(getDebugLog('komodo', 50));
} else {
dispatch(getDebugLog('komodo', 50, coin));
}
dispatch(toggleCoindDownModal(true));
} else {
json = JSON.parse(json);
@ -179,7 +195,11 @@ export function getSyncInfoNative(coin, skipDebug) {
if (json.error &&
json.error.message.indexOf('Activating best') === -1) {
if (coin === 'KMD') {
dispatch(getDebugLog('komodo', 1));
} else {
dispatch(getDebugLog('komodo', 1, coin));
}
}
if (Config.debug) {
@ -196,6 +216,7 @@ export function getSyncInfoNative(coin, skipDebug) {
skipDebug
)
);
}
})
}
}

6
react/src/actions/actions/settings.js

@ -167,12 +167,16 @@ function getDebugLogState(json) {
}
}
export function getDebugLog(target, linesCount) {
export function getDebugLog(target, linesCount, acName) {
const payload = {
'herdname': target,
'lastLines': linesCount
};
if (acName) {
payload['ac'] = acName;
}
return dispatch => {
return fetch(`http://127.0.0.1:${Config.agamaPort}/shepherd/debuglog`, {
method: 'POST',

1
react/src/actions/storeType.js

@ -46,3 +46,4 @@ export const CLI = 'CLI';
export const LOGOUT = 'LOGOUT';
export const DISPLAY_COIND_DOWN_MODAL = 'DISPLAY_COIND_DOWN_MODAL';
export const DISPLAY_LOGIN_SETTINGS_MODAL = 'DISPLAY_LOGIN_SETTINGS_MODAL';
export const DISPLAY_CLAIM_INTEREST_MODAL = 'DISPLAY_CLAIM_INTEREST_MODAL';

0
react/src/assets/images/cryptologo/AUD.png → react/src/assets/images/cryptologo/aud.png

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
react/src/assets/images/cryptologo/BET.png → react/src/assets/images/cryptologo/bet.png

Before

Width:  |  Height:  |  Size: 3.4 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

0
react/src/assets/images/cryptologo/BGN.png → react/src/assets/images/cryptologo/bgn.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/BOTS.png → react/src/assets/images/cryptologo/bots.png

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
react/src/assets/images/cryptologo/BRL.png → react/src/assets/images/cryptologo/brl.png

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
react/src/assets/images/cryptologo/CAD.png → react/src/assets/images/cryptologo/cad.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/CEAL.png → react/src/assets/images/cryptologo/ceal.png

Before

Width:  |  Height:  |  Size: 4.3 KiB

After

Width:  |  Height:  |  Size: 4.3 KiB

0
react/src/assets/images/cryptologo/CHF.png → react/src/assets/images/cryptologo/chf.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/CNY.png → react/src/assets/images/cryptologo/cny.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

BIN
react/src/assets/images/cryptologo/coqui.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.6 KiB

0
react/src/assets/images/cryptologo/CRYPTO.png → react/src/assets/images/cryptologo/crypto.png

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
react/src/assets/images/cryptologo/CZK.png → react/src/assets/images/cryptologo/czk.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/DKK.png → react/src/assets/images/cryptologo/dkk.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/EUR.png → react/src/assets/images/cryptologo/eur.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/GAME.png → react/src/assets/images/cryptologo/game.png

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

0
react/src/assets/images/cryptologo/GBP.png → react/src/assets/images/cryptologo/gbp.png

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

0
react/src/assets/images/cryptologo/HKD.png → react/src/assets/images/cryptologo/hkd.png

Before

Width:  |  Height:  |  Size: 8.9 KiB

After

Width:  |  Height:  |  Size: 8.9 KiB

0
react/src/assets/images/cryptologo/HODL.png → react/src/assets/images/cryptologo/hodl.png

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

0
react/src/assets/images/cryptologo/HRK.png → react/src/assets/images/cryptologo/hrk.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/HUF.png → react/src/assets/images/cryptologo/huf.png

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

0
react/src/assets/images/cryptologo/IDR.png → react/src/assets/images/cryptologo/idr.png

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

0
react/src/assets/images/cryptologo/ILS.png → react/src/assets/images/cryptologo/ils.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/INR.png → react/src/assets/images/cryptologo/inr.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/JPY.png → react/src/assets/images/cryptologo/jpy.png

Before

Width:  |  Height:  |  Size: 9.0 KiB

After

Width:  |  Height:  |  Size: 9.0 KiB

0
react/src/assets/images/cryptologo/JUMBLR.png → react/src/assets/images/cryptologo/jumblr.png

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

0
react/src/assets/images/cryptologo/komodo.png → react/src/assets/images/cryptologo/kmd.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/KRW.png → react/src/assets/images/cryptologo/krw.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/KV.png → react/src/assets/images/cryptologo/kv.png

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
react/src/assets/images/cryptologo/MESH.png → react/src/assets/images/cryptologo/mesh.png

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 8.5 KiB

0
react/src/assets/images/cryptologo/MGW.png → react/src/assets/images/cryptologo/mgw.png

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
react/src/assets/images/cryptologo/MVP.png → react/src/assets/images/cryptologo/mvp.png

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

0
react/src/assets/images/cryptologo/MXN.png → react/src/assets/images/cryptologo/mxn.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/MYR.png → react/src/assets/images/cryptologo/myr.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/NOK.png → react/src/assets/images/cryptologo/nok.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/NZD.png → react/src/assets/images/cryptologo/nzd.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/PANGEA.png → react/src/assets/images/cryptologo/pangea.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/PHP.png → react/src/assets/images/cryptologo/php.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

0
react/src/assets/images/cryptologo/PLN.png → react/src/assets/images/cryptologo/pln.png

Before

Width:  |  Height:  |  Size: 9.9 KiB

After

Width:  |  Height:  |  Size: 9.9 KiB

0
react/src/assets/images/cryptologo/REVS.png → react/src/assets/images/cryptologo/revs.png

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 3.8 KiB

0
react/src/assets/images/cryptologo/RON.png → react/src/assets/images/cryptologo/ron.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/RUB.png → react/src/assets/images/cryptologo/rub.png

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

0
react/src/assets/images/cryptologo/SEK.png → react/src/assets/images/cryptologo/sek.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/SGD.png → react/src/assets/images/cryptologo/sgd.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/SHARK.png → react/src/assets/images/cryptologo/shark.png

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

0
react/src/assets/images/cryptologo/SUPERNET.png → react/src/assets/images/cryptologo/supernet.png

Before

Width:  |  Height:  |  Size: 3.6 KiB

After

Width:  |  Height:  |  Size: 3.6 KiB

0
react/src/assets/images/cryptologo/THB.png → react/src/assets/images/cryptologo/thb.png

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

0
react/src/assets/images/cryptologo/TRY.png → react/src/assets/images/cryptologo/try.png

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 12 KiB

0
react/src/assets/images/cryptologo/WLC.png → react/src/assets/images/cryptologo/wlc.png

Before

Width:  |  Height:  |  Size: 16 KiB

After

Width:  |  Height:  |  Size: 16 KiB

0
react/src/assets/images/cryptologo/ZAR.png → react/src/assets/images/cryptologo/zar.png

Before

Width:  |  Height:  |  Size: 13 KiB

After

Width:  |  Height:  |  Size: 13 KiB

1
react/src/components/addcoin/addcoinOptionsAC.js

@ -8,6 +8,7 @@ class AddCoinOptionsAC extends React.Component {
<option value="BET|basilisk|native">BET (BET)</option>
<option value="BOTS|basilisk|native">BOTS (BOTS)</option>
<option value="CEAL|basilisk|native">CEAL NET (CEAL)</option>
<option value="COQUI|basilisk|native">COQUI (COQUI)</option>
<option value="CRYPTO|basilisk|native">CRYPTO (CRYPTO)</option>
<option value="HOD|basilisk|native">HODL (HODL)</option>
<option value="DEX|basilisk|native">InstantDEX (DEX)</option>

31
react/src/components/addcoin/payload.js

@ -1,4 +1,5 @@
// TODO: merge check functions
// move to nodejs
export function checkAC(coinVal) {
if (coinVal === 'SUPERNET' ||
@ -9,6 +10,7 @@ export function checkAC(coinVal) {
coinVal === 'JUMBLR' ||
coinVal === 'BET' ||
coinVal === 'CRYPTO' ||
coinVal === 'COQUI' ||
coinVal === 'HODL' ||
coinVal === 'SHARK' ||
coinVal === 'BOTS' ||
@ -98,6 +100,7 @@ export function checkCoinType(coin) {
coin === 'JUMBLR' ||
coin === 'BET' ||
coin === 'CRYPTO' ||
coin === 'COQUI' ||
coin === 'HODL' ||
coin === 'SHARK' ||
coin === 'BOTS' ||
@ -131,10 +134,10 @@ export function checkCoinType(coin) {
}
export function startCrypto(confpath, coin, mode) {
let tmpinternval = 0,
AddCoinData = {},
tmpPendValue = 1, // TODO: hook up to shepherd sysinfo
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let tmpinternval = 0;
let AddCoinData = {};
let tmpPendValue = 1; // TODO: hook up to shepherd sysinfo
let tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
if (coin !== 'BTC' &&
coin !== 'LTC' &&
@ -176,9 +179,9 @@ export function startCrypto(confpath, coin, mode) {
}
export function startCurrencyAssetChain(confpath, coin, mode) {
let AddCoinDataPayload = {},
tmpPendValue = 1,
tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
let AddCoinDataPayload = {};
let tmpPendValue = 1;
let tmpIguanaRPCAuth = `tmpIgRPCUser@${sessionStorage.getItem('IguanaRPCAuth')}`;
if (coin !== 'BTC' &&
coin !== 'LTC' &&
@ -702,7 +705,7 @@ export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
},
'DEX': {
'name': 'DEX',
'supply': 1300000,
'supply': 999999,
'AddCoinData': confpath ? Object.assign({}, _acPayloadOrigin, {"coin":"DEX","conf":"DEX.conf","path":confpath,"RELAY":-1,"VALIDATE":1,"startpend":4,"endpend":4,"maxpeers":8,"newcoin":"DEX","name":"DEX","netmagic":"f2ae0516","p2p":9502,"rpc":9503}) : {},
'AddCoinDataVar': Object.assign({}, _acPayloadOrigin, {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"maxpeers":8,"newcoin":"DEX","name":"DEX","netmagic":"f2ae0516","p2p":9502,"rpc":9503})
},
@ -726,7 +729,7 @@ export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
},
'HODL': {
'name': 'HODL',
'supply': 999999,
'supply': 9999999,
'AddCoinData': confpath ? Object.assign({}, _acPayloadOrigin, {"coin":"HODL","conf":"HODL.conf","path":confpath,"RELAY":-1,"VALIDATE":1,"startpend":4,"endpend":4,"maxpeers":8,"newcoin":"HODL","name":"HODL","netmagic":"9b13fb5f","p2p":8009,"rpc":8010}) : {},
'AddCoinDataVar': Object.assign({}, _acPayloadOrigin, {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"maxpeers":8,"newcoin":"HODL","name":"HODL","netmagic":"9b13fb5f","p2p":8009,"rpc":8010})
},
@ -756,7 +759,7 @@ export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
},
'KV': {
'name': 'KV',
'supply': 999999,
'supply': 1000000,
'AddCoinData': confpath ? Object.assign({}, _acPayloadOrigin, {"coin":"KV","conf":"KV.conf","path":confpath,"RELAY":-1,"VALIDATE":1,"startpend":4,"endpend":4,"maxpeers":8,"newcoin":"KV","name":"KV","netmagic":"b09a2d65","p2p":9746,"rpc":9747}) : {},
'AddCoinDataVar': Object.assign(_acPayloadOrigin, {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"maxpeers":8,"newcoin":"KV","name":"KV","netmagic":"b09a2d65","p2p":9746,"rpc":9747})
},
@ -768,9 +771,15 @@ export function startAssetChain(confpath, coin, mode, getSuppyOnly) {
},
'MESH': {
'name': 'MESH',
'supply': 1000000,
'supply': 1000007,
'AddCoinData': confpath ? Object.assign({}, _acPayloadOrigin, {"coin":"MESH","conf":"MESH.conf","path":confpath,"RELAY":-1,"VALIDATE":1,"startpend":4,"endpend":4,"maxpeers":8,"newcoin":"MESH","name":"MESH","netmagic":"f0265c67","p2p":8399,"rpc":8400}) : {},
'AddCoinDataVar': Object.assign({}, _acPayloadOrigin, {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"maxpeers":8,"newcoin":"MESH","name":"MESH","netmagic":"f0265c67","p2p":8399,"rpc":8400})
},
'COQUI': {
'name': 'COQUI',
'supply': 72000000,
'AddCoinData': confpath ? Object.assign({}, _acPayloadOrigin, {"coin":"COQUI","conf":"COQUI.conf","path":confpath,"RELAY":-1,"VALIDATE":1,"startpend":4,"endpend":4,"maxpeers":8,"newcoin":"COQUI","name":"COQUI","netmagic":"4cbd5ef4","p2p":14275,"rpc":14276}) : {},
'AddCoinDataVar': Object.assign({}, _acPayloadOrigin, {'userpass':tmpIguanaRPCAuth,"RELAY":mode,"VALIDATE":mode,"startpend":tmpPendValue,"endpend":tmpPendValue,"maxpeers":8,"newcoin":"COQUI","name":"COQUI","netmagic":"4cbd5ef4","p2p":14275,"rpc":14276})
}
};

136
react/src/components/dashboard/claimInterestModal/claimInterestModal.js

@ -0,0 +1,136 @@
import React from 'react';
import ReactDOM from 'react-dom';
import Store from '../../../store';
import {
toggleClaimInterestModal,
getListUnspent,
getRawTransaction,
copyString,
sendToAddressPromise,
triggerToaster
} from '../../../actions/actionCreators';
import { translate } from '../../../translate/translate';
import {
ClaimInterestModalRender,
_ClaimInterestTableRender
} from './claimInterestModal.render';
class ClaimInterestModal extends React.Component {
constructor(props) {
super(props);
this.state = {
open: false,
isLoading: true,
transactionsList: [],
showZeroInterest: true,
};
this.claimInterestTableRender = this.claimInterestTableRender.bind(this);
this.toggleZeroInterest = this.toggleZeroInterest.bind(this);
this.loadListUnspent = this.loadListUnspent.bind(this);
this.checkTransactionsListLength = this.checkTransactionsListLength.bind(this);
}
componentWillMount() {
this.loadListUnspent();
}
loadListUnspent() {
let _transactionsList = [];
getListUnspent(this.props.ActiveCoin.coin)
.then((json) => {
if (json &&
json.length) {
for (let i = 0; i < json.length; i++) {
getRawTransaction(this.props.ActiveCoin.coin, json[i].txid)
.then((_json) => {
_transactionsList.push({
address: json[i].address,
locktime: _json.locktime,
amount: json[i].amount,
interest: json[i].interest,
txid: json[i].txid,
});
if (i === json.length - 1) {
this.setState({
transactionsList: _transactionsList,
isLoading: false,
});
}
});
}
}
});
}
claimInterest(address, amount) {
sendToAddressPromise(this.props.ActiveCoin.coin, this.state.transactionsList[0].address, this.props.ActiveCoin.balance.transparent)
.then((json) => {
if (json.error &&
json.error.code) {
Store.dispatch(
triggerToaster(
json.error.message,
'Error',
'error'
)
);
} else if (json.result && json.result.length && json.result.length === 64) {
Store.dispatch(
triggerToaster(
`Your full balance is sent to address ${this.state.transactionsList[0].address}. Check back your new balance in a few minutes.`,
translate('TOASTR.WALLET_NOTIFICATION'),
'success',
false
)
);
}
});
}
checkTransactionsListLength() {
if (this.state.transactionsList && this.state.transactionsList.length) {
return true;
} else if (!this.state.transactionsList || !this.state.transactionsList.length) {
return false;
}
}
toggleZeroInterest() {
this.setState({
showZeroInterest: !this.state.showZeroInterest,
});
}
copyTxId(txid) {
Store.dispatch(copyString(txid, 'Transaction ID copied'));
}
claimInterestTableRender() {
return _ClaimInterestTableRender.call(this);
}
componentWillReceiveProps(props) {
if (props.Dashboard.displayClaimInterestModal !== this.state.open) {
this.setState({
open: props.Dashboard.displayClaimInterestModal,
});
}
if (!this.state.open &&
props.Dashboard.displayClaimInterestModal) {
this.loadListUnspent();
}
}
closeModal() {
Store.dispatch(toggleClaimInterestModal(false));
}
render() {
return ClaimInterestModalRender.call(this);
}
}
export default ClaimInterestModal;

132
react/src/components/dashboard/claimInterestModal/claimInterestModal.render.js

@ -0,0 +1,132 @@
import React from 'react';
import { translate } from '../../../translate/translate';
const MIN_INTEREST_THRESHOLD = 0.001;
export const _ClaimInterestTableRender = function() {
const _transactionsList = this.state.transactionsList;
let _items = [];
for (let i = 0; i < _transactionsList.length; i++) {
if ((_transactionsList[i].interest === 0 && this.state.showZeroInterest) || (_transactionsList[i].amount > 0 && _transactionsList[i].interest > 0)) {
_items.push(
<tr key={ `${_transactionsList[i].txid}${_transactionsList[i].address}` }>
<td>
<button
className="btn btn-default btn-xs clipboard-edexaddr copy-string-btn"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this.copyTxId(_transactionsList[i].txid) }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
</td>
<td>{ _transactionsList[i].address }</td>
<td className={ _transactionsList[i].amount > 10 ? 'green bold' : '' }>{ _transactionsList[i].amount }</td>
<td>{ _transactionsList[i].interest }</td>
<td className="locktime center">
{ _transactionsList[i].locktime &&
<i className="fa-check-circle green"></i>
}
{ !_transactionsList[i].locktime &&
<i className="fa-exclamation-circle red"></i>
}
</td>
</tr>
);
}
}
return (
<span>
<div className="padding-bottom-20">
<strong>Requirements to accrue interest:</strong> locktime field is set and amount is greater than <strong>10 KMD</strong>
</div>
<div className="text-left padding-top-10 padding-bottom-10">
<label className="switch">
<input
type="checkbox"
checked={ this.state.showZeroInterest } />
<div
className="slider"
onClick={ this.toggleZeroInterest }></div>
</label>
<div
className="toggle-label margin-right-15 pointer"
onClick={ this.toggleZeroInterest }>
Show zero interest
</div>
</div>
<button
type="button"
className="btn btn-success waves-effect waves-light claim-btn"
onClick={ () => this.claimInterest() }>
<i className="icon fa-dollar"></i> Claim interest
</button>
<div className="table-scroll">
<table className="table table-hover dataTable table-striped">
<thead>
<tr>
<th></th>
<th>Address</th>
<th>Amount</th>
<th>Interest</th>
<th>Locktime</th>
</tr>
</thead>
<tbody>
{ _items }
</tbody>
<tfoot>
<tr>
<th></th>
<th>Address</th>
<th>Amount</th>
<th>Interest</th>
<th>Locktime</th>
</tr>
</tfoot>
</table>
</div>
</span>
);
};
export const ClaimInterestModalRender = function() {
return (
<span>
<div className={ 'modal modal-claim-interest modal-3d-sign ' + (this.state.open ? 'show in' : 'fade hide') }>
<div className="modal-dialog modal-center modal-sm">
<div className="modal-content">
<div className="modal-header bg-orange-a400 wallet-send-header">
<button
type="button"
className="close white"
onClick={ this.closeModal }>
<span>×</span>
</button>
<h4 className="modal-title white text-left">Claim interest</h4>
</div>
<div className="modal-body">
<i
className="icon fa-refresh pointer refresh-icon"
onClick={ this.loadListUnspent }></i>
<div className="animsition vertical-align fade-in">
<div className="page-content vertical-align-middle full-width">
{ this.state.isLoading &&
<span>Loading interest data...</span>
}
{ !this.state.isLoading && this.checkTransactionsListLength() &&
<div>{ this.claimInterestTableRender() }</div>
}
{ !this.state.isLoading && !this.checkTransactionsListLength() &&
<div>No data</div>
}
</div>
</div>
</div>
</div>
</div>
</div>
<div className={ 'modal-backdrop ' + (this.state.open ? 'show in' : 'fade hide') }></div>
</span>
);
};

7
react/src/components/dashboard/coinTile/coinTileItem.js

@ -111,6 +111,11 @@ class CoinTileItem extends React.Component {
setTimeout(() => {
this.dispatchCoinActions(coin, mode);
}, 100);
if (mode === 'native') { // faster coin data load if fully synced
setTimeout(() => {
this.dispatchCoinActions(coin, mode);
}, 1000);
}
Store.dispatch(
stopInterval(
@ -141,7 +146,7 @@ class CoinTileItem extends React.Component {
if (mode === 'native') {
const _iguanaActiveHandle = setInterval(() => {
this.dispatchCoinActions(coin, mode);
}, coin === 'KMD' ? IGUNA_ACTIVE_HANDLE_TIMEOUT_KMD_NATIVE : IGUNA_ACTIVE_HANDLE_TIMEOUT);
}, IGUNA_ACTIVE_HANDLE_TIMEOUT_KMD_NATIVE);
Store.dispatch(startInterval('sync', _iguanaActiveHandle));
}

2
react/src/components/dashboard/coinTile/coinTileItem.render.js

@ -12,7 +12,7 @@ const CoinTileItemRender = function() {
<a className="avatar margin-bottom-5">
<img
className="img-responsive"
src={ `assets/images/cryptologo/${item.coinlogo}.png` }
src={ `assets/images/cryptologo/${item.coinlogo.toLowerCase()}.png` }
alt={ item.coinname }/>
<span className={ `badge up badge-${item.modecolor}` }>
{ item.modecode }

2
react/src/components/dashboard/coindDownModal/coindDownModal.render.js

@ -16,7 +16,7 @@ const CoindDownModalRender = function () {
onClick={ this.dismiss }>
<span>×</span>
</button>
<h4 className="modal-title white">Komodod is down!</h4>
<h4 className="modal-title white">{ this.props.ActiveCoin.coin === 'KMD' ? 'Komodod' : `Komodod / ${this.props.ActiveCoin.coin}` } is down!</h4>
</div>
<div className="modal-body">
<div className="vertical-align text-center">

387
react/src/components/dashboard/jumblr/jumblr.js

@ -1,14 +1,391 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import {
dashboardChangeActiveCoin,
getKMDAddressesNative,
startInterval,
stopInterval,
triggerToaster,
setJumblrAddress,
importPrivkey,
copyCoinAddress,
copyString
} from '../../../actions/actionCreators';
import Store from '../../../store';
import Config from '../../../config';
import {
JumblrRender,
JumblrRenderSecretAddressList
} from './jumblr.render';
import { PassPhraseGenerator } from '../../../util/crypto/passphrasegenerator';
import JumblrRender from './jumblr.render';
// import gen komodo keys utils
import '../../../util/crypto/gen/array.map.js';
import '../../../util/crypto/gen/cryptojs.js';
import '../../../util/crypto/gen/cryptojs.sha256.js';
import '../../../util/crypto/gen/cryptojs.pbkdf2.js';
import '../../../util/crypto/gen/cryptojs.hmac.js';
import '../../../util/crypto/gen/cryptojs.aes.js';
import '../../../util/crypto/gen/cryptojs.blockmodes.js';
import '../../../util/crypto/gen/cryptojs.ripemd160.js';
import '../../../util/crypto/gen/securerandom.js';
import '../../../util/crypto/gen/ellipticcurve.js';
import '../../../util/crypto/gen/biginteger.js';
import '../../../util/crypto/gen/crypto-scrypt.js';
import { Bitcoin } from '../../../util/crypto/gen/bitcoin.js';
if (!window.jumblrPasshrase) { // gen jumblr passphrase
window.jumblrPasshrase = 'jumblr ' + PassPhraseGenerator.generatePassPhrase(256);
}
class Jumblr extends React.Component {
constructor(props) {
super(props);
this.state = {
activeTab: 0,
randomSeed: window.jumblrPasshrase,
jumblrDepositAddress: null,
jumblrDepositAddressPBased: true,
jumblrSecretAddressShow: true,
jumblrSecretAddress: [],
jumblrSecretAddressImport: [],
jumblrSecretAddressCountImport: 0,
jumblrSecretAddressShowImport: true,
jumblrSecretAddressCount: 0,
jumblrMode: 'public',
secretAddressCount: 1,
secretAddressCountImport: 1,
jumblrPassphraseImport: '',
};
this.generateJumblrDepositAddress = this.generateJumblrDepositAddress.bind(this);
this.generateJumblrSecretAddress = this.generateJumblrSecretAddress.bind(this);
this.checkJumblrSecretAddressListLength = this.checkJumblrSecretAddressListLength.bind(this);
this.returnPassphrase = this.returnPassphrase.bind(this);
this.generateKeys = this.generateKeys.bind(this);
this._copyCoinAddress = this._copyCoinAddress.bind(this);
this.copyPassphrase = this.copyPassphrase.bind(this);
this.checkPassphraseValid = this.checkPassphraseValid.bind(this);
this.importJumblrSecretAddress = this.importJumblrSecretAddress.bind(this);
this.onChange = this.onChange.bind(this);
}
generateKeys(passphrase) {
if (!passphrase) {
const key = new Bitcoin.ECKey(false).setCompressed(true);
const kmdAddress = key.getBitcoinAddress();
const wifAddress = key.getBitcoinWalletImportFormat();
return {
address: kmdAddress,
wif: wifAddress,
};
} else {
const bytes = Crypto.SHA256(passphrase, { asBytes: true });
const btcKey = new Bitcoin.ECKey(bytes).setCompressed(true);
const kmdAddress = btcKey.getBitcoinAddress();
const wifAddress = btcKey.getBitcoinWalletImportFormat();
return {
address: kmdAddress,
wif: wifAddress,
};
}
}
_JumblrRenderSecretAddressList(type) {
return JumblrRenderSecretAddressList.call(this, type);
}
onChange(e) {
const regex = /^[0-9\b]+$/;
if (e.target.value === '' ||
regex.test(e.target.value)) {
this.setState({
[e.target.name]: e.target.value,
});
}
}
passphraseOnChange(e) {
this.setState({
[e.target.name]: e.target.value,
});
}
returnPassphrase() {
this.setState({
randomSeed: window.jumblrPasshrase,
});
}
toggle(prop) {
const _prop = this.state[prop];
this.setState({
[prop]: !_prop,
});
}
/*toggleAddressGenMod() {
this.setState({
jumblrDepositAddressPBased: !this.state.jumblrDepositAddressPBased,
});
}*/
generateJumblrSecretAddress() {
let _jumblrSecretAddress = [];
let _apiSuccessCount = 0;
if (this.state.secretAddressCount === '') {
Store.dispatch(
triggerToaster(
'Enter a correct address count value',
'Jumblr',
'error'
)
);
} else {
for (let i = 0; i < this.state.secretAddressCount; i++) {
let _genKeys;
if (this.state.jumblrDepositAddressPBased) {
let _postfix;
if (i < 9) {
_postfix = `00${i + 1}`;
} else if (i > 10 && i < 100) {
_postfix = `0${i + 1}`;
}
_genKeys = this.generateKeys(`${this.state.randomSeed} ${_postfix}`);
// console.warn(`${this.state.randomSeed} ${_postfix}`);
} else {
_genKeys = this.generateKeys();
}
setJumblrAddress(this.props.ActiveCoin.coin, 'secret', _genKeys.address)
.then((json) => {
if (json.error &&
json.error.code) {
Store.dispatch(
triggerToaster(
json.error.message,
'Error',
'error'
)
);
} else if (json.result && json.result.result && json.result.result === 'success') {
_jumblrSecretAddress.push(_genKeys);
this.setState(Object.assign({}, this.state, {
jumblrSecretAddress: _jumblrSecretAddress,
}));
if (_apiSuccessCount === this.state.secretAddressCount - 1) {
Store.dispatch(
triggerToaster(
this.state.secretAddressCount > 1 ? 'Jumblr secret addresses are set' : 'Jumblr secret address is set',
'Jumblr',
'success'
)
);
}
_apiSuccessCount++;
}
});
}
}
}
checkPassphraseValid() { // test passphrase validity
const _passphrase = this.state.jumblrPassphraseImport;
const _jumblrPrefix = _passphrase.substring(0, 6);
const _passphraseWords = _passphrase.substring(6, _passphrase.length);
let _errors = {
prefix: false, // jumblr
length: false, // 24
};
if (_jumblrPrefix !== 'jumblr') {
_errors.prefix = true;
}
try {
const _passphraseWordsSplit = _passphraseWords.split(' ');
let _correctWords = 0;
if (_passphraseWordsSplit &&
_passphraseWordsSplit.length) {
for (let i = 0; i < _passphraseWordsSplit.length; i++) {
if (_passphraseWordsSplit[i].length > 2) {
_correctWords++;
}
}
if (_correctWords !== _passphraseWordsSplit.length - 1 || _correctWords !== 24) {
_errors.length = true;
}
} else {
_errors.length = true;
}
} catch(e) {
_errors.length = true;
}
if (_errors.length ||
_errors.prefix) {
Store.dispatch(
triggerToaster(
'Provided passphrase has wrong format',
'Jumblr',
'error',
false
)
);
return false;
}
return true;
}
importJumblrSecretAddress() {
let _jumblrSecretAddress = [];
let _apiSuccessCount = 0;
if (this.state.secretAddressCountImport === '') {
Store.dispatch(
triggerToaster(
'Enter a correct address count value',
'Jumblr',
'error'
)
);
} else {
if (this.checkPassphraseValid()) {
for (let i = 0; i < this.state.secretAddressCountImport; i++) {
let _genKeys;
if (this.state.jumblrDepositAddressPBased) {
let _postfix;
if (i < 9) {
_postfix = `00${i + 1}`;
} else if (i > 10 && i < 100) {
_postfix = `0${i + 1}`;
}
_genKeys = this.generateKeys(`${this.state.jumblrPassphraseImport} ${_postfix}`);
} else {
_genKeys = this.generateKeys();
}
importPrivkey(this.props.ActiveCoin.coin, _genKeys.wif)
.then((json) => {
if (!json.id && !json.result && !json.error) {
_jumblrSecretAddress.push(_genKeys);
this.setState(Object.assign({}, this.state, {
jumblrSecretAddressImport: _jumblrSecretAddress,
}));
if (_apiSuccessCount === this.state.secretAddressCountImport - 1) {
Store.dispatch(
triggerToaster(
this.state.secretAddressCountImport > 1 ? 'Jumblr secret addresses imported' : 'Jumblr secret address imported',
'Jumblr',
'success'
)
);
}
_apiSuccessCount++;
} else {
Store.dispatch(
triggerToaster(
json.error.message,
'Error',
'error'
)
);
}
});
}
}
}
}
checkJumblrSecretAddressListLength(type) {
if (type === 'gen') {
if (this.state.jumblrSecretAddress &&
this.state.jumblrSecretAddress.length) {
return true;
} else {
return false;
}
} else {
if (this.state.jumblrSecretAddressImport &&
this.state.jumblrSecretAddressImport.length) {
return true;
} else {
return false;
}
}
}
generateJumblrDepositAddress() {
let _genKeys;
if (this.state.jumblrDepositAddressPBased) {
_genKeys = this.generateKeys(this.state.randomSeed);
} else {
_genKeys = this.generateKeys();
}
importPrivkey(this.props.ActiveCoin.coin, _genKeys.wif)
.then((json) => {
if (!json.id && !json.result && !json.error) {
// console.warn('importPrivkey', json);
setJumblrAddress(this.props.ActiveCoin.coin, 'deposit', _genKeys.address)
.then((json) => {
if (json.error &&
json.error.code) {
Store.dispatch(
triggerToaster(
json.error.message,
'Error',
'error'
)
);
} else if (json.result && json.result.result === 0) {
this.setState(Object.assign({}, this.state, {
jumblrDepositAddress: {
address: _genKeys.address,
wif: _genKeys.wif,
},
}));
Store.dispatch(
triggerToaster(
'Jumblr deposit address is set',
'Jumblr',
'success'
)
);
}
});
} else {
Store.dispatch(
triggerToaster(
json.error.message,
'Error',
'error'
)
);
}
});
}
switchJumblrMode(mode) {
this.setState(Object.assign({}, this.state, {
jumblrMode: mode,
activeTab: 0,
}));
}
openTab(tab) {
@ -17,6 +394,14 @@ class Jumblr extends React.Component {
}));
}
_copyCoinAddress(address) {
Store.dispatch(copyCoinAddress(address));
}
copyPassphrase() {
Store.dispatch(copyString(this.state.randomSeed, 'Passphrase copied'));
}
renderLB(_translationID) {
const _translationComponents = translate(_translationID).split('<br>');

543
react/src/components/dashboard/jumblr/jumblr.render.js

@ -2,10 +2,52 @@ import React from 'react';
import { translate } from '../../../translate/translate';
import WalletsHeader from '../walletsHeader/walletsHeader';
import WalletsNativeSend from '../walletsNativeSend/walletsNativeSend';
import ReceiveCoin from '../receiveCoin/receiveCoin';
const JumblrRender = function() {
export const JumblrRenderSecretAddressList = function(type) {
const _jumblrAddressList = type === 'gen' ? this.state.jumblrSecretAddress : this.state.jumblrSecretAddressImport;
let _items = [];
if (_jumblrAddressList &&
_jumblrAddressList.length) {
for (let i = 0; i < _jumblrAddressList.length; i++) {
_items.push(
<tr key={ `jumblr-secret-address-${i}` }>
<td>{ _jumblrAddressList[i].address }</td>
<td>{ _jumblrAddressList[i].wif }</td>
</tr>
);
}
return _items;
} else {
return null;
}
};
/* passphrase toggle
<div className={ 'toggle-box padding-top-20 padding-bottom-' + (this.state.jumblrDepositAddressPBased ? '10' : '30') }>
<span className="pointer">
<label className="switch">
<input
type="checkbox"
checked={ this.state.jumblrDepositAddressPBased } />
<div
className="slider"
onClick={ () => this.toggleAddressGenMod() }></div>
</label>
<div
className="toggle-label"
onClick={ () => this.toggleAddressGenMod() }>
Passphrase based address
</div>
</span>
</div>
*/
export const JumblrRender = function() {
return (
<div className="page margin-left-0">
<div className="page margin-left-0 jumblr">
<WalletsHeader activeSection="jumblr" />
<div className="page-content margin-top-30">
<div className="row">
@ -32,87 +74,135 @@ const JumblrRender = function() {
<span>×</span>
</button>
<span className="jumblr-header">
<i className="icon fa-paw"></i> { translate('JUMBLR.NEED_NATIVE') }
<i className="icon fa-paw"></i> About Jumblr
</span>
<br />
{ translate('JUMBLR.TO_USE_JUMBLR') }
<br />
{ translate('JUMBLR.IF_YOU_ALREADY_RUNNING') }
<p>
Jumblr functions all locally which means no middle man is required to jumble your funds. You take control over the whole process.
</p>
<p>
<strong>Tip:</strong> to achive maximum anonimity setup Jumblr node on a dedicated piece of hardware (laptop or VPS), use a separate IP address for main Jumblr node.
</p>
</div>
</div>
<div className="col-xlg-12 col-md-12">
<p>{ translate('JUMBLR.THIS_SCREEN_DOESNT_REFRESH') }</p>
<div className="col-xlg-12 col-md-12 padding-top-20 padding-bottom-30">
<div
className="form-group col-lg-2 col-md-2 col-sm-2 col-xs-2"
style={{ padding: 0 }}>
<input
type="radio"
className="to-labelauty labelauty"
name={ `mode-public` }
id={ `mode-public` }
checked={ this.state.jumblrMode === 'public' ? true : false } />
<label
htmlFor={ `mode-public` }
style={{ margin: 0 }}
onClick={ () => this.switchJumblrMode('public') }>
<span
className="labelauty-unchecked-image"
style={{ display: this.state.jumblrMode === 'public' ? 'none' : 'inline-block' }}></span>
<span
className="labelauty-unchecked"
style={{ display: this.state.jumblrMode === 'public' ? 'none' : 'inline-block' }}>
Public node
</span>
<span
className="labelauty-checked-image"
style={{ display: this.state.jumblrMode === 'public' ? 'inline-block' : 'none' }}></span>
<span
className="labelauty-checked"
style={{ display: this.state.jumblrMode === 'public' ? 'inline-block' : 'none' }}>
Public node
</span>
</label>
</div>
<div className="col-xs-12">
<div className="panel-group">
<div className="panel">
<div
className="panel-heading"
onClick={ () => this.openTab(0) }>
<a className={ this.state.activeTab === 0 ? 'panel-title' : 'panel-title collapsed' }>{ translate('JUMBLR.FEW_SECURITY_NOTES') }</a>
</div>
<div className={ this.state.activeTab === 0 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }>
<div className="panel-body">
<ul>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC1') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC2') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC3') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC4') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC5') }</li>
</ul>
</div>
className="form-group col-lg-2 col-md-2 col-sm-2 col-xs-2"
style={{ padding: 0 }}>
<input
type="radio"
className="to-labelauty labelauty"
name={ `mode-private` }
id={ `mode-private` }
checked={ this.state.jumblrMode === 'private' ? true : false } />
<label
htmlFor={ `mode-private` }
style={{ margin: 0 }}
onClick={ () => this.switchJumblrMode('private') }>
<span
className="labelauty-unchecked-image"
style={{ display: this.state.jumblrMode === 'private' ? 'none' : 'inline-block' }}></span>
<span
className="labelauty-unchecked"
style={{ display: this.state.jumblrMode === 'private' ? 'none' : 'inline-block' }}>
Private node
</span>
<span
className="labelauty-checked-image"
style={{ display: this.state.jumblrMode === 'private' ? 'inline-block' : 'none' }}></span>
<span
className="labelauty-checked"
style={{ display: this.state.jumblrMode === 'private' ? 'inline-block' : 'none' }}>
Private node
</span>
</label>
</div>
</div>
<div className="panel">
<div
className="panel-heading"
onClick={ () => this.openTab(1) }>
<a className={ this.state.activeTab === 1 ? 'panel-title' : 'panel-title collapsed' }>{ translate('JUMBLR.ACCESS_JUMBLR_FUNDS') }</a>
<div className="col-xlg-12 col-md-12">
{ this.state.jumblrMode === 'public' &&
<div className="jumblr-mode-selector nav-tabs-horizontal nav-tabs-inverse">
<div className="img-responsive">
<span className="coin">{ this.props.ActiveCoin.coin }</span>
<img
className="image"
src={ `assets/images/cryptologo/${this.props.ActiveCoin.coin.toLowerCase()}.png` }
alt={ this.props.ActiveCoin.coin }/>
</div>
<div className={ this.state.activeTab === 1 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }>
<div className="panel-body">
<p>{ translate('JUMBLR.ADDRESS_ACCESSIBLE_EASILY') }</p>
<ul>
<code>duck dog cat donkey</code>
</ul>
<ol>
<li>{ translate('JUMBLR.TO_ACCESS') }</li>
<li>{ translate('JUMBLR.CLOSE_IAPP') }</li>
<li>{ translate('JUMBLR.START_IAPP') }</li>
<li>{ translate('JUMBLR.START_KMD') }</li>
<li>{ translate('JUMBLR.ACCESS_JUMBLR_FUNDS') }
<ul>
<li>{ translate('JUMBLR.SMALL_LETTERS') }</li>
<li>{ translate('JUMBLR.WHITE_SPACE') }</li>
</ul>
<ul className="nav nav-tabs">
<li
className={ this.state.activeTab === 0 ? 'active' : '' }
onClick={ () => this.openTab(0) }>
<a>
{ translate('JUMBLR.USING_JUMBLR') }
</a>
</li>
<li>
{ translate('JUMBLR.PER_EXAMPLE') }
<br />
<code>jumblr duck dog cat donkey</code>
<li
className={ this.state.activeTab === 1 ? 'active' : '' }
onClick={ () => this.openTab(1) }>
<a>
Deposit address
</a>
</li>
<li>{ translate('JUMBLR.LOGIN_WITH_JUMBLR') }</li>
</ol>
<h4>{ translate('JUMBLR.AGAIN_DONT_SHARE') }</h4>
</div>
</div>
</div>
<div className="panel">
<div
className="panel-heading"
<li
className={ this.state.activeTab === 2 ? 'active' : '' }
onClick={ () => this.openTab(2) }>
<a className={ this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed' }>{ translate('JUMBLR.USING_JUMBLR') }</a>
</div>
<div className={ this.state.activeTab === 2 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }>
<div className="panel-body">
<a>
Secret address
</a>
</li>
<li
className={ this.state.activeTab === 3 ? 'active' : '' }
onClick={ () => this.openTab(3) }>
<a>
Deposit funds
</a>
</li>
</ul>
<div className="tab-content padding-20">
<div className={ 'tab-pane' + (this.state.activeTab === 0 ? ' active' : '') }>
<button
type="button"
className="btn btn-success waves-effect waves-light margin-top-20 btn-next"
onClick={ () => this.openTab(1) }>Next</button>
<h5>How to use Jumblr</h5>
<ul>
<li>{ translate('JUMBLR.RUN_KMD') }</li>
<li>{ translate('JUMBLR.LOGIN_KMD') }</li>
<li>{ translate('JUMBLR.GO_TO') }</li>
<li>{ translate('JUMBLR.FIND_DEPOSIT_ADDR') }</li>
<li>{ translate('JUMBLR.YOU_SEND_FUNDS') }</li>
<li>Create deposit address</li>
<li>Create secret address</li>
<li>Send funds to deposit address</li>
<li>{ translate('JUMBLR.KEEP_WALLET_OPEN') }</li>
<li>{ translate('JUMBLR.IMPORTANT_FUNDS') }</li>
<li>{ translate('JUMBLR.LARGE_LOT') }</li>
@ -122,105 +212,276 @@ const JumblrRender = function() {
<p>{ translate('JUMBLR.TO_CLEAR_THEM') }</p>
<p>{ translate('JUMBLR.WHEN_IT_TOTALS') }</p>
</div>
<div className={ 'tab-pane' + (this.state.activeTab === 1 ? ' active' : '') }>
<button
type="button"
className="btn btn-success waves-effect waves-light btn-next"
onClick={ () => this.openTab(2) }>Next</button>
<h5>{ translate('JUMBLR.FEW_SECURITY_NOTES') }</h5>
<div className="col-xs-12 nofloat">
<ul className="padding-bottom-20">
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC1') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC2') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC3') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC4') }</li>
<li>{ translate('JUMBLR.FEW_SECURITY_NOTES_DESC5') }</li>
</ul>
</div>
{ this.state.jumblrDepositAddressPBased &&
<div className="padding-bottom-30">
<div className="padding-bottom-20">
<p>
<strong>Please write down your Jumblr passphrase and keept it safe.</strong>
</p>
<p>This is your main recovery passphrase.</p>
<p>All Jumblr addresses can be regenrated based on it.</p>
<p>
<strong>Tip:</strong> do not use smart editors to store your passphrase as they tend to add extra characters.<br />This may result in passphrase mismatch with the original passphrase.
</p>
</div>
<label>Passphrase</label>
<input
type="text"
className="form-control"
name="loginPassphrase"
onChange={ this.returnPassphrase }
value={ this.state.randomSeed } />
<button
className="btn btn-default btn-xs clipboard-edexaddr copy-string-btn"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this.copyPassphrase() }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
</div>
</div>
<div className="col-xlg-12 col-md-12">
<h4 className="font-size-14 text-uppercase">{ translate('JUMBLR.JADDR') }</h4>
<div className="panel">
<div className="table-responsive">
<table className="table table-striped">
<tbody>
<tr>
<td width="20%">{ translate('JUMBLR.BTC_DEPOSIT') }</td>
<td>
<span></span>
</td>
</tr>
<tr>
<td>BTC Jumblr</td>
<td>
}
<button
type="button"
className="btn btn-animate btn-animate-side btn-default btn-sm waves-effect waves-light">
<span>
<i className="icon fa-eye"></i> { translate('JUMBLR.SHOW_HIDE') }
</span>
className="btn btn-info waves-effect waves-light"
onClick={ this.generateJumblrDepositAddress }>Create Jumblr deposit address</button>
{ this.state.jumblrDepositAddress && this.state.jumblrDepositAddress.address &&
<div className="padding-top-40">
<strong>Your Jumblr deposit address:</strong>
<p>
{ this.state.jumblrDepositAddress.address }
<button
className="btn btn-default btn-xs clipboard-edexaddr margin-left-10"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this._copyCoinAddress(this.state.jumblrDepositAddress.address) }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
<span className="label label-lg label-outline label-success hide"></span>
<span className="label label-lg label-outline label-default">{ translate('JUMBLR.HIDDEN') }</span>
</td>
</tr>
<tr>
<td>{ translate('JUMBLR.KMD_DEPOSIT') }</td>
<td></td>
</tr>
<tr>
<td>KMD Jumblr</td>
<td>
</p>
<p>
{ this.state.jumblrDepositAddress.wif }
<button
className="btn btn-default btn-xs clipboard-edexaddr margin-left-10"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this._copyCoinAddress(this.state.jumblrDepositAddress.wif) }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
</p>
</div>
}
</div>
<div className={ 'tab-pane' + (this.state.activeTab === 2 ? ' active' : '') }>
<button
type="button"
className="btn btn-animate btn-animate-side btn-default btn-sm waves-effect waves-light">
<span>
<i className="icon fa-eye"></i> { translate('JUMBLR.SHOW_HIDE') }
</span>
className="btn btn-success waves-effect waves-light margin-top-20 btn-next"
onClick={ () => this.openTab(3) }>Next</button>
<p>Jumblr secret addresses are used for the final z -> t transactions.</p>
<p>In order to allow larger accounts to obtain privacy, up to 777 secret addresses are supported.</p>
<p>Whenever a z -> t stage is activated, a random secret address from the list of the then active secret addresses is selected.</p>
<p>To add a new set of secret addresses enter address count below. The passphrase below is exactly the same you saw on the previous step.</p>
<p>Your Jumblr secret address recovery passphrase will have the following pattern <code>jumblr muffin smart educate tomato boss foil open dirt opinion pizza goddess skate action card garden cotton life write life note shine myself gloom summer XXX</code>. Where XXX any number from 001 to 777.</p>
{ this.state.jumblrDepositAddressPBased &&
<div className="padding-bottom-20 padding-top-20">
<label>Passphrase</label>
<input
type="text"
className="form-control"
name="jumblrPassphrase"
onChange={ this.returnPassphrase }
value={ this.state.randomSeed } />
<button
className="btn btn-default btn-xs clipboard-edexaddr copy-string-btn"
title={ translate('INDEX.COPY_TO_CLIPBOARD') }
onClick={ () => this.copyPassphrase() }>
<i className="icon wb-copy"></i> { translate('INDEX.COPY') }
</button>
<span className="label label-lg label-outline label-success hide"></span>
<span className="label label-lg label-outline label-default">
{ translate('JUMBLR.HIDDEN') }
</div>
}
<div className="col-xs-2 nofloat padding-top-30">Number of secret addresses</div>
<div className="col-xs-2 nofloat padding-left-10">
<input
type="text"
pattern="[0-9]*"
className="form-control"
name="secretAddressCount"
min="1"
max="777"
onChange={ this.onChange }
value={ this.state.secretAddressCount } />
</div>
<div className="col-xs-2 nofloat">
<button
type="button"
className="btn btn-info waves-effect waves-light"
onClick={ this.generateJumblrSecretAddress }>Create Jumblr secret address(es)</button>
</div>
<div className="toggle-box padding-top-20">
<span className="pointer">
<label className="switch">
<input
type="checkbox"
checked={ this.state.jumblrSecretAddressShow } />
<div
className="slider"
onClick={ () => this.toggle('jumblrSecretAddressShow') }></div>
</label>
<div
className="toggle-label"
onClick={ () => this.toggle('jumblrSecretAddressShow') }>
Show address list
</div>
</span>
</div>
<div className="col-xlg-12 col-md-12 padding-top-20 nofloat">
{ this.state.jumblrSecretAddressShow && this.checkJumblrSecretAddressListLength('gen') &&
<table className="table table-hover dataTable table-striped">
<thead>
<tr>
<td>
<strong>Address</strong>
</td>
<td>
<strong>Wif</strong>
</td>
</tr>
</thead>
<tbody>
{ this._JumblrRenderSecretAddressList('gen') }
</tbody>
</table>
}
</div>
</div>
<div className={ 'tab-pane' + (this.state.activeTab === 3 ? ' active' : '') }>
<p>Use the form below to send funds to your jumblr deposit address.</p>
<p className="padding-bottom-20">You can also send funds to deposit address from an external service or another wallet.</p>
<WalletsNativeSend
{...this.props}
renderFormOnly="true"
activeSection="send" />
</div>
</div>
</div>
}
{ this.state.jumblrMode === 'private' &&
<div className="jumblr-mode-selector nav-tabs-horizontal nav-tabs-inverse">
<ul className="nav nav-tabs">
<li
className={ this.state.activeTab === 0 ? 'active' : '' }
onClick={ () => this.openTab(0) }>
<a>
Import secret address
</a>
</li>
<li
className={ this.state.activeTab === 1 ? 'active' : '' }
onClick={ () => this.openTab(1) }>
<a>
Check funds
</a>
</li>
</ul>
<div className="tab-content padding-20">
<div className={ 'tab-pane' + (this.state.activeTab === 0 ? ' active' : '') }>
<button
type="button"
className="btn btn-success waves-effect waves-light margin-top-20 btn-next"
onClick={ () => this.openTab(1) }>Next</button>
<div className="col-xlg-12 col-md-12 nofloat">
<p>Enter your Jumblr passphrase you got previously during Public node configuration to import secret address.</p>
<p>Passphrase example: <code>jumblr muffin smart educate tomato boss foil open dirt opinion pizza goddess skate action card garden cotton life write life note shine myself gloom summer</code>.</p>
<p>The form below will "regenerate" Jumblr secret address based on passphrase provided.</p>
<p>After this final step expect to see funds processed and credited to your address after 2 days period.</p>
<div className="col-xlg-12 col-md-12">
<h4 className="font-size-14 text-uppercase">
{ translate('JUMBLR.JSTATUS') }
</h4>
<div className="panel">
<div className="table-responsive">
<table className="table table-striped">
<tbody>
{ this.state.jumblrDepositAddressPBased &&
<div className="padding-bottom-20 padding-top-20">
<label>Passphrase</label>
<input
type="text"
className="form-control"
name="jumblrPassphraseImport"
onChange={ (event) => this.passphraseOnChange(event) }
value={ this.state.jumblrPassphraseImport } />
</div>
}
<div className="col-xs-2 nofloat padding-top-30">Number of secret addresses</div>
<div className="col-xs-2 nofloat padding-left-10">
<input
type="text"
pattern="[0-9]*"
className="form-control"
name="secretAddressCountImport"
min="1"
max="777"
onChange={ this.onChange }
value={ this.state.secretAddressCountImport } />
</div>
<div className="col-xs-2 nofloat">
<button
type="button"
className="btn btn-info waves-effect waves-light"
onClick={ this.importJumblrSecretAddress }>Import Jumblr secret address(es)</button>
</div>
<div className="toggle-box padding-top-20">
<span className="pointer">
<label className="switch">
<input
type="checkbox"
checked={ this.state.jumblrSecretAddressShowImport } />
<div
className="slider"
onClick={ () => this.toggle('jumblrSecretAddressShowImport') }></div>
</label>
<div
className="toggle-label"
onClick={ () => this.toggle('jumblrSecretAddressShowImport') }>
Show address list
</div>
</span>
</div>
<div className="col-xlg-12 col-md-12 padding-top-20 nofloat">
{ this.state.jumblrSecretAddressShowImport && this.checkJumblrSecretAddressListLength('import') &&
<table className="table table-hover dataTable table-striped">
<thead>
<tr>
<td width="20%">{ translate('JUMBLR.RESULT') }</td>
<td>
<span className="label label-success"></span>
<strong>Address</strong>
</td>
<td>
<strong>Wif</strong>
</td>
</tr>
<tr>
<td>{ translate('JUMBLR.DEPOSITED') }</td>
<td></td>
</tr>
<tr>
<td>{ translate('JUMBLR.PUB_TO_PRIV') }</td>
<td></td>
</tr>
<tr>
<td>{ translate('JUMBLR.PRIV_TO_PRIV') }</td>
<td></td>
</tr>
<tr>
<td>{ translate('JUMBLR.PRIV_TO_PUB') }</td>
<td></td>
</tr>
<tr>
<td>{ translate('JUMBLR.FINISHED') }</td>
<td></td>
</tr>
<tr>
<td>{ translate('JUMBLR.PENDING') }</td>
<td></td>
</tr>
</thead>
<tbody>
{ this._JumblrRenderSecretAddressList('import') }
</tbody>
</table>
}
</div>
</div>
</div>
<div className={ 'tab-pane' + (this.state.activeTab === 1 ? ' active' : '') }>
<ReceiveCoin
{...this.props.ActiveCoin}
activeSection="receive"
renderTableOnly="true" />
</div>
</div>
</div>
}
</div>
</div>
</div>

6
react/src/components/dashboard/navbar/navbar.js

@ -10,6 +10,7 @@ import {
} from '../../../actions/actionCreators';
import Store from '../../../store';
import Config from '../../../config';
import { checkAC } from '../../addcoin/payload';
import NavbarRender from './navbar.render';
@ -23,6 +24,7 @@ class Navbar extends React.Component {
this.openDropMenu = this.openDropMenu.bind(this);
this.logout = this.logout.bind(this);
this.handleClickOutside = this.handleClickOutside.bind(this);
this._checkAC = this._checkAC.bind(this);
}
componentWillMount() {
@ -67,6 +69,10 @@ class Navbar extends React.Component {
Store.dispatch(dashboardChangeSection(sectionName));
}
_checkAC() {
return checkAC(this.props.ActiveCoin.coin);
}
logout() {
Store.dispatch(
stopInterval(

4
react/src/components/dashboard/navbar/navbar.render.js

@ -57,11 +57,13 @@ const NavbarRender = function() {
<i className="site-menu-icon"></i> BarterDEX
</a>
</li>
<li className={ 'hide ' + (this.isSectionActive('jumblr') ? 'active nav-top-menu' : 'nav-top-menu') }>
{ this.props.ActiveCoin && this.props.ActiveCoin.mode === 'native' && (this._checkAC() || this.props.ActiveCoin.coin === 'KMD') &&
<li className={ this.isSectionActive('jumblr') ? 'active nav-top-menu' : 'nav-top-menu' }>
<a onClick={ () => this.dashboardChangeSection('jumblr') }>
<i className="site-menu-icon"></i> Jumblr
</a>
</li>
}
<li className={ this.state.nativeOnly ? 'hide' : (this.isSectionActive('atomic') ? 'active nav-top-menu' : 'nav-top-menu') }>
<a onClick={ () => this.dashboardChangeSection('atomic') }>
<i className="site-menu-icon"></i> Atomic Explorer

16
react/src/components/dashboard/receiveCoin/receiveCoin.js

@ -10,7 +10,8 @@ import {
AddressActionsBasiliskModeRender,
AddressActionsNonBasiliskModeRender,
AddressItemRender,
ReceiveCoinRender
ReceiveCoinRender,
_ReceiveCoinTableRender
} from './receiveCoin.render';
// TODO: implement balance/interest sorting
@ -28,6 +29,11 @@ class ReceiveCoin extends React.Component {
this.handleClickOutside = this.handleClickOutside.bind(this);
this.toggleVisibleAddress = this.toggleVisibleAddress.bind(this);
this.checkTotalBalance = this.checkTotalBalance.bind(this);
this.ReceiveCoinTableRender = _ReceiveCoinTableRender.bind(this);
}
ReceiveCoinTableRender() {
return this._ReceiveCoinTableRender();
}
componentWillMount() {
@ -108,7 +114,7 @@ class ReceiveCoin extends React.Component {
}
getNewAddress(type) {
Store.dispatch(getNewKMDAddresses(this.props.coin, type));
Store.dispatch(getNewKMDAddresses(this.props.coin, type, this.props.mode));
}
toggleVisibleAddress() {
@ -181,7 +187,7 @@ class ReceiveCoin extends React.Component {
}
if (this.state.hideZeroAddresses) {
if (!this.hasNoAmount) {
if (!this.hasNoAmount(address)) {
items.push(
AddressItemRender.call(this, address, type)
);
@ -200,10 +206,10 @@ class ReceiveCoin extends React.Component {
}
render() {
// TODO nativeActiveSection === 'receive' should be removed when native mode is fully merged
// TODO activeSection === 'receive' should be removed when native mode is fully merged
// into the rest of the components
if (this.props &&
(this.props.receive || (this.isNativeMode() && this.props.nativeActiveSection === 'receive'))) {
(this.props.receive || (this.isNativeMode() && this.props.activeSection === 'receive'))) {
return ReceiveCoinRender.call(this);
}

98
react/src/components/dashboard/receiveCoin/receiveCoin.render.js

@ -61,50 +61,11 @@ export const AddressItemRender = function(address, type) {
);
};
export const ReceiveCoinRender = function() {
export const _ReceiveCoinTableRender = function() {
return (
<div>
<div className="col-xs-12 margin-top-20">
<div className="panel nav-tabs-horizontal">
<div>
<div className="col-xlg-12 col-lg-12 col-sm-12 col-xs-12">
<div className="panel">
<header className="panel-heading">
{this.isNativeMode() &&
<div className="panel-actions">
<div
className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }>
<a className="dropdown-toggle white btn btn-warning">
<i className="icon md-arrows margin-right-10"></i> { translate('INDEX.GET_NEW_ADDRESS') }
<span className="caret"></span>
</a>
<ul
className="dropdown-menu dropdown-menu-right">
<li>
<a onClick={ () => this.getNewAddress('public') }>
<i className="icon fa-eye"></i> { translate('INDEX.TRANSPARENT_ADDRESS') }
</a>
</li>
<li>
<a onClick={ () => this.getNewAddress('private') }>
<i className="icon fa-eye-slash"></i> { translate('INDEX.PRIVATE_Z_ADDRESS') }
</a>
</li>
</ul>
</div>
</div>
}
<h4 className="panel-title">{ translate('INDEX.RECEIVING_ADDRESS') }</h4>
</header>
<div className="panel-body">
{ this.checkTotalBalance() === 0 &&
<span>
{ this.checkTotalBalance() !== 0 &&
<div className="text-left padding-top-10 padding-bottom-10">
<div
className="toggle-label margin-right-15 pointer"
onClick={ this.toggleVisibleAddress }>
{ translate('INDEX.TOGGLE_ZERO_ADDRESSES') }
</div>
<label className="switch">
<input
type="checkbox"
@ -113,6 +74,11 @@ export const ReceiveCoinRender = function() {
className="slider"
onClick={ this.toggleVisibleAddress }></div>
</label>
<div
className="toggle-label margin-right-15 pointer"
onClick={ this.toggleVisibleAddress }>
{ translate('INDEX.TOGGLE_ZERO_ADDRESSES') }
</div>
</div>
}
<table className="table table-hover dataTable table-striped">
@ -153,6 +119,53 @@ export const ReceiveCoinRender = function() {
}
</tfoot>
</table>
</span>
);
};
export const ReceiveCoinRender = function() {
if (this.props.renderTableOnly) {
return (
<div>{ this.ReceiveCoinTableRender() }</div>
);
} else {
return (
<div>
<div className="col-xs-12 margin-top-20">
<div className="panel nav-tabs-horizontal">
<div>
<div className="col-xlg-12 col-lg-12 col-sm-12 col-xs-12">
<div className="panel">
<header className="panel-heading">
{ this.isNativeMode() &&
<div className="panel-actions">
<div
className={ 'dropdown' + (this.state.openDropMenu ? ' open' : '') }
onClick={ this.openDropMenu }>
<a className="dropdown-toggle white btn btn-warning">
<i className="icon md-arrows margin-right-10"></i> { translate('INDEX.GET_NEW_ADDRESS') }
<span className="caret"></span>
</a>
<ul
className="dropdown-menu dropdown-menu-right">
<li>
<a onClick={ () => this.getNewAddress('public') }>
<i className="icon fa-eye"></i> { translate('INDEX.TRANSPARENT_ADDRESS') }
</a>
</li>
<li>
<a onClick={ () => this.getNewAddress('private') }>
<i className="icon fa-eye-slash"></i> { translate('INDEX.PRIVATE_Z_ADDRESS') }
</a>
</li>
</ul>
</div>
</div>
}
<h4 className="panel-title">{ translate('INDEX.RECEIVING_ADDRESS') }</h4>
</header>
<div className="panel-body">
{ this.ReceiveCoinTableRender() }
</div>
</div>
</div>
@ -161,5 +174,6 @@ export const ReceiveCoinRender = function() {
</div>
</div>
);
}
};

2
react/src/components/dashboard/walletsBalance/walletsBalance.js

@ -167,7 +167,7 @@ class WalletsBalance extends React.Component {
}
isNativeBalanceActive() {
return this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default';
return this.isNativeMode() && this.props.ActiveCoin.activeSection === 'default';
}
isNonNativeBalanceActive() {

23
react/src/components/dashboard/walletsData/pagination.js

@ -4,42 +4,43 @@ import PaginationRender from './pagination.render';
export default class TablePaginationRenderer extends Component {
constructor (props) {
super();
this.getSafePage = this.getSafePage.bind(this);
this.changePage = this.changePage.bind(this);
this.applyPage = this.applyPage.bind(this);
this.state = {
page: props.page
}
this.getSafePage = this.getSafePage.bind(this);
this.changePage = this.changePage.bind(this);
this.applyPage = this.applyPage.bind(this);
}
componentWillReceiveProps (nextProps) {
componentWillReceiveProps(nextProps) {
this.setState({ page: nextProps.page });
}
getSafePage (page) {
getSafePage(page) {
if (isNaN(page)) {
page = this.props.page;
}
return Math.min(Math.max(page, 0), this.props.pages - 1);
}
changePage (page) {
changePage(page) {
page = this.getSafePage(page);
this.setState({ page });
if (this.props.page !== page) {
this.props.onPageChange(page);
}
}
applyPage (e) {
e && e.preventDefault();
applyPage(e) {
const page = this.state.page;
e && e.preventDefault();
this.changePage(page === '' ? this.props.page : page);
}
render () {
render() {
return PaginationRender.call(this);
}
}

40
react/src/components/dashboard/walletsData/pagination.render.js

@ -27,25 +27,23 @@ const PaginationRender = function() {
return (
<div
className={classnames(className, '-pagination')}
style={this.props.paginationStyle}
>
<div className='-previous'>
style={this.props.paginationStyle}>
<div className="-previous">
<PreviousComponent
onClick={e => {
if (!canPrevious) return;
this.changePage(page - 1)
}}
disabled={!canPrevious}
>
disabled={!canPrevious}>
{this.props.previousText}
</PreviousComponent>
</div>
<div className='-center'>
<span className='-pageInfo'>
<div className="-center">
<span className="-pageInfo">
{this.props.pageText}{' '}
{showPageJump
?
<div className='-pageJump'>
<div className="-pageJump">
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
@ -58,40 +56,38 @@ const PaginationRender = function() {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage();
}
}}
/>
}} />
</div>
:
<span className='-currentPage'>
<span className="-currentPage">
{page + 1}
</span>}{' '}
{this.props.ofText}{' '}
<span className='-totalPages'>{pages || 1}</span>
<span className="-totalPages">{pages || 1}</span>
</span>
{showPageSizeOptions &&
<span className='select-wrap -pageSizeOptions'>
{ showPageSizeOptions &&
<span className="select-wrap -pageSizeOptions">
<select
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}
>
{pageSizeOptions.map((option, i) => {
value={pageSize}>
{ pageSizeOptions.map((option, i) => {
return (
<option key={i} value={option}>
{option} {this.props.rowsText}
</option>
)
);
})}
</select>
</span>}
</span>
}
</div>
<div className='-next'>
<div className="-next">
<NextComponent
onClick={e => {
if (!canNext) return;
this.changePage(page + 1)
}}
disabled={!canNext}
>
disabled={!canNext}>
{this.props.nextText}
</NextComponent>
</div>

30
react/src/components/dashboard/walletsData/walletsData.js

@ -53,7 +53,7 @@ class WalletsData extends React.Component {
totalStackLength: 0,
useCache: true,
itemsListColumns: this.generateItemsListColumns(),
pageSize: 20,
pageSize: 10,
showPagination: false,
searchTerm: null,
coin: null,
@ -117,6 +117,9 @@ class WalletsData extends React.Component {
id: 'direction',
Header: translate('INDEX.DIRECTION'),
Footer: translate('INDEX.DIRECTION'),
className: 'colum--direction',
headerClassName: 'colum--direction',
footerClassName: 'colum--direction',
accessor: (tx) => TxTypeRender.call(this, tx.category || tx.type)
},
{
@ -158,15 +161,15 @@ class WalletsData extends React.Component {
});
}
const txDetailColumnCssClasses = this.isBasiliskMode() ? 'hidden-xs hidden-sm text-center' : 'hidden-xs hidden-sm';
// const txDetailColumnCssClasses = this.isBasiliskMode() ? 'hidden-xs hidden-sm' : 'hidden-xs hidden-sm';
columns.push({
id: 'tx-detail',
Header: translate('INDEX.TX_DETAIL'),
Footer: translate('INDEX.TX_DETAIL'),
headerClassName: txDetailColumnCssClasses,
footerClassName: txDetailColumnCssClasses,
className: txDetailColumnCssClasses,
className: 'colum--txinfo',
headerClassName: 'colum--txinfo',
footerClassName: 'colum--txinfo',
Cell: props => TransactionDetailRender.call(this, props.index)
});
@ -389,15 +392,21 @@ class WalletsData extends React.Component {
// TODO: add basilisk first run check, display no data if second run
renderTxHistoryList() {
if (this.state.itemsList === 'loading') {
if (!this.isNativeMode() || this.isFullySynced()) {
if (this.state.itemsList === 'loading' || this.state.itemsList.length == 0) {
if (this.isFullySynced()) {
return (
<tr className="hover--none">
<td colSpan="7">{ translate('INDEX.LOADING_HISTORY') }...</td>
</tr>
);
} else {
return (
<tr className="hover--none">
<td colSpan="7">Synchronization is in progress...</td>
</tr>
);
}
} else if (this.state.itemsList === 'no data' || this.state.itemsList.length == 0) {
} else if (this.state.itemsList === 'no data') {
return (
<tr className="hover--none">
<td colSpan="7">{ translate('INDEX.NO_DATA') }</td>
@ -413,7 +422,7 @@ class WalletsData extends React.Component {
onPageSizeChange(pageSize, pageIndex) {
this.setState(Object.assign({}, this.state, {
pageSize: pageSize,
showPagination: this.state.itemsList && this.state.itemsList.length >= pageSize
showPagination: this.state.itemsList && this.state.itemsList.length >= pageSize,
}))
}
@ -547,6 +556,7 @@ class WalletsData extends React.Component {
}
shouldDisplayAddressList() {
//return true;
return this.props.Dashboard &&
this.props.Dashboard.activeHandle &&
this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin];
@ -613,7 +623,7 @@ class WalletsData extends React.Component {
!this.props.ActiveCoin.receive
) || (
this.props.ActiveCoin.mode === 'native' &&
this.props.ActiveCoin.nativeActiveSection === 'default'
this.props.ActiveCoin.activeSection === 'default'
)) {
return WalletsDataRender.call(this);
} else {

35
react/src/components/dashboard/walletsData/walletsData.render.js

@ -13,11 +13,11 @@ import Config from '../../../config';
export const AddressTypeRender = function() {
return (
<td>
<span>
<span className="label label-default">
<i className="icon fa-eye"></i> { translate('IAPI.PUBLIC_SM') }
</span>
</td>
</span>
);
};
@ -49,7 +49,8 @@ export const AddressRender = function(tx) {
export const AddressItemRender = function(address, type, amount, coin) {
return (
<li key={address}
<li
key={address}
className={ address === this.state.currentAddress ? 'selected' : '' }>
<a onClick={ () => this.updateAddressSelection(address) }>
<i className={ 'icon fa-eye' + (type === 'public' ? '' : '-slash') }></i>&nbsp;&nbsp;
@ -136,12 +137,12 @@ export const TxTypeRender = function(category) {
export const TxAmountRender = function (tx) {
if (Config.roundValues) {
return (
<td title={ tx.amount }>{ formatValue('round', tx.amount, -6) || translate('DASHBOARD.UNKNOWN') }</td>
<span title={ tx.amount }>{ formatValue('round', tx.amount, -6) || translate('DASHBOARD.UNKNOWN') }</span>
);
}
return (
<td>{ tx.amount || translate('DASHBOARD.UNKNOWN') }</td>
<span>{ tx.amount || translate('DASHBOARD.UNKNOWN') }</span>
);
};
@ -151,15 +152,14 @@ export const TxHistoryListRender = function() {
data={this.state.filteredItemsList}
columns={this.state.itemsListColumns}
sortable={true}
className='-striped -highlight'
className="-striped -highlight"
PaginationComponent={TablePaginationRenderer}
nextText={translate('INDEX.NEXT_PAGE')}
previousText={translate('INDEX.PREVIOUS_PAGE')}
showPaginationBottom={this.state.showPagination}
showPaginationTop={this.state.showPagination}
pageSize={this.pageSize}
onPageSizeChange={(pageSize, pageIndex) => this.onPageSizeChange(pageSize, pageIndex)}
/>
onPageSizeChange={(pageSize, pageIndex) => this.onPageSizeChange(pageSize, pageIndex)} />
);
};
@ -240,22 +240,23 @@ export const WalletsDataRender = function() {
null
}
</div>
<h4 className='panel-title'>{ translate('INDEX.TRANSACTION_HISTORY') }</h4>
<h4 className="panel-title">{ translate('INDEX.TRANSACTION_HISTORY') }</h4>
</header>
<div className='panel-body'>
<div className='row padding-bottom-20'>
{this.shouldDisplayAddressList() &&
<div className='col-sm-8'>
<div className="panel-body">
<div className="row padding-bottom-20">
{ this.shouldDisplayAddressList() &&
<div className="col-sm-8">
{this.renderAddressList()}
</div>
}
<div className='col-sm-4'>
<input className="form-control"
<div className="col-sm-4">
<input
className="form-control"
onChange={e => this.onSearchTermChange(e.target.value)}
placeholder='Search' />
placeholder="Search" />
</div>
</div>
<div className='row'>
<div className="row">
{ this.renderTxHistoryList() }
</div>
</div>

28
react/src/components/dashboard/walletsInfo/walletsInfo.js

@ -0,0 +1,28 @@
import React from 'react';
import WalletsNativeInfoRender from './walletsInfo.render';
import { toggleClaimInterestModal } from '../../../actions/actionCreators';
import Store from '../../../store';
class WalletsNativeInfo extends React.Component {
constructor(props) {
super(props);
this.openClaimInterestModal = this.openClaimInterestModal.bind(this);
}
openClaimInterestModal() {
Store.dispatch(toggleClaimInterestModal(true));
}
render() {
if (this.props &&
this.props.Dashboard &&
this.props.Dashboard.progress &&
this.props.ActiveCoin.activeSection === 'settings') {
return WalletsNativeInfoRender.call(this);
}
return null;
}
}
export default WalletsNativeInfo;

14
react/src/components/dashboard/walletsNativeInfo/walletsNativeInfo.render.js → react/src/components/dashboard/walletsInfo/walletsInfo.render.js

@ -1,7 +1,8 @@
import React from 'react';
import { translate } from '../../../translate/translate';
import ClaimInterestModal from '../claimInterestModal/claimInterestModal';
const WalletsNativeInfoRender = function() {
const WalletsInfoRender = function() {
return (
<div>
<div className="col-xlg-6 col-md-4">
@ -40,6 +41,15 @@ const WalletsNativeInfoRender = function() {
</table>
</div>
</div>
{ this.props.ActiveCoin.coin === 'KMD' &&
<div>
<button
type="button"
className="btn btn-success waves-effect waves-light margin-top-20 btn-next"
onClick={ () => this.openClaimInterestModal() }>Claim interest</button>
<ClaimInterestModal {...this.props} />
</div>
}
</div>
<div className="col-xlg-6 col-md-8">
@ -146,4 +156,4 @@ const WalletsNativeInfoRender = function() {
);
};
export default WalletsNativeInfoRender;
export default WalletsInfoRender;

25
react/src/components/dashboard/walletsNative/walletsNative.js

@ -2,6 +2,7 @@ import React from 'react';
import WalletsNativeRender from './walletsNative.render';
import { translate } from '../../../translate/translate';
import { triggerToaster } from '../../../actions/actionCreators';
import { getCoinTitle } from '../../../util/coinHelper';
import Config from '../../../config';
import Store from '../../../store';
@ -13,6 +14,10 @@ const socket = io.connect(`http://127.0.0.1:${Config.agamaPort}`);
class WalletsNative extends React.Component {
constructor(props) {
super(props);
this.state = {
nativeOnly: Config.iguanaLessMode,
};
this.getCoinStyle = this.getCoinStyle.bind(this);
socket.on('service', msg => this.updateSocketsData(msg));
}
@ -35,11 +40,21 @@ class WalletsNative extends React.Component {
}
}
defaultBG() {
if (this.props.ActiveCoin.coin === 'REVS') {
return 'supernet';
} else {
return this.props.ActiveCoin.coin.toLowerCase();
getCoinStyle(type) {
if (type === 'transparent') {
if (getCoinTitle(this.props.ActiveCoin.coin).transparentBG && getCoinTitle().logo) {
return { 'backgroundImage': `url("assets/images/bg/${getCoinTitle().logo.toLowerCase()}_transparent_header_bg.png")` };
}
} else if (type === 'title') {
let _iconPath;
if (getCoinTitle(this.props.ActiveCoin.coin).titleBG) {
_iconPath = `assets/images/native/${getCoinTitle(this.props.ActiveCoin.coin).logo.toLowerCase()}_header_title_logo.png`;
} else if (!getCoinTitle(this.props.ActiveCoin.coin).titleBG && getCoinTitle(this.props.ActiveCoin.coin).logo) {
_iconPath = `assets/images/cryptologo/${getCoinTitle(this.props.ActiveCoin.coin).logo.toLowerCase()}.png`;
}
return _iconPath;
}
}

14
react/src/components/dashboard/walletsNative/walletsNative.render.js

@ -1,6 +1,6 @@
import React from 'react';
import WalletsBalance from '../walletsBalance/walletsBalance';
import WalletsNativeInfo from '../walletsNativeInfo/walletsNativeInfo';
import WalletsInfo from '../walletsInfo/walletsInfo';
import WalletsNativeSend from '../walletsNativeSend/walletsNativeSend';
import WalletsProgress from '../walletsProgress/walletsProgress';
import WalletsData from '../walletsData/walletsData';
@ -13,12 +13,14 @@ const WalletsNativeRender = function() {
<div
id="easydex-header-div"
className="background-color-white"
style={{ 'backgroundImage': `url("assets/images/bg/${this.defaultBG()}_transparent_header_bg.png")` }}>
<ol className="breadcrumb">
style={ this.getCoinStyle('transparent') }>
<ol className={ (!this.state.nativeOnly ? 'breadcrumb breadcrumb--normal' : 'breadcrumb') + (this.props.ActiveCoin.coin === 'KMD' || this.props.ActiveCoin.coin === 'JUMBLR' || this.props.ActiveCoin.coin === 'MESH' || this.props.ActiveCoin.coin === 'MVP' ? ' coin-logo-wide' : '') + (this.state.nativeOnly ? ' native-coin-logo' : '') }>
<li className="header-easydex-section">
<img src={ `assets/images/native/${this.defaultBG()}_header_title_logo.png` } />
{ this.getCoinStyle('title') &&
<img src={ this.getCoinStyle('title') } />
}
<span
className={ `easydex-section-image ${(this.props.ActiveCoin.coin === 'KMD' ? 'hide' : '')}` }
className={ `easydex-section-image ${(this.props.ActiveCoin.coin === 'KMD' || this.props.ActiveCoin.coin === 'JUMBLR' || this.props.ActiveCoin.coin === 'MESH' || this.props.ActiveCoin.coin === 'MVP' ? 'hide' : '')}` }
style={{ marginLeft: '20px' }}>
{ this.props.ActiveCoin.coin }
</span>
@ -32,7 +34,7 @@ const WalletsNativeRender = function() {
<ReceiveCoin {...this.props.ActiveCoin} />
<WalletsData {...this.props} />
<WalletsNativeSend {...this.props} />
<WalletsNativeInfo {...this.props} />
<WalletsInfo {...this.props} />
</div>
</div>
</div>

21
react/src/components/dashboard/walletsNativeInfo/walletsNativeInfo.js

@ -1,21 +0,0 @@
import React from 'react';
import WalletsNativeInfoRender from './walletsNativeInfo.render';
class WalletsNativeInfo extends React.Component {
constructor(props) {
super(props);
}
render() {
if (this.props &&
this.props.Dashboard &&
this.props.Dashboard.progress &&
this.props.ActiveCoin.nativeActiveSection === 'settings') {
return WalletsNativeInfoRender.call(this);
}
return null;
}
}
export default WalletsNativeInfo;

11
react/src/components/dashboard/walletsNativeSend/walletsNativeSend.js

@ -12,7 +12,9 @@ import Store from '../../../store';
import {
AddressListRender,
OASendUIRender,
WalletsNativeSendRender
WalletsNativeSendRender,
WalletsNativeSendFormRender,
_WalletsNativeSendFormRender
} from './walletsNativeSend.render';
class WalletsNativeSend extends React.Component {
@ -37,6 +39,11 @@ class WalletsNativeSend extends React.Component {
this.checkZAddressCount = this.checkZAddressCount.bind(this);
this.setRecieverFromScan = this.setRecieverFromScan.bind(this);
this.renderOPIDListCheck = this.renderOPIDListCheck.bind(this);
this.WalletsNativeSendFormRender = _WalletsNativeSendFormRender.bind(this);
}
WalletsNativeSendFormRender() {
return this._WalletsNativeSendFormRender();
}
componentWillMount() {
@ -344,7 +351,7 @@ class WalletsNativeSend extends React.Component {
render() {
if (this.props &&
this.props.ActiveCoin &&
this.props.ActiveCoin.nativeActiveSection === 'send') {
(this.props.ActiveCoin.activeSection === 'send' || this.props.activeSection === 'send')) {
return WalletsNativeSendRender.call(this);
}

46
react/src/components/dashboard/walletsNativeSend/walletsNativeSend.render.js

@ -65,24 +65,8 @@ export const OASendUIRender = function() {
);
};
export const WalletsNativeSendRender = function() {
export const _WalletsNativeSendFormRender = function() {
return (
<div id="kmd_wallet_send">
<div className="col-xlg-12 col-md-12 col-sm-12 col-xs-12">
<div
className="panel"
id="projects">
<div className="panel-heading">
<h3 className="panel-title">
{ translate('INDEX.SEND') } { this.props.ActiveCoin.coin }
</h3>
</div>
<div className="qr-modal-send-block">
<QRModal
mode="scan"
setRecieverFromScan={ this.setRecieverFromScan } />
</div>
<div className="panel-body container-fluid">
<form
className="extcoin-send-form"
method="post"
@ -162,6 +146,33 @@ export const WalletsNativeSendRender = function() {
</div>
</div>
</form>
);
}
export const WalletsNativeSendRender = function() {
if (this.props.renderFormOnly) {
return (
<div>{ this.WalletsNativeSendFormRender() }</div>
);
} else {
return (
<div id="kmd_wallet_send">
<div className="col-xlg-12 col-md-12 col-sm-12 col-xs-12">
<div
className="panel"
id="projects">
<div className="panel-heading">
<h3 className="panel-title">
{ translate('INDEX.SEND') } { this.props.ActiveCoin.coin }
</h3>
</div>
<div className="qr-modal-send-block">
<QRModal
mode="scan"
setRecieverFromScan={ this.setRecieverFromScan } />
</div>
<div className="panel-body container-fluid">
{ this.WalletsNativeSendFormRender() }
</div>
</div>
</div>
@ -212,4 +223,5 @@ export const WalletsNativeSendRender = function() {
}
</div>
);
}
};

6
react/src/components/dashboard/walletsNav/walletsNav.js

@ -73,7 +73,7 @@ class WalletsNav extends React.Component {
if (this.props.ActiveCoin.mode === 'native') {
Store.dispatch(
toggleDashboardActiveSection(
this.props.ActiveCoin.nativeActiveSection === 'settings' ? 'default' : 'settings'
this.props.ActiveCoin.activeSection === 'settings' ? 'default' : 'settings'
)
);
} else {
@ -93,7 +93,7 @@ class WalletsNav extends React.Component {
if (this.props.ActiveCoin.mode === 'native') {
Store.dispatch(
toggleDashboardActiveSection(
this.props.ActiveCoin.nativeActiveSection === 'send' ? 'default' : 'send'
this.props.ActiveCoin.activeSection === 'send' ? 'default' : 'send'
)
);
} else {
@ -105,7 +105,7 @@ class WalletsNav extends React.Component {
if (this.props.ActiveCoin.mode === 'native') {
Store.dispatch(
toggleDashboardActiveSection(
this.props.ActiveCoin.nativeActiveSection === 'receive' ? 'default' : 'receive'
this.props.ActiveCoin.activeSection === 'receive' ? 'default' : 'receive'
)
);
} else {

4
react/src/components/dashboard/walletsNav/walletsNav.render.js

@ -24,9 +24,9 @@ export const WalletsNavWithWalletRender = function() {
return (
<div>
<div
className={ 'page-header page-header-bordered header-easydex padding-bottom-' + (this.state.nativeOnly ? '40' : '20') }
className={ 'page-header page-header-bordered header-easydex padding-bottom-' + (this.state.nativeOnly ? '40 page-header--native' : '20') }
id="header-dashboard"
style={{ marginBottom: this.props.ActiveCoin.mode === 'basilisk' ? '30px' : '0' }}>
style={{ marginBottom: this.props.ActiveCoin.mode === 'basilisk' ? '30px' : (this.state.nativeOnly ? '30px' : '0') }}>
<ol className={ this.state.nativeOnly ? 'hide' : 'breadcrumb' }>
<strong>{ translate('INDEX.MY') } { this.props && this.props.ActiveCoin ? this.props.ActiveCoin.coin : '-' } { translate('INDEX.ADDRESS') }: </strong>
{ this.props && this.props.Dashboard && this.props.Dashboard.activeHandle ? this.props.Dashboard.activeHandle[this.props.ActiveCoin.coin] : '-' }

2
react/src/components/dashboard/walletsTxInfo/walletsTxInfo.js

@ -43,7 +43,7 @@ class WalletsTxInfo extends React.Component {
// TODO the conditions below should be merged once the native mode components are fully merged
// into the rest of the components
(!this.isNativeMode() ||
(this.isNativeMode() && this.props.ActiveCoin.nativeActiveSection === 'default'))) {
(this.isNativeMode() && this.props.ActiveCoin.activeSection === 'default'))) {
const txInfo = sortByDate(this.props.ActiveCoin.txhistory)[this.props.ActiveCoin.showTransactionInfoTxIndex];
return WalletsTxInfoRender.call(this, txInfo);
}

16
react/src/components/main/main.js

@ -5,7 +5,8 @@ import Store from '../../store';
import {
Config,
getDexCoins,
iguanaActiveHandle
iguanaActiveHandle,
triggerToaster
} from '../../actions/actionCreators';
const IGUANA_ACTIVE_HANDLE_TIMEOUT = 30000;
@ -24,15 +25,28 @@ class Main extends React.Component {
componentDidMount() {
let appVersion;
let zcashParamsExist;
try {
appVersion = window.require('electron').remote.getCurrentWindow().appBasicInfo;
zcashParamsExist = window.require('electron').remote.getCurrentWindow().zcashParamsExist;
} catch (e) {}
if (appVersion) {
document.title = `${appVersion.name} (v${appVersion.version.replace('version=', '')}-beta)`;
}
if (!zcashParamsExist) {
Store.dispatch(
triggerToaster(
'Zcash params are missing',
'Komodo',
'error',
false
)
);
}
Store.dispatch(iguanaActiveHandle());
const _iguanaActiveHandle = setInterval(function() {
Store.dispatch(iguanaActiveHandle());

245
react/src/components/overrides.scss

@ -94,7 +94,8 @@ body {
display: block;
}
.collapse-active {
.collapse-active,
.panel>:not(.panel-loading):not(.collapsing) {
transition: height 0.3s ease-out;
}
@ -628,12 +629,19 @@ select{
> div {
height: 100%;
}
.form-group {
&.form-material {
&.floating {
height: 80%;
}
}
}
.page-content {
width: 90%;
height: 100%;
textarea {
min-height: 200px;
height: 100%;
}
}
}
@ -685,3 +693,236 @@ select{
}
}
}
.breadcrumb {
padding: 8px 30px 0;
position: relative;
top: -10px;
}
.header-easydex-section {
img {
max-width: 60px;
}
}
.coin-logo-wide {
padding: 8px 30px 0;
position: relative;
top: 0;
.header-easydex-section {
img {
width: inherit;
max-width: inherit;
position: relative;
top: -5px;
}
}
}
.native-coin-logo {
float: left;
position: absolute;
top: -105px;
z-index: 100;
.header-easydex-section {
img {
width: 60px;
}
}
}
.coin-logo-wide {
&.native-coin-logo {
top: -93px;
.header-easydex-section img {
width: inherit;
}
}
}
.page-header--native {
height: 75px;
}
#toast-container {
> div {
opacity: 1;
}
}
/* jumblr */
.jumblr {
p {
width: calc(100% - 100px);
}
.breadcrumb {
padding: 8px 30px;
position: relative;
top: 0;
}
.img-responsive {
position: absolute;
top: -28px;
right: 18px;
.coin {
font-size: 30px;
position: relative;
left: -18px;
top: 4px;
}
.image {
width: 60px;
}
}
.header-easydex-section {
img {
max-width: inherit;
}
}
.copy-string-btn {
position: absolute;
right: 36px;
margin-top: -68px;
}
.btn-next {
position: absolute;
top: 60px;
right: 32px;
}
input.labelauty+label,
input.labelauty+label {
background: #d6d5d5;
color: #504e4e;
}
input.labelauty:checked+label {
color: #fff;
background-color: #3949ab;
}
input.labelauty + label:hover .labelauty-unchecked,
input.labelauty + label .labelauty-unchecked {
color: #504e4e;
}
.nofloat {
float: none;
display: inline-block;
padding-left: 0;
}
}
.jumblr-mode-selector {
.nav-tabs {
li {
cursor: pointer;
&.active {
> a {
cursor: pointer;
color: #fff;
background-color: #62a8ea;
border-color: transparent;
border-bottom-color: #62a8ea;
}
}
}
}
.panel-heading {
background: #f3f3f3;
cursor: pointer;
}
.panel-title {
color: #676767;
}
.jumblr-addresses-list {
.col-xs-3 {
padding: 0;
}
}
}
.modal-claim-interest {
.modal-dialog {
width: 70%;
.table > tbody > tr > td,
.table > tbody > tr > th,
.table > tfoot > tr > td,
.table > tfoot > tr > th,
.table > thead > tr > td,
.table > thead > tr > th {
padding: 8px 30px 8px 0;
}
.claim-btn {
position: absolute;
right: 29px;
top: 66px;
}
.table-scroll {
height: 366px;
overflow-y: auto;
overflow-x: hidden;
width: 100%;
}
.bold {
font-weight: bold;
}
.green {
color: #66bb6a;
}
.red {
color: #f96868;
}
.locktime {
i {
font-size: 20px;
line-height: 1.1;
}
}
.refresh-icon {
position: absolute;
right: 20px;
font-size: 20px;
z-index: 100;
}
}
}
.ReactTable {
border: none;
.pagination-top {
display: none;
}
.rt-td {
text-align: center;
}
.ReactTable .rt-thead .rt-th,
.ReactTable .rt-thead .rt-td {
padding: 10px 5px;
}
.rt-table {
border: 1px solid rgba(0, 0, 0, 0.1);
}
.rt-tfoot {
border-top: 1px solid rgba(0, 0, 0, 0.1);
}
.rt-thead {
border-bottom: 1px solid rgba(0, 0, 0, 0.1);
}
.rt-thead .rt-th,
.rt-thead .rt-td {
padding: 10px 5px;
}
.colum--direction {
width: 40px !important;
flex: 40 0 auto !important;
padding-right: 10px;
}
}

14
react/src/reducers/activeCoin.js

@ -27,7 +27,7 @@ export function ActiveCoin(state = {
send: false,
receive: false,
balance: 0,
nativeActiveSection: 'default',
activeSection: 'default',
showTransactionInfo: false,
showTransactionInfoTxIndex: null,
txhistory: [],
@ -53,7 +53,7 @@ export function ActiveCoin(state = {
receive: state.receive,
showTransactionInfo: state.showTransactionInfo,
showTransactionInfoTxIndex: state.showTransactionInfoTxIndex,
nativeActiveSection: state.nativeActiveSection,
activeSection: state.activeSection,
lastSendToResponse: state.lastSendToResponse,
mainBasiliskAddress: state.mainBasiliskAddress,
opids: state.opids,
@ -73,7 +73,7 @@ export function ActiveCoin(state = {
receive: _coinData.receive,
showTransactionInfo: _coinData.showTransactionInfo,
showTransactionInfoTxIndex: _coinData.showTransactionInfoTxIndex,
nativeActiveSection: _coinData.nativeActiveSection,
activeSection: _coinData.activeSection,
lastSendToResponse: _coinData.lastSendToResponse,
mainBasiliskAddress: _coinData.mainBasiliskAddress,
opids: _coinData.opids,
@ -91,7 +91,7 @@ export function ActiveCoin(state = {
receive: state.receive,
showTransactionInfo: state.showTransactionInfo,
showTransactionInfoTxIndex: state.showTransactionInfoTxIndex,
nativeActiveSection: state.nativeActiveSection,
activeSection: state.activeSection,
lastSendToResponse: state.lastSendToResponse,
mainBasiliskAddress: state.mainBasiliskAddress,
opids: state.opids,
@ -110,7 +110,7 @@ export function ActiveCoin(state = {
receive: false,
showTransactionInfo: false,
showTransactionInfoTxIndex: null,
nativeActiveSection: 'default',
activeSection: 'default',
});
} else {
return Object.assign({}, state, {
@ -122,7 +122,7 @@ export function ActiveCoin(state = {
receive: false,
showTransactionInfo: false,
showTransactionInfoTxIndex: null,
nativeActiveSection: 'default',
activeSection: 'default',
});
}
}
@ -151,7 +151,7 @@ export function ActiveCoin(state = {
});
case DASHBOARD_ACTIVE_SECTION:
return Object.assign({}, state, {
nativeActiveSection: action.section,
activeSection: action.section,
});
case DASHBOARD_ACTIVE_TXINFO_MODAL:
return Object.assign({}, state, {

9
react/src/reducers/dashboard.js

@ -9,7 +9,8 @@ import {
VIEW_CACHE_DATA,
LOG_GUI_HTTP,
TOGGLE_NOTIFICATIONS_MODAL,
DISPLAY_COIND_DOWN_MODAL
DISPLAY_COIND_DOWN_MODAL,
DISPLAY_CLAIM_INTEREST_MODAL
} from '../actions/storeType';
const HTTP_STACK_MAX_ENTRIES = 150; // limit stack mem length to N records per type
@ -38,6 +39,7 @@ export function Dashboard(state = {
},
guiLog: {},
displayCoindDownModal: false,
displayClaimInterestModal: false,
}, action) {
switch (action.type) {
case DASHBOARD_SECTION_CHANGE:
@ -104,6 +106,11 @@ export function Dashboard(state = {
displayCoindDownModal: action.displayCoindDownModal,
});
break;
case DISPLAY_CLAIM_INTEREST_MODAL:
return Object.assign({}, state, {
displayClaimInterestModal: action.displayClaimInterestModal,
});
break;
default:
return state;
}

4
react/src/translate/en.js

@ -281,7 +281,7 @@ export const _lang = {
},
'JUMBLR': {
'NOTICE': 'EXPERIMENTAL TEST VERSION ONLY',
'DESCRIPTION': 'Jumblr feature is very experimental and for now, is Only enabled for testing and debugging.' +
'DESCRIPTION': 'Jumblr feature is very experimental and for now, is Only enabled for testing and debugging. ' +
'Please use the current version of Jumblr only with small amounts if you are participating in testing this feature.',
'NEED_NATIVE': 'Need Native Mode Komodo',
'TO_USE_JUMBLR': 'To use Jumblr feature, you need to activate Komodo in Native Mode.',
@ -289,7 +289,7 @@ export const _lang = {
'THIS_SCREEN_DOESNT_REFRESH': 'This screen does not auto refresh. ' +
'You will need to hit the Refresh button on the top right corner of the screen to get latest Jumblr data.',
'FEW_SECURITY_NOTES': 'Few Security Notes for your Privacy and Anonymity of funds',
'FEW_SECURITY_NOTES_DESC1': 'Jumblr addresses (BTC Jumbler and KMD Jumbler) addresses are your Private Addresses.',
'FEW_SECURITY_NOTES_DESC1': 'Jumblr addresses addresses are your Private Addresses.',
'FEW_SECURITY_NOTES_DESC2': 'DO NOT SHARE your Jumblr addresses with anyone.',
'FEW_SECURITY_NOTES_DESC3': 'Jumblr addresses are like YOUR PASSWORD. Keep them safe, secure and hidden.',
'FEW_SECURITY_NOTES_DESC4': 'Only YOU should know your Jumblr Address. Nobody else.',

91
react/src/util/coinHelper.js

@ -1,6 +1,9 @@
export function getCoinTitle(coin) {
let coinlogo,
coinname;
let coinlogo;
let coinname;
let transparentBG = false;
let titleBG = false;
let hideTitle = false;
switch (coin) {
case 'BTC':
@ -56,7 +59,10 @@ export function getCoinTitle(coin) {
coinname = 'Zetacoin';
break;
case 'KMD':
coinlogo = 'komodo';
hideTitle = true;
titleBG = true;
transparentBG = true;
coinlogo = 'kmd';
coinname = 'Komodo';
break;
case 'BTM':
@ -80,6 +86,7 @@ export function getCoinTitle(coin) {
coinname = 'GameCredits';
break;
case 'SUPERNET':
titleBG = true;
coinlogo = 'SUPERNET';
coinname = 'SUPERNET';
break;
@ -88,14 +95,20 @@ export function getCoinTitle(coin) {
coinname = 'REVS';
break;
case 'WLC':
titleBG = true;
transparentBG = true;
coinlogo = 'WLC';
coinname = 'WIRELESS';
break;
case 'PANGEA':
titleBG = true;
coinlogo = 'PANGEA';
coinname = 'PANGEA';
break;
case 'JUMBLR':
titleBG = true;
transparentBG = true;
hideTitle = true;
coinlogo = 'JUMBLR';
coinname = 'JUMBLR';
break;
@ -124,6 +137,9 @@ export function getCoinTitle(coin) {
coinname = 'MultiGateway';
break;
case 'MVP':
hideTitle = true;
titleBG = true;
transparentBG = true;
coinlogo = 'MVP';
coinname = 'MVP Lineup';
break;
@ -132,138 +148,197 @@ export function getCoinTitle(coin) {
coinname = 'KV';
break;
case 'CEAL':
titleBG = true;
transparentBG = true;
coinlogo = 'CEAL';
coinname = 'CEAL NET';
break;
case 'COQUI':
coinlogo = 'COQUI';
coinname = 'COQUI';
break;
case 'MESH':
hideTitle = true;
titleBG = true;
transparentBG = true;
coinlogo = 'MESH';
coinname = 'SpaceMesh';
break;
case 'USD':
titleBG = true;
transparentBG = true;
coinlogo = 'usd';
coinname = 'US Dollar';
break;
case 'RON':
titleBG = true;
transparentBG = true;
coinlogo = 'RON';
coinname = 'Romanian Leu';
break;
case 'EUR':
titleBG = true;
transparentBG = true;
coinlogo = 'EUR';
coinname = 'Euro';
break;
case 'JPY':
titleBG = true;
transparentBG = true;
coinlogo = 'JPY';
coinname = 'Japanese Yen';
break;
case 'GBP':
titleBG = true;
transparentBG = true;
coinlogo = 'GBP';
coinname = 'British Pound';
break;
case 'AUD':
titleBG = true;
transparentBG = true;
coinlogo = 'AUD';
coinname = 'Australian Dollar';
break;
case 'CAD':
titleBG = true;
transparentBG = true;
coinlogo = 'CAD';
coinname = 'Canadian Dollar';
break;
case 'CHF':
titleBG = true;
transparentBG = true;
coinlogo = 'CHF';
coinname = 'Swiss Franc';
break;
case 'NZD':
titleBG = true;
transparentBG = true;
coinlogo = 'NZD';
coinname = 'New Zealand Dollar';
break;
case 'CNY':
titleBG = true;
transparentBG = true;
coinlogo = 'CNY';
coinname = 'Chinese Yuan';
break;
case 'RUB':
titleBG = true;
transparentBG = true;
coinlogo = 'RUB';
coinname = 'Russian Ruble';
break;
case 'MXN':
titleBG = true;
transparentBG = true;
coinlogo = 'MXN';
coinname = 'Mexican peso';
break;
case 'BRL':
titleBG = true;
transparentBG = true;
coinlogo = 'BRL';
coinname = 'Brazilian Real';
break;
case 'INR':
titleBG = true;
transparentBG = true;
coinlogo = 'INR';
coinname = 'Indian Rupee';
break;
case 'HKD':
titleBG = true;
transparentBG = true;
coinlogo = 'HKD';
coinname = 'Hong Kong Dollar';
break;
case 'TRY':
titleBG = true;
transparentBG = true;
coinlogo = 'TRY';
coinname = 'Turkish Lira';
break;
case 'ZAR':
titleBG = true;
transparentBG = true;
coinlogo = 'ZAR';
coinname = 'South African Rand';
break;
case 'PLN':
titleBG = true;
transparentBG = true;
coinlogo = 'PLN';
coinname = 'Polish Zloty';
break;
case 'NOK':
titleBG = true;
coinlogo = 'NOK';
coinname = 'Norwegian Krone';
break;
case 'SEK':
titleBG = true;
coinlogo = 'SEK';
coinname = 'Swedish Krona';
break;
case 'DKK':
titleBG = true;
coinlogo = 'DKK';
coinname = 'Danish Krone';
break;
case 'CZK':
titleBG = true;
coinlogo = 'CZK';
coinname = 'Czech Koruna';
break;
case 'HUF':
titleBG = true;
coinlogo = 'HUF';
coinname = 'Hungarian Forint';
break;
case 'ILS':
titleBG = true;
coinlogo = 'ILS';
coinname = 'Israeli Shekel';
break;
case 'KRW':
titleBG = true;
coinlogo = 'KRW';
coinname = 'Korean Won';
break;
case 'MYR':
titleBG = true;
coinlogo = 'MYR';
coinname = 'Malaysian Ringgit';
break;
case 'PHP':
titleBG = true;
coinlogo = 'PHP';
coinname = 'Philippine Peso';
break;
case 'SGD':
titleBG = true;
coinlogo = 'SGD';
coinname = 'Singapore Dollar';
break;
case 'THB':
titleBG = true;
coinlogo = 'THB';
coinname = 'Thai Baht';
break;
case 'BGN':
titleBG = true;
coinlogo = 'BGN';
coinname = 'Bulgarian Lev';
break;
case 'IDR':
titleBG = true;
coinlogo = 'IDR';
coinname = 'Indonesian Rupiah';
break;
case 'HRK':
titleBG = true;
coinlogo = 'HRK';
coinname = 'Croatian Kuna';
break;
@ -271,14 +346,16 @@ export function getCoinTitle(coin) {
return {
'logo': coinlogo,
'name': coinname
'name': coinname,
titleBG,
transparentBG,
};
}
export function getModeInfo(mode) {
let modecode,
modetip,
modecolor;
let modecode;
let modetip;
let modecolor;
switch (mode) {
case 'native':

57
react/src/util/crypto/gen/array.map.js

@ -0,0 +1,57 @@
// Array.prototype.map function is in the public domain.
// Production steps of ECMA-262, Edition 5, 15.4.4.19
// Reference: http://es5.github.com/#x15.4.4.19
if (!Array.prototype.map) {
Array.prototype.map = function (callback, thisArg) {
var T, A, k;
if (this == null) {
throw new TypeError(" this is null or not defined");
}
// 1. Let O be the result of calling ToObject passing the |this| value as the argument.
var O = Object(this);
// 2. Let lenValue be the result of calling the Get internal method of O with the argument "length".
// 3. Let len be ToUint32(lenValue).
var len = O.length >>> 0;
// 4. If IsCallable(callback) is false, throw a TypeError exception.
// See: http://es5.github.com/#x9.11
if ({}.toString.call(callback) != "[object Function]") {
throw new TypeError(callback + " is not a function");
}
// 5. If thisArg was supplied, let T be thisArg; else let T be undefined.
if (thisArg) {
T = thisArg;
}
// 6. Let A be a new array created as if by the expression new Array(len) where Array is
// the standard built-in constructor with that name and len is the value of len.
A = new Array(len);
// 7. Let k be 0
k = 0;
// 8. Repeat, while k < len
while (k < len) {
var kValue, mappedValue;
// a. Let Pk be ToString(k).
// This is implicit for LHS operands of the in operator
// b. Let kPresent be the result of calling the HasProperty internal method of O with argument Pk.
// This step can be combined with c
// c. If kPresent is true, then
if (k in O) {
// i. Let kValue be the result of calling the Get internal method of O with argument Pk.
kValue = O[k];
// ii. Let mappedValue be the result of calling the Call internal method of callback
// with T as the this value and argument list containing kValue, k, and O.
mappedValue = callback.call(T, kValue, k, O);
// iii. Call the DefineOwnProperty internal method of A with arguments
// Pk, Property Descriptor {Value: mappedValue, Writable: true, Enumerable: true, Configurable: true},
// and false.
// In browsers that support Object.defineProperty, use the following:
// Object.defineProperty(A, Pk, { value: mappedValue, writable: true, enumerable: true, configurable: true });
// For best browser support, use the following:
A[k] = mappedValue;
}
// d. Increase k by 1.
k++;
}
// 9. return A
return A;
};
}

1271
react/src/util/crypto/gen/biginteger.js

File diff suppressed because it is too large

1974
react/src/util/crypto/gen/bitcoin.js

File diff suppressed because it is too large

295
react/src/util/crypto/gen/crypto-scrypt.js

@ -0,0 +1,295 @@
/*
* Copyright (c) 2010-2011 Intalio Pte, All Rights Reserved
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
// https://github.com/cheongwy/node-scrypt-js
(function () {
var MAX_VALUE = 2147483647;
var workerUrl = null;
//function scrypt(byte[] passwd, byte[] salt, int N, int r, int p, int dkLen)
/*
* N = Cpu cost
* r = Memory cost
* p = parallelization cost
*
*/
window.Crypto_scrypt = function (passwd, salt, N, r, p, dkLen, callback) {
if (N == 0 || (N & (N - 1)) != 0) throw Error("N must be > 0 and a power of 2");
if (N > MAX_VALUE / 128 / r) throw Error("Parameter N is too large");
if (r > MAX_VALUE / 128 / p) throw Error("Parameter r is too large");
var PBKDF2_opts = { iterations: 1, hasher: Crypto.SHA256, asBytes: true };
var B = Crypto.PBKDF2(passwd, salt, p * 128 * r, PBKDF2_opts);
try {
var i = 0;
var worksDone = 0;
var makeWorker = function () {
if (!workerUrl) {
var code = '(' + scryptCore.toString() + ')()';
var blob;
try {
blob = new Blob([code], { type: "text/javascript" });
} catch (e) {
window.BlobBuilder = window.BlobBuilder || window.WebKitBlobBuilder || window.MozBlobBuilder || window.MSBlobBuilder;
blob = new BlobBuilder();
blob.append(code);
blob = blob.getBlob("text/javascript");
}
workerUrl = URL.createObjectURL(blob);
}
var worker = new Worker(workerUrl);
worker.onmessage = function (event) {
var Bi = event.data[0], Bslice = event.data[1];
worksDone++;
if (i < p) {
worker.postMessage([N, r, p, B, i++]);
}
var length = Bslice.length, destPos = Bi * 128 * r, srcPos = 0;
while (length--) {
B[destPos++] = Bslice[srcPos++];
}
if (worksDone == p) {
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts));
}
};
return worker;
};
var workers = [makeWorker(), makeWorker()];
workers[0].postMessage([N, r, p, B, i++]);
if (p > 1) {
workers[1].postMessage([N, r, p, B, i++]);
}
} catch (e) {
window.setTimeout(function () {
scryptCore();
callback(Crypto.PBKDF2(passwd, B, dkLen, PBKDF2_opts));
}, 0);
}
// using this function to enclose everything needed to create a worker (but also invokable directly for synchronous use)
function scryptCore() {
var XY = [], V = [];
if (typeof B === 'undefined') {
onmessage = function (event) {
var data = event.data;
var N = data[0], r = data[1], p = data[2], B = data[3], i = data[4];
var Bslice = [];
arraycopy32(B, i * 128 * r, Bslice, 0, 128 * r);
smix(Bslice, 0, r, N, V, XY);
postMessage([i, Bslice]);
};
} else {
for (var i = 0; i < p; i++) {
smix(B, i * 128 * r, r, N, V, XY);
}
}
function smix(B, Bi, r, N, V, XY) {
var Xi = 0;
var Yi = 128 * r;
var i;
arraycopy32(B, Bi, XY, Xi, Yi);
for (i = 0; i < N; i++) {
arraycopy32(XY, Xi, V, i * Yi, Yi);
blockmix_salsa8(XY, Xi, Yi, r);
}
for (i = 0; i < N; i++) {
var j = integerify(XY, Xi, r) & (N - 1);
blockxor(V, j * Yi, XY, Xi, Yi);
blockmix_salsa8(XY, Xi, Yi, r);
}
arraycopy32(XY, Xi, B, Bi, Yi);
}
function blockmix_salsa8(BY, Bi, Yi, r) {
var X = [];
var i;
arraycopy32(BY, Bi + (2 * r - 1) * 64, X, 0, 64);
for (i = 0; i < 2 * r; i++) {
blockxor(BY, i * 64, X, 0, 64);
salsa20_8(X);
arraycopy32(X, 0, BY, Yi + (i * 64), 64);
}
for (i = 0; i < r; i++) {
arraycopy32(BY, Yi + (i * 2) * 64, BY, Bi + (i * 64), 64);
}
for (i = 0; i < r; i++) {
arraycopy32(BY, Yi + (i * 2 + 1) * 64, BY, Bi + (i + r) * 64, 64);
}
}
function R(a, b) {
return (a << b) | (a >>> (32 - b));
}
function salsa20_8(B) {
var B32 = new Array(32);
var x = new Array(32);
var i;
for (i = 0; i < 16; i++) {
B32[i] = (B[i * 4 + 0] & 0xff) << 0;
B32[i] |= (B[i * 4 + 1] & 0xff) << 8;
B32[i] |= (B[i * 4 + 2] & 0xff) << 16;
B32[i] |= (B[i * 4 + 3] & 0xff) << 24;
}
arraycopy(B32, 0, x, 0, 16);
for (i = 8; i > 0; i -= 2) {
x[4] ^= R(x[0] + x[12], 7); x[8] ^= R(x[4] + x[0], 9);
x[12] ^= R(x[8] + x[4], 13); x[0] ^= R(x[12] + x[8], 18);
x[9] ^= R(x[5] + x[1], 7); x[13] ^= R(x[9] + x[5], 9);
x[1] ^= R(x[13] + x[9], 13); x[5] ^= R(x[1] + x[13], 18);
x[14] ^= R(x[10] + x[6], 7); x[2] ^= R(x[14] + x[10], 9);
x[6] ^= R(x[2] + x[14], 13); x[10] ^= R(x[6] + x[2], 18);
x[3] ^= R(x[15] + x[11], 7); x[7] ^= R(x[3] + x[15], 9);
x[11] ^= R(x[7] + x[3], 13); x[15] ^= R(x[11] + x[7], 18);
x[1] ^= R(x[0] + x[3], 7); x[2] ^= R(x[1] + x[0], 9);
x[3] ^= R(x[2] + x[1], 13); x[0] ^= R(x[3] + x[2], 18);
x[6] ^= R(x[5] + x[4], 7); x[7] ^= R(x[6] + x[5], 9);
x[4] ^= R(x[7] + x[6], 13); x[5] ^= R(x[4] + x[7], 18);
x[11] ^= R(x[10] + x[9], 7); x[8] ^= R(x[11] + x[10], 9);
x[9] ^= R(x[8] + x[11], 13); x[10] ^= R(x[9] + x[8], 18);
x[12] ^= R(x[15] + x[14], 7); x[13] ^= R(x[12] + x[15], 9);
x[14] ^= R(x[13] + x[12], 13); x[15] ^= R(x[14] + x[13], 18);
}
for (i = 0; i < 16; ++i) B32[i] = x[i] + B32[i];
for (i = 0; i < 16; i++) {
var bi = i * 4;
B[bi + 0] = (B32[i] >> 0 & 0xff);
B[bi + 1] = (B32[i] >> 8 & 0xff);
B[bi + 2] = (B32[i] >> 16 & 0xff);
B[bi + 3] = (B32[i] >> 24 & 0xff);
}
}
function blockxor(S, Si, D, Di, len) {
var i = len >> 6;
while (i--) {
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
D[Di++] ^= S[Si++]; D[Di++] ^= S[Si++];
}
}
function integerify(B, bi, r) {
var n;
bi += (2 * r - 1) * 64;
n = (B[bi + 0] & 0xff) << 0;
n |= (B[bi + 1] & 0xff) << 8;
n |= (B[bi + 2] & 0xff) << 16;
n |= (B[bi + 3] & 0xff) << 24;
return n;
}
function arraycopy(src, srcPos, dest, destPos, length) {
while (length--) {
dest[destPos++] = src[srcPos++];
}
}
function arraycopy32(src, srcPos, dest, destPos, length) {
var i = length >> 5;
while (i--) {
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
dest[destPos++] = src[srcPos++]; dest[destPos++] = src[srcPos++];
}
}
} // scryptCore
}; // window.Crypto_scrypt
})();

407
react/src/util/crypto/gen/cryptojs.aes.js

@ -0,0 +1,407 @@
/*!
* Crypto-JS v2.5.4 AES.js
* http://code.google.com/p/crypto-js/
* Copyright (c) 2009-2013, Jeff Mott. All rights reserved.
* http://code.google.com/p/crypto-js/wiki/License
*/
(function () {
// Shortcuts
var C = Crypto,
util = C.util,
charenc = C.charenc,
UTF8 = charenc.UTF8;
// Precomputed SBOX
var SBOX = [0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5,
0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc,
0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a,
0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b,
0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85,
0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17,
0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88,
0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9,
0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6,
0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94,
0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68,
0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16];
// Compute inverse SBOX lookup table
for (var INVSBOX = [], i = 0; i < 256; i++) INVSBOX[SBOX[i]] = i;
// Compute multiplication in GF(2^8) lookup tables
var MULT2 = [],
MULT3 = [],
MULT9 = [],
MULTB = [],
MULTD = [],
MULTE = [];
function xtime(a, b) {
for (var result = 0, i = 0; i < 8; i++) {
if (b & 1) result ^= a;
var hiBitSet = a & 0x80;
a = (a << 1) & 0xFF;
if (hiBitSet) a ^= 0x1b;
b >>>= 1;
}
return result;
}
for (var i = 0; i < 256; i++) {
MULT2[i] = xtime(i, 2);
MULT3[i] = xtime(i, 3);
MULT9[i] = xtime(i, 9);
MULTB[i] = xtime(i, 0xB);
MULTD[i] = xtime(i, 0xD);
MULTE[i] = xtime(i, 0xE);
}
// Precomputed RCon lookup
var RCON = [0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36];
// Inner state
var state = [[], [], [], []],
keylength,
nrounds,
keyschedule;
var AES = C.AES = {
/**
* Public API
*/
encrypt: function (message, password, options) {
options = options || {};
// Determine mode
var mode = options.mode || new C.mode.OFB;
// Allow mode to override options
if (mode.fixOptions) mode.fixOptions(options);
var
// Convert to bytes if message is a string
m = (
message.constructor == String ?
UTF8.stringToBytes(message) :
message
),
// Generate random IV
iv = options.iv || util.randomBytes(AES._blocksize * 4),
// Generate key
k = (
password.constructor == String ?
// Derive key from pass-phrase
C.PBKDF2(password, iv, 32, { asBytes: true }) :
// else, assume byte array representing cryptographic key
password
);
// Encrypt
AES._init(k);
mode.encrypt(AES, m, iv);
// Return ciphertext
m = options.iv ? m : iv.concat(m);
return (options && options.asBytes) ? m : util.bytesToBase64(m);
},
decrypt: function (ciphertext, password, options) {
options = options || {};
// Determine mode
var mode = options.mode || new C.mode.OFB;
// Allow mode to override options
if (mode.fixOptions) mode.fixOptions(options);
var
// Convert to bytes if ciphertext is a string
c = (
ciphertext.constructor == String ?
util.base64ToBytes(ciphertext) :
ciphertext
),
// Separate IV and message
iv = options.iv || c.splice(0, AES._blocksize * 4),
// Generate key
k = (
password.constructor == String ?
// Derive key from pass-phrase
C.PBKDF2(password, iv, 32, { asBytes: true }) :
// else, assume byte array representing cryptographic key
password
);
// Decrypt
AES._init(k);
mode.decrypt(AES, c, iv);
// Return plaintext
return (options && options.asBytes) ? c : UTF8.bytesToString(c);
},
/**
* Package private methods and properties
*/
_blocksize: 4,
_encryptblock: function (m, offset) {
// Set input
for (var row = 0; row < AES._blocksize; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = m[offset + col * 4 + row];
}
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[col][row];
}
for (var round = 1; round < nrounds; round++) {
// Sub bytes
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = SBOX[state[row][col]];
}
// Shift rows
state[1].push(state[1].shift());
state[2].push(state[2].shift());
state[2].push(state[2].shift());
state[3].unshift(state[3].pop());
// Mix columns
for (var col = 0; col < 4; col++) {
var s0 = state[0][col],
s1 = state[1][col],
s2 = state[2][col],
s3 = state[3][col];
state[0][col] = MULT2[s0] ^ MULT3[s1] ^ s2 ^ s3;
state[1][col] = s0 ^ MULT2[s1] ^ MULT3[s2] ^ s3;
state[2][col] = s0 ^ s1 ^ MULT2[s2] ^ MULT3[s3];
state[3][col] = MULT3[s0] ^ s1 ^ s2 ^ MULT2[s3];
}
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[round * 4 + col][row];
}
}
// Sub bytes
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = SBOX[state[row][col]];
}
// Shift rows
state[1].push(state[1].shift());
state[2].push(state[2].shift());
state[2].push(state[2].shift());
state[3].unshift(state[3].pop());
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[nrounds * 4 + col][row];
}
// Set output
for (var row = 0; row < AES._blocksize; row++) {
for (var col = 0; col < 4; col++)
m[offset + col * 4 + row] = state[row][col];
}
},
_decryptblock: function (c, offset) {
// Set input
for (var row = 0; row < AES._blocksize; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = c[offset + col * 4 + row];
}
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[nrounds * 4 + col][row];
}
for (var round = 1; round < nrounds; round++) {
// Inv shift rows
state[1].unshift(state[1].pop());
state[2].push(state[2].shift());
state[2].push(state[2].shift());
state[3].push(state[3].shift());
// Inv sub bytes
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = INVSBOX[state[row][col]];
}
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[(nrounds - round) * 4 + col][row];
}
// Inv mix columns
for (var col = 0; col < 4; col++) {
var s0 = state[0][col],
s1 = state[1][col],
s2 = state[2][col],
s3 = state[3][col];
state[0][col] = MULTE[s0] ^ MULTB[s1] ^ MULTD[s2] ^ MULT9[s3];
state[1][col] = MULT9[s0] ^ MULTE[s1] ^ MULTB[s2] ^ MULTD[s3];
state[2][col] = MULTD[s0] ^ MULT9[s1] ^ MULTE[s2] ^ MULTB[s3];
state[3][col] = MULTB[s0] ^ MULTD[s1] ^ MULT9[s2] ^ MULTE[s3];
}
}
// Inv shift rows
state[1].unshift(state[1].pop());
state[2].push(state[2].shift());
state[2].push(state[2].shift());
state[3].push(state[3].shift());
// Inv sub bytes
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] = INVSBOX[state[row][col]];
}
// Add round key
for (var row = 0; row < 4; row++) {
for (var col = 0; col < 4; col++)
state[row][col] ^= keyschedule[col][row];
}
// Set output
for (var row = 0; row < AES._blocksize; row++) {
for (var col = 0; col < 4; col++)
c[offset + col * 4 + row] = state[row][col];
}
},
/**
* Private methods
*/
_init: function (k) {
keylength = k.length / 4;
nrounds = keylength + 6;
AES._keyexpansion(k);
},
// Generate a key schedule
_keyexpansion: function (k) {
keyschedule = [];
for (var row = 0; row < keylength; row++) {
keyschedule[row] = [
k[row * 4],
k[row * 4 + 1],
k[row * 4 + 2],
k[row * 4 + 3]
];
}
for (var row = keylength; row < AES._blocksize * (nrounds + 1); row++) {
var temp = [
keyschedule[row - 1][0],
keyschedule[row - 1][1],
keyschedule[row - 1][2],
keyschedule[row - 1][3]
];
if (row % keylength == 0) {
// Rot word
temp.push(temp.shift());
// Sub word
temp[0] = SBOX[temp[0]];
temp[1] = SBOX[temp[1]];
temp[2] = SBOX[temp[2]];
temp[3] = SBOX[temp[3]];
temp[0] ^= RCON[row / keylength];
} else if (keylength > 6 && row % keylength == 4) {
// Sub word
temp[0] = SBOX[temp[0]];
temp[1] = SBOX[temp[1]];
temp[2] = SBOX[temp[2]];
temp[3] = SBOX[temp[3]];
}
keyschedule[row] = [
keyschedule[row - keylength][0] ^ temp[0],
keyschedule[row - keylength][1] ^ temp[1],
keyschedule[row - keylength][2] ^ temp[2],
keyschedule[row - keylength][3] ^ temp[3]
];
}
}
};
})();

410
react/src/util/crypto/gen/cryptojs.blockmodes.js

@ -0,0 +1,410 @@
/*!
* Crypto-JS 2.5.4 BlockModes.js
* contribution from Simon Greatrix
*/
(function (C) {
// Create pad namespace
var C_pad = C.pad = {};
// Calculate the number of padding bytes required.
function _requiredPadding(cipher, message) {
var blockSizeInBytes = cipher._blocksize * 4;
var reqd = blockSizeInBytes - message.length % blockSizeInBytes;
return reqd;
}
// Remove padding when the final byte gives the number of padding bytes.
var _unpadLength = function (cipher, message, alg, padding) {
var pad = message.pop();
if (pad == 0) {
throw new Error("Invalid zero-length padding specified for " + alg
+ ". Wrong cipher specification or key used?");
}
var maxPad = cipher._blocksize * 4;
if (pad > maxPad) {
throw new Error("Invalid padding length of " + pad
+ " specified for " + alg
+ ". Wrong cipher specification or key used?");
}
for (var i = 1; i < pad; i++) {
var b = message.pop();
if (padding != undefined && padding != b) {
throw new Error("Invalid padding byte of 0x" + b.toString(16)
+ " specified for " + alg
+ ". Wrong cipher specification or key used?");
}
}
};
// No-operation padding, used for stream ciphers
C_pad.NoPadding = {
pad: function (cipher, message) { },
unpad: function (cipher, message) { }
};
// Zero Padding.
//
// If the message is not an exact number of blocks, the final block is
// completed with 0x00 bytes. There is no unpadding.
C_pad.ZeroPadding = {
pad: function (cipher, message) {
var blockSizeInBytes = cipher._blocksize * 4;
var reqd = message.length % blockSizeInBytes;
if (reqd != 0) {
for (reqd = blockSizeInBytes - reqd; reqd > 0; reqd--) {
message.push(0x00);
}
}
},
unpad: function (cipher, message) {
while (message[message.length - 1] == 0) {
message.pop();
}
}
};
// ISO/IEC 7816-4 padding.
//
// Pads the plain text with an 0x80 byte followed by as many 0x00
// bytes are required to complete the block.
C_pad.iso7816 = {
pad: function (cipher, message) {
var reqd = _requiredPadding(cipher, message);
message.push(0x80);
for (; reqd > 1; reqd--) {
message.push(0x00);
}
},
unpad: function (cipher, message) {
var padLength;
for (padLength = cipher._blocksize * 4; padLength > 0; padLength--) {
var b = message.pop();
if (b == 0x80) return;
if (b != 0x00) {
throw new Error("ISO-7816 padding byte must be 0, not 0x" + b.toString(16) + ". Wrong cipher specification or key used?");
}
}
throw new Error("ISO-7816 padded beyond cipher block size. Wrong cipher specification or key used?");
}
};
// ANSI X.923 padding
//
// The final block is padded with zeros except for the last byte of the
// last block which contains the number of padding bytes.
C_pad.ansix923 = {
pad: function (cipher, message) {
var reqd = _requiredPadding(cipher, message);
for (var i = 1; i < reqd; i++) {
message.push(0x00);
}
message.push(reqd);
},
unpad: function (cipher, message) {
_unpadLength(cipher, message, "ANSI X.923", 0);
}
};
// ISO 10126
//
// The final block is padded with random bytes except for the last
// byte of the last block which contains the number of padding bytes.
C_pad.iso10126 = {
pad: function (cipher, message) {
var reqd = _requiredPadding(cipher, message);
for (var i = 1; i < reqd; i++) {
message.push(Math.floor(Math.random() * 256));
}
message.push(reqd);
},
unpad: function (cipher, message) {
_unpadLength(cipher, message, "ISO 10126", undefined);
}
};
// PKCS7 padding
//
// PKCS7 is described in RFC 5652. Padding is in whole bytes. The
// value of each added byte is the number of bytes that are added,
// i.e. N bytes, each of value N are added.
C_pad.pkcs7 = {
pad: function (cipher, message) {
var reqd = _requiredPadding(cipher, message);
for (var i = 0; i < reqd; i++) {
message.push(reqd);
}
},
unpad: function (cipher, message) {
_unpadLength(cipher, message, "PKCS 7", message[message.length - 1]);
}
};
// Create mode namespace
var C_mode = C.mode = {};
/**
* Mode base "class".
*/
var Mode = C_mode.Mode = function (padding) {
if (padding) {
this._padding = padding;
}
};
Mode.prototype = {
encrypt: function (cipher, m, iv) {
this._padding.pad(cipher, m);
this._doEncrypt(cipher, m, iv);
},
decrypt: function (cipher, m, iv) {
this._doDecrypt(cipher, m, iv);
this._padding.unpad(cipher, m);
},
// Default padding
_padding: C_pad.iso7816
};
/**
* Electronic Code Book mode.
*
* ECB applies the cipher directly against each block of the input.
*
* ECB does not require an initialization vector.
*/
var ECB = C_mode.ECB = function () {
// Call parent constructor
Mode.apply(this, arguments);
};
// Inherit from Mode
var ECB_prototype = ECB.prototype = new Mode;
// Concrete steps for Mode template
ECB_prototype._doEncrypt = function (cipher, m, iv) {
var blockSizeInBytes = cipher._blocksize * 4;
// Encrypt each block
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
cipher._encryptblock(m, offset);
}
};
ECB_prototype._doDecrypt = function (cipher, c, iv) {
var blockSizeInBytes = cipher._blocksize * 4;
// Decrypt each block
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
cipher._decryptblock(c, offset);
}
};
// ECB never uses an IV
ECB_prototype.fixOptions = function (options) {
options.iv = [];
};
/**
* Cipher block chaining
*
* The first block is XORed with the IV. Subsequent blocks are XOR with the
* previous cipher output.
*/
var CBC = C_mode.CBC = function () {
// Call parent constructor
Mode.apply(this, arguments);
};
// Inherit from Mode
var CBC_prototype = CBC.prototype = new Mode;
// Concrete steps for Mode template
CBC_prototype._doEncrypt = function (cipher, m, iv) {
var blockSizeInBytes = cipher._blocksize * 4;
// Encrypt each block
for (var offset = 0; offset < m.length; offset += blockSizeInBytes) {
if (offset == 0) {
// XOR first block using IV
for (var i = 0; i < blockSizeInBytes; i++)
m[i] ^= iv[i];
} else {
// XOR this block using previous crypted block
for (var i = 0; i < blockSizeInBytes; i++)
m[offset + i] ^= m[offset + i - blockSizeInBytes];
}
// Encrypt block
cipher._encryptblock(m, offset);
}
};
CBC_prototype._doDecrypt = function (cipher, c, iv) {
var blockSizeInBytes = cipher._blocksize * 4;
// At the start, the previously crypted block is the IV
var prevCryptedBlock = iv;
// Decrypt each block
for (var offset = 0; offset < c.length; offset += blockSizeInBytes) {
// Save this crypted block
var thisCryptedBlock = c.slice(offset, offset + blockSizeInBytes);
// Decrypt block
cipher._decryptblock(c, offset);
// XOR decrypted block using previous crypted block
for (var i = 0; i < blockSizeInBytes; i++) {
c[offset + i] ^= prevCryptedBlock[i];
}
prevCryptedBlock = thisCryptedBlock;
}
};
/**
* Cipher feed back
*
* The cipher output is XORed with the plain text to produce the cipher output,
* which is then fed back into the cipher to produce a bit pattern to XOR the
* next block with.
*
* This is a stream cipher mode and does not require padding.
*/
var CFB = C_mode.CFB = function () {
// Call parent constructor
Mode.apply(this, arguments);
};
// Inherit from Mode
var CFB_prototype = CFB.prototype = new Mode;
// Override padding
CFB_prototype._padding = C_pad.NoPadding;
// Concrete steps for Mode template
CFB_prototype._doEncrypt = function (cipher, m, iv) {
var blockSizeInBytes = cipher._blocksize * 4,
keystream = iv.slice(0);
// Encrypt each byte
for (var i = 0; i < m.length; i++) {
var j = i % blockSizeInBytes;
if (j == 0) cipher._encryptblock(keystream, 0);
m[i] ^= keystream[j];
keystream[j] = m[i];
}
};
CFB_prototype._doDecrypt = function (cipher, c, iv) {
var blockSizeInBytes = cipher._blocksize * 4,
keystream = iv.slice(0);
// Encrypt each byte
for (var i = 0; i < c.length; i++) {
var j = i % blockSizeInBytes;
if (j == 0) cipher._encryptblock(keystream, 0);
var b = c[i];
c[i] ^= keystream[j];
keystream[j] = b;
}
};
/**
* Output feed back
*
* The cipher repeatedly encrypts its own output. The output is XORed with the
* plain text to produce the cipher text.
*
* This is a stream cipher mode and does not require padding.
*/
var OFB = C_mode.OFB = function () {
// Call parent constructor
Mode.apply(this, arguments);
};
// Inherit from Mode
var OFB_prototype = OFB.prototype = new Mode;
// Override padding
OFB_prototype._padding = C_pad.NoPadding;
// Concrete steps for Mode template
OFB_prototype._doEncrypt = function (cipher, m, iv) {
var blockSizeInBytes = cipher._blocksize * 4,
keystream = iv.slice(0);
// Encrypt each byte
for (var i = 0; i < m.length; i++) {
// Generate keystream
if (i % blockSizeInBytes == 0)
cipher._encryptblock(keystream, 0);
// Encrypt byte
m[i] ^= keystream[i % blockSizeInBytes];
}
};
OFB_prototype._doDecrypt = OFB_prototype._doEncrypt;
/**
* Counter
* @author Gergely Risko
*
* After every block the last 4 bytes of the IV is increased by one
* with carry and that IV is used for the next block.
*
* This is a stream cipher mode and does not require padding.
*/
var CTR = C_mode.CTR = function () {
// Call parent constructor
Mode.apply(this, arguments);
};
// Inherit from Mode
var CTR_prototype = CTR.prototype = new Mode;
// Override padding
CTR_prototype._padding = C_pad.NoPadding;
CTR_prototype._doEncrypt = function (cipher, m, iv) {
var blockSizeInBytes = cipher._blocksize * 4;
var counter = iv.slice(0);
for (var i = 0; i < m.length; ) {
// do not lose iv
var keystream = counter.slice(0);
// Generate keystream for next block
cipher._encryptblock(keystream, 0);
// XOR keystream with block
for (var j = 0; i < m.length && j < blockSizeInBytes; j++, i++) {
m[i] ^= keystream[j];
}
// Increase counter
if (++(counter[blockSizeInBytes - 1]) == 256) {
counter[blockSizeInBytes - 1] = 0;
if (++(counter[blockSizeInBytes - 2]) == 256) {
counter[blockSizeInBytes - 2] = 0;
if (++(counter[blockSizeInBytes - 3]) == 256) {
counter[blockSizeInBytes - 3] = 0;
++(counter[blockSizeInBytes - 4]);
}
}
}
}
};
CTR_prototype._doDecrypt = CTR_prototype._doEncrypt;
})(Crypto);

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save