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. 87
      react/src/actions/actions/nativeSyncInfo.js
  10. 6
      react/src/actions/actions/settings.js
  11. 3
      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. 593
      react/src/components/dashboard/jumblr/jumblr.render.js
  70. 6
      react/src/components/dashboard/navbar/navbar.js
  71. 12
      react/src/components/dashboard/navbar/navbar.render.js
  72. 16
      react/src/components/dashboard/receiveCoin/receiveCoin.js
  73. 196
      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. 96
      react/src/components/dashboard/walletsData/pagination.render.js
  77. 30
      react/src/components/dashboard/walletsData/walletsData.js
  78. 59
      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. 284
      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. 13
      react/src/reducers/dashboard.js
  93. 6
      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 {
@ -366,4 +369,11 @@ export function toggleLoginSettingsModal(display) {
type: DISPLAY_LOGIN_SETTINGS_MODAL,
displayLoginSettingsModal: display,
}
}
export function toggleClaimInterestModal(display) {
return {
type: DISPLAY_CLAIM_INTEREST_MODAL,
displayClaimInterestModal: display,
}
}

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

@ -14,4 +14,18 @@ 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,
@ -284,4 +284,48 @@ 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);
})
});
}

87
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,41 +163,60 @@ export function getSyncInfoNative(coin, skipDebug) {
return _response;
})
.then(json => {
if (!json &&
Config.cli.default) {
if (json === 'Work queue depth exceeded') {
dispatch(
triggerToaster(
'Komodod is down',
'Critical Error',
'error',
true
getSyncInfoNativeState(
{ result: 'daemon is busy', error: null, id: null },
coin,
skipDebug
)
);
dispatch(getDebugLog('komodo', 50));
dispatch(toggleCoindDownModal(true));
} else {
json = JSON.parse(json);
}
if (!json &&
Config.cli.default) {
dispatch(
triggerToaster(
'Komodod is down',
'Critical Error',
'error',
true
)
);
if (json.error &&
json.error.message.indexOf('Activating best') === -1) {
dispatch(getDebugLog('komodo', 1));
}
if (coin === 'KMD') {
dispatch(getDebugLog('komodo', 50));
} else {
dispatch(getDebugLog('komodo', 50, coin));
}
dispatch(toggleCoindDownModal(true));
} else {
json = JSON.parse(json);
}
if (Config.debug) {
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',
'response': json,
}));
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) {
dispatch(logGuiHttp({
'timestamp': _timestamp,
'status': 'success',
'response': json,
}));
}
dispatch(
getSyncInfoNativeState(
json,
coin,
skipDebug
)
);
}
dispatch(
getSyncInfoNativeState(
json,
coin,
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',

3
react/src/actions/storeType.js

@ -45,4 +45,5 @@ export const LOG_GUI_HTTP = 'LOG_GUI_HTTP';
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_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>');

593
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="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="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>
</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>
<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>
</li>
<li>
{ translate('JUMBLR.PER_EXAMPLE') }
<br />
<code>jumblr duck dog cat donkey</code>
</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"
onClick={ () => this.openTab(2) }>
<a className={ this.state.activeTab === 2 ? 'panel-title' : 'panel-title collapsed' }>{ translate('JUMBLR.USING_JUMBLR') }</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 === 2 ? 'panel-collapse collapse in' : 'panel-collapse collapse' }>
<div className="panel-body">
<ul className="nav nav-tabs">
<li
className={ this.state.activeTab === 0 ? 'active' : '' }
onClick={ () => this.openTab(0) }>
<a>
{ translate('JUMBLR.USING_JUMBLR') }
</a>
</li>
<li
className={ this.state.activeTab === 1 ? 'active' : '' }
onClick={ () => this.openTab(1) }>
<a>
Deposit address
</a>
</li>
<li
className={ this.state.activeTab === 2 ? 'active' : '' }
onClick={ () => this.openTab(2) }>
<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>
</div>
</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>
<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
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-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') }</span>
</td>
</tr>
<tr>
<td>{ translate('JUMBLR.KMD_DEPOSIT') }</td>
<td></td>
</tr>
<tr>
<td>KMD Jumblr</td>
<td>
</div>
}
<button
type="button"
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>
</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-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
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-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') }
</span>
</td>
</tr>
</tbody>
</table>
</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>
</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>
<tr>
<td width="20%">{ translate('JUMBLR.RESULT') }</td>
<td>
<span className="label label-success"></span>
</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>
</tbody>
</table>
{ 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>
<strong>Address</strong>
</td>
<td>
<strong>Wif</strong>
</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>
</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(

12
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') }>
<a onClick={ () => this.dashboardChangeSection('jumblr') }>
<i className="site-menu-icon"></i> Jumblr
</a>
</li>
{ 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);
}

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

@ -61,105 +61,119 @@ 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 &&
<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"
checked={ this.state.hideZeroAddresses } />
<span>
{ this.checkTotalBalance() !== 0 &&
<div className="text-left padding-top-10 padding-bottom-10">
<label className="switch">
<input
type="checkbox"
checked={ this.state.hideZeroAddresses } />
<div
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">
<thead>
{ this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th> {translate('INDEX.INTEREST') }</th>
</tr>
}
</thead>
<tbody>
{ this.renderAddressList('public') }
{ this.isNativeMode() && this.renderAddressList('private') }
</tbody>
<tfoot>
{ this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th>{ translate('INDEX.INTEREST') }</th>
</tr>
}
</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="slider"
onClick={ this.toggleVisibleAddress }></div>
</label>
</div>
}
<table className="table table-hover dataTable table-striped">
<thead>
{ this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th> {translate('INDEX.INTEREST') }</th>
</tr>
}
</thead>
<tbody>
{ this.renderAddressList('public') }
{ this.isNativeMode() && this.renderAddressList('private') }
</tbody>
<tfoot>
{ this.isNativeMode() ?
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.AMOUNT') }</th>
</tr>
:
<tr>
<th>{ translate('INDEX.TYPE') }</th>
<th>{ translate('INDEX.ADDRESS') }</th>
<th>{ translate('INDEX.BALANCE') }</th>
<th>{ translate('INDEX.INTEREST') }</th>
</tr>
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>
}
</tfoot>
</table>
<h4 className="panel-title">{ translate('INDEX.RECEIVING_ADDRESS') }</h4>
</header>
<div className="panel-body">
{ this.ReceiveCoinTableRender() }
</div>
</div>
</div>
</div>
</div>
</div>
</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);
}
}

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

@ -27,71 +27,67 @@ 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'>
{this.props.pageText}{' '}
{showPageJump
?
<div className='-pageJump'>
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value;
this.changePage(val - 1);
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage();
}
}}
/>
</div>
:
<span className='-currentPage'>
{page + 1}
</span>}{' '}
{this.props.ofText}{' '}
<span className='-totalPages'>{pages || 1}</span>
<div className="-center">
<span className="-pageInfo">
{this.props.pageText}{' '}
{showPageJump
?
<div className="-pageJump">
<input
type={this.state.page === '' ? 'text' : 'number'}
onChange={e => {
const val = e.target.value;
this.changePage(val - 1);
}}
value={this.state.page === '' ? '' : this.state.page + 1}
onBlur={this.applyPage}
onKeyPress={e => {
if (e.which === 13 || e.keyCode === 13) {
this.applyPage();
}
}} />
</div>
:
<span className="-currentPage">
{page + 1}
</span>}{' '}
{this.props.ofText}{' '}
<span className="-totalPages">{pages || 1}</span>
</span>
{ showPageSizeOptions &&
<span className="select-wrap -pageSizeOptions">
<select
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}>
{ pageSizeOptions.map((option, i) => {
return (
<option key={i} value={option}>
{option} {this.props.rowsText}
</option>
);
})}
</select>
</span>
{showPageSizeOptions &&
<span className='select-wrap -pageSizeOptions'>
<select
onChange={e => onPageSizeChange(Number(e.target.value))}
value={pageSize}
>
{pageSizeOptions.map((option, i) => {
return (
<option key={i} value={option}>
{option} {this.props.rowsText}
</option>
)
})}
</select>
</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 {

59
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,8 +49,9 @@ export const AddressRender = function(tx) {
export const AddressItemRender = function(address, type, amount, coin) {
return (
<li key={address}
className={ address === this.state.currentAddress ? 'selected' : '' }>
<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;
<span className="text">[ { amount } { coin } ]{ address }</span>
@ -98,37 +99,37 @@ export const TxTypeRender = function(category) {
category === 'sent') {
return (
<span className="label label-danger">
<i className="icon fa-arrow-circle-left"></i> <span>{ translate('DASHBOARD.OUT') }</span>
</span>
<i className="icon fa-arrow-circle-left"></i> <span>{ translate('DASHBOARD.OUT') }</span>
</span>
);
}
if (category === 'receive' ||
category === 'received') {
return (
<span className="label label-success">
<i className="icon fa-arrow-circle-right"></i> <span>{ translate('DASHBOARD.IN') }</span>
</span>
<i className="icon fa-arrow-circle-right"></i> <span>{ translate('DASHBOARD.IN') }</span>
</span>
);
}
if (category === 'generate') {
return (
<span>
<i className="icon fa-cogs"></i> <span>{ translate('DASHBOARD.MINED') }</span>
</span>
<i className="icon fa-cogs"></i> <span>{ translate('DASHBOARD.MINED') }</span>
</span>
);
}
if (category === 'immature') {
return (
<span>
<i className="icon fa-clock-o"></i> <span>{ translate('DASHBOARD.IMMATURE') }</span>
</span>
<i className="icon fa-clock-o"></i> <span>{ translate('DASHBOARD.IMMATURE') }</span>
</span>
);
}
if (category === 'unknown') {
return (
<span>
<i className="icon fa-meh-o"></i> <span>{ translate('DASHBOARD.UNKNOWN') }</span>
</span>
<i className="icon fa-meh-o"></i> <span>{ translate('DASHBOARD.UNKNOWN') }</span>
</span>
);
}
};
@ -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"
onChange={e => this.onSearchTermChange(e.target.value)}
placeholder='Search' />
<div className="col-sm-4">
<input
className="form-control"
onChange={e => this.onSearchTermChange(e.target.value)}
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);
}

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

@ -65,151 +65,163 @@ 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"
autoComplete="off">
{ this.state.renderAddressDropdown &&
<div className="row">
<div className="col-xlg-12 form-group form-material">
<label className="control-label">{ translate('INDEX.SEND_FROM') }</label>
{ this.renderAddressList() }
</div>
</div>
}
{ this.renderOASendUI() }
<div className="row">
<div className="col-xlg-12 form-group form-material">
<label
className="control-label"
htmlFor="kmdWalletSendTo">{ translate('INDEX.SEND_TO') }</label>
<input
type="text"
className="form-control"
name="sendTo"
onChange={ this.updateInput }
value={ this.state.sendTo }
id="kmdWalletSendTo"
placeholder={ translate('SEND.ENTER_T_OR_Z_ADDR') }
autoComplete="off"
required />
</div>
<div className="col-lg-12 form-group form-material">
<label
className="control-label"
htmlFor="kmdWalletAmount">
{ translate('INDEX.AMOUNT') }
</label>
<input
type="text"
className="form-control"
name="amount"
value={ this.state.amount !== 0 ? this.state.amount : '' }
onChange={ this.updateInput }
id="kmdWalletAmount"
placeholder="0.000"
autoComplete="off" />
</div>
<div className="col-lg-6 form-group form-material hide">
<label
className="control-label"
htmlFor="kmdWalletFee">
{ translate('INDEX.FEE') }
</label>
<input
type="text"
className="form-control"
name="fee"
onChange={ this.updateInput }
id="kmdWalletFee"
placeholder="0.000"
value={ this.state.fee !== 0 ? this.state.fee : '' }
autoComplete="off" />
</div>
<div className="col-lg-12 hide">
<span>
<strong>{ translate('INDEX.TOTAL') }:</strong>&nbsp;
{ this.state.amount } - { this.state.fee }/kb = { Number(this.state.amount) - Number(this.state.fee) }&nbsp;
{ this.props.ActiveCoin.coin }
</span>
</div>
<div className="col-lg-12">
<button
type="button"
className="btn btn-primary waves-effect waves-light pull-right"
onClick={ this.handleSubmit }
disabled={ !this.state.sendTo || !this.state.amount }>
{ translate('INDEX.SEND') } { this.state.amount } { this.props.ActiveCoin.coin }
</button>
</div>
</div>
</form>
<form
className="extcoin-send-form"
method="post"
autoComplete="off">
{ this.state.renderAddressDropdown &&
<div className="row">
<div className="col-xlg-12 form-group form-material">
<label className="control-label">{ translate('INDEX.SEND_FROM') }</label>
{ this.renderAddressList() }
</div>
</div>
}
{ this.renderOASendUI() }
<div className="row">
<div className="col-xlg-12 form-group form-material">
<label
className="control-label"
htmlFor="kmdWalletSendTo">{ translate('INDEX.SEND_TO') }</label>
<input
type="text"
className="form-control"
name="sendTo"
onChange={ this.updateInput }
value={ this.state.sendTo }
id="kmdWalletSendTo"
placeholder={ translate('SEND.ENTER_T_OR_Z_ADDR') }
autoComplete="off"
required />
</div>
<div className="col-lg-12 form-group form-material">
<label
className="control-label"
htmlFor="kmdWalletAmount">
{ translate('INDEX.AMOUNT') }
</label>
<input
type="text"
className="form-control"
name="amount"
value={ this.state.amount !== 0 ? this.state.amount : '' }
onChange={ this.updateInput }
id="kmdWalletAmount"
placeholder="0.000"
autoComplete="off" />
</div>
<div className="col-lg-6 form-group form-material hide">
<label
className="control-label"
htmlFor="kmdWalletFee">
{ translate('INDEX.FEE') }
</label>
<input
type="text"
className="form-control"
name="fee"
onChange={ this.updateInput }
id="kmdWalletFee"
placeholder="0.000"
value={ this.state.fee !== 0 ? this.state.fee : '' }
autoComplete="off" />
</div>
<div className="col-lg-12 hide">
<span>
<strong>{ translate('INDEX.TOTAL') }:</strong>&nbsp;
{ this.state.amount } - { this.state.fee }/kb = { Number(this.state.amount) - Number(this.state.fee) }&nbsp;
{ this.props.ActiveCoin.coin }
</span>
</div>
<div className="col-lg-12">
<button
type="button"
className="btn btn-primary waves-effect waves-light pull-right"
onClick={ this.handleSubmit }
disabled={ !this.state.sendTo || !this.state.amount }>
{ translate('INDEX.SEND') } { this.state.amount } { this.props.ActiveCoin.coin }
</button>
</div>
</div>
</form>
);
}
{ this.renderOPIDListCheck() &&
<div className="col-xs-12">
<div className="row">
<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">
<h3 className="panel-title">
{ translate('INDEX.OPERATIONS_STATUSES') }
</h3>
</header>
<div className="panel-body">
<table
className="table table-hover dataTable table-striped"
width="100%">
<thead>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</thead>
<tbody>
{ this.renderOPIDList() }
</tbody>
<tfoot>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</tfoot>
</table>
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>
{ this.renderOPIDListCheck() &&
<div className="col-xs-12">
<div className="row">
<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">
<h3 className="panel-title">
{ translate('INDEX.OPERATIONS_STATUSES') }
</h3>
</header>
<div className="panel-body">
<table
className="table table-hover dataTable table-striped"
width="100%">
<thead>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</thead>
<tbody>
{ this.renderOPIDList() }
</tbody>
<tfoot>
<tr>
<th>{ translate('INDEX.STATUS') }</th>
<th>ID</th>
<th>{ translate('INDEX.TIME') }</th>
<th>{ translate('INDEX.RESULT') }</th>
</tr>
</tfoot>
</table>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
}
</div>
);
}
</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%;
}
}
}
@ -684,4 +692,237 @@ 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, {

13
react/src/reducers/dashboard.js

@ -9,14 +9,15 @@ 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
const trimHTTPLogs = (logObject) => {
const logObjectArray = Object.keys(logObject);
if (logObjectArray.length - HTTP_STACK_MAX_ENTRIES === 1) {
delete logObject[logObjectArray.shift()];
}
@ -38,6 +39,7 @@ export function Dashboard(state = {
},
guiLog: {},
displayCoindDownModal: false,
displayClaimInterestModal: false,
}, action) {
switch (action.type) {
case DASHBOARD_SECTION_CHANGE:
@ -95,7 +97,7 @@ export function Dashboard(state = {
const logItem = { [actionTS]: action.log };
newLogState = trimHTTPLogs(Object.assign({}, logState, logItem));
}
return Object.assign({}, state, {
guiLog: newLogState,
});
@ -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;
}

6
react/src/translate/en.js

@ -281,15 +281,15 @@ 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.',
'IF_YOU_ALREADY_RUNNING': 'If you are already running Komodo in either Basilisk Mode or Full Mode, close the wallet and restart again to start Komodo In Native Mode.',
'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.',
'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