Compare commits

..

471 Commits

Author SHA1 Message Date
0158c875e5
Fixing FLO Private key in ETH converter
Some checks failed
Workflow push to Dappbundle / Build (push) Has been cancelled
BTC Private key and FLO private key were the same in ETH converter. This has been fixed
2024-07-11 20:22:06 +05:30
SaketAnand
dbc5cfda95 Update index.html 2024-07-01 03:30:16 +05:30
sairaj mote
b61565398c Update index.html 2024-05-22 17:15:04 +05:30
sairaj mote
d6d3da01e0 "No API available" issue fix 2024-05-07 00:36:14 +05:30
sairaj mote
bb8a5a4dd1 bug fix: stopped unnecessary address API calls when no address is present on first load 2024-04-14 23:14:46 +05:30
sairaj mote
712515a990 bug fixes 2024-04-04 13:15:27 +05:30
sairaj mote
6aa9fa0255 code refactoring 2024-02-13 18:08:21 +05:30
sairaj mote
fca68debf1 adding price history toggle to transaction details page 2024-01-25 01:56:49 +05:30
sairaj mote
c5b61f3c05 valuation switches to historic prices if current value not present 2024-01-19 01:10:33 +05:30
sairaj mote
2e3b0209b5 error handling if historic api takes too long to respond 2024-01-16 15:28:49 +05:30
sairaj mote
33a972afc6 added error handling for when historic price api fails 2024-01-16 15:12:02 +05:30
sairaj mote
a52b27a4d5 adding different tor detection 2024-01-16 05:42:43 +05:30
sairaj mote
74bb2608dc adding historic price for transactions 2024-01-16 03:29:36 +05:30
sairaj mote
c857c04b85 code refactoring 2024-01-09 03:34:57 +05:30
sairaj mote
cd89411365 uncommenting other APIs 2024-01-05 20:33:10 +05:30
sairaj mote
4403cee668 testing broadcast APIs 2024-01-05 14:16:43 +05:30
sairaj mote
32cc6e166c Added better confirmations counting 2024-01-05 02:54:42 +05:30
sairaj mote
779af53fcb UX improvements and code refactoring
-- added address and private key matching for increase fee option
2024-01-05 00:21:18 +05:30
sairaj mote
f09870bf3a fixed issue with broadcasting tx 2024-01-02 09:58:07 +05:30
sairaj mote
74def25d14 fixed pending transaction tip text 2024-01-02 08:59:51 +05:30
sairaj mote
83e3905408 better handling for insufficient balance case 2023-12-31 03:21:45 +05:30
sairaj mote
5203782935 updated version number 2023-12-29 04:54:12 +05:30
sairaj mote
9412a707d8 Bug fixes 2023-12-29 04:52:43 +05:30
sairaj mote
f28ecf5f3f Update index.html 2023-12-28 15:53:28 +05:30
sairaj mote
09a4943298 Update index.html 2023-12-28 14:51:03 +05:30
sairaj mote
22672d0172 Fixed Tx time bug 2023-12-26 23:38:44 +05:30
sairaj mote
0b02732f48 UI bug fix 2023-12-26 23:31:10 +05:30
sairaj mote
52de5ff1cd moving most of the API calls to multi-api mode 2023-12-26 23:23:39 +05:30
sairaj mote
1f11a8f286 Adding multi API support 2023-12-24 02:03:19 +05:30
sairaj mote
1fd6dbbf9c Update push-dappbundle.yml 2023-12-18 22:04:45 +05:30
Vivek Teega
e0c8f9ee7a
Cleaning all git data in workflow 2023-12-18 20:19:38 +05:30
Vivek Teega
129daf7a5b
Update README.md 2023-12-18 20:13:58 +05:30
Vivek Teega
80c74cd9d9 Push dappbundle 2023-12-18 20:12:33 +05:30
sairaj mote
d714feebc8 Update repopush.yml 2023-12-18 16:02:51 +05:30
sairaj mote
718cb919cf Update repopush.yml 2023-12-18 16:01:56 +05:30
sairaj mote
d78a6489a6 Update repopush.yml 2023-12-18 01:21:05 +05:30
sairaj mote
25848b626a Update repopush.yml 2023-12-18 01:14:29 +05:30
sairaj mote
a40da68188 Update repopush.yml 2023-12-17 03:12:14 +05:30
sairaj mote
c276cb008a Update repopush.yml 2023-12-17 03:11:35 +05:30
sairaj mote
7f69399943 Update repopush.yml 2023-12-17 03:10:31 +05:30
sairaj mote
fcae04d86c Update repopush.yml 2023-12-17 03:07:23 +05:30
sairaj mote
94e6d96b08 Update repopush.yml 2023-12-17 03:04:37 +05:30
sairaj mote
49b8c080de Update repopush.yml 2023-12-17 02:55:58 +05:30
sairaj mote
fec2c9c94a Update repopush.yml 2023-12-17 02:53:26 +05:30
sairaj mote
abb572a2b9 testing a workflow 2023-12-17 02:41:50 +05:30
sairaj mote
a47ccad92d tweaked 2023-12-07 01:22:04 +05:30
sairaj mote
c454a638f0 minor tweak 2023-12-07 00:22:10 +05:30
sairaj mote
0c537be007 removed some console logs 2023-12-01 21:45:54 +05:30
sairaj mote
ba549b787f feature and bug fixes
-- added option to allow unconfirmed UTXOs while creating transaction
2023-12-01 20:55:24 +05:30
sairaj mote
dc0e199d58 Fixed btc to flo address conversion 2023-11-20 14:05:48 +05:30
sairaj mote
daee409af8 Bug fix for amount conversion 2023-11-09 04:00:42 +05:30
sairaj mote
ed558ca5a1 Update index.html 2023-10-25 21:38:44 +05:30
sairaj mote
5fc4a08ca1 code refactoring 2023-10-25 21:14:36 +05:30
sairaj mote
d52358b33b Added better conversion page and routing 2023-10-21 04:48:34 +05:30
sairaj mote
7dd51b3c65 removed tap_combined.js 2023-10-19 17:46:16 +05:30
sairaj mote
d8509e75af Update index.html 2023-10-19 17:32:23 +05:30
60f3b5bd6b
Update floEthereum.js 2023-10-19 17:29:22 +05:30
fc6e2bc18b
Update floEthereum.js 2023-10-19 17:25:37 +05:30
ba1463ce6d
Update floEthereum.js 2023-10-19 17:23:45 +05:30
1599937156
Update floEthereum.js 2023-10-19 17:12:27 +05:30
abd8bc683e
Fixed the floEthereum functions 2023-10-19 17:12:05 +05:30
sairaj mote
dcdada2464 Bug fixes 2023-10-19 13:42:19 +05:30
75696ff968
Update lib.js 2023-10-19 10:20:22 +05:30
d67c6c9e05
Update UI.md 2023-10-19 08:39:26 +05:30
4da84280b3
Update UI.md 2023-10-19 08:37:10 +05:30
48a0b6fa43
Create UI.md 2023-10-19 07:03:51 +05:30
sairaj mote
dd20ae57bd added FLO/BTC private key to ethereum address/private key generation 2023-10-19 05:52:37 +05:30
sairaj mote
aa0f305172 Added better amount validation 2023-10-18 02:10:45 +05:30
sairaj mote
4519ee5bb3 Update index.html 2023-10-15 04:15:54 +05:30
sairaj mote
af80f63a47 Bug fixes 2023-10-15 02:37:04 +05:30
sairaj mote
67d049b259 changed multisig member address to bech32 2023-10-11 13:54:39 +05:30
sairaj mote
02084081f1 Added multisig fee increase 2023-10-11 03:12:02 +05:30
bf3a47594f
Update btcOperator.js 2023-09-30 13:53:04 +05:30
19441ef04e
Update btcOperator.js
1. Added editFee_corewallet function to handle Bech32 multisig fee edits
2. Added btcOperator.extractLastHexStrings funtion to extract last item of witness to get RedeemScript
3. Exposed internal functions to btcOperator so that they can be accessed externally
2023-09-30 13:47:34 +05:30
sairaj mote
eb26e95545 Update index.html 2023-09-28 05:08:58 +05:30
sairaj mote
461c8c878b Update components.js 2023-09-28 04:18:16 +05:30
sairaj mote
fb7d6e8897 Added better error handling 2023-09-28 04:13:03 +05:30
sairaj mote
3a73b4f59b adding UI for multisig fee increase 2023-09-13 22:45:37 +05:30
sairaj mote
ef9dbd70cb removed fee increase option for multisig txs 2023-09-10 20:20:47 +05:30
sairaj mote
09d4d82ea5 UI fixes 2023-08-31 15:53:19 +05:30
sairaj mote
6d96f999ec Update components.js 2023-08-31 14:28:45 +05:30
sairaj mote
e80acce0e8 Bug fix and UX improvements 2023-08-31 14:24:11 +05:30
sairaj mote
695ec0ddb4 UX improvements 2023-08-24 19:32:34 +05:30
sairaj mote
95001530e0 UI improvements 2023-08-24 16:41:04 +05:30
sairaj mote
059fb939ef Fixed input field validation bug 2023-08-23 01:11:56 +05:30
sairaj mote
344db632e6 Added Taproot validation for sender 2023-08-16 01:37:38 +05:30
38decb511c
Removed Debugger from btcOperator.sendTx 2023-08-14 07:47:23 +05:30
sairaj mote
3b0899c280 Merge branch 'main' of https://github.com/ranchimall/btcwallet 2023-08-09 00:45:40 +05:30
sairaj mote
2d5c90c3bd Merge branch 'main' of https://github.com/ranchimall/btcwallet 2023-08-09 00:44:57 +05:30
sairaj mote
e9efb9b176 Better tx details UI 2023-08-09 00:42:48 +05:30
5380758775
SpendScript Taproot output enhancement 2023-08-08 18:33:47 +05:30
b7d102ec12
Taproot Outputs spend capacity 2023-08-08 18:32:09 +05:30
1a74ca0f4d
Taproot Address Decoding Added 2023-08-08 16:47:06 +05:30
adca3623fd
Position change of Taproot functions 2023-08-08 16:25:35 +05:30
6c2c53e47c
Fixing variable scope issue in Taproot validation
Created GLOBAL.bech32 and GLOBAL.segwit_addr to expose these functions
2023-08-08 15:58:56 +05:30
56fe27b77d
Adding Taproot Validation
This adds two new objects in main score bech32, and segwit_addr, and provide a set of functions to validate and extract information from Taproot addresses
2023-08-08 15:45:55 +05:30
SaketAnand
8aabf8389e
Update README.md 2023-07-17 16:03:05 +05:30
SaketAnand
72f6004834
Update README.md 2023-07-17 16:02:01 +05:30
SaketAnand
60bdd3d776
Update README.md 2023-07-17 16:01:42 +05:30
sairaj mote
40230fa3d8 UI enhancement 2023-07-15 15:40:28 +05:30
SaketAnand
c7e809ed47
Update README.md 2023-07-14 04:23:09 +05:30
SaketAnand
09b2b28919
Update README.md 2023-07-14 04:22:25 +05:30
SaketAnand
848c3f2822
Update README.md 2023-07-14 01:57:32 +05:30
SaketAnand
e1d674c8f6
Update README.md 2023-07-14 00:06:51 +05:30
SaketAnand
880c6eecef
Update README.md 2023-07-13 21:56:58 +05:30
SaketAnand
0505ec33d4
Update README.md 2023-07-13 21:55:40 +05:30
SaketAnand
2886f1e00f
Update README.md 2023-07-13 21:53:56 +05:30
SaketAnand
89e3cf0a5d
Update README.md 2023-07-13 21:52:50 +05:30
SaketAnand
bf39f402c3
Update README.md 2023-07-13 21:51:57 +05:30
SaketAnand
d93f2c218f
Update README.md 2023-07-13 21:50:35 +05:30
SaketAnand
aedc787bd3
Update README.md 2023-07-13 02:10:19 +05:30
SaketAnand
badecdb8e8
Update README.md 2023-07-13 01:52:57 +05:30
SaketAnand
1ef8e8361f
Update README.md 2023-07-13 01:52:20 +05:30
SaketAnand
27733885fb
Update README.md 2023-07-13 01:51:39 +05:30
sairaj mote
ba75609ce5 New app name format 2023-07-05 03:08:51 +05:30
sairaj mote
deb52a3ca1 Bug fixes 2023-06-05 16:22:16 +05:30
sairaj mote
988bb1376b Minor UX improvements 2023-06-05 03:26:17 +05:30
sairaj mote
8000f7a97a Added transaction fee increase feature UI 2023-06-05 03:15:36 +05:30
sairaj mote
a25d7f3911 Minor UI/UX changes 2023-06-03 03:42:00 +05:30
sairajzero
8de817482a Merge https://github.com/ranchimall/Standard_Operations 2023-06-01 21:13:02 +05:30
sairajzero
49d5c2411c btcOperator v1.1.3b: fix
- Fixed: fee increment minimum value
Minimum fee increment should be atleast MIN_FEE_UPDATE (219 satoshi)
2023-06-01 21:09:50 +05:30
sairajzero
365d3d4503 btcOperator v1.1.3a: bug fix
- Fixed: minor syntax errors and typos
- Fixed: createTransaction not giving correct fee and output value when dust is ignored
2023-06-01 21:06:04 +05:30
sairajzero
34c30aea05 btcOperator v1.1.3: increase fee
- editFee: increase the fee for the given transaction.
can pass either tx hex directly to edit it, or pass txid of unconfirmed tx to edit it for rebroadcasting

- transaction outputs will be removed if the value is less than DUST amount (546 satoshi)
2023-06-01 20:03:42 +05:30
Sai Raj
daeef19d5a
Merge pull request #10 from ranchimall/master 2023-05-19 01:01:09 +05:30
Sai Raj
3a00221587
Merge branch 'sairajzero:master' into master 2023-05-19 00:59:49 +05:30
sairajzero
92303cbc47 floBlockchainAPI v2.5.6b: bug fix 2023-05-13 18:18:23 +05:30
sairaj mote
dbba2c7d5b Added BTC private key conversion 2023-05-11 20:32:13 +05:30
sairajzero
c417af24d1 moving required stdop files into script/ 2023-05-10 18:05:38 +05:30
sairajzero
ef09b3d114 Merge https://github.com/ranchimall/Standard_Operations 2023-05-10 18:03:45 +05:30
sairajzero
41bf3dbf2e remove stdop file for pull from template 2023-05-10 18:03:24 +05:30
Sai Raj
0eb4215f23
Merge branch 'sairajzero:master' into master 2023-05-10 02:13:33 +05:30
sairajzero
d777303097 floTokenAPI v1.0.4a
- fixed: typo in bulkTransferTokens
2023-05-10 02:01:47 +05:30
sairajzero
94fb4f4849 compactIDB v2.1.2
- Fixed: options.limit not working in searchData
- Added option reverse to searchData (if set to true, the ordering will be reversed
2023-05-10 01:50:46 +05:30
sairajzero
1390c91907 floBlockchainAPI v2.5.6a
- minor bug fix: default value for options missing in readAllTxs fn
- removed flosight.duckdns.org from apiURL
2023-05-10 01:46:36 +05:30
SaketAnand
1f45ad65df Update index.html 2023-05-09 05:15:15 +05:30
sairaj mote
0e696badda Fixed taproot addresses not searchable bug 2023-05-06 19:58:43 +05:30
sairajzero
46ae8581e4 floDapps v2.4.0
- Update for new flosight version
- requires floBlockchainAPI >= v2.5.6
- requires floCloudAPI >= v2.4.3a

- lastTx now stores the lastItem property (ie, txid)
- backward-support: maintaining support for idb data (lastTx) from old floDapps module to be converted to this version
2023-05-04 17:09:02 +05:30
sairajzero
9e10a02dc8 floBlockchainAPI v2.5.6
- All search query (get method) now uses URLSearchParams to construct the string
- renamed all lastKey property to lastItem to match flosight response
2023-05-04 17:04:55 +05:30
sairajzero
704def4db1 floCloudAPI v2.4.3a
- Added property: SNStorageName (string content "SuperNodeStorage"
2023-05-04 16:59:10 +05:30
sairajzero
7e618c98f2 floTokenAPI v1.0.4: Added bunkTransferTokens
- Added bunkTransferTokens: bulk transfer tokens to multiple receivers
- usage: floWebWallet.bunkTransferTokens(sender, privKey, token, receivers)
sender: floID of sender
privKey: private key of sender
token: token to send
receivers: an object representing receiver floID and token amount
ie, {receiverID1: amount1, receiverID2: amount2....}
eg: {Fxyz: 123, Fpqr:321, Fabc: 987}
2023-05-02 22:15:54 +05:30
sairajzero
a762f4441b floBlockchainAPI v2.5.5a: bug fix 2023-05-02 21:47:48 +05:30
sairajzero
b09c88f0df floDapps v2.3.5
- Added get property trustedIDs to floGlobals
ie, floGlobals.trustedIDs will give the list of trustedIDs for the app
2023-05-01 20:44:44 +05:30
sairajzero
8afde73e78 floBlockchainAPI v2.5.5: adding getLatestData
- Added getLatestData: Get the latest flo Data that match the caseFn from txs of given Address
2023-04-29 05:29:39 +05:30
sairajzero
fe33250b47 floBlockchainAPI v2.5.4
- Adding support for 'before' and 'latest' option in readTxs and its derivatives
2023-04-29 04:36:56 +05:30
sairajzero
7bd528d55e floBlockchainAPI v2.5.3
- Added waitForConfirmation: Wait for the given txid to get confirmation in blockchain
2023-04-29 03:22:38 +05:30
sairajzero
456e9097de floBlockchainAPI v2.5.2: Added splitUTXOs
- splitUTXOs: split sufficient UTXOs of a given floID for a parallel sending
2023-04-29 03:03:45 +05:30
sairaj mote
e9f67f516a added multisig address conversion 2023-04-26 18:40:14 +05:30
sairaj mote
1c5126fdcb code refactoring 2023-04-25 18:44:32 +05:30
sairaj mote
c214841389 Better error message 2023-04-25 03:31:30 +05:30
Sai Raj
3bb03efa88
Merge pull request #20 from sairajzero/master
Pull updates from master
2023-04-15 00:53:18 +05:30
sairajzero
e37e808a98 floBlockchainAPI v2.5.1: updated readData
- uses readAllTxs to chain query the txs from flosight
- keeping ignoreOld option to support backward compatibility, but resolved value no longer have totalTxs.
- new option 'after': fetch after the given txid
- new option 'mempool': query mempool tx or not (options same as readAllTx, DEFAULT=false: ignore unconfirmed tx)
- the resolved value have the following structure based on options.tx
true: {lastKey, items}
false (DEFAULT}: {lastKey, data}
- Optimized the query and filter process
2023-04-15 00:43:45 +05:30
sairajzero
a296a5c986 floBlockchainAPI v2.5.0
1. Updated readTxs: from, to parameter are replaced with options parameter.
'options' available
- after: query after the given tx
- from/to: query from and to (deprecated, support for backward compatibility)
- mempool: query mempool values (true, false, only)

2. Updated readAllTxs: chain queries the data from flosight when address have too many tx
2023-04-14 03:52:39 +05:30
sairajzero
ca0d8c68f3 floBlockchainAPI v2.4.6
Improved utxo and unconfirmed-spent api fetch in send/create tx
2023-04-14 03:36:23 +05:30
sairajzero
9c0730e051 floBlockchainAPI v2.4.5: getBalance improvements
- Updated getBalance: now chain queries for addr with more than 1000 tx to get the net balance.
- (optional): can use 'after' parameter to get the balance(update) after a given txid
2023-04-13 03:15:26 +05:30
sairaj mote
8797bca3c6 Increased spacing between transactions 2023-04-04 02:14:44 +05:30
sairaj mote
f21f34ec80 Minor UI fix 2023-04-04 01:57:51 +05:30
sairaj mote
4e546b248f UX change
-- by default transactions only show 2 transacting addresses with a button to see all
2023-04-04 01:44:14 +05:30
sairaj mote
002a4d4dff grammatical error fix 2023-03-23 18:48:46 +05:30
sairaj mote
0eaa74647e min btc amount changed 2023-03-21 00:03:41 +05:30
sairajzero
3643f310c2 floDapps v2.3.4: startUpOptions
Added startUpOptions
- cloud: (DEFAULT=true). set to false for app that doesnt require floCloudAPI module
- app_config: (DEFAULT=true). set to false for app that doesnt require configs from adminID (via blockchain)
2023-03-20 20:10:52 +05:30
sairajzero
0ab284b41b floBlockchainAPI v2.4.4
- Updated writeDataMultiple: use options (bool: preserveRatio, float: sendAmt)
- Updated default values to reduce flo spent during tx
2023-03-20 19:44:52 +05:30
sairajzero
b16473f982 floCrypto v2.3.6
- Added hashID(str): returns a floID based on the hash of given string
- Added rawToFloID(raw_bytes): return floID from the given raw_bytes (20 bytes)
2023-03-08 03:13:36 +05:30
Sai Raj
37408f3983
Merge pull request #19 from sairajzero/master
lib v1.4.2b: bug fix
2023-02-25 15:03:50 +05:30
sairajzero
2e24f024d1 lib v1.4.2b: bug fix
- Fixed: FLO multisig signing not working when redeemscript length is large
2023-02-25 15:01:13 +05:30
Sai Raj
948a58c901
Merge pull request #18 from sairajzero/master
testnet fixes
2023-02-24 18:51:13 +05:30
sairajzero
1a8e1abe45 Update index.html
Only for Testing purpose
- Added quick param: pass quick in url query to ignore onLoadStartup
- Added testnet param: pass testnet in url query to change blockchain to FLO_TEST (testnet FLO)
2023-02-24 18:49:22 +05:30
sairajzero
bf9e018883 lib v1.4.2a and floCrypto v2.3.5a
lib v1.4.2a
- Fixed multisig for testnet

floCrypto v2.3.5a
- Fixed: getMultisigAddress accepting requiredSignatures value greater than pubkeys array length (now it will return null instead)
2023-02-24 18:34:49 +05:30
Sai Raj
009b7e1a0d
Merge branch 'sairajzero:master' into master 2023-02-24 02:14:37 +05:30
Sai Raj
476b95c679
Create LICENCE 2023-02-24 02:12:46 +05:30
Sai Raj
ce2a0daaa5
Merge pull request #17 from sairajzero/master 2023-02-24 02:07:53 +05:30
sairajzero
9db998c176 floBlockchainAPI v2.4.3: utility fns
- Added parseTransaction: parse the given txhex
- Added Sat_to_FLO and FLO_to_Sat to .util
2023-02-24 00:46:00 +05:30
sairajzero
7b298ceb50 floBlockchainAPI v2.4.2: tx utility fns
- Added checkSigned: check if the tx is signed or not (if optional args is passed as false, returns a detailed array indicating if each input is signed or not)
- Added checkIfSameTx: check if the passed 2 tx are same or not (ie, input, output and flodata are same or not)
- Added transactionID: returns the transaction id of the tx hex
2023-02-24 00:05:18 +05:30
sairajzero
daec31c1ac btcOperator v1.1.2a: bug fix
- Fixed: checkIfSameTx loop in comparing outputs using incorrect length
2023-02-23 23:24:55 +05:30
sairajzero
09e306d312 floBlockchainAPI v2.4.1: Improvements and signTx
- Added createTx: create unsigned tx (resolves tx-hex )
- Updated createMultisigTx: resolve tx-hex instead of tx object
- Added signTx: (synchronized fn) sign the given tx (hex or object) with given private key and returns the signed txhex
2023-02-23 23:07:54 +05:30
sairajzero
24415b835c lib v1.4.2: (flo) bitjs.transaction deserialize
- pass tx_data (hex or byte array) to bitjs.transaction to deserialize the transaction
ie, `tx = bitjs.transaction(tx_data)`
- invoking without any parameter `bitjs.transaction()` will create an empty tx as before (no change)
2023-02-23 22:49:32 +05:30
sairajzero
e4fd63912c floCrypto v2.3.5: multisig address utils
- Added toMultisigFloID: converts given multisig address to FLO multisig ID

- Improved verifyPubKey: also support verifying multisig redeemScript for the multisig address

- Improved isSameAddr: supports multisig bech32
- Improved decodeAddress: supports multisig bech32
2023-02-23 02:49:42 +05:30
sairajzero
070d2198ba btcOperator v1.1.2: multisig utils
- Added decodeRedeemScript: decodes the given redeemScript and return {address, pubKeys, required}. (optional bech32; default=true. if true return bech32 address. if false returns legacy multisig address)

- Added convert.multisig2multisig: convert from one multisig address to another. (optional target_version; default=btc-multisig-version)
- Added convert.bech2multisig: converts multisig bech32 address to multisig address. (optional target_version; default=btc-multisig-version)

- Added encodeLegacy, decodeLegacy, encodeBech32, decodeBech32 to util
2023-02-23 02:13:31 +05:30
sairajzero
6288dc82d9 lib v1.4.1b: Minor fixes in coinjs multisig-addr
- pubkeys2MultisigAddressBech32: returns another value 'scripthash'
- Fixed multisigBech32Address: returning scripthash as redeemScript. (now returns both scripthash and redeemScript
2023-02-23 02:04:16 +05:30
sairaj mote
9a644ad9ec text change 2023-02-22 01:44:11 +05:30
sairaj mote
041d0d364d Better error handling 2023-02-22 01:43:39 +05:30
Sai Raj
6c8fe10453
Merge pull request #16 from sairajzero/master
support for FLO multisig address and transactions
2023-02-20 17:11:38 +05:30
sairajzero
9132d169d2 lib v1.4.1a: bug fix
- Fixed: bitjs.btrx.decodeRedeemScript not throwing Invalid RedeemScript error
2023-02-20 05:20:04 +05:30
sairajzero
a102f5225b floCrypto v2.3.4a: bug fix
- Fixed: verifyPrivKey incorrectly returning false when pubkey is lowercase. (pubkey hex is case-insensitive)
2023-02-20 05:02:43 +05:30
sairajzero
2e0846edc4 floBlockchainAPI v2.4.0: multisig tx
Changes:
- multisig addresses are accepted as receiver address in all send-tx fns
- multisig addresses are accepted in query fns
- sendTx: sender can be regular address only

Added 3 multisig transaction fns:
- createMultisigTx: creates unsigned tx for multisig sender
- sendMultisigTx: create signed multisig tx and broadcast it
- writeMultisigData: same as writeData(), but for multisig
2023-02-20 04:59:23 +05:30
sairajzero
dac87a8595 floCrypto v2.3.4: multisig address
- Added getMultisigAddress(pubkeys, required_sigs): returns a multisig address from given pubkey list and required signatures
- Added decodeRedeemScript (redeemScript): decodes the given redeemscript (of multisig)
- Updated validateFloID: now validates FLO regular and multisig address. optional argument regularOnly(default=false) if true validates only FLO regular address.
2023-02-20 03:10:15 +05:30
sairajzero
0031761a06 lib v1.4.1: Bitcoin.Address: FLO-multisig support
- Bitcoin.Address now supports multisg version
- new Bitcoin.Address (hex) will now assign the respective version when its regular or multisig address

- Added constants: Bitcoin.Address
  .standardVersion= 0x23
  .multisigVersion = 0x5e
  .testnetVersion = 0x73
2023-02-20 03:09:46 +05:30
sairajzero
1f670be893 lib v1.4.0: Support for FLO multisig address 2023-02-19 17:43:07 +05:30
sairajzero
7d31dec230 lib v1.3.3: Improvements to bitjs for flo
- Updated tx.addflodata: will now check if the data is valid or not
- Optimized tx.serialize: changed complex code for appending flodata to a simple one
- Added bitjs.strToBytes: converts string (ascii) to strToBytes
- Added bitjs.pubkeydecompress: decompresses the public key
- Added bitjs.verifySignature: verify the signature (of hash and pubkey)
2023-02-19 17:39:19 +05:30
sairaj mote
047e78bd4b UI bug fixes 2023-02-19 00:49:50 +05:30
sairaj mote
26b21597de bug fix
--If external APIs fail and there is already a currency other than BTC is selected it'll default to BTC
2023-02-19 00:41:30 +05:30
sairaj mote
94e48dcd6b UI bug fixes 2023-02-19 00:23:44 +05:30
sairaj mote
47f20ab77c bug fixes 2023-02-19 00:16:49 +05:30
sairaj mote
8a1e253ed1 Bug fixes 2023-02-19 00:10:09 +05:30
sairaj mote
eb708fdb36
Merge pull request #1 from sairaj-mote/main
Error handling for exteral API not working
2023-02-18 18:38:10 +05:30
sairaj mote
07a3384eba bug fix 2023-02-18 01:06:03 +05:30
sairaj mote
e92c813a23 Handled API not working in UI 2023-02-18 00:36:58 +05:30
sairaj mote
9c99228119 app name change 2023-02-16 22:39:11 +05:30
sairaj mote
c19c9e28ee changed title 2023-02-16 20:38:22 +05:30
sairaj mote
7a4c6baae3 Bug fixes 2023-02-15 23:19:53 +05:30
sairaj mote
42ec55e68e fixed approx. fee showing 0 2023-02-15 23:01:17 +05:30
sairaj mote
917a797a0c Added approx. transaction fees 2023-02-15 22:43:30 +05:30
Sai Raj
837f4b4a6f
Merge pull request #15 from sairajzero/master 2023-02-08 19:23:28 +05:30
sairajzero
ca0d557d94 btcOperator v1.1.1: getTx.hex
- Added getTx.hex(txid): resolves the tx hex of the txid
- Update: api responses are checked for response.ok
- Fixed: getTx giving incorrect confirmation value for unconfirmed tx
2023-01-31 02:13:37 +05:30
sairajzero
c2a94e6246 btcOperator v1.1.0: updating API provider
updating API link to blockchain.info
2023-01-31 01:21:48 +05:30
sairajzero
c2b836c069 Updating floSight URLs 2022-12-23 22:48:52 +05:30
sairajzero
cc4380d623 floDapps v2.3.3
- Added support: update cloud node URL
- Added support: trusted IDs (configured by adminID)
- Trusted IDs have permission to edit tag data
2022-12-18 03:44:04 +05:30
sairajzero
ea4d1f67d6 bug fix: btcOperator v1.0.14b (ignore dust-change) 2022-12-16 20:47:21 +05:30
sairajzero
a71c851cc2 btcOperator v1.0.14a
- Added multisig-bech32 to auto-fee calc
- Fixed: createMultiSigTx not working with bech32 sender
- Fixed: checkSigned for multisig-bech32
2022-11-27 02:47:02 +05:30
sairajzero
aebda7ec80 btcOperator v1.0.14: multisig-bech32 (p2wsh) 2022-11-24 03:25:52 +05:30
sairajzero
7a6a02f2b6 Update lib.js
- support for multisig-bech32 (p2wsh)
2022-11-24 03:25:35 +05:30
sairajzero
b7254bc3ac btcOperator v1.0.13c bug fix
Fixed: tx outputs with 0 value (such as change amount) not removed
2022-11-20 19:46:22 +05:30
sairajzero
006ff9f0a9 btcOperator v1.0.13b: Fee from receiver
- Added: fee_from_receiver option to create transaction.
- change_address and fee_from_receiver are passed as options for createTx, createSignedTx, sendTx and createMultiSigTx
- Fixed: getTx not rejecting properly when txid is invalid
2022-11-18 17:49:03 +05:30
sairajzero
663dfe2d54 floCloudAPI v2.4.3
- Fixed a rare bug where array has empty value
- now `null` is supported by objectData update (ie, objects can now have null as value)
2022-11-06 04:27:24 +05:30
sairajzero
bffb130bd4 floBlockchainAPI v2.3.3d
- renamed sender and receiver options to senders and receivers (bug fix)
2022-10-26 20:17:48 +05:30
sairajzero
d21db616da btcOperator v1.0.12
- Changed broadcastTx to coinb API to eliminate $.ajax requirement
- Set default value for fee=null (automatic fee) to createSignedTx and createMultiSigTx
2022-10-24 15:39:54 +05:30
sairajzero
87f0260fe4 btcOperator v1.0.11
- Added createSignedTx: creates a signed tx (same as sendTx, but doesnt broadcast)
- Added transactionID: returns the txid of the tx_hex (or tx-object)
2022-10-18 04:43:53 +05:30
sairajzero
c38b7257cf Minor fixes
floCrypto v2.3.3e
- Adding options args to toFloID function. options object accept std and/or bech properties. if specified only converts if given address are from specified version

floBlockchainAPI v2.3.3c
- Fixed: tx failing due to dust amount in change value
- readData: when passes tx option as true, now also gives senders and receivers (Set)

btcOperator v1.0.10b
- Fixed: minor bugs
2022-10-14 23:11:05 +05:30
sairajzero
7d84ded426 btcOperator v1.0.10a: broadcastTx resolves txid
- When broadcast is successful, txid is resolved
- sendTx also resolves txid due to the above change
2022-09-30 05:11:09 +05:30
sairajzero
084ffe10e2 btcOperator v1.0.10: parseTransaction
- Added parseTransaction: parse the given transaction
Parameters:
tx : transaction hex (or tx object from coinjs.transaction)
Resolves: parsed object
2022-09-11 22:36:50 +05:30
sairajzero
39d34f6e8c floCloudAPI v2.4.2e
- Adding generalDataset to floGlobals: returns the filtered general data set. (Parameters type and options)
2022-09-04 04:09:27 +05:30
sairajzero
04aad28600 Improved auto-fee calc
- createTx and createMultiSigTx will now resolve an object with tx_hex and other values (amount, size, etc)
2022-08-25 03:04:56 +05:30
sairajzero
77ff76d787 Replacing Math.random with securedMathRandom 2022-08-22 22:06:14 +05:30
sairajzero
7b5a5e6bfe Bug fixes and improvements
floCrypto v2.3.3b
floCloudAPI v2.4.2d
floDapps v2.3.2d
2022-08-21 21:14:29 +05:30
sairajzero
67386fd69f Update btcOperator.js
- Added checkIfSameTx(tx1, tx2): checks if the transactions is of the same
2022-08-16 20:39:49 +05:30
sairajzero
dc19a4e565 Bug fixes: floBlockchainAPI and lib.js 2022-08-16 17:30:46 +05:30
sairajzero
f0a4837222 btcOperator v1.0.7c
- Fixed: createTransaction not returning promise
- Fixed: script not correctly added for multisig inputs
- Fixed: signTx throwing syntax error
- Added checkSigned(tx, bool?): check if the tx is signed or not. (bool is optional, default=true, if true returns a boolean value, else returns a detailed array of input's length)

- Fixed minor bugs in lib.js
2022-08-16 03:24:55 +05:30
sairajzero
6e5cdbd820 floCrypto v2.3.3b
- Added floCrypto.tmpID: generates a random floID with no private key (use this only for one-time id)
- Added toFloID(address): returns equivalent floID (btc-segwit address NOT supported)
- Fixed bug: legacy addresses of length 33 not working in verifyPubKey and validateAddr
2022-08-16 03:11:24 +05:30
sairajzero
36a4067d67 bug fix 2022-08-16 00:37:38 +05:30
sairajzero
45878e6ebe Update floDapps.js
- myFloID, myPubKey, myPrivKey will now return undefined when user not logged in
2022-08-14 18:38:29 +05:30
sairajzero
91e6b82387 btcOperator v1.0.7b
- Added: signTx
- Added multiSigAddress
2022-08-10 02:58:36 +05:30
sairajzero
bc44405102 btcOperator v1.0.7a
- Adding auto fee calculation
- Optimized the code
- Fixed minor bugs
2022-08-09 03:19:56 +05:30
sairajzero
4244774635 btcOperator v1.0.7
- Added createTx: Create an unsigned tx (no privkey required) [segwit sender not supported for now as redeem-script needed]
- Added createMultiSigTx: Create an unsigned tx for multisig address
- Optimised sendTx to reuse code (no functional change)
2022-08-03 03:54:58 +05:30
sairajzero
9dd132b145 Update README.md 2022-07-28 02:45:56 +05:30
sairajzero
4bced4352d floDapps, floCloudAPI: retain blkchain id on login
floDapps login:
- login to btc address when btc private key is entered
- login to flo id when flo (or any other) private key is entered

floCloudAPI user:
- accept userID and private key for user set

Others:
- Fixed: minor bugs
2022-07-28 02:27:07 +05:30
sairajzero
f673d3f37a floCrypto v2.3.3a
floCrypto.verifyPubKey: verify public key of any blockchain address
- Parameters:
1. pubKeyHex - public key hex
2. address - blockchain address

floCrypto.getAddress: get address respective to the blockchain
- Parameters:
1. privateKeyHex - private key (WIF)
2. strict - (optional, default=false) if false returns floID when no match of privatekey prefix found.
2022-07-28 02:11:48 +05:30
sairajzero
2b8e77b5f7 Bug fixes
- floCrypto.validateAddr: bech default=true
- floCloudAPI: proxyID
- commented coinjs api vars
2022-07-26 15:16:22 +05:30
sairajzero
8a211be849 Adding btcOperator module 2022-07-24 20:33:45 +05:30
sairajzero
0526a1f29f floCloudAPI v2.4.2: cross-blockchain receiverID
- Accept any blockchain ID as receiverID and automatically convert it into floID
2022-07-24 02:34:02 +05:30
sairajzero
fa3d790c6c floDapps v2.3.2: lock privkey by default
- Removed the options for launchStartUp
- private-key is on lock mode by default
- Added utility functions that uses private-key without entering password in .user
  .sign(message): signs message
  .decrypt(data): decrypts ciphertext in asymmetric
  .encipher(message): encrypts message in symmetric
  .decipher(data): decrypts ciphertext in symmetric
2022-07-24 02:29:04 +05:30
sairajzero
0a74e393ed floCrypto v2.3.2: validate any address
floCrypto.validateAddr: validate any blockchain address
- Parameters:
1. address - address to validate
2. std - checks for legacy version (optional, default=true) (true: allow any, array: list of versions, value: one version only, false: allow none)
3. bech - checks for bech version (optional, default=false) (true: allow any, array: list of versions, value: one version only, false: allow none)

- For validating only floID, use floCrypto.validateFloID(floID)
2022-07-19 21:21:06 +05:30
sairajzero
fcc5f3ce4e Edit library to accept WIF of other versions 2022-07-17 17:04:03 +05:30
sairajzero
b80bd43313 floDapps, floCloudAPI: Secure private key
- Store AES-encrypted private key in memory. (exploring memory of browser will not have raw private key)
- floDapps lock/unlock (in user): locks or unlock the private key (ie, lock= Password required, unlock= password not required in returning private key)
- floDapps.launchStartUp now accepts options object
- to lock the private key on startup, pass {lock_key: true} in options objects of launchStartUp
2022-07-17 17:02:27 +05:30
sairajzero
5ab0bc36f0 Update floCrypto.js
- Removing explicit use of BigInteger in signing(/verify-sign) data
2022-07-16 03:32:44 +05:30
sairajzero
cfc36b80cd Secure private key using capsule 2022-07-16 03:30:03 +05:30
Sai Raj
80b4a8b9fe
Merge pull request #9 from ranchimall/master
Update README.md
2022-07-12 19:13:20 +05:30
Sai Raj
151ea8f751
Update README.md 2022-07-01 21:55:45 +05:30
sairajzero
9435592c8b floTokenAPI v1.0.3b
- floGlobals.currency serves as getter and setter for DEFAULT.currency in tokenAPI module
2022-05-25 02:45:50 +05:30
sairajzero
29e20de25b floTokenAPI v1.0.3a
check if amount is not NaN before sendToken
2022-05-24 19:41:45 +05:30
sairajzero
960aa1f52d floBlockchainAPI v2.3.3
- If API is called when serverList is empty, reset the list and try again once
2022-05-24 02:25:44 +05:30
sairajzero
0683bf7318 floTokenAPI v1.0.3
- getAllTxs: get all transactions of the given floID and token
- util.parseTxData: parse the txData resolved by getTx and getAllTxs
2022-05-24 01:32:23 +05:30
sairajzero
5d7d3bdb53 floBlockchainAPI v2.3.2a
sendTx:
- check total balance before processing utxos
- reject "Insufficient FLO: Some UTXOs are unconfirmed" when balance is there but some utxo are used/unconfimed
2022-05-21 22:19:54 +05:30
sairajzero
8603cde17e Moving all defaults/containers to resp. modules
- Removed default values from floGlobals
- Default values are now in their respective modules
- The following properties of floGlobals can be use to override the default values of respective modules: apiURL, sendAmt, fee, tokenURL, currency, SNStorageID
- Default/current values can be obtained from each module with getter properties
- Some current values can be set with setter properties
- The containers for appObjects, generalData, lastVC are now in floCloudAPI module. Also automatically adds get/set properties for them in floGlobals. Thus can be accessed from floGlobals as before
2022-05-16 21:20:21 +05:30
sairajzero
99368151d5 Adding floTokenAPI
- Token Operator to send/receive tokens via blockchain using token system API

floBlockchainAPI v2.3.1
- Added options parameter to writeData . Options can have the following properties:
 . strict_utxo : passes strict_utxo parameter to sendTx (Default: true)
 . sendAmt : amount of FLO to send (Default: floGlobals.sendAmt)
2022-05-16 18:46:22 +05:30
sairajzero
94f90807f7 Update lib.js
- Added support when floGlobals is undefined
2022-04-03 20:15:58 +05:30
sairajzero
b34ef8ca93 Merge branch 'master' of https://github.com/sairajzero/Standard_Operations 2022-04-03 20:09:06 +05:30
Sai Raj
ca243bf0e4
Update lib.js
Adding default cryptocoin as FLO
2022-04-03 19:40:01 +05:30
sairajzero
4b7f6184a3 Bug fix: floDapps
- Fixed: setCustomPrivKeyInput not working
- Added semicolon at the end of all stdop files
2022-04-02 02:06:44 +05:30
sairajzero
5bb0ee8588 Update lib.js
- Added require-support for BuildKBucket
- BuildKBucket now works with and without `new`
- Renamed instance name to KBucket
2022-03-31 22:25:22 +05:30
Sai Raj
37edbfc461
Merge pull request #8 from sairajzero/split-files
Split files
2022-03-31 21:58:54 +05:30
sairajzero
f27c8c4f03 Bug fixes
- Renamed standard_Operations.html to index.html
- Fixed some minor bugs in floCloudAPI
- Added: floCrypto.validateFloID (alias for floCrypto.validateAddr)
2022-03-31 21:54:51 +05:30
sairajzero
3d4aee6359 Move scripts to respective split files 2022-03-30 03:45:41 +05:30
sairajzero
a939545e31 Bug fix: floCloudAPI v2.1.3a 2022-03-23 18:10:44 +05:30
sairajzero
481ec83f78 floBlockchainAPI v2.2.1a | floCloudAPI v2.1.3
floBlockchainAPI v2.2.1a
- Minor bug fixed: Out of bound index when handling unconfirmed transactions in readData

floCloudAPI v2.1.3
- fetching object-data will now properly check for correct object when updating in local and ignores vc that have been parsed previously
- fetching general-data will now use afterTime instead of lowerVectorClock (thus, any change in tag/note is reflected in it).
  . existing apps will automatically change the stored lastVC of generalData to respective afterTime value
- Fixed: objectifier not called on singleRequests for objectData and generalData
2022-03-08 04:28:40 +05:30
sairajzero
ecb4266a89 floBlockchainAPI_v2.2.1 | floCloudAPI_v2.1.2a
(Bug fixes)
floBlockchainAPI v2.2.1
- Fixed: Unconfirmed transaction (propably dropped) causing new transaction not to be read in readData

floCloudAPI v2.1.2a
- Fixed: singleRequest not returning response correctly
- Fixed: afterTime optional parameter not added in requests
- Fixed: setStatus and requestStatus not working
2022-03-08 02:19:15 +05:30
sairajzero
85baa8e6e1 floCloudAPI v2.1.2
Added support for status feature
1. setStatus(options): set status as online for myFloID
2. requestStatus(trackList, options) : request status of floID(s) in trackList
- Both uses websocket connection
- resolves a reqID (local) that can be used in closeRequest function
- Use callback parameter in options to use the response from cloud

Added support for note feature
1. noteApplicationData(vectorClock, note): add/edit a note for a data in cloud
- Only allows receiverID of the data to add/edit note
- subAdmin can use it as exception, when receiverID is adminID

Other changes
- Fixed issues of tagApplicationData (previously markApplicationData) not working.
- Fixed issue where senderID option not working correctly in requesting data from cloud (new cloud uses 'senderID' parameter for both array of floIDs or a single floID)
*NOTE: change senderIDs to senderID in apps if any*
2022-03-04 06:47:04 +05:30
Sai Raj
f99a97e53e
Merge pull request #7 from ranchimall/master
Update readme
2022-02-27 22:16:48 +05:30
sairajzero
6f47473408 Moved cryptocoin initialization to 'lib' script-tag 2022-02-27 22:10:49 +05:30
sairajzero
3f54c5aa5c Some minor fixes: floCloudAPI v2.1.1
- MarkApplicationData not working correctly when Array is passed
- Marking data should fetch to data's receiverID supernode
- findDiff and mergeDiff moved to bottom of floCloudAPI tag
2022-02-27 21:41:35 +05:30
sairajzero
0eb4d59dc3 Bug fix 2022-02-27 21:34:05 +05:30
sairajzero
10fa130229 Organizing scripts: floBlockchainAPI v2.2.0
- converted XMLHttpRequest to fetch request
2022-02-27 20:38:14 +05:30
sairajzero
3cb6c3f60c Organizing scripts: floCrypto v2.2.0 2022-02-27 20:33:51 +05:30
sairajzero
8094660f53 Organizing scripts: lib v1.2.0 2022-02-27 20:31:15 +05:30
790db7d276
Update README.md 2021-12-31 08:15:10 +05:30
1e26b5b723
Update README.md 2021-12-31 07:53:27 +05:30
e981c26e25
Update README.md 2021-12-29 19:35:46 +05:30
4fec06df0e
Update README.md 2021-12-29 18:37:18 +05:30
4824c416b5
Update README.md 2021-12-29 18:01:05 +05:30
442982f073
Update README.md 2021-12-29 17:58:54 +05:30
b85ea1cbe6
Update README.md 2021-12-29 17:28:52 +05:30
f426875692
Update README.md 2021-12-29 17:27:02 +05:30
ae82e254d2
Incomplete shares bugfix
Bugfix: Clears credentials and reloads if all shares are not present
2021-12-29 16:05:33 +05:30
822b446d18
Update README.md 2021-12-23 13:47:38 +05:30
4d5196bac4
Update README.md 2021-12-22 12:24:04 +05:30
38d1d798d5
Update README.md 2021-12-22 12:23:08 +05:30
f34bcc9374
Update README.md 2021-12-22 12:22:31 +05:30
9678176f3b
Update README.md 2021-12-22 12:08:24 +05:30
f75337c9b0
Update README.md 2021-12-22 12:06:28 +05:30
f38f9fe28d
Update README.md 2021-12-22 12:02:35 +05:30
86458d5d3c
Update README.md 2021-12-22 12:01:39 +05:30
2c5dac54b2
Update README.md 2021-12-22 12:00:46 +05:30
22f6f5ae81
Update README.md 2021-12-21 08:38:32 +05:30
420c3a7164
Update README.md 2021-12-21 08:29:50 +05:30
b66fe52f54
Update README.md 2021-12-21 08:29:05 +05:30
d34143a3dc
Update README.md 2021-12-21 08:21:46 +05:30
13007684f0
Update README.md 2021-12-21 08:12:49 +05:30
85ddbc16a5
Update README.md 2021-12-21 08:07:11 +05:30
4cb88db46f
Update README.md 2021-12-19 18:28:38 +05:30
aa7fce1c02
Update README.md 2021-12-19 18:27:22 +05:30
Sai Raj
0b42046022
Merge branch 'sairajzero:master' into master 2021-11-05 18:18:23 +05:30
sairajzero
6caa0658f6 floCloudAPI v2.1.0a (bugFix)
Fixed bug: UpdateObjectData not working correctly
2021-11-05 18:18:09 +05:30
Sai Raj
b2d77a3c2a
Merge branch 'sairajzero:master' into master 2021-09-25 16:27:30 +05:30
sairajzero
57ef8d14df floBlockchainAPI_v2.1.1a
- formatting the code
2021-09-17 02:46:48 +05:30
sairajzero
5c21a01b68 floBlockchainAPI v2.1.1
- improved sendTx to check if the utxo is already used but unconfirmed (ie, still in mempool) and ignore those utxos.
This allows users to send multiple tx from the same floID without the need to wait for confirmation of prev tx as long as enough utxos are available.

- Optional parameter: strict_utxo (boolean): Default=true (safe mode).
If false, allows unconfirmed UTXOs to be included in the txn.
This will allow users to chain send tx as long as enough balance FLO is available.
WARNING: if one tx in the chain is dropped, all next tx dependent on that tx will be dropped too.

- writeData (as it invokes sendTx) also have the above improvements
2021-09-17 02:25:16 +05:30
sairajzero
f8954a2532 floBlockchainAPI v2.1.0
- readData: option txid changed to tx. now resolves data with txid, time, blockheight along with flo data as an object [if option tx is true].
Note: backward not compactible when txid was passed as option
2021-08-12 21:47:02 +05:30
Sai Raj
09539c1dc6
Merge pull request #14 from sairajzero/master 2021-07-24 04:24:32 +05:30
Sai Raj
4df09c206f
Merge branch 'master' into master 2021-07-24 04:24:02 +05:30
sairajzero
b575432ace floCloudAPI_v2.1.0
- Updating to node version of SuperNodeStorage
2021-07-24 04:09:44 +05:30
Sai Raj
571499907e
Update README.md 2021-06-25 15:16:48 +05:30
ea2a586b5a
Updted Flosight list 2021-06-22 18:59:26 +05:30
sairajzero
df8df5edbc floBlockchainAPI_2.0.1e
- Adding floBlockchainAPI.util.current(): returns the current working flosight link (to be used after at least 1 API request'
2021-06-07 14:27:52 +05:30
sairajzero
25df4bbbc0 bugfix (floBlockchainAPI_v2.0.1d)
floBlockchainAPI_v2.0.1d
- fetch_retry removes incorrect uri when parallel requests are called.
2021-06-06 17:10:55 +05:30
Sai Raj
f7fcaf12c6 Merge branch 'sairajzero:master' into master 2021-06-05 12:34:53 +05:30
sairajzero
99ac3accb9 bugfix: (floBlockchainAPI v2.0.1c)
-Fixed: no Flosight working error shown even when there  are flosight(s) working
2021-06-05 12:27:32 +05:30
sairajzero
962f68c230 floBlockchainAPI v2.0.1b
Additional filter options to readData function
- receivedOnly: filters only received data
- txid: (boolean) resolve txid or not
- sender: flo-id(s) of sender
- receiver: flo-id(s) of receiver
2021-04-22 02:09:48 +05:30
sairajzero
05f110661e floCrypto_v2.0.1, floBlockchainAPI_v2.0.1a
floCrypto_v2.0.1 (ASCII fns)
- validateASCII
- convertToASCII
- revertUnicode

floBlockchainAPI_v2.0.1a
bugfix
2021-04-18 02:36:51 +05:30
sairajzero
836f359cf2 floDapps_v2.0.1c
- Added verifyPin: function to verify the pin of login credentials without logging in (ie, not storing the keys in memory)
- 'pin' argument can be ignored to check if private key is secured or not.
2021-02-12 03:06:42 +05:30
sairajzero
dd59c25d73 floCloudAPI_v2.0.2e
- Fixed bug: multiple cloud connection caused issue with inactive array.
Hence replaced Array with Set
2021-01-20 22:54:38 +05:30
sairajzero
b5532444fb floCloudAPI_v2.0.2d | floDapps_v2.0.1b
floCloudAPI_v2.0.2d
- Fixed bug: syntax error in requestObjectData
 - Added closeRequest: closes the active live requests

floDapps_v2.0.1b
- minor improvements and alignment.
- Fixed: deleteAppData deletes the lastTx data of the adminID.
2021-01-02 19:11:15 +05:30
sairajzero
1a57f74704 Alignment
- Moving onLoadStartUp script tag to head
2020-12-31 23:20:51 +05:30
Sai Raj
634aa5aebd
Merge pull request #13 from sairajzero/master 2020-12-19 22:35:42 +05:30
sairajzero
fc747dae83 floBlockchainAPI v2.0.1 | floCloudAPI v2.0.2c
- Added: getTx(txid) to floBlockchainAPI. resolves the tx data of the given txid.

-
2020-12-19 22:26:00 +05:30
sairajzero
30c13ae12f compactIDB v2.0.1
- Fixed bug: database upgrade not working correctly when upgrading existing db.
- Added upgradeDB as a standalone function. (also called by initDB if upgrade is required)
- Added getDBversion: resolves the version of the db
- Improved openDB: rejects if the db is not found
2020-12-15 05:02:50 +05:30
sairajzero
b0e15d1a7f Minor bug fixes 2020-12-09 03:49:32 +05:30
Sai Raj
cafd76655e
Merge pull request #12 from sairajzero/master 2020-11-30 03:31:31 +05:30
sairajzero
99ce43c089 floCloudAPI_v2.0.2a | floDapps_v2.0.1
floCloudAPI v2.0.2a
- deleteApplicationData accepts options instead of application (to match other functions).
- Added editApplicationData
- sendGeneralData not longer stores data in IDB.
- fixed bug: Infinite callback loop in requestGeneralData and requestObjectData

floDapps v2.0.1
- added mid startup support
- added deleteUserData and deleteAppData
- replaced reactor startup logger with setCustomStartupLogger
2020-11-30 03:29:06 +05:30
Sai Raj
5a1aff68ce
Merge pull request #11 from sairajzero/master 2020-10-15 01:46:04 +05:30
Sai Raj
a650ed17a8
Merge pull request #6 from sairajzero/dev
version update (Major changes)
2020-10-15 01:43:29 +05:30
Sai Raj
50594b6bd9
Merge pull request #5 from ranchimall/master 2020-10-15 01:41:32 +05:30
sairajzero
f5f29cb620 bug fix
- Changed SNStorageID
- fixed bug: supernodes not read from blockchain
- generalData incorrectly stored
2020-10-15 01:33:19 +05:30
sairajzero
a8218630ea Contacts feature
- spliting IDB into 3 parts:
1. floDapps - common DB for all apps across all users
2. userDB - common DB for all apps for specific user floID
3. appDB - app DB across all users

- contacts, pubKeys can be stored by users in userDB
- users can send direct message across all apps using floDapps.sendMessage
- syncData can be used to sync user data between devices
2020-10-12 02:38:28 +05:30
sairajzero
cc2d4f8248 Mark feature 2020-09-27 03:21:43 +05:30
sairajzero
65f16fa14b Bug fixes
minor bug fixes
2020-09-20 13:11:07 +05:30
sairajzero
4e9af8060a stdop Improvement
STD_OP

floGlobals
- combined vectorClock (for objectData) and generalVC (for generalData) into lastVC.

init
- Bug fixed: floData of 16 character dropped by floSight.

floCrypto
- Improved getFloIDfromPubkeyHex to getFloID: return floID from either pubKey or privKey.
- verifyPrivKey, validateAddr return false if arguments are empty.

floSupernode
- Removed floSupernode module.
- Kbucket submodule moved to floCloudAPI

Kbucket (subModule)
- Improved KBucket module
- Kbucket cyclic array (SNCO) is formed (w.r.t. distance) when kBucket is launched
- nextNode, prevNode are determined by SNCO

compactIDB
- Improved searchData (accepts option parameter instead of patternEval)
	.options (lowerKey, upperKey, atKey, patternEval, lastOnly)

floCloudAPI
- Improved data signature during sending.
	.current format ( ["receiverID", "time", "application", "type", "message", "comment"])
- Adding live request:
	.requesting data now accepts option callback
	.when callback option is passed, the request becomes live request
	.ie, cloud automatically forwards new data received by the requested floID
	.callback function is called with new data is received
	.callback supported functions: requestApplicationData, requestGeneralData, requestObjectData
- Adding feature to delete from cloud.
	.data received can now be deleted from cloud
	.signature is required for verification (thus requires privKey logged in)
	.can only delete own data (received only)

floDapps
- merged manageSubAdmins and setApplicationSettings into manageAppConfig(adminPrivKey, addList, rmList, settings)
- Improved getNextGeneralData
	.getNextGeneralData can now sub-categorize comment (even when generalData is request for all comment)
	.getNextGeneralData now keeps a track pointer of previously called. [vectorClock (ie, second parameter) must be null, default is null]
2020-09-19 03:39:19 +05:30
sairaj mote
2c58bd662a
Added link for different sections 2020-09-17 13:59:05 +05:30
Sai Raj
8078a83122
Merge pull request #10 from sairajzero/master 2020-08-25 18:05:57 +05:30
sairajzero
9b7dd8214d bug fix
- Fixed: Invalid private key on signing in error not working correctly and cause other bugs
2020-08-25 18:03:12 +05:30
Sai Raj
49d4377900
Merge pull request #9 from sairajzero/master 2020-08-20 17:53:05 +05:30
sairajzero
5e8f0dddb5 Update README.md 2020-08-07 04:34:14 +05:30
sairajzero
fe1ce64562 minor change
-  floBlockchainAPI's readData: changing default limit option value from 1000 to no limit
2020-08-07 04:34:03 +05:30
sairajzero
58bee2e9db minor bug fix
- floBlockchainAPI.readData's option pattern ll now test for JSON key matching the pattern
- startUp fn readAppConfigFromAPI checks if the content is a object or not to prevent errors
2020-08-07 04:19:38 +05:30
sairajzero
ceecfab2b7 Merge branch 'master' of https://github.com/sairajzero/Standard_Operations 2020-08-05 14:05:37 +05:30
sairajzero
c3607aa58f Update README.md 2020-08-05 13:56:12 +05:30
Sai Raj
d4ce67033d
Merge pull request #4 from ranchimall/master 2020-08-05 13:51:17 +05:30
5b93464f42
Update README.md 2020-08-05 13:49:07 +05:30
sairajzero
f6a07b20ba Minor Improvements
- generalData now also stores sign and pubKey.
- renamed startup fn readSubAdminListFromAPI to readAppConfigFromAPI.
- readAppConfigFromAPI also loads settings from the IDB to floGlobals.
2020-08-01 18:38:10 +05:30
sairajzero
62c190567e Adding settings and encrypted generalData feature
- floDapps now reads 'settings' from blockchain
- improved manageSubAdmins: doesnot send tx if addList and rmList are empty (i.e, no changes)
- setApplicationSettings: used to set settings for the application.
Note: existing settings are overwritten (ie, not appended) if same key is used.
- sendGeneralData now supports a new option (encrypt): Encrypts the message before sending.
Note: option value can be boolean true or pubKey of a floID. Passing true will encrypt the data using the default encryptionKey (default 'encryptionKey' must be set in settings).
- getNextGeneralData now supports a new option (decrypt): Decrypts the message if possible.
Note: option value can be true, privateKey or array of privateKeys.
If boolean true is passed, decrypts using myPrivKey (loggedIn privateKey).
If privateKey (string) is passed, decrypts using the given privateKey.
If array of privateKeys are passed, decrypts the message using the suitable key from the given array. (for example, say messages A, B, C are encrypted for keys X, Y, Z respectively, passing [X, Z] will decrypt messages A and C.
2020-07-31 22:24:27 +05:30
e2d9adde07
Update README.md 2020-07-05 23:16:52 +05:30
9d909ebc8c
Update README.md 2020-07-05 23:14:32 +05:30
2edf26228a
Update README.md 2020-07-05 22:26:22 +05:30
be52706a05
Update README.md 2020-07-05 22:16:52 +05:30
9be2c5103d
Update README.md 2020-07-05 19:03:29 +05:30
f13e87dbf9
Update README.md 2020-07-05 18:18:11 +05:30
084aced9b7
Update README.md 2020-07-05 18:15:34 +05:30
70f8cd95b1
Update README.md 2020-07-05 17:15:35 +05:30
e065f688af
Update README.md 2020-07-05 17:06:15 +05:30
6c55653f2a
Update README.md 2020-07-05 14:26:54 +05:30
0050648da2
Update README.md 2020-07-05 14:24:37 +05:30
120ebcf036
Update README.md 2020-07-05 14:21:28 +05:30
5216154940
Update README.md 2020-07-05 14:14:39 +05:30
8a6a4fb1d6
Update README.md 2020-07-05 14:06:27 +05:30
4818cc410a
Update README.md 2020-07-05 13:43:32 +05:30
ec0d420ca7
Update README.md 2020-07-05 13:36:14 +05:30
beebb5795a
Update README.md 2020-07-05 13:12:16 +05:30
39a09be7d9
Update README.md 2020-07-05 11:16:08 +05:30
01b5c5f490
Update README.md 2020-07-05 10:26:00 +05:30
b6affaf6ea
Update README.md 2020-07-05 10:23:00 +05:30
863e4f465d
Update README.md 2020-06-23 20:36:11 +05:30
a33e79a8d0
Update README.md 2020-06-23 20:35:41 +05:30
8e61606de7
Update README.md 2020-06-23 20:33:29 +05:30
25424b9476
Update README.md 2020-06-23 20:21:57 +05:30
14d54c2046
Update README.md 2020-06-23 20:19:01 +05:30
754738f06f
Update README.md 2020-06-23 20:08:13 +05:30
ee26c73936
Update README.md 2020-06-23 19:59:09 +05:30
4f91a3e44e
Update README.md 2020-06-23 19:57:55 +05:30
f23dd9e6e8
Update README.md 2020-06-23 19:53:38 +05:30
33ec57cea1
Update README.md 2020-06-23 19:52:57 +05:30
e7fcd3dd0e
Update README.md 2020-06-23 19:48:38 +05:30
ee267bc31d
Update README.md 2020-06-23 19:32:49 +05:30
1925462202
Update README.md 2020-06-23 19:28:29 +05:30
Sai Raj
09569e729b
Merge pull request #8 from sairajzero/master 2020-05-22 18:53:22 +05:30
Sai Raj
7cbb0908d8
Merge pull request #3 from ranchimall/master 2020-05-22 18:52:17 +05:30
sairajzero
5e1e8a624f bug fix: new line in floData cause error
since newline char is not supported in floData, new line (\n) is replaced with space.
2020-05-22 18:50:29 +05:30
SaketAnand
57ff5ae0b9
README.md
Corrected the spelling of "retrieve" from "retrive' in floCloudAPI Section
2020-05-17 10:45:43 +05:30
5699e8dee4
Update README.md 2020-05-16 18:13:42 +05:30
aa7c5c909e
Update README.md 2020-05-16 17:55:30 +05:30
2265581971
Update README.md 2020-05-16 17:53:05 +05:30
6175ac9314
Update README.md 2020-05-16 17:47:27 +05:30
3a23206af9
Update README.md 2020-05-16 15:35:51 +05:30
cc20e28de3
Update README.md 2020-05-16 10:39:59 +05:30
afc286964f
Update README.md 2020-05-16 10:36:45 +05:30
572c559096
Update README.md 2020-05-16 10:33:04 +05:30
09490c560d
Update README.md 2020-05-16 10:14:11 +05:30
2099fa61ba
Update README.md 2020-05-16 09:37:08 +05:30
59dfc6f449
Update README.md 2020-05-16 09:35:17 +05:30
42f493b01b
Update README.md 2020-05-16 09:32:12 +05:30
3d9c763bee
Update README.md 2020-05-16 09:30:31 +05:30
aae73da57f
Update README.md 2020-05-16 09:07:07 +05:30
2f118217d9
Update README.md 2020-05-15 13:40:16 +05:30
Sai Raj
eee8e2e365
Merge pull request #7 from sairajzero/master 2020-05-14 04:00:51 +05:30
Sai Raj
aff5b927e9
Merge branch 'master' into master 2020-05-14 04:00:38 +05:30
Sai Raj
7d65c4da8e
Update README.md 2020-05-14 03:57:23 +05:30
sairajzero
fccf2fdebd Update README.md 2020-05-14 03:52:45 +05:30
sairajzero
a66c2d91c2 minor changes
-Renamed defaultDB propertyName in compactIDB
-Fixed error in writeDataMultiple comment
2020-05-14 03:52:39 +05:30
4eb9649622
Added new standard functions 2020-05-13 10:04:27 +05:30
sairajzero
32da4e28af Improved initDB
initDB also deletes objectstores on upgrade needed (version change)
2020-05-07 15:46:58 +05:30
sairajzero
489996c1b8 Improve clearCredentials
Clearing the private key, public key and floID from memory on clearCredentials
2020-05-06 19:56:31 +05:30
Sai Raj
1e6d2462af
Merge pull request #6 from sairajzero/master 2020-05-06 19:03:08 +05:30
sairajzero
d90e9f6ed4 Adding secure PrivateKey feature
floDapps.securePrivKey(pwd): replaces the stored private key with encrypted variant.
Changed made in startup function getCredentials to support securePrivateKey.

Improved and promisified clearCredentials.
2020-05-06 00:31:44 +05:30
sairajzero
0308af983f Adding clearData to CompactIDB
compactIDB.clearData clears all data in the given objectstore.
2020-05-02 18:48:02 +05:30
sairajzero
38f43d805d InitDB: add missing objectStores
InitDB now automatically adds the missing objectstore instead of rejecting
2020-05-02 18:10:47 +05:30
sairajzero
1954fc0782 Improved sendTxMultiple and writeDataMultiple
sendTxMultiple:
There are 2 modes (given send amount, preserve ratio)
- Given Send Amount: Uses the given send amount from each sender IDs. Pass the senderPrivKeys as object with amount to invoke this mode
eg. { privateKey1: sendAmt1, privateKey2: sendAmt2...}
- preserveRatio: The ratio of the balance of the senders are maintained. Pass the senderPrivKeys as array of private keys.
eg. [privatekey1, privatekey2....]
*Note: receivers must always be object of floIDs with receive amount.
eg. {receiverID1: receiveAmt1, receiver2: receiveAmt2...}

writeDataMultiple:
There are 2 modes (preserveRatio, equalContribution)
- preserveRatio: preserves the ratio of the balance of senders
- equalContribution: all senders contribute equal amount to the transaction
Note:
*senderPrivKey and receivers are arrays
eq. [privateKey1, privateKey2, ..] and [receiverID1, receiverID2...]
*sends default amount (floGlobals.sendAmt) to each receiver)
*last (4th) parameter is optional:
(default) true: invokes preserveRatio mode
false: invokes equalContibution mode
2020-04-26 01:04:12 +05:30
sairajzero
a569adcb74 Adding mergeUTXOs, sendTxMulti and writeDataMulti
mergeUTXOs: /merge all UTXOs of a given floID into a single UTXO

sendTxMulti: Send Tx from (and/or) to multiple floID

writeDataMulti: Write data into blockchain from (and/or) to multiple floID
2020-04-25 17:54:13 +05:30
sairajzero
0a6fb69349 Beautify the scripts 2020-04-23 21:16:54 +05:30
sairajzero
3d0c8883b7 Improved floCloudAPI
floCloudAPI now stores the lastCommit value of the objects via requestObjectData, resetObjectData, updateObjectData

resetObjectData and updateObjectData now takes the new and old value from floGlobals.appObjects and lastCommit respectively

Parameter changes:
resetObjectData: function(objectName, options = {})
updateObjectData: function(objectName, options = {})
2020-03-10 22:00:56 +05:30
sairajzero
8652959e54 floCrypto: errorHanding
errorHanding added to floCrypto.getPubKeyHex and floCrypto.getFloIDfromPubkeyHex
2020-03-04 03:45:50 +05:30
sairajzero
47ca6a802e moving onloadStartup to a seperate script tag 2020-02-16 02:38:51 +05:30
sairajzero
d6c4b4882e changing TEST_MODE adminID 2020-02-16 02:36:35 +05:30
sairajzero
86ea714139 adding manage subAdmin to floDapps
floDapps.manageSubAdmins() allows the user to add and/or remove subadmin list via blockchain
*Requires Admin Privatekey of the app
2020-02-16 02:34:58 +05:30
sairajzero
c3a51f44a7 bug fix 2020-02-06 14:56:12 +05:30
sairajzero
7a6a2dc9ea Custom privKeyInput is made promisified
privKeyInput now uses given key when resolved and generates random key when rejected
2020-02-06 13:38:09 +05:30
sairajzero
cdeab33c20 Login as guest feature
Entering a empty string for private Key now automatically generated a random key and logins as guest
2020-02-03 18:43:29 +05:30
Sai Raj
43afe64fbf
Merge pull request #4 from sairajzero/master 2020-01-31 22:06:52 +05:30
sairajzero
2bf166ffd1 bug fix: floSupernode module 2020-01-31 20:22:35 +05:30
sairajzero
a44fe4be72 adding custom input for privkey 2020-01-31 14:42:42 +05:30
sairajzero
e3e034ae0a bug fix: vectorClock IDB 2020-01-22 22:25:02 +05:30
sairajzero
556f4ddadd bug fix: floCloudAPI 2020-01-07 15:06:03 +05:30
Sai Raj
bbb2a4596b
Merge pull request #3 from sairajzero/master 2020-01-05 20:53:21 +05:30
sairajzero
f5f44f9415 Merge branch 'master' of https://github.com/sairajzero/Standard_Operations 2020-01-05 20:44:14 +05:30
sairajzero
efbb6fa9e2 bug fix 2020-01-05 20:44:09 +05:30
sairajzero
73965d87fc adding event listner to startup functions
startUpSuccessLog and startUpSuccessLog Events are registered to log the start up functions
2020-01-05 20:40:53 +05:30
Sai Raj
2c6b422533
Merge pull request #2 from sairajzero/master 2020-01-05 20:17:37 +05:30
Sai Raj
2b847b7a4e
Update README.md 2020-01-05 20:13:53 +05:30
sairajzero
1301caaa40 adding a dummy floID as adminID 2020-01-05 20:00:02 +05:30
Sai Raj
8dbace647f
Merge pull request #1 from sairajzero/master 2020-01-05 19:55:09 +05:30
sairajzero
e40771eb23 bug fix: some missing libraries 2020-01-05 19:43:09 +05:30
sairajzero
c473d200c0 Improving floSupernode.kBucket module
Adding getInnerNodes and getOuterNodes
getPrevSupernode, getNextSupernode and determineClosestSupernode now return an array of floIDs
2020-01-05 19:42:34 +05:30
sairajzero
5e9926b87b bug fix: floDapps 2019-12-19 22:28:43 +05:30
sairajzero
5a2b6250ca adding floDapps std_Op
This std_op contains functions for FLO Dapp startup and other useful functions for FLO Dapps
2019-12-19 22:03:53 +05:30
sairajzero
e42a972f12 floCloudAPI: moving the reactor events to util and Promisifying all canon operations 2019-12-19 21:42:02 +05:30
sairajzero
afa8714d0e bug fix 2019-12-19 20:31:30 +05:30
sairajzero
8f3ef66d15 moving KBucket library to floSupernode tag 2019-12-19 20:27:21 +05:30
sairajzero
d09ada8261 floCrypto improvement
moving non canon functions to util property
2019-12-19 20:25:14 +05:30
sairajzero
7a60c9f134 Moving libraries to init_lib 2019-12-19 20:23:24 +05:30
sairajzero
a06f455026 Moved floGlobals to to head and added id to std_op script tag 2019-12-19 20:08:11 +05:30
sairajzero
e691662c82 adding send and request general data to floCloudAPI
sendGeneralData : sends general data to the cloud
requestGeneralData : request general data from the cloud
2019-12-12 18:11:26 +05:30
sairajzero
e7a74c785e Adding Shamir's Shared Secret to floCrypto
Adding Shamir's Shared Secret to floCrypto module
createShamirsSecretShares: create the shamirs secret shares
retrieveShamirSecret: retrives the secret from shares
verifyShamirsSecret: verify the shares with secret
Also adding randInt and randString to floCrypto module
2019-12-01 11:45:00 +05:30
sairajzero
577bee4d37 Adding requestApplicationData
requestApplicationData : request any message from the supernode cloud
Fixed minor bugs
2019-11-20 20:20:39 +05:30
Sai Raj
62ac2a9371
Merge pull request #2 from ranchimall/master 2019-11-20 18:20:13 +05:30
Sai Raj
5ae3214a67
Rename index.html to standard_Operations.html 2019-11-20 18:15:34 +05:30
sairajzero
ce28df6834 adding automatic fetch for flosight API 2019-11-20 02:07:35 +05:30
sairajzero
289089d972 Adding floCloudAPI
floCloudAPI has methods to send application data, request application data, reset or update object data.
2019-11-19 20:11:32 +05:30
sairajzero
d79d54b400 Updating to match the backup node feature of SN 2019-11-19 20:09:15 +05:30
sairaj mote
10a5393373
Update README.md 2019-10-20 01:15:39 +05:30
sairaj mote
41eb1dc452
added description for floBlockchainAPI and compact IDB operations 2019-10-20 01:07:28 +05:30
Sai Raj
57d16248d9
fixing bug in initDB 2019-10-17 17:21:07 +05:30
Sai Raj
049cd5823c
changing ws:// to wss:// in supernode module 2019-10-17 15:55:24 +05:30
Sai Raj
b1c6d8c153
fixing broadcastTx not been asynchronized call 2019-10-13 03:04:28 +05:30
sairajzero
ed59eeeb65 Added removeData in compactIDB 2019-10-06 03:51:13 +05:30
sairajzero
68472cad56 floBlockchainAPI.readData will now return a object with totalTxs and data 2019-10-06 03:15:18 +05:30
sairajzero
9da3168f45 Improved Read Data from blockchain via API
Replaced floBlockchainAPI's readSentData, readDataPattern, readSentDataPattern, readDataContains, readSentDataContains with a improved version 'readData'
readData is Promisfied function that reads and resolves floData from blockchain using API
Arguments :
addr - address from which the floData should be read
options - (optional object, default = {})
Options :
limit - maximum number of filtered data (default = 1000, negative  = no limit)
ignoreOld - ignore old txs (default = 0)
sentOnly - filters only sent data
pattern - filters data that starts with a pattern
contains - filters data that contains a string
filter - custom filter funtion for floData (eg . filter: d => {return d[0] == '$'})
2019-10-06 02:52:34 +05:30
sairajzero
8fd579dc5e Removed supernode Server
Removed supernode server so that this repo can be templated directly for projects
2019-10-04 21:16:55 +05:30
sairajzero
243e3300ae Merge branch 'master' of https://github.com/ranchimall/Standard_Operations 2019-10-04 20:41:08 +05:30
sairajzero
ae71390df4 fixing bugs 2019-10-04 20:35:10 +05:30
sairajzero
9bdac8b042 fixing some bugs 2019-10-04 20:34:26 +05:30
sairajzero
2ea373ef2d improved reading floData via API 2019-10-04 20:31:56 +05:30
Sai Raj
268ffe4197
Update index.html 2019-10-03 00:20:20 +05:30
Sai Raj
e2948b1db5
Update README.md 2019-09-29 22:07:01 +05:30
Sai Raj
d7f1d215dd
Update README.md 2019-09-29 22:04:11 +05:30
sairajzero
bd52c44169 Added compactIDB operations and fixed bugs 2019-09-29 13:55:46 +05:30
sairajzero
dd402cd454 Adding files 2019-09-27 21:34:16 +05:30
sairajzero
bf24208898 Initial commit 2019-09-27 21:10:01 +05:30
19 changed files with 8483 additions and 1937 deletions

32
.github/workflows/push-dappbundle.yml vendored Normal file
View File

@ -0,0 +1,32 @@
name: Workflow push to Dappbundle
on: [push]
jobs:
build:
name: Build
runs-on: self-hosted
steps:
- name: Executing remote command
uses: appleboy/ssh-action@v1.0.0
with:
host: ${{ secrets.R_HOST }}
username: ${{ secrets.P_USERNAME }}
password: ${{ secrets.P_PASSWORD }}
port: ${{ secrets.SSH_PORT }}
script: |
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle" ]; then
echo "Folder exists. Skipping Git clone."
else
echo "Folder does not exist. Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/ && git clone https://github.com/ranchimall/dappbundle.git
fi
if [ -d "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" ]; then
echo "Repository exists. Remove folder "
rm -r "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}"
fi
echo "Cloning repository..."
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle && git clone https://github.com/ranchimall/${{ github.event.repository.name }}
cd "${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/${{ github.event.repository.name }}" && rm -rf .gitattributes .git .github .gitignore
cd ${{ secrets.DEPLOYMENT_LOCATION}}/dappbundle/ && git add . && git commit -m "Workflow updating files of ${{ github.event.repository.name }}" && git push "https://ranchimalldev:${{ secrets.RM_ACCESS_TOKEN }}@github.com/ranchimall/dappbundle.git"

21
LICENCE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Sai Raj
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.

View File

@ -1,2 +1,82 @@
# btc-webwallet
# BTC Wallet
[![Workflow push to Dappbundle](https://github.com/ranchimall/btcwallet/actions/workflows/push-dappbundle.yml/badge.svg)](https://github.com/ranchimall/btcwallet/actions/workflows/push-dappbundle.yml)
BTC Wallet
It is a web-based Bitcoin wallet and Bitcoin explorer that promotes self-custody by generating Bitcoin addresses and private keys locally on the user's device. If you are suspicious about internet monitoring, then open the URL, disconnect your computer from the internet, and then generate the Bitcoin address and private key.
These are client-side scripts that can generate Bitcoin addresses, send Bitcoin transactions to the blockchain, and monitor Bitcoin data from the Bitcoin blockchain.
### Live URL for BTC Wallet:
*https://ranchimall.github.io/btcwallet/*
#### Do not forget to copy and save the private key in a safe place. This BTC wallet doesn't give a seed phrase but directly the original private key, which makes it more secure for the users to take full custody of their bitcoins.
#### Note:
Seed phrases are English words and can be memorized by someone who is looking at your screen. Private keys are random characters that hide inside asterisk signs that make it difficult for anyone to look at them and memorize them.
## Instructions to use
Note: BTC Wallet uses IndedxedDB for storing data, which means data is stored in the respective browser you used to open the web wallet. Data stored by one browser can't be accessed by other browsers.
## Functions:
### Generate BTC address
Click on "Generate BTC address" to generate a new Bitcoin address with its private key. With the use of the "Copy" button, both the BTC address and private key can be copied to save it somewhere safe.
Note: Do not share your private key with anyone and keep it safe. Once lost a private key can't be recovered.
### Retrieve BTC address
In case you have forgotten your Bitcoin address but still have the private key, you can retrieve the Bitcoin address. Simply enter the private key and click on the "Recover" button.
### Search BTC address or transaction ID (Bitcoin Explorer)
Any Bitcoin address or a Bitcoin transaction id can be searched to fetch the blockchain data. Simply enter the Bitcoin address or the transaction id, press "Enter" or click on "Search" to fetch the blockchain transactions.
### Send
i) The "Send" button can be used to send bitcoins to other Bitcoin addresses. <br>
ii) Click on the "Send" button from the left menu bar <br>
iii) Enter or paste the "Sender's Bitcoin address" <br>
iv) Enter or paste the "Sender's Bitcoin private key" <br>
v) Upon entering the private key, the balance of the address will reflect on the screen <br>
vi) Enter the "Reciever's Bitcoin address" <br>
vi) Enter the "amount" of bitcoin to be sent <br>
vii) Amount can be entered in the form of BTC, USD, or INR <br>
viii) Amount entered in USD or INR will automatically convert to the equivalent BTC amount <br>
ix) Approximate fees will show up before making the transaction <br>
x) Fees can be modified by the user. An increased fee increases the chance of transactions taking place faster <br>
xi) Click on the "Send" button to initiate the transaction <br>
xii) This will give the transaction id using which the transaction details and confirmation can be monitored <br>
#### Note: Multiple senders and multiple receiver addresses can be used to send Bitcoins to multiple receivers. For multiple senders, all their corresponding private keys will be required
#### Note: The fee is comparatively low than other Bitcoin wallets or other Exchange wallets because RanchiMall does not have any additional fees for any transaction.
## Convert
i) "Convert" is a special feature developed by RanchiMall which converts a FLO blockchain address to an equivalent Bitcoin address <br>
ii) The same can be done with a Bitcoin address as well. A Bitcoin address can be converted to its equivalent FLO address <br>
### Why is "Converter" required
i) RanchiMall has built all dapps on the FLO blockchain <br>
ii) All the dapps require a FLO private key to be signed in <br>
iii) Later RanchiMall developed a Bitcoin address sign-in architecture for its dapps <br>
iv) If a user has a FLO address and he/she uses any of RanchiMall dapps, then using an equivalent Bitcoin address to sign in will also take the user to the same account which he/she signed into using their FLO private key.
### More about Converter
i) Both the FLO or BTC address and the Private keys can be converted for each other <br>
ii) This means a FLO address can have its equivalent BTC address and a BTC address can have its equivalent FLO address <br>
iii) A FLO private key can be converted to its equivalent BTC address's private key <br>
#### Note: The pairing of this conversion will always remain the same. <br>
a) A FLO blockchain address can have only one equivalent BTC address <br>
b) A Bitcoin blockchain address can have only one equivalent FLO blockchain address <br>
c) Along with the FLO or BTC address, their private keys can also be converted <br>
### How to use Converter
i) Click on the "Convert" button on the homepage <br>
ii) Click on "FLO" if you want to convert a FLO blockchain address or FLO private key to its equivalent BTC address or BTC private key <br>
iii) Under the "Private key converter", enter the private key of the FLO address. This will convert the FLO private key to the equivalent BTC private key and BTC address <br>
iv) Click on "BTC" if you want to convert a Bitcoin blockchain address or BTC private key to its equivalent FLO address or FLO private key <br>
v) Under the "Address converter", enter the FLO address to get the equivalent BTC address and vice versa <br>

View File

@ -1,851 +0,0 @@
(function (EXPORTS) { //btcOperator v1.1.1
/* BTC Crypto and API Operator */
const btcOperator = EXPORTS;
//This library uses API provided by chain.so (https://chain.so/)
const URL = "https://blockchain.info/";
const fetch_api = btcOperator.fetch = function (api, json_res = true) {
return new Promise((resolve, reject) => {
console.debug(URL + api);
fetch(URL + api).then(response => {
if (response.ok) {
(json_res ? response.json() : response.text())
.then(result => resolve(result))
.catch(error => reject(error))
} else {
response.json()
.then(result => reject(result))
.catch(error => reject(error))
}
}).catch(error => reject(error))
})
};
const SATOSHI_IN_BTC = 1e8;
const util = btcOperator.util = {};
util.Sat_to_BTC = value => parseFloat((value / SATOSHI_IN_BTC).toFixed(8));
util.BTC_to_Sat = value => parseInt(value * SATOSHI_IN_BTC);
function get_fee_rate() {
return new Promise((resolve, reject) => {
fetch('https://api.blockchain.info/mempool/fees').then(response => {
if (response.ok)
response.json()
.then(result => resolve(util.Sat_to_BTC(result.regular)))
.catch(error => reject(error));
else
reject(response);
}).catch(error => reject(error))
})
}
const broadcastTx = btcOperator.broadcastTx = rawTxHex => new Promise((resolve, reject) => {
let url = 'https://coinb.in/api/?uid=1&key=12345678901234567890123456789012&setmodule=bitcoin&request=sendrawtransaction';
fetch(url, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: "rawtx=" + rawTxHex
}).then(response => {
response.text().then(resultText => {
let r = resultText.match(/<result>.*<\/result>/);
if (!r)
reject(resultText);
else {
r = r.pop().replace('<result>', '').replace('</result>', '');
if (r == '1') {
let txid = resultText.match(/<txid>.*<\/txid>/).pop().replace('<txid>', '').replace('</txid>', '');
resolve(txid);
} else if (r == '0') {
let error = resultText.match(/<response>.*<\/response>/).pop().replace('<response>', '').replace('</response>', '');
reject(decodeURIComponent(error.replace(/\+/g, " ")));
} else reject(resultText);
}
}).catch(error => reject(error))
}).catch(error => reject(error))
});
Object.defineProperties(btcOperator, {
newKeys: {
get: () => {
let r = coinjs.newKeys();
r.segwitAddress = coinjs.segwitAddress(r.pubkey).address;
r.bech32Address = coinjs.bech32Address(r.pubkey).address;
return r;
}
},
pubkey: {
value: key => key.length >= 66 ? key : (key.length == 64 ? coinjs.newPubkey(key) : coinjs.wif2pubkey(key).pubkey)
},
address: {
value: (key, prefix = undefined) => coinjs.pubkey2address(btcOperator.pubkey(key), prefix)
},
segwitAddress: {
value: key => coinjs.segwitAddress(btcOperator.pubkey(key)).address
},
bech32Address: {
value: key => coinjs.bech32Address(btcOperator.pubkey(key)).address
}
});
coinjs.compressed = true;
const verifyKey = btcOperator.verifyKey = function (addr, key) {
if (!addr || !key)
return undefined;
switch (coinjs.addressDecode(addr).type) {
case "standard":
return btcOperator.address(key) === addr;
case "multisig":
return btcOperator.segwitAddress(key) === addr;
case "bech32":
return btcOperator.bech32Address(key) === addr;
default:
return null;
}
}
const validateAddress = btcOperator.validateAddress = function (addr) {
if (!addr)
return undefined;
let type = coinjs.addressDecode(addr).type;
if (["standard", "multisig", "bech32", "multisigBech32"].includes(type))
return type;
else
return false;
}
btcOperator.multiSigAddress = function (pubKeys, minRequired, bech32 = true) {
if (!Array.isArray(pubKeys))
throw "pubKeys must be an array of public keys";
else if (pubKeys.length < minRequired)
throw "minimum required should be less than the number of pubKeys";
if (bech32)
return coinjs.pubkeys2MultisigAddressBech32(pubKeys, minRequired);
else
return coinjs.pubkeys2MultisigAddress(pubKeys, minRequired);
}
//convert from one blockchain to another blockchain (target version)
btcOperator.convert = {};
btcOperator.convert.wif = function (source_wif, target_version = coinjs.priv) {
let keyHex = decodeLegacy(source_wif).hex;
if (!keyHex || keyHex.length < 66 || !/01$/.test(keyHex))
return null;
else
return encodeLegacy(keyHex, target_version);
}
btcOperator.convert.legacy2legacy = function (source_addr, target_version = coinjs.pub) {
let rawHex = decodeLegacy(source_addr).hex;
if (!rawHex)
return null;
else
return encodeLegacy(rawHex, target_version);
}
btcOperator.convert.legacy2bech = function (source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
let rawHex = decodeLegacy(source_addr).hex;
if (!rawHex)
return null;
else
return encodeBech32(rawHex, target_version, target_hrp);
}
btcOperator.convert.bech2bech = function (source_addr, target_version = coinjs.bech32.version, target_hrp = coinjs.bech32.hrp) {
let rawHex = decodeBech32(source_addr).hex;
if (!rawHex)
return null;
else
return encodeBech32(rawHex, target_version, target_hrp);
}
btcOperator.convert.bech2legacy = function (source_addr, target_version = coinjs.pub) {
let rawHex = decodeBech32(source_addr).hex;
if (!rawHex)
return null;
else
return encodeLegacy(rawHex, target_version);
}
function decodeLegacy(source) {
var decode = coinjs.base58decode(source);
var raw = decode.slice(0, decode.length - 4),
checksum = decode.slice(decode.length - 4);
var hash = Crypto.SHA256(Crypto.SHA256(raw, {
asBytes: true
}), {
asBytes: true
});
if (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3])
return null;
let version = raw.shift();
return {
version: version,
hex: Crypto.util.bytesToHex(raw)
}
}
function encodeLegacy(hex, version) {
var bytes = Crypto.util.hexToBytes(hex);
bytes.unshift(version);
var hash = Crypto.SHA256(Crypto.SHA256(bytes, {
asBytes: true
}), {
asBytes: true
});
var checksum = hash.slice(0, 4);
return coinjs.base58encode(bytes.concat(checksum));
}
function decodeBech32(source) {
let decode = coinjs.bech32_decode(source);
if (!decode)
return null;
var raw = decode.data;
let version = raw.shift();
raw = coinjs.bech32_convert(raw, 5, 8, false);
return {
hrp: decode.hrp,
version: version,
hex: Crypto.util.bytesToHex(raw)
}
}
function encodeBech32(hex, version, hrp) {
var bytes = Crypto.util.hexToBytes(hex);
bytes = coinjs.bech32_convert(bytes, 8, 5, true);
bytes.unshift(version)
return coinjs.bech32_encode(hrp, bytes);
}
//BTC blockchain APIs
btcOperator.getBalance = addr => new Promise((resolve, reject) => {
fetch_api(`q/addressbalance/${addr}`)
.then(result => resolve(util.Sat_to_BTC(result)))
.catch(error => reject(error))
});
const BASE_TX_SIZE = 12,
BASE_INPUT_SIZE = 41,
LEGACY_INPUT_SIZE = 107,
BECH32_INPUT_SIZE = 27,
BECH32_MULTISIG_INPUT_SIZE = 35,
SEGWIT_INPUT_SIZE = 59,
MULTISIG_INPUT_SIZE_ES = 351,
BASE_OUTPUT_SIZE = 9,
LEGACY_OUTPUT_SIZE = 25,
BECH32_OUTPUT_SIZE = 23,
BECH32_MULTISIG_OUTPUT_SIZE = 34,
SEGWIT_OUTPUT_SIZE = 23;
function _redeemScript(addr, key) {
let decode = coinjs.addressDecode(addr);
switch (decode.type) {
case "standard":
return false;
case "multisig":
return key ? coinjs.segwitAddress(btcOperator.pubkey(key)).redeemscript : null;
case "bech32":
return decode.redeemscript;
default:
return null;
}
}
function _sizePerInput(addr, rs) {
switch (coinjs.addressDecode(addr).type) {
case "standard":
return BASE_INPUT_SIZE + LEGACY_INPUT_SIZE;
case "bech32":
return BASE_INPUT_SIZE + BECH32_INPUT_SIZE;
case "multisigBech32":
return BASE_INPUT_SIZE + BECH32_MULTISIG_INPUT_SIZE;
case "multisig":
switch (coinjs.script().decodeRedeemScript(rs).type) {
case "segwit__":
return BASE_INPUT_SIZE + SEGWIT_INPUT_SIZE;
case "multisig__":
return BASE_INPUT_SIZE + MULTISIG_INPUT_SIZE_ES;
default:
return null;
};
default:
return null;
}
}
function _sizePerOutput(addr) {
switch (coinjs.addressDecode(addr).type) {
case "standard":
return BASE_OUTPUT_SIZE + LEGACY_OUTPUT_SIZE;
case "bech32":
return BASE_OUTPUT_SIZE + BECH32_OUTPUT_SIZE;
case "multisigBech32":
return BASE_OUTPUT_SIZE + BECH32_MULTISIG_OUTPUT_SIZE;
case "multisig":
return BASE_OUTPUT_SIZE + SEGWIT_OUTPUT_SIZE;
default:
return null;
}
}
function validateTxParameters(parameters) {
let invalids = [];
//sender-ids
if (parameters.senders) {
if (!Array.isArray(parameters.senders))
parameters.senders = [parameters.senders];
parameters.senders.forEach(id => !validateAddress(id) ? invalids.push(id) : null);
if (invalids.length)
throw "Invalid senders:" + invalids;
}
if (parameters.privkeys) {
if (!Array.isArray(parameters.privkeys))
parameters.privkeys = [parameters.privkeys];
if (parameters.senders.length != parameters.privkeys.length)
throw "Array length for senders and privkeys should be equal";
parameters.senders.forEach((id, i) => {
let key = parameters.privkeys[i];
if (!verifyKey(id, key)) //verify private-key
invalids.push(id);
if (key.length === 64) //convert Hex to WIF if needed
parameters.privkeys[i] = coinjs.privkey2wif(key);
});
if (invalids.length)
throw "Invalid private key for address:" + invalids;
}
//receiver-ids (and change-id)
if (!Array.isArray(parameters.receivers))
parameters.receivers = [parameters.receivers];
parameters.receivers.forEach(id => !validateAddress(id) ? invalids.push(id) : null);
if (invalids.length)
throw "Invalid receivers:" + invalids;
if (parameters.change_address && !validateAddress(parameters.change_address))
throw "Invalid change_address:" + parameters.change_address;
//fee and amounts
if ((typeof parameters.fee !== "number" || parameters.fee <= 0) && parameters.fee !== null) //fee = null (auto calc)
throw "Invalid fee:" + parameters.fee;
if (!Array.isArray(parameters.amounts))
parameters.amounts = [parameters.amounts];
if (parameters.receivers.length != parameters.amounts.length)
throw "Array length for receivers and amounts should be equal";
parameters.amounts.forEach(a => typeof a !== "number" || a <= 0 ? invalids.push(a) : null);
if (invalids.length)
throw "Invalid amounts:" + invalids;
//return
return parameters;
}
function createTransaction(senders, redeemScripts, receivers, amounts, fee, change_address, fee_from_receiver) {
return new Promise((resolve, reject) => {
let total_amount = parseFloat(amounts.reduce((t, a) => t + a, 0).toFixed(8));
const tx = coinjs.transaction();
let output_size = addOutputs(tx, receivers, amounts, change_address);
addInputs(tx, senders, redeemScripts, total_amount, fee, output_size, fee_from_receiver).then(result => {
if (result.change_amount > 0 && result.change_amount > result.fee) //add change amount if any (ignore dust change)
tx.outs[tx.outs.length - 1].value = util.BTC_to_Sat(result.change_amount); //values are in satoshi
if (fee_from_receiver) { //deduce fee from receivers if fee_from_receiver
let fee_remaining = util.BTC_to_Sat(result.fee);
for (let i = 0; i < tx.outs.length - 1 && fee_remaining > 0; i++) {
if (fee_remaining < tx.outs[i].value) {
tx.outs[i].value -= fee_remaining;
fee_remaining = 0;
} else {
fee_remaining -= tx.outs[i].value;
tx.outs[i].value = 0;
}
}
if (fee_remaining > 0)
return reject("Send amount is less than fee");
}
tx.outs = tx.outs.filter(o => o.value != 0); //remove all output with value 0
result.output_size = output_size;
result.output_amount = total_amount - (fee_from_receiver ? result.fee : 0);
result.total_size = BASE_TX_SIZE + output_size + result.input_size;
result.transaction = tx;
resolve(result);
}).catch(error => reject(error))
})
}
function addInputs(tx, senders, redeemScripts, total_amount, fee, output_size, fee_from_receiver) {
return new Promise((resolve, reject) => {
if (fee !== null) {
addUTXOs(tx, senders, redeemScripts, fee_from_receiver ? total_amount : total_amount + fee, false).then(result => {
result.fee = fee;
resolve(result);
}).catch(error => reject(error))
} else {
get_fee_rate().then(fee_rate => {
let net_fee = BASE_TX_SIZE * fee_rate;
net_fee += (output_size * fee_rate);
(fee_from_receiver ?
addUTXOs(tx, senders, redeemScripts, total_amount, false) :
addUTXOs(tx, senders, redeemScripts, total_amount + net_fee, fee_rate)
).then(result => {
result.fee = parseFloat((net_fee + (result.input_size * fee_rate)).toFixed(8));
result.fee_rate = fee_rate;
resolve(result);
}).catch(error => reject(error))
}).catch(error => reject(error))
}
})
}
function addUTXOs(tx, senders, redeemScripts, required_amount, fee_rate, rec_args = {}) {
return new Promise((resolve, reject) => {
required_amount = parseFloat(required_amount.toFixed(8));
if (typeof rec_args.n === "undefined") {
rec_args.n = 0;
rec_args.input_size = 0;
rec_args.input_amount = 0;
}
if (required_amount <= 0)
return resolve({
input_size: rec_args.input_size,
input_amount: rec_args.input_amount,
change_amount: required_amount * -1 //required_amount will be -ve of change_amount
});
else if (rec_args.n >= senders.length)
return reject("Insufficient Balance");
let addr = senders[rec_args.n],
rs = redeemScripts[rec_args.n];
let addr_type = coinjs.addressDecode(addr).type;
let size_per_input = _sizePerInput(addr, rs);
fetch_api(`unspent?active=${addr}`).then(result => {
let utxos = result.unspent_outputs;
console.debug("add-utxo", addr, rs, required_amount, utxos);
for (let i = 0; i < utxos.length && required_amount > 0; i++) {
if (!utxos[i].confirmations) //ignore unconfirmed utxo
continue;
var script;
if (!rs || !rs.length) //legacy script
script = utxos[i].script;
else if (((rs.match(/^00/) && rs.length == 44)) || (rs.length == 40 && rs.match(/^[a-f0-9]+$/gi)) || addr_type === 'multisigBech32') {
//redeemScript for segwit/bech32 and multisig (bech32)
let s = coinjs.script();
s.writeBytes(Crypto.util.hexToBytes(rs));
s.writeOp(0);
s.writeBytes(coinjs.numToBytes(utxos[i].value.toFixed(0), 8));
script = Crypto.util.bytesToHex(s.buffer);
} else //redeemScript for multisig (segwit)
script = rs;
tx.addinput(utxos[i].tx_hash_big_endian, utxos[i].tx_output_n, script, 0xfffffffd /*sequence*/); //0xfffffffd for Replace-by-fee
//update track values
rec_args.input_size += size_per_input;
rec_args.input_amount += util.Sat_to_BTC(utxos[i].value);
required_amount -= util.Sat_to_BTC(utxos[i].value);
if (fee_rate) //automatic fee calculation (dynamic)
required_amount += size_per_input * fee_rate;
}
rec_args.n += 1;
addUTXOs(tx, senders, redeemScripts, required_amount, fee_rate, rec_args)
.then(result => resolve(result))
.catch(error => reject(error))
}).catch(error => reject(error))
})
}
function addOutputs(tx, receivers, amounts, change_address) {
let size = 0;
for (let i in receivers) {
tx.addoutput(receivers[i], amounts[i]);
size += _sizePerOutput(receivers[i]);
}
tx.addoutput(change_address, 0);
size += _sizePerOutput(change_address);
return size;
}
/*
function autoFeeCalc(tx) {
return new Promise((resolve, reject) => {
get_fee_rate().then(fee_rate => {
let tx_size = tx.size();
for (var i = 0; i < this.ins.length; i++)
switch (tx.extractScriptKey(i).type) {
case 'scriptpubkey':
tx_size += SIGN_SIZE;
break;
case 'segwit':
case 'multisig':
tx_size += SIGN_SIZE * 0.25;
break;
default:
console.warn('Unknown script-type');
tx_size += SIGN_SIZE;
}
resolve(tx_size * fee_rate);
}).catch(error => reject(error))
})
}
function editFee(tx, current_fee, target_fee, index = -1) {
//values are in satoshi
index = parseInt(index >= 0 ? index : tx.outs.length - index);
if (index < 0 || index >= tx.outs.length)
throw "Invalid index";
let edit_value = parseInt(current_fee - target_fee), //rip of any decimal places
current_value = tx.outs[index].value; //could be BigInterger
if (edit_value < 0 && edit_value > current_value)
throw "Insufficient value at vout";
tx.outs[index].value = current_value instanceof BigInteger ?
current_value.add(new BigInteger('' + edit_value)) : parseInt(current_value + edit_value);
}
*/
btcOperator.sendTx = function (senders, privkeys, receivers, amounts, fee = null, options = {}) {
return new Promise((resolve, reject) => {
createSignedTx(senders, privkeys, receivers, amounts, fee, options).then(result => {
debugger;
broadcastTx(result.transaction.serialize())
.then(txid => resolve(txid))
.catch(error => reject(error));
}).catch(error => reject(error))
})
}
const createSignedTx = btcOperator.createSignedTx = function (senders, privkeys, receivers, amounts, fee = null, options = {}) {
return new Promise((resolve, reject) => {
try {
({
senders,
privkeys,
receivers,
amounts
} = validateTxParameters({
senders,
privkeys,
receivers,
amounts,
fee,
change_address: options.change_address
}));
} catch (e) {
return reject(e)
}
let redeemScripts = [],
wif_keys = [];
for (let i in senders) {
let rs = _redeemScript(senders[i], privkeys[i]); //get redeem-script (segwit/bech32)
redeemScripts.push(rs);
rs === false ? wif_keys.unshift(privkeys[i]) : wif_keys.push(privkeys[i]); //sorting private-keys (wif)
}
if (redeemScripts.includes(null)) //TODO: segwit
return reject("Unable to get redeem-script");
//create transaction
createTransaction(senders, redeemScripts, receivers, amounts, fee, options.change_address || senders[0], options.fee_from_receiver).then(result => {
let tx = result.transaction;
console.debug("Unsigned:", tx.serialize());
new Set(wif_keys).forEach(key => console.debug("Signing key:", key, tx.sign(key, 1 /*sighashtype*/))); //Sign the tx using private key WIF
console.debug("Signed:", tx.serialize());
resolve(result);
}).catch(error => reject(error));
})
}
btcOperator.createTx = function (senders, receivers, amounts, fee = null, options = {}) {
return new Promise((resolve, reject) => {
try {
({
senders,
receivers,
amounts
} = validateTxParameters({
senders,
receivers,
amounts,
fee,
change_address: options.change_address
}));
} catch (e) {
return reject(e)
}
let redeemScripts = senders.map(id => _redeemScript(id));
if (redeemScripts.includes(null)) //TODO: segwit
return reject("Unable to get redeem-script");
//create transaction
createTransaction(senders, redeemScripts, receivers, amounts, fee, options.change_address || senders[0], options.fee_from_receiver).then(result => {
result.tx_hex = result.transaction.serialize();
delete result.transaction;
resolve(result);
}).catch(error => reject(error))
})
}
btcOperator.createMultiSigTx = function (sender, redeemScript, receivers, amounts, fee = null, options = {}) {
return new Promise((resolve, reject) => {
//validate tx parameters
let addr_type = validateAddress(sender);
if (!(["multisig", "multisigBech32"].includes(addr_type)))
return reject("Invalid sender (multisig):" + sender);
else {
let script = coinjs.script();
let decode = (addr_type == "multisig") ?
script.decodeRedeemScript(redeemScript) :
script.decodeRedeemScriptBech32(redeemScript);
if (!decode || decode.address !== sender)
return reject("Invalid redeem-script");
}
try {
({
receivers,
amounts
} = validateTxParameters({
receivers,
amounts,
fee,
change_address: options.change_address
}));
} catch (e) {
return reject(e)
}
//create transaction
createTransaction([sender], [redeemScript], receivers, amounts, fee, options.change_address || sender, options.fee_from_receiver).then(result => {
result.tx_hex = result.transaction.serialize();
delete result.transaction;
resolve(result);
}).catch(error => reject(error))
})
}
function deserializeTx(tx) {
if (typeof tx === 'string' || Array.isArray(tx)) {
try {
tx = coinjs.transaction().deserialize(tx);
} catch {
throw "Invalid transaction hex";
}
} else if (typeof tx !== 'object' || typeof tx.sign !== 'function')
throw "Invalid transaction object";
return tx;
}
btcOperator.signTx = function (tx, privkeys, sighashtype = 1) {
tx = deserializeTx(tx);
if (!Array.isArray(privkeys))
privkeys = [privkeys];
for (let i in privkeys)
if (privkeys[i].length === 64)
privkeys[i] = coinjs.privkey2wif(privkeys[i]);
new Set(privkeys).forEach(key => tx.sign(key, sighashtype)); //Sign the tx using private key WIF
return tx.serialize();
}
const checkSigned = btcOperator.checkSigned = function (tx, bool = true) {
tx = deserializeTx(tx);
let n = [];
for (let i in tx.ins) {
var s = tx.extractScriptKey(i);
if (s['type'] !== 'multisig' && s['type'] !== 'multisig_bech32')
n.push(s.signed == 'true' || (tx.witness[i] && tx.witness[i].length == 2))
else {
var rs = coinjs.script().decodeRedeemScript(s.script); //will work for bech32 too, as only address is diff
let x = {
s: s['signatures'],
r: rs['signaturesRequired'],
t: rs['pubkeys'].length
};
if (x.r > x.t)
throw "signaturesRequired is more than publicKeys";
else if (x.s < x.r)
n.push(x);
else
n.push(true);
}
}
return bool ? !(n.filter(x => x !== true).length) : n;
}
btcOperator.checkIfSameTx = function (tx1, tx2) {
tx1 = deserializeTx(tx1);
tx2 = deserializeTx(tx2);
if (tx1.ins.length !== tx2.ins.length || tx1.outs.length !== tx2.outs.length)
return false;
for (let i = 0; i < tx1.ins.length; i++)
if (tx1.ins[i].outpoint.hash !== tx2.ins[i].outpoint.hash || tx1.ins[i].outpoint.index !== tx2.ins[i].outpoint.index)
return false;
for (let i = 0; i < tx2.ins.length; i++)
if (tx1.outs[i].value !== tx2.outs[i].value || Crypto.util.bytesToHex(tx1.outs[i].script.buffer) !== Crypto.util.bytesToHex(tx2.outs[i].script.buffer))
return false;
return true;
}
const getTxOutput = (txid, i) => new Promise((resolve, reject) => {
fetch_api(`rawtx/${txid}`)
.then(result => resolve(result.out[i]))
.catch(error => reject(error))
});
btcOperator.parseTransaction = function (tx) {
return new Promise((resolve, reject) => {
tx = deserializeTx(tx);
let result = {};
let promises = [];
//Parse Inputs
for (let i = 0; i < tx.ins.length; i++)
promises.push(getTxOutput(tx.ins[i].outpoint.hash, tx.ins[i].outpoint.index));
Promise.all(promises).then(inputs => {
result.inputs = inputs.map(inp => Object({
address: inp.addr,
value: util.Sat_to_BTC(inp.value)
}));
let signed = checkSigned(tx, false);
result.inputs.forEach((inp, i) => inp.signed = signed[i]);
//Parse Outputs
result.outputs = tx.outs.map(out => {
var address;
switch (out.script.chunks[0]) {
case 0: //bech32, multisig-bech32
address = encodeBech32(Crypto.util.bytesToHex(out.script.chunks[1]), coinjs.bech32.version, coinjs.bech32.hrp);
break;
case 169: //segwit, multisig-segwit
address = encodeLegacy(Crypto.util.bytesToHex(out.script.chunks[1]), coinjs.multisig);
break;
case 118: //legacy
address = encodeLegacy(Crypto.util.bytesToHex(out.script.chunks[2]), coinjs.pub);
}
return {
address,
value: util.Sat_to_BTC(out.value)
}
});
//Parse Totals
result.total_input = parseFloat(result.inputs.reduce((a, inp) => a += inp.value, 0).toFixed(8));
result.total_output = parseFloat(result.outputs.reduce((a, out) => a += out.value, 0).toFixed(8));
result.fee = parseFloat((result.total_input - result.total_output).toFixed(8));
resolve(result);
}).catch(error => reject(error))
})
}
btcOperator.transactionID = function (tx) {
tx = deserializeTx(tx);
let clone = coinjs.clone(tx);
clone.witness = null;
let raw_bytes = Crypto.util.hexToBytes(clone.serialize());
let txid = Crypto.SHA256(Crypto.SHA256(raw_bytes, { asBytes: true }), { asBytes: true }).reverse();
return Crypto.util.bytesToHex(txid);
}
const getLatestBlock = btcOperator.getLatestBlock = () => new Promise((resolve, reject) => {
fetch_api(`q/getblockcount`)
.then(result => resolve(result))
.catch(error => reject(error))
})
btcOperator.getTx = txid => new Promise((resolve, reject) => {
fetch_api(`rawtx/${txid}`).then(result => {
getLatestBlock().then(latest_block => resolve({
block: result.block_height,
txid: result.hash,
time: result.time * 1000,
confirmations: result.block_height === null ? 0 : latest_block - result.block_height, //calculate confirmations using latest block number as api doesnt relay it
size: result.size,
fee: util.Sat_to_BTC(result.fee),
inputs: result.inputs.map(i => Object({ address: i.prev_out.addr, value: util.Sat_to_BTC(i.prev_out.value) })),
total_input_value: util.Sat_to_BTC(result.inputs.reduce((a, i) => a + i.prev_out.value, 0)),
outputs: result.out.map(o => Object({ address: o.addr, value: util.Sat_to_BTC(o.value) })),
total_output_value: util.Sat_to_BTC(result.out.reduce((a, o) => a += o.value, 0)),
}))
}).catch(error => reject(error))
});
btcOperator.getTx.hex = txid => new Promise((resolve, reject) => {
fetch_api(`rawtx/${txid}?format=hex`, false)
.then(result => resolve(result))
.catch(error => reject(error))
})
btcOperator.getAddressData = address => new Promise((resolve, reject) => {
fetch_api(`rawaddr/${address}`).then(data => {
let details = {};
details.balance = util.Sat_to_BTC(data.final_balance);
details.address = data.address;
details.txs = data.txs.map(tx => {
let d = {
txid: tx.hash,
time: tx.time * 1000, //s to ms
block: tx.block_height,
}
//sender list
d.tx_senders = {};
tx.inputs.forEach(i => {
if (i.prev_out.addr in d.tx_senders)
d.tx_senders[i.prev_out.addr] += i.prev_out.value;
else d.tx_senders[i.prev_out.addr] = i.prev_out.value;
});
d.tx_input_value = 0;
for (let s in d.tx_senders) {
let val = d.tx_senders[s];
d.tx_senders[s] = util.Sat_to_BTC(val);
d.tx_input_value += val;
}
d.tx_input_value = util.Sat_to_BTC(d.tx_input_value);
//receiver list
d.tx_receivers = {};
tx.out.forEach(o => {
if (o.addr in d.tx_receivers)
d.tx_receivers[o.addr] += o.value;
else d.tx_receivers[o.addr] = o.value;
});
d.tx_output_value = 0;
for (let r in d.tx_receivers) {
let val = d.tx_receivers[r];
d.tx_receivers[r] = util.Sat_to_BTC(val);
d.tx_output_value += val;
}
d.tx_output_value = util.Sat_to_BTC(d.tx_output_value);
d.tx_fee = util.Sat_to_BTC(tx.fee);
//tx type
if (tx.result > 0) { //net > 0, balance inc => type=in
d.type = "in";
d.amount = util.Sat_to_BTC(tx.result);
d.sender = Object.keys(d.tx_senders).filter(s => s !== address);
} else if (Object.keys(d.tx_receivers).some(r => r !== address)) { //net < 0, balance dec & receiver present => type=out
d.type = "out";
d.amount = util.Sat_to_BTC(tx.result * -1);
d.receiver = Object.keys(d.tx_receivers).filter(r => r !== address);
d.fee = d.tx_fee;
} else { //net < 0 (fee) & no other id in receiver list => type=self
d.type = "self";
d.amount = d.tx_receivers[address];
d.address = address
}
return d;
})
resolve(details);
}).catch(error => reject(error))
});
btcOperator.getBlock = block => new Promise((resolve, reject) => {
fetch_api(`rawblock/${block}`).then(result => resolve({
height: result.height,
hash: result.hash,
merkle_root: result.mrkl_root,
prev_block: result.prev_block,
next_block: result.next_block[0],
size: result.size,
time: result.time * 1000, //s to ms
txs: result.tx.map(t => Object({
fee: t.fee,
size: t.size,
inputs: t.inputs.map(i => Object({ address: i.prev_out.addr, value: util.Sat_to_BTC(i.prev_out.value) })),
total_input_value: util.Sat_to_BTC(t.inputs.reduce((a, i) => a + i.prev_out.value, 0)),
outputs: t.out.map(o => Object({ address: o.addr, value: util.Sat_to_BTC(o.value) })),
total_output_value: util.Sat_to_BTC(t.out.reduce((a, o) => a += o.value, 0)),
}))
})).catch(error => reject(error))
});
})('object' === typeof module ? module.exports : window.btcOperator = {});

File diff suppressed because one or more lines are too long

View File

@ -20,14 +20,13 @@ body {
--text-color: 20, 20, 20;
--foreground-color: 252, 253, 255;
--background-color: 241, 243, 248;
--danger-color: rgb(255, 75, 75);
--danger-color: rgb(225, 58, 58);
--green: #1cad59;
--yellow: rgb(220, 165, 0);
--yellow: rgb(255, 207, 65);
scrollbar-width: thin;
scrollbar-gutter: stable;
color: rgba(var(--text-color), 1);
background-color: rgba(var(--background-color), 1);
transition: background-color 0.3s;
position: relative;
display: flex;
flex-direction: column;
@ -47,21 +46,6 @@ body[data-theme=dark] sm-popup::part(popup) {
background-color: rgba(var(--foreground-color), 1);
}
h1, h1 > *,
h2,
h2 > *,
h3,
h3 > *,
h4,
h4 > *,
h5,
h5 > *,
h6,
h6 > * {
font-weight: 400;
font-family: "Calistoga", cursive;
}
p,
strong {
font-size: 0.9rem;
@ -87,15 +71,8 @@ a:focus-visible {
box-shadow: 0 0 0 0.1rem rgba(var(--text-color), 1) inset;
}
a.button {
padding: 0.4rem 0.6rem;
border-radius: 0.3rem;
font-size: 0.9rem;
font-weight: 500;
color: inherit;
}
button {
button,
.button {
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
@ -110,22 +87,26 @@ button {
font-weight: 500;
white-space: nowrap;
padding: 0.8rem;
border-radius: 0.3rem;
border-radius: 0.5rem;
justify-content: center;
flex-shrink: 0;
}
button:focus-visible {
button:focus-visible,
.button:focus-visible {
outline: var(--accent-color) solid medium;
}
button:not(:disabled) {
button:not(:disabled),
.button:not(:disabled) {
color: var(--accent-color);
cursor: pointer;
}
button .icon {
button .icon,
.button .icon {
fill: var(--accent-color);
}
.button {
display: inline-flex;
background-color: rgba(var(--text-color), 0.06);
}
.button--primary, .button--danger {
@ -143,6 +124,12 @@ button .icon {
.button--small {
padding: 0.4rem 0.5rem;
}
.button--colored {
color: var(--accent-color) !important;
}
.button--colored .icon {
fill: var(--accent-color);
}
.cta {
text-transform: uppercase;
@ -182,14 +169,17 @@ a:any-link:focus-visible {
details summary {
display: flex;
gap: 0.3rem;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
cursor: pointer;
align-items: center;
justify-content: space-between;
color: var(--accent-color);
}
details summary .down-arrow {
fill: var(--accent-color);
}
details[open] summary {
margin-bottom: 1rem;
@ -201,7 +191,7 @@ details[open] > summary .down-arrow {
sm-input,
sm-textarea {
width: 100%;
--border-radius: 0.4rem;
--border-radius: 0.5rem;
--background-color: rgba(var(--foreground-color), 1);
}
sm-input button .icon,
@ -244,13 +234,13 @@ sm-option {
sm-chips {
--gap: 0;
background-color: rgba(var(--text-color), 0.06);
border-radius: 0.3rem;
border-radius: 0.5rem;
padding: 0.3rem;
}
sm-chip {
font-size: 0.9rem;
--border-radius: 0.2rem;
--border-radius: 0.3rem;
-webkit-user-select: none;
-moz-user-select: none;
user-select: none;
@ -260,6 +250,10 @@ sm-chip[selected] {
--background: var(--accent-color);
}
sm-notifications {
z-index: 100000;
}
ul,
ol {
list-style: none;
@ -316,8 +310,6 @@ ol li::before {
overflow-wrap: break-word;
word-wrap: break-word;
word-break: break-word;
-webkit-hyphens: auto;
hyphens: auto;
}
.full-bleed {
@ -353,6 +345,10 @@ ol li::before {
flex: 1;
}
.flex-direction-column {
flex-direction: column;
}
.grid {
display: grid;
}
@ -389,10 +385,18 @@ ol li::before {
text-align: right;
}
.align-start {
.align-content-start {
align-content: flex-start;
}
.align-items-start {
align-items: flex-start;
}
.align-self-start {
align-self: flex-start;
}
.align-center {
align-items: center;
}
@ -518,6 +522,10 @@ ol li::before {
margin-right: 0.5rem;
}
.margin-right-auto {
margin-right: auto;
}
.margin-left-0-5 {
margin-left: 0.5rem;
}
@ -581,19 +589,19 @@ ol li::before {
}
#confirmation_popup h4,
#prompt_popup h4 {
margin-bottom: 0.5rem;
margin-bottom: 1.5rem;
}
#confirmation_popup sm-button,
#prompt_popup sm-button {
margin: 0;
}
#confirmation_popup .flex,
#prompt_popup .flex {
#confirmation_popup > .flex:last-of-type,
#prompt_popup > .flex:last-of-type {
padding: 0;
margin-top: 1rem;
}
#confirmation_popup .flex sm-button:first-of-type,
#prompt_popup .flex sm-button:first-of-type {
#confirmation_popup > .flex:last-of-type sm-button:first-of-type,
#prompt_popup > .flex:last-of-type sm-button:first-of-type {
margin-right: 0.6rem;
margin-left: auto;
}
@ -615,12 +623,6 @@ ol li::before {
margin-left: -0.5rem;
}
.flo-icon {
margin-right: 0.3rem;
height: 1.5rem;
width: 1.5rem;
}
#secondary_pages {
display: flex;
flex-direction: column;
@ -644,8 +646,38 @@ ol li::before {
font-size: clamp(2rem, 5vw, 5rem);
}
#loading_page {
display: grid;
gap: 1rem;
place-content: center;
place-items: center;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: 20;
background-color: rgba(var(--foreground-color), 1);
}
#main_header {
padding: 1.5rem max(1rem, 4vw);
padding: 1rem max(1rem, 4vw);
}
.app-brand {
display: flex;
gap: 0.3rem;
align-items: center;
}
.app-brand .icon {
height: 1.7rem;
width: 1.7rem;
}
.app-name__company {
font-size: 0.8rem;
font-weight: 500;
color: rgba(var(--text-color), 0.8);
}
#main_card {
@ -654,7 +686,6 @@ ol li::before {
grid-template-rows: auto 1fr;
height: 100%;
width: 100%;
transition: background-color 0.3s;
background-color: rgba(var(--foreground-color), 1);
}
@ -737,12 +768,14 @@ ol li::before {
display: grid;
text-align: center;
align-items: center;
justify-items: center;
}
.multi-state-button > * {
grid-area: 1/1/2/2;
}
.multi-state-button button {
z-index: 1;
width: 100%;
}
.scrolling-wrapper {
@ -764,13 +797,11 @@ ol li::before {
background-color: transparent;
border: thin solid rgba(var(--text-color), 0.3);
text-align: left;
flex-shrink: 1;
}
.primary-action .icon {
fill: var(--accent-color);
}
.primary-action:not(:last-of-type) {
margin-right: 0.5rem;
}
#flo_id_warning {
padding-bottom: 1.5rem;
@ -794,6 +825,10 @@ ol li::before {
margin-bottom: 0.3rem;
}
#search_query_input {
font-weight: 500;
}
#address_balance_card {
padding: 1.5rem;
border-radius: 0.5rem;
@ -808,6 +843,13 @@ ol li::before {
color: var(--accent-color);
}
#filter_selector {
--padding: 0.3rem 0.5rem;
}
#filter_selector sm-chip {
font-weight: 500;
}
.card {
padding: 0.5rem 0;
border: none;
@ -842,50 +884,69 @@ ol li::before {
border-bottom: thin solid rgba(var(--text-color), 0.3);
}
#tx_details__header:has(#tx_status) time {
text-align: left;
margin-right: auto;
}
#tx_details__header:has(:not(#tx_status)) time {
text-align: right;
margin-left: auto;
}
#transactions_list {
display: grid;
gap: 2rem;
padding-bottom: 4rem;
padding-top: 2rem;
}
transaction-card {
position: relative;
}
transaction-card:not(:last-of-type) {
padding-bottom: 2rem;
}
transaction-card:not(:last-of-type)::after {
content: "";
position: absolute;
bottom: 0;
right: 0;
height: 1px;
width: calc(100% - 3.5rem);
background-color: rgba(var(--text-color), 0.2);
}
.transaction {
grid-template-columns: auto 1fr auto;
position: relative;
grid-template-columns: auto 1fr;
gap: 0.5rem 1rem;
align-items: center;
grid-template-areas: "icon time amount" "icon receiver receiver" "icon txid txid";
}
.transaction:not(:last-of-type) {
padding-bottom: 1rem;
}
.transaction__amount {
white-space: nowrap;
}
.transaction.out .icon {
fill: var(--danger-color);
}
.transaction.out .transaction__amount {
color: var(--danger-color);
}
.transaction.out .transaction__amount::before {
content: "- ";
}
.transaction.in .icon {
fill: var(--green);
}
.transaction.in .transaction__amount {
color: var(--green);
}
.transaction.in .transaction__amount::before {
content: "+ ";
content: "+";
}
.transaction.unconfirmed-tx {
grid-template-areas: "icon time amount" "icon receiver receiver" "icon txid txid" "icon unconfirmed unconfirmed" "icon badge badge";
.transaction.out .transaction__amount {
color: var(--danger-color);
}
.transaction.unconfirmed-tx .icon {
.transaction.out .transaction__amount::before {
content: "-";
}
.transaction__amount {
white-space: nowrap;
}
.transaction.out .transaction__icon .icon {
fill: var(--danger-color);
}
.transaction.in .transaction__icon .icon {
fill: var(--green);
}
.transaction.unconfirmed-tx .transaction__icon .icon {
fill: var(--yellow);
}
.transaction__icon {
grid-area: icon;
display: flex;
align-items: center;
justify-content: center;
@ -895,39 +956,31 @@ ol li::before {
border-radius: 2rem;
}
.transaction__receiver {
grid-area: receiver;
font-weight: 500;
margin-bottom: 0.3rem;
line-height: 1.5;
}
.transaction__time {
grid-area: time;
font-size: 0.9rem;
color: rgba(var(--text-color), 0.8);
}
.transaction .pending-badge {
grid-area: badge;
font-size: 0.8rem;
padding: 0.2rem 0.5rem;
border-radius: 0.5rem;
background-color: var(--yellow);
color: rgba(var(--foreground-color), 1);
font-weight: 500;
justify-self: flex-start;
text-wrap: balance;
}
.transaction__amount {
grid-area: amount;
font-size: 1rem;
font-weight: 700;
}
.transaction__id {
grid-area: txid;
font-size: 0.9rem;
color: rgba(var(--text-color), 0.8);
}
.transaction .unconfirmed-wrapper {
grid-area: unconfirmed;
padding: 0.5rem 0;
.pending-badge {
font-size: 0.8rem;
padding: 0.2rem 0.5rem;
border-radius: 0.5rem;
background-color: var(--yellow);
color: rgba(0, 0, 0, 0.8);
font-weight: 500;
justify-self: flex-start;
}
.tx-participant:not(:last-of-type) {
@ -937,15 +990,80 @@ ol li::before {
content: ",";
}
table tr {
text-align: left;
#tx_details time {
padding: 0.3rem 0.8rem;
border-radius: 5rem;
background-color: rgba(var(--text-color), 0.06);
font-weight: 500;
font-size: 0.9rem;
text-wrap: balance;
}
table tr td,
table tr th {
padding: 0.8rem 0.5rem;
#tx_status {
display: flex;
align-items: center;
gap: 0.5rem;
padding: 0.6rem 0.8rem;
border-radius: 0.5rem;
background-color: rgba(var(--text-color), 0.03);
color: var(--danger-color);
width: -webkit-fit-content;
width: -moz-fit-content;
width: fit-content;
}
table tr:nth-child(even) {
background-color: rgba(var(--text-color), 0.05);
#tx_status .icon {
fill: var(--danger-color);
}
#tx_amount {
font-size: max(2rem, 4vw);
font-weight: 700;
text-wrap: balance;
}
#tx_amount:has(+ *) {
margin-bottom: 0.5rem;
}
#tx_technicals .tx-detail:first-of-type {
position: relative;
}
#tx_technicals .tx-detail:first-of-type::before {
content: "";
position: absolute;
top: 50%;
left: 0;
transform: translateY(-50%);
width: 0.2rem;
height: calc(100% - 2rem);
background-color: var(--accent-color);
border-radius: 0 1rem 1rem 0;
}
.details-wrapper {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
width: 100%;
}
.tx-detail {
display: grid;
gap: 0.5rem;
align-content: flex-start;
background-color: rgba(var(--text-color), 0.03);
padding: 1rem;
border-radius: 0.5rem;
flex: 1 1 8rem;
}
.tx-detail .flex div {
color: rgba(var(--text-color), 0.8);
font-size: 0.9rem;
font-weight: 500;
}
.tx-detail > div {
font-weight: 700;
font-size: 1rem;
color: rgba(var(--text-color), 0.9);
}
#in_out_wrapper {
@ -994,6 +1112,10 @@ table tr:nth-child(even) {
background-color: rgba(var(--foreground-color), 1);
}
#txid {
font-size: 0.9rem;
}
.user-action-result__icon {
justify-self: center;
height: 4rem;
@ -1051,6 +1173,55 @@ table tr:nth-child(even) {
transform: scale(1) translateY(0);
}
}
.increase-fee-sender,
.increase-fee-receiver {
padding: 1rem;
border-radius: 0.5rem;
border: solid thin rgba(var(--text-color), 0.3);
}
.input-action-wrapper {
display: flex;
gap: 0.5rem;
flex-wrap: wrap;
width: 100%;
align-items: start;
container: input-action/inline-size;
}
.input-action-wrapper sm-input {
width: auto;
flex: 1;
min-width: 20rem;
}
.input-action-wrapper button {
min-width: 7rem;
min-height: 3.15rem;
}
@container input-action (max-width: 28rem) {
sm-input {
width: 100%;
min-width: 16rem !important;
}
button {
flex: 1;
}
}
#conversion_view_selector {
margin-right: auto;
font-weight: 500;
}
.converted-card:not(:empty) {
border-radius: 0.5rem;
padding: 1rem;
background-color: rgba(var(--text-color), 0.03);
}
.converted-card:not(:empty) sm-copy {
font-weight: 500;
color: rgba(var(--text-color), 0.9);
}
@media screen and (max-width: 40rem) {
#main_navbar.hide-away {
bottom: 0;
@ -1083,6 +1254,7 @@ table tr:nth-child(even) {
}
#main_header {
grid-area: header;
padding: 1.5rem max(1rem, 4vw);
}
#main_navbar {
grid-area: nav;
@ -1108,13 +1280,24 @@ table tr:nth-child(even) {
body[data-theme=dark] #main_navbar {
background-color: rgba(0, 0, 0, 0.2);
}
#pages_container {
padding: 0 4vw;
.page {
width: min(60rem, 100%);
margin: 0 auto;
}
#generate_btc_addr_popup,
#retrieve_btc_addr_popup {
--width: 28rem;
}
#convert {
width: min(72rem, 100%);
}
#key_conversion_content {
grid-template-columns: 1fr 1fr;
align-items: flex-start;
}
#increase_fee_popup {
--width: 30rem;
}
}
@media screen and (min-width: 48rem) {
.sender-card,
@ -1122,11 +1305,6 @@ table tr:nth-child(even) {
grid-template-columns: 1fr 1fr;
}
}
@media screen and (min-width: 64rem) {
#pages_container {
padding: 0 12vw;
}
}
@media (any-hover: hover) {
::-webkit-scrollbar {
width: 0.5rem;

2
css/main.min.css vendored

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

86
docs/UI.md Normal file
View File

@ -0,0 +1,86 @@
## routeTo(targetPage, options = {}) explanation
- routeTo handles routing and animation logic for our web applications. This function takes a targetPage and an optional options object as parameters.
- Destructures options Object: firstLoad, hashChange, and isPreview are destructured from the options object.
- Parsing targetPage:
1. If targetPage is an empty string, pageId is set to 'check_details'.
2. If targetPage contains a slash (/), it splits targetPage into parts. The first part is the pageId, and the second part (if any) is further split into subPageId1.
Query parameters are parsed from the search parameters of the URL, if available.
- Handling check_details Page:
1. If the pageId is 'check_details', it checks for query parameters. If there are query parameters, it updates the search input value and renders query results.
- Animating Navigation:
1. Animates the transition of the navigation menu based on the current and previous active elements.
2. Handles the indicator animation to show the active menu item.
3. If the current page is not found in the navigation menu, it hides the navigation bar.
- Showing/Hiding Pages:
1. Hides all pages, then shows the target page and animates its opacity to make it visible.
- Updating pagesData.lastPage:
1. Updates the lastPage property of pagesData to keep track of the last visited page.
## UI Page Flow
- Linking scripts are added first
- Create sm-notifications thereafter
- Create sm-popup
- Then create `<div id="main_card">`
- Then create `<header></header>` inside the main card
- Then create `<main id="pages_container" class="grid">`
- Then the first page `<div id="check_details" class="page hidden">`
- Then the second page `<div id="send" class="page">`
- Then the third page `<div id="convert_key" class="page hidden flex flex-direction-column gap-1-5">`
- Inside a page
1. Fieldsets
2. Input inside it
3. Then button <button type="submit" onclick="convertBtcPrivateKey()" class="button button--primary cta" disabled="">Convert</button>
- Clicking a button will lead to action <button type="submit" onclick="convertBtcPrivateKey()"
- Everything happens through clicking
```javascript
<button id="convert_to_flo" class="button--primary justify-self-center cta" type="submit" disabled="">
Convert
</button>
<div id="btc_address_converter_result"></div>
getRef('convert_to_flo').onclick = evt => {
const btc_bech = getRef('convert_btc_input').value.trim();
if (btc_bech === '') {
getRef('convert_btc_input').focusIn()
return notify('Please enter BTC address', 'error');
}
```
- Or we can add eventlisteners from Javascript side
- We add eventListeners to any id
```javascript
getRef('convert_btc_private_key_form').addEventListener('invalid', e => {
getRef('flo_private').value = '';
getRef('converted_flo_address').value = '';
})
```
- Then the navbar
` <nav id="main_navbar">`
- Navbar goes into bottom of the page
- Then you place your popups
```
<sm-popup id="txid_popup">
getRef('txid_popup__resolved_txid').value = txid;
openPopup('txid_popup', true);
```
- Now there is <script id="ui_utils"> this is the script with UI Javascript logic
- And finally the <script></script> with actual business logic
- Attach eventlisteners to different buttons, and handle them as per the busines logic

2295
index.html

File diff suppressed because one or more lines are too long

1503
scripts/btcOperator.js Normal file

File diff suppressed because it is too large Load Diff

1
scripts/btcOperator.min.js vendored Normal file

File diff suppressed because one or more lines are too long

12
scripts/components.js Normal file

File diff suppressed because one or more lines are too long

1
scripts/components.min.js vendored Normal file

File diff suppressed because one or more lines are too long

530
scripts/floCrypto.js Normal file
View File

@ -0,0 +1,530 @@
(function (EXPORTS) { //floCrypto v2.3.6a
/* FLO Crypto Operators */
'use strict';
const floCrypto = EXPORTS;
const p = BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F", 16);
const ecparams = EllipticCurve.getSECCurveByName("secp256k1");
const ascii_alternatives = ` '\n '\n“ "\n” "\n --\n— ---\n≥ >=\n≤ <=\n≠ !=\n× *\n÷ /\n← <-\n→ ->\n↔ <->\n⇒ =>\n⇐ <=\n⇔ <=>`;
const exponent1 = () => p.add(BigInteger.ONE).divide(BigInteger("4"));
coinjs.compressed = true; //defaulting coinjs compressed to true;
function calculateY(x) {
let exp = exponent1();
// x is x value of public key in BigInteger format without 02 or 03 or 04 prefix
return x.modPow(BigInteger("3"), p).add(BigInteger("7")).mod(p).modPow(exp, p)
}
function getUncompressedPublicKey(compressedPublicKey) {
// Fetch x from compressedPublicKey
let pubKeyBytes = Crypto.util.hexToBytes(compressedPublicKey);
const prefix = pubKeyBytes.shift() // remove prefix
let prefix_modulus = prefix % 2;
pubKeyBytes.unshift(0) // add prefix 0
let x = new BigInteger(pubKeyBytes)
let xDecimalValue = x.toString()
// Fetch y
let y = calculateY(x);
let yDecimalValue = y.toString();
// verify y value
let resultBigInt = y.mod(BigInteger("2"));
let check = resultBigInt.toString() % 2;
if (prefix_modulus !== check)
yDecimalValue = y.negate().mod(p).toString();
return {
x: xDecimalValue,
y: yDecimalValue
};
}
function getSenderPublicKeyString() {
let privateKey = ellipticCurveEncryption.senderRandom();
var senderPublicKeyString = ellipticCurveEncryption.senderPublicString(privateKey);
return {
privateKey: privateKey,
senderPublicKeyString: senderPublicKeyString
}
}
function deriveSharedKeySender(receiverPublicKeyHex, senderPrivateKey) {
let receiverPublicKeyString = getUncompressedPublicKey(receiverPublicKeyHex);
var senderDerivedKey = ellipticCurveEncryption.senderSharedKeyDerivation(
receiverPublicKeyString.x, receiverPublicKeyString.y, senderPrivateKey);
return senderDerivedKey;
}
function deriveSharedKeyReceiver(senderPublicKeyString, receiverPrivateKey) {
return ellipticCurveEncryption.receiverSharedKeyDerivation(
senderPublicKeyString.XValuePublicString, senderPublicKeyString.YValuePublicString, receiverPrivateKey);
}
function getReceiverPublicKeyString(privateKey) {
return ellipticCurveEncryption.receiverPublicString(privateKey);
}
function wifToDecimal(pk_wif, isPubKeyCompressed = false) {
let pk = Bitcoin.Base58.decode(pk_wif)
pk.shift()
pk.splice(-4, 4)
//If the private key corresponded to a compressed public key, also drop the last byte (it should be 0x01).
if (isPubKeyCompressed == true) pk.pop()
pk.unshift(0)
let privateKeyDecimal = BigInteger(pk).toString()
let privateKeyHex = Crypto.util.bytesToHex(pk)
return {
privateKeyDecimal: privateKeyDecimal,
privateKeyHex: privateKeyHex
}
}
//generate a random Interger within range
floCrypto.randInt = function (min, max) {
min = Math.ceil(min);
max = Math.floor(max);
return Math.floor(securedMathRandom() * (max - min + 1)) + min;
}
//generate a random String within length (options : alphaNumeric chars only)
floCrypto.randString = function (length, alphaNumeric = true) {
var result = '';
var characters = alphaNumeric ? 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789' :
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789_+-./*?@#&$<>=[]{}():';
for (var i = 0; i < length; i++)
result += characters.charAt(Math.floor(securedMathRandom() * characters.length));
return result;
}
//Encrypt Data using public-key
floCrypto.encryptData = function (data, receiverPublicKeyHex) {
var senderECKeyData = getSenderPublicKeyString();
var senderDerivedKey = deriveSharedKeySender(receiverPublicKeyHex, senderECKeyData.privateKey);
let senderKey = senderDerivedKey.XValue + senderDerivedKey.YValue;
let secret = Crypto.AES.encrypt(data, senderKey);
return {
secret: secret,
senderPublicKeyString: senderECKeyData.senderPublicKeyString
};
}
//Decrypt Data using private-key
floCrypto.decryptData = function (data, privateKeyHex) {
var receiverECKeyData = {};
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
let privateKey = wifToDecimal(privateKeyHex, true);
if (typeof privateKey.privateKeyDecimal !== "string") throw new Error("Failed to detremine your private key.");
receiverECKeyData.privateKey = privateKey.privateKeyDecimal;
var receiverDerivedKey = deriveSharedKeyReceiver(data.senderPublicKeyString, receiverECKeyData.privateKey);
let receiverKey = receiverDerivedKey.XValue + receiverDerivedKey.YValue;
let decryptMsg = Crypto.AES.decrypt(data.secret, receiverKey);
return decryptMsg;
}
//Sign data using private-key
floCrypto.signData = function (data, privateKeyHex) {
var key = new Bitcoin.ECKey(privateKeyHex);
var messageHash = Crypto.SHA256(data);
var messageSign = Bitcoin.ECDSA.sign(messageHash, key.priv);
var sighex = Crypto.util.bytesToHex(messageSign);
return sighex;
}
//Verify signatue of the data using public-key
floCrypto.verifySign = function (data, signatureHex, publicKeyHex) {
var msgHash = Crypto.SHA256(data);
var sigBytes = Crypto.util.hexToBytes(signatureHex);
var publicKeyPoint = ecparams.getCurve().decodePointHex(publicKeyHex);
var verify = Bitcoin.ECDSA.verify(msgHash, sigBytes, publicKeyPoint);
return verify;
}
//Generates a new flo ID and returns private-key, public-key and floID
const generateNewID = floCrypto.generateNewID = function () {
var key = new Bitcoin.ECKey(false);
key.setCompressed(true);
return {
floID: key.getBitcoinAddress(),
pubKey: key.getPubKeyHex(),
privKey: key.getBitcoinWalletImportFormat()
}
}
Object.defineProperties(floCrypto, {
newID: {
get: () => generateNewID()
},
hashID: {
value: (str) => {
let bytes = ripemd160(Crypto.SHA256(str, { asBytes: true }), { asBytes: true });
bytes.unshift(bitjs.pub);
var hash = Crypto.SHA256(Crypto.SHA256(bytes, {
asBytes: true
}), {
asBytes: true
});
var checksum = hash.slice(0, 4);
return bitjs.Base58.encode(bytes.concat(checksum));
}
},
tmpID: {
get: () => {
let bytes = Crypto.util.randomBytes(20);
bytes.unshift(bitjs.pub);
var hash = Crypto.SHA256(Crypto.SHA256(bytes, {
asBytes: true
}), {
asBytes: true
});
var checksum = hash.slice(0, 4);
return bitjs.Base58.encode(bytes.concat(checksum));
}
}
});
//Returns public-key from private-key
floCrypto.getPubKeyHex = function (privateKeyHex) {
if (!privateKeyHex)
return null;
var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null)
return null;
key.setCompressed(true);
return key.getPubKeyHex();
}
//Returns flo-ID from public-key or private-key
floCrypto.getFloID = function (keyHex) {
if (!keyHex)
return null;
try {
var key = new Bitcoin.ECKey(keyHex);
if (key.priv == null)
key.setPub(keyHex);
return key.getBitcoinAddress();
} catch {
return null;
}
}
floCrypto.getAddress = function (privateKeyHex, strict = false) {
if (!privateKeyHex)
return;
var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null)
return null;
key.setCompressed(true);
let pubKey = key.getPubKeyHex(),
version = bitjs.Base58.decode(privateKeyHex)[0];
switch (version) {
case coinjs.priv: //BTC
return coinjs.bech32Address(pubKey).address;
case bitjs.priv: //FLO
return bitjs.pubkey2address(pubKey);
default:
return strict ? false : bitjs.pubkey2address(pubKey); //default to FLO address (if strict=false)
}
}
//Verify the private-key for the given public-key or flo-ID
floCrypto.verifyPrivKey = function (privateKeyHex, pubKey_floID, isfloID = true) {
if (!privateKeyHex || !pubKey_floID)
return false;
try {
var key = new Bitcoin.ECKey(privateKeyHex);
if (key.priv == null)
return false;
key.setCompressed(true);
if (isfloID && pubKey_floID == key.getBitcoinAddress())
return true;
else if (!isfloID && pubKey_floID.toUpperCase() == key.getPubKeyHex().toUpperCase())
return true;
else
return false;
} catch {
return null;
}
}
floCrypto.getMultisigAddress = function (publicKeyList, requiredSignatures) {
if (!Array.isArray(publicKeyList) || !publicKeyList.length)
return null;
if (!Number.isInteger(requiredSignatures) || requiredSignatures < 1 || requiredSignatures > publicKeyList.length)
return null;
try {
var multisig = bitjs.pubkeys2multisig(publicKeyList, requiredSignatures);
return multisig;
} catch {
return null;
}
}
floCrypto.decodeRedeemScript = function (redeemScript) {
try {
var decoded = bitjs.transaction().decodeRedeemScript(redeemScript);
return decoded;
} catch {
return null;
}
}
//Check if the given flo-id is valid or not
floCrypto.validateFloID = function (floID, regularOnly = false) {
if (!floID)
return false;
try {
let addr = new Bitcoin.Address(floID);
if (regularOnly && addr.version != Bitcoin.Address.standardVersion)
return false;
return true;
} catch {
return false;
}
}
//Check if the given address (any blockchain) is valid or not
floCrypto.validateAddr = function (address, std = true, bech = true) {
let raw = decodeAddress(address);
if (!raw)
return false;
if (typeof raw.version !== 'undefined') { //legacy or segwit
if (std == false)
return false;
else if (std === true || (!Array.isArray(std) && std === raw.version) || (Array.isArray(std) && std.includes(raw.version)))
return true;
else
return false;
} else if (typeof raw.bech_version !== 'undefined') { //bech32
if (bech === false)
return false;
else if (bech === true || (!Array.isArray(bech) && bech === raw.bech_version) || (Array.isArray(bech) && bech.includes(raw.bech_version)))
return true;
else
return false;
} else //unknown
return false;
}
//Check the public-key (or redeem-script) for the address (any blockchain)
floCrypto.verifyPubKey = function (pubKeyHex, address) {
let raw = decodeAddress(address);
if (!raw)
return;
let pub_hash = Crypto.util.bytesToHex(ripemd160(Crypto.SHA256(Crypto.util.hexToBytes(pubKeyHex), { asBytes: true })));
if (typeof raw.bech_version !== 'undefined' && raw.bytes.length == 32) //bech32-multisig
raw.hex = Crypto.util.bytesToHex(ripemd160(raw.bytes, { asBytes: true }));
return pub_hash === raw.hex;
}
//Convert the given address (any blockchain) to equivalent floID
floCrypto.toFloID = function (address, options = null) {
if (!address)
return;
let raw = decodeAddress(address);
if (!raw)
return;
else if (options) { //if (optional) version check is passed
if (typeof raw.version !== 'undefined' && (!options.std || !options.std.includes(raw.version)))
return;
if (typeof raw.bech_version !== 'undefined' && (!options.bech || !options.bech.includes(raw.bech_version)))
return;
}
raw.bytes.unshift(bitjs.pub);
let hash = Crypto.SHA256(Crypto.SHA256(raw.bytes, {
asBytes: true
}), {
asBytes: true
});
return bitjs.Base58.encode(raw.bytes.concat(hash.slice(0, 4)));
}
//Convert raw address bytes to floID
floCrypto.rawToFloID = function (raw_bytes) {
if (typeof raw_bytes === 'string')
raw_bytes = Crypto.util.hexToBytes(raw_bytes);
if (raw_bytes.length != 20)
return null;
raw_bytes.unshift(bitjs.pub);
let hash = Crypto.SHA256(Crypto.SHA256(raw_bytes, {
asBytes: true
}), {
asBytes: true
});
return bitjs.Base58.encode(raw_bytes.concat(hash.slice(0, 4)));
}
//Convert the given multisig address (any blockchain) to equivalent multisig floID
floCrypto.toMultisigFloID = function (address, options = null) {
if (!address)
return;
let raw = decodeAddress(address);
if (!raw)
return;
else if (options) { //if (optional) version check is passed
if (typeof raw.version !== 'undefined' && (!options.std || !options.std.includes(raw.version)))
return;
if (typeof raw.bech_version !== 'undefined' && (!options.bech || !options.bech.includes(raw.bech_version)))
return;
}
if (typeof raw.bech_version !== 'undefined') {
if (raw.bytes.length != 32) return; //multisig bech address have 32 bytes
//multisig-bech:hash=SHA256 whereas multisig:hash=r160(SHA265), thus ripemd160 the bytes from multisig-bech
raw.bytes = ripemd160(raw.bytes, {
asBytes: true
});
}
raw.bytes.unshift(bitjs.multisig);
let hash = Crypto.SHA256(Crypto.SHA256(raw.bytes, {
asBytes: true
}), {
asBytes: true
});
return bitjs.Base58.encode(raw.bytes.concat(hash.slice(0, 4)));
}
//Checks if the given addresses (any blockchain) are same (w.r.t keys)
floCrypto.isSameAddr = function (addr1, addr2) {
if (!addr1 || !addr2)
return;
let raw1 = decodeAddress(addr1),
raw2 = decodeAddress(addr2);
if (!raw1 || !raw2)
return false;
else {
if (typeof raw1.bech_version !== 'undefined' && raw1.bytes.length == 32) //bech32-multisig
raw1.hex = Crypto.util.bytesToHex(ripemd160(raw1.bytes, { asBytes: true }));
if (typeof raw2.bech_version !== 'undefined' && raw2.bytes.length == 32) //bech32-multisig
raw2.hex = Crypto.util.bytesToHex(ripemd160(raw2.bytes, { asBytes: true }));
return raw1.hex === raw2.hex;
}
}
const decodeAddress = floCrypto.decodeAddr = function (address) {
if (!address)
return;
else if (address.length == 33 || address.length == 34) { //legacy encoding
let decode = bitjs.Base58.decode(address);
let bytes = decode.slice(0, decode.length - 4);
let checksum = decode.slice(decode.length - 4),
hash = Crypto.SHA256(Crypto.SHA256(bytes, {
asBytes: true
}), {
asBytes: true
});
return (hash[0] != checksum[0] || hash[1] != checksum[1] || hash[2] != checksum[2] || hash[3] != checksum[3]) ? null : {
version: bytes.shift(),
hex: Crypto.util.bytesToHex(bytes),
bytes
}
} else if (address.length == 42 || address.length == 62) { //bech encoding
let decode = coinjs.bech32_decode(address);
if (decode) {
let bytes = decode.data;
let bech_version = bytes.shift();
bytes = coinjs.bech32_convert(bytes, 5, 8, false);
return {
bech_version,
hrp: decode.hrp,
hex: Crypto.util.bytesToHex(bytes),
bytes
}
} else
return null;
}
}
//Split the str using shamir's Secret and Returns the shares
floCrypto.createShamirsSecretShares = function (str, total_shares, threshold_limit) {
try {
if (str.length > 0) {
var strHex = shamirSecretShare.str2hex(str);
var shares = shamirSecretShare.share(strHex, total_shares, threshold_limit);
return shares;
}
return false;
} catch {
return false
}
}
//Returns the retrived secret by combining the shamirs shares
const retrieveShamirSecret = floCrypto.retrieveShamirSecret = function (sharesArray) {
try {
if (sharesArray.length > 0) {
var comb = shamirSecretShare.combine(sharesArray.slice(0, sharesArray.length));
comb = shamirSecretShare.hex2str(comb);
return comb;
}
return false;
} catch {
return false;
}
}
//Verifies the shares and str
floCrypto.verifyShamirsSecret = function (sharesArray, str) {
if (!str)
return null;
else if (retrieveShamirSecret(sharesArray) === str)
return true;
else
return false;
}
const validateASCII = floCrypto.validateASCII = function (string, bool = true) {
if (typeof string !== "string")
return null;
if (bool) {
let x;
for (let i = 0; i < string.length; i++) {
x = string.charCodeAt(i);
if (x < 32 || x > 127)
return false;
}
return true;
} else {
let x, invalids = {};
for (let i = 0; i < string.length; i++) {
x = string.charCodeAt(i);
if (x < 32 || x > 127)
if (x in invalids)
invalids[string[i]].push(i)
else
invalids[string[i]] = [i];
}
if (Object.keys(invalids).length)
return invalids;
else
return true;
}
}
floCrypto.convertToASCII = function (string, mode = 'soft-remove') {
let chars = validateASCII(string, false);
if (chars === true)
return string;
else if (chars === null)
return null;
let convertor, result = string,
refAlt = {};
ascii_alternatives.split('\n').forEach(a => refAlt[a[0]] = a.slice(2));
mode = mode.toLowerCase();
if (mode === "hard-unicode")
convertor = (c) => `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
else if (mode === "soft-unicode")
convertor = (c) => refAlt[c] || `\\u${('000' + c.charCodeAt().toString(16)).slice(-4)}`;
else if (mode === "hard-remove")
convertor = c => "";
else if (mode === "soft-remove")
convertor = c => refAlt[c] || "";
else
return null;
for (let c in chars)
result = result.replaceAll(c, convertor(c));
return result;
}
floCrypto.revertUnicode = function (string) {
return string.replace(/\\u[\dA-F]{4}/gi,
m => String.fromCharCode(parseInt(m.replace(/\\u/g, ''), 16)));
}
})('object' === typeof module ? module.exports : window.floCrypto = {});

46
scripts/floEthereum.js Normal file
View File

@ -0,0 +1,46 @@
(function (EXPORTS) { //floEthereum v1.0.1a
/* FLO Ethereum Operators */
/* Make sure you added Taproot, Keccak, FLO and BTC Libraries before */
'use strict';
const floEthereum = EXPORTS;
const ethPrivateKeyFromWif = floEthereum.ethPrivateKeyFromWif = function (privateKey,) {
return coinjs.wif2privkey(privateKey).privkey;
}
const ethAddressFromPrivateKey = floEthereum.ethAddressFromPrivateKey = function (privateKey, onlyEvenY = false) {
var t1, t1_x, t1_y, t1_y_BigInt, t2, t3, t4;
var groupOrder = BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");
t1 = bitjs.newPubkey(privateKey);
t1_x = t1.slice(2, 66); t1_y = t1.slice(-64);
if (onlyEvenY) {
t1_y_BigInt = BigInt("0x" + t1_y);
if (t1_y_BigInt % 2n !== 0n) { t1_y_BigInt = (groupOrder - t1_y_BigInt) % groupOrder; t1_y = t1_y_BigInt.toString(16) }
};
t2 = t1_x.toString(16) + t1_y.toString(16);
t3 = keccak.keccak_256(Crypto.util.hexToBytes(t2));
t4 = keccak.extractLast20Bytes(t3);
return "0x" + t4;
}
const ethAddressFromCompressedPublicKey = floEthereum.ethAddressFromCompressedPublicKey = function (compressedPublicKey) {
var t1, t2, t3, t4;
t1 = coinjs.compressedToUncompressed(compressedPublicKey);
t2 = t1.slice(2);
t3 = keccak.keccak_256(Crypto.util.hexToBytes(t2));
t4 = keccak.extractLast20Bytes(t3);
return "0x" + t4;
}
const ethAddressFromUncompressedPublicKey = floEthereum.ethAddressFromUncompressedPublicKey = function (unCompressedPublicKey) {
var t1, t2, t3, t4;
t1 = unCompressedPublicKey;
t2 = t1.slice(2);
t3 = keccak.keccak_256(Crypto.util.hexToBytes(t2));
t4 = keccak.extractLast20Bytes(t3);
return "0x" + t4;
}
})('object' === typeof module ? module.exports : window.floEthereum = {});

1
scripts/floEthereum.min.js vendored Normal file
View File

@ -0,0 +1 @@
!function(EXPORTS){"use strict";const floEthereum="object"===typeof module?module.exports:window.floEthereum={};floEthereum.ethPrivateKeyFromWif=function(privateKey){return coinjs.wif2privkey(privateKey).privkey},floEthereum.ethAddressFromPrivateKey=function(privateKey,onlyEvenY=!1){var t1,t1_x,t1_y,t1_y_BigInt,t2,t3,groupOrder=BigInt("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEFFFFFC2F");return t1_x=(t1=bitjs.newPubkey(privateKey)).slice(2,66),t1_y=t1.slice(-64),onlyEvenY&&(t1_y_BigInt=BigInt("0x"+t1_y))%2n!==0n&&(t1_y=(t1_y_BigInt=(groupOrder-t1_y_BigInt)%groupOrder).toString(16)),t2=t1_x.toString(16)+t1_y.toString(16),t3=keccak.keccak_256(Crypto.util.hexToBytes(t2)),"0x"+keccak.extractLast20Bytes(t3)},floEthereum.ethAddressFromCompressedPublicKey=function(compressedPublicKey){var t2,t3;return t2=coinjs.compressedToUncompressed(compressedPublicKey).slice(2),t3=keccak.keccak_256(Crypto.util.hexToBytes(t2)),"0x"+keccak.extractLast20Bytes(t3)},floEthereum.ethAddressFromUncompressedPublicKey=function(unCompressedPublicKey){var t2,t3;return t2=unCompressedPublicKey.slice(2),t3=keccak.keccak_256(Crypto.util.hexToBytes(t2)),"0x"+keccak.extractLast20Bytes(t3)}}();

673
scripts/keccak.js Normal file
View File

@ -0,0 +1,673 @@
(function () {
'use strict';
var INPUT_ERROR = 'input is invalid type';
var FINALIZE_ERROR = 'finalize already called';
var WINDOW = typeof window === 'object';
var root = WINDOW ? (window.keccak = window.keccak || {}) : {};
if (root.JS_SHA3_NO_WINDOW) {
WINDOW = false;
}
var WEB_WORKER = !WINDOW && typeof self === 'object';
var NODE_JS = !root.JS_SHA3_NO_NODE_JS && typeof process === 'object' && process.versions && process.versions.node;
if (NODE_JS) {
root = global;
} else if (WEB_WORKER) {
root = self;
}
var COMMON_JS = !root.JS_SHA3_NO_COMMON_JS && typeof module === 'object' && module.exports;
var AMD = typeof define === 'function' && define.amd;
var ARRAY_BUFFER = !root.JS_SHA3_NO_ARRAY_BUFFER && typeof ArrayBuffer !== 'undefined';
var HEX_CHARS = '0123456789abcdef'.split('');
var SHAKE_PADDING = [31, 7936, 2031616, 520093696];
var CSHAKE_PADDING = [4, 1024, 262144, 67108864];
var KECCAK_PADDING = [1, 256, 65536, 16777216];
var PADDING = [6, 1536, 393216, 100663296];
var SHIFT = [0, 8, 16, 24];
var RC = [1, 0, 32898, 0, 32906, 2147483648, 2147516416, 2147483648, 32907, 0, 2147483649,
0, 2147516545, 2147483648, 32777, 2147483648, 138, 0, 136, 0, 2147516425, 0,
2147483658, 0, 2147516555, 0, 139, 2147483648, 32905, 2147483648, 32771,
2147483648, 32770, 2147483648, 128, 2147483648, 32778, 0, 2147483658, 2147483648,
2147516545, 2147483648, 32896, 2147483648, 2147483649, 0, 2147516424, 2147483648];
var BITS = [224, 256, 384, 512];
var SHAKE_BITS = [128, 256];
var OUTPUT_TYPES = ['hex', 'buffer', 'arrayBuffer', 'array', 'digest'];
var CSHAKE_BYTEPAD = {
'128': 168,
'256': 136
};
var isArray = root.JS_SHA3_NO_NODE_JS || !Array.isArray
? function (obj) {
return Object.prototype.toString.call(obj) === '[object Array]';
}
: Array.isArray;
var isView = (ARRAY_BUFFER && (root.JS_SHA3_NO_ARRAY_BUFFER_IS_VIEW || !ArrayBuffer.isView))
? function (obj) {
return typeof obj === 'object' && obj.buffer && obj.buffer.constructor === ArrayBuffer;
}
: ArrayBuffer.isView;
// [message: string, isString: bool]
var formatMessage = function (message) {
var type = typeof message;
if (type === 'string') {
return [message, true];
}
if (type !== 'object' || message === null) {
throw new Error(INPUT_ERROR);
}
if (ARRAY_BUFFER && message.constructor === ArrayBuffer) {
return [new Uint8Array(message), false];
}
if (!isArray(message) && !isView(message)) {
throw new Error(INPUT_ERROR);
}
return [message, false];
}
var empty = function (message) {
return formatMessage(message)[0].length === 0;
};
var createOutputMethod = function (bits, padding, outputType) {
return function (message) {
return new Keccak(bits, padding, bits).update(message)[outputType]();
};
};
var createShakeOutputMethod = function (bits, padding, outputType) {
return function (message, outputBits) {
return new Keccak(bits, padding, outputBits).update(message)[outputType]();
};
};
var createCshakeOutputMethod = function (bits, padding, outputType) {
return function (message, outputBits, n, s) {
return methods['cshake' + bits].update(message, outputBits, n, s)[outputType]();
};
};
var createKmacOutputMethod = function (bits, padding, outputType) {
return function (key, message, outputBits, s) {
return methods['kmac' + bits].update(key, message, outputBits, s)[outputType]();
};
};
var createOutputMethods = function (method, createMethod, bits, padding) {
for (var i = 0; i < OUTPUT_TYPES.length; ++i) {
var type = OUTPUT_TYPES[i];
method[type] = createMethod(bits, padding, type);
}
return method;
};
var createMethod = function (bits, padding) {
var method = createOutputMethod(bits, padding, 'hex');
method.create = function () {
return new Keccak(bits, padding, bits);
};
method.update = function (message) {
return method.create().update(message);
};
return createOutputMethods(method, createOutputMethod, bits, padding);
};
var createShakeMethod = function (bits, padding) {
var method = createShakeOutputMethod(bits, padding, 'hex');
method.create = function (outputBits) {
return new Keccak(bits, padding, outputBits);
};
method.update = function (message, outputBits) {
return method.create(outputBits).update(message);
};
return createOutputMethods(method, createShakeOutputMethod, bits, padding);
};
var createCshakeMethod = function (bits, padding) {
var w = CSHAKE_BYTEPAD[bits];
var method = createCshakeOutputMethod(bits, padding, 'hex');
method.create = function (outputBits, n, s) {
if (empty(n) && empty(s)) {
return methods['shake' + bits].create(outputBits);
} else {
return new Keccak(bits, padding, outputBits).bytepad([n, s], w);
}
};
method.update = function (message, outputBits, n, s) {
return method.create(outputBits, n, s).update(message);
};
return createOutputMethods(method, createCshakeOutputMethod, bits, padding);
};
var createKmacMethod = function (bits, padding) {
var w = CSHAKE_BYTEPAD[bits];
var method = createKmacOutputMethod(bits, padding, 'hex');
method.create = function (key, outputBits, s) {
return new Kmac(bits, padding, outputBits).bytepad(['KMAC', s], w).bytepad([key], w);
};
method.update = function (key, message, outputBits, s) {
return method.create(key, outputBits, s).update(message);
};
return createOutputMethods(method, createKmacOutputMethod, bits, padding);
};
var algorithms = [
{ name: 'keccak', padding: KECCAK_PADDING, bits: BITS, createMethod: createMethod },
{ name: 'sha3', padding: PADDING, bits: BITS, createMethod: createMethod },
{ name: 'shake', padding: SHAKE_PADDING, bits: SHAKE_BITS, createMethod: createShakeMethod },
{ name: 'cshake', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createCshakeMethod },
{ name: 'kmac', padding: CSHAKE_PADDING, bits: SHAKE_BITS, createMethod: createKmacMethod }
];
var methods = {}, methodNames = [];
for (var i = 0; i < algorithms.length; ++i) {
var algorithm = algorithms[i];
var bits = algorithm.bits;
for (var j = 0; j < bits.length; ++j) {
var methodName = algorithm.name + '_' + bits[j];
methodNames.push(methodName);
methods[methodName] = algorithm.createMethod(bits[j], algorithm.padding);
if (algorithm.name !== 'sha3') {
var newMethodName = algorithm.name + bits[j];
methodNames.push(newMethodName);
methods[newMethodName] = methods[methodName];
}
}
}
methodNames.push("extractLast20Bytes");
methods["extractLast20Bytes"] = extractLast20Bytes;
function Keccak(bits, padding, outputBits) {
this.blocks = [];
this.s = [];
this.padding = padding;
this.outputBits = outputBits;
this.reset = true;
this.finalized = false;
this.block = 0;
this.start = 0;
this.blockCount = (1600 - (bits << 1)) >> 5;
this.byteCount = this.blockCount << 2;
this.outputBlocks = outputBits >> 5;
this.extraBytes = (outputBits & 31) >> 3;
for (var i = 0; i < 50; ++i) {
this.s[i] = 0;
}
}
Keccak.prototype.update = function (message) {
if (this.finalized) {
throw new Error(FINALIZE_ERROR);
}
var result = formatMessage(message);
message = result[0];
var isString = result[1];
var blocks = this.blocks, byteCount = this.byteCount, length = message.length,
blockCount = this.blockCount, index = 0, s = this.s, i, code;
while (index < length) {
if (this.reset) {
this.reset = false;
blocks[0] = this.block;
for (i = 1; i < blockCount + 1; ++i) {
blocks[i] = 0;
}
}
if (isString) {
for (i = this.start; index < length && i < byteCount; ++index) {
code = message.charCodeAt(index);
if (code < 0x80) {
blocks[i >> 2] |= code << SHIFT[i++ & 3];
} else if (code < 0x800) {
blocks[i >> 2] |= (0xc0 | (code >> 6)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else if (code < 0xd800 || code >= 0xe000) {
blocks[i >> 2] |= (0xe0 | (code >> 12)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (message.charCodeAt(++index) & 0x3ff));
blocks[i >> 2] |= (0xf0 | (code >> 18)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 12) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | ((code >> 6) & 0x3f)) << SHIFT[i++ & 3];
blocks[i >> 2] |= (0x80 | (code & 0x3f)) << SHIFT[i++ & 3];
}
}
} else {
for (i = this.start; index < length && i < byteCount; ++index) {
blocks[i >> 2] |= message[index] << SHIFT[i++ & 3];
}
}
this.lastByteIndex = i;
if (i >= byteCount) {
this.start = i - byteCount;
this.block = blocks[blockCount];
for (i = 0; i < blockCount; ++i) {
s[i] ^= blocks[i];
}
f(s);
this.reset = true;
} else {
this.start = i;
}
}
return this;
};
Keccak.prototype.encode = function (x, right) {
var o = x & 255, n = 1;
var bytes = [o];
x = x >> 8;
o = x & 255;
while (o > 0) {
bytes.unshift(o);
x = x >> 8;
o = x & 255;
++n;
}
if (right) {
bytes.push(n);
} else {
bytes.unshift(n);
}
this.update(bytes);
return bytes.length;
};
Keccak.prototype.encodeString = function (str) {
var result = formatMessage(str);
str = result[0];
var isString = result[1];
var bytes = 0, length = str.length;
if (isString) {
for (var i = 0; i < str.length; ++i) {
var code = str.charCodeAt(i);
if (code < 0x80) {
bytes += 1;
} else if (code < 0x800) {
bytes += 2;
} else if (code < 0xd800 || code >= 0xe000) {
bytes += 3;
} else {
code = 0x10000 + (((code & 0x3ff) << 10) | (str.charCodeAt(++i) & 0x3ff));
bytes += 4;
}
}
} else {
bytes = length;
}
bytes += this.encode(bytes * 8);
this.update(str);
return bytes;
};
Keccak.prototype.bytepad = function (strs, w) {
var bytes = this.encode(w);
for (var i = 0; i < strs.length; ++i) {
bytes += this.encodeString(strs[i]);
}
var paddingBytes = (w - bytes % w) % w;
var zeros = [];
zeros.length = paddingBytes;
this.update(zeros);
return this;
};
Keccak.prototype.finalize = function () {
if (this.finalized) {
return;
}
this.finalized = true;
var blocks = this.blocks, i = this.lastByteIndex, blockCount = this.blockCount, s = this.s;
blocks[i >> 2] |= this.padding[i & 3];
if (this.lastByteIndex === this.byteCount) {
blocks[0] = blocks[blockCount];
for (i = 1; i < blockCount + 1; ++i) {
blocks[i] = 0;
}
}
blocks[blockCount - 1] |= 0x80000000;
for (i = 0; i < blockCount; ++i) {
s[i] ^= blocks[i];
}
f(s);
};
Keccak.prototype.toString = Keccak.prototype.hex = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var hex = '', block;
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F] +
HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F] +
HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F] +
HEX_CHARS[(block >> 28) & 0x0F] + HEX_CHARS[(block >> 24) & 0x0F];
}
if (j % blockCount === 0) {
f(s);
i = 0;
}
}
if (extraBytes) {
block = s[i];
hex += HEX_CHARS[(block >> 4) & 0x0F] + HEX_CHARS[block & 0x0F];
if (extraBytes > 1) {
hex += HEX_CHARS[(block >> 12) & 0x0F] + HEX_CHARS[(block >> 8) & 0x0F];
}
if (extraBytes > 2) {
hex += HEX_CHARS[(block >> 20) & 0x0F] + HEX_CHARS[(block >> 16) & 0x0F];
}
}
return hex;
};
Keccak.prototype.arrayBuffer = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var bytes = this.outputBits >> 3;
var buffer;
if (extraBytes) {
buffer = new ArrayBuffer((outputBlocks + 1) << 2);
} else {
buffer = new ArrayBuffer(bytes);
}
var array = new Uint32Array(buffer);
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
array[j] = s[i];
}
if (j % blockCount === 0) {
f(s);
}
}
if (extraBytes) {
array[i] = s[i];
buffer = buffer.slice(0, bytes);
}
return buffer;
};
Keccak.prototype.buffer = Keccak.prototype.arrayBuffer;
Keccak.prototype.digest = Keccak.prototype.array = function () {
this.finalize();
var blockCount = this.blockCount, s = this.s, outputBlocks = this.outputBlocks,
extraBytes = this.extraBytes, i = 0, j = 0;
var array = [], offset, block;
while (j < outputBlocks) {
for (i = 0; i < blockCount && j < outputBlocks; ++i, ++j) {
offset = j << 2;
block = s[i];
array[offset] = block & 0xFF;
array[offset + 1] = (block >> 8) & 0xFF;
array[offset + 2] = (block >> 16) & 0xFF;
array[offset + 3] = (block >> 24) & 0xFF;
}
if (j % blockCount === 0) {
f(s);
}
}
if (extraBytes) {
offset = j << 2;
block = s[i];
array[offset] = block & 0xFF;
if (extraBytes > 1) {
array[offset + 1] = (block >> 8) & 0xFF;
}
if (extraBytes > 2) {
array[offset + 2] = (block >> 16) & 0xFF;
}
}
return array;
};
function Kmac(bits, padding, outputBits) {
Keccak.call(this, bits, padding, outputBits);
}
Kmac.prototype = new Keccak();
Kmac.prototype.finalize = function () {
this.encode(this.outputBits, true);
return Keccak.prototype.finalize.call(this);
};
var f = function (s) {
var h, l, n, c0, c1, c2, c3, c4, c5, c6, c7, c8, c9,
b0, b1, b2, b3, b4, b5, b6, b7, b8, b9, b10, b11, b12, b13, b14, b15, b16, b17,
b18, b19, b20, b21, b22, b23, b24, b25, b26, b27, b28, b29, b30, b31, b32, b33,
b34, b35, b36, b37, b38, b39, b40, b41, b42, b43, b44, b45, b46, b47, b48, b49;
for (n = 0; n < 48; n += 2) {
c0 = s[0] ^ s[10] ^ s[20] ^ s[30] ^ s[40];
c1 = s[1] ^ s[11] ^ s[21] ^ s[31] ^ s[41];
c2 = s[2] ^ s[12] ^ s[22] ^ s[32] ^ s[42];
c3 = s[3] ^ s[13] ^ s[23] ^ s[33] ^ s[43];
c4 = s[4] ^ s[14] ^ s[24] ^ s[34] ^ s[44];
c5 = s[5] ^ s[15] ^ s[25] ^ s[35] ^ s[45];
c6 = s[6] ^ s[16] ^ s[26] ^ s[36] ^ s[46];
c7 = s[7] ^ s[17] ^ s[27] ^ s[37] ^ s[47];
c8 = s[8] ^ s[18] ^ s[28] ^ s[38] ^ s[48];
c9 = s[9] ^ s[19] ^ s[29] ^ s[39] ^ s[49];
h = c8 ^ ((c2 << 1) | (c3 >>> 31));
l = c9 ^ ((c3 << 1) | (c2 >>> 31));
s[0] ^= h;
s[1] ^= l;
s[10] ^= h;
s[11] ^= l;
s[20] ^= h;
s[21] ^= l;
s[30] ^= h;
s[31] ^= l;
s[40] ^= h;
s[41] ^= l;
h = c0 ^ ((c4 << 1) | (c5 >>> 31));
l = c1 ^ ((c5 << 1) | (c4 >>> 31));
s[2] ^= h;
s[3] ^= l;
s[12] ^= h;
s[13] ^= l;
s[22] ^= h;
s[23] ^= l;
s[32] ^= h;
s[33] ^= l;
s[42] ^= h;
s[43] ^= l;
h = c2 ^ ((c6 << 1) | (c7 >>> 31));
l = c3 ^ ((c7 << 1) | (c6 >>> 31));
s[4] ^= h;
s[5] ^= l;
s[14] ^= h;
s[15] ^= l;
s[24] ^= h;
s[25] ^= l;
s[34] ^= h;
s[35] ^= l;
s[44] ^= h;
s[45] ^= l;
h = c4 ^ ((c8 << 1) | (c9 >>> 31));
l = c5 ^ ((c9 << 1) | (c8 >>> 31));
s[6] ^= h;
s[7] ^= l;
s[16] ^= h;
s[17] ^= l;
s[26] ^= h;
s[27] ^= l;
s[36] ^= h;
s[37] ^= l;
s[46] ^= h;
s[47] ^= l;
h = c6 ^ ((c0 << 1) | (c1 >>> 31));
l = c7 ^ ((c1 << 1) | (c0 >>> 31));
s[8] ^= h;
s[9] ^= l;
s[18] ^= h;
s[19] ^= l;
s[28] ^= h;
s[29] ^= l;
s[38] ^= h;
s[39] ^= l;
s[48] ^= h;
s[49] ^= l;
b0 = s[0];
b1 = s[1];
b32 = (s[11] << 4) | (s[10] >>> 28);
b33 = (s[10] << 4) | (s[11] >>> 28);
b14 = (s[20] << 3) | (s[21] >>> 29);
b15 = (s[21] << 3) | (s[20] >>> 29);
b46 = (s[31] << 9) | (s[30] >>> 23);
b47 = (s[30] << 9) | (s[31] >>> 23);
b28 = (s[40] << 18) | (s[41] >>> 14);
b29 = (s[41] << 18) | (s[40] >>> 14);
b20 = (s[2] << 1) | (s[3] >>> 31);
b21 = (s[3] << 1) | (s[2] >>> 31);
b2 = (s[13] << 12) | (s[12] >>> 20);
b3 = (s[12] << 12) | (s[13] >>> 20);
b34 = (s[22] << 10) | (s[23] >>> 22);
b35 = (s[23] << 10) | (s[22] >>> 22);
b16 = (s[33] << 13) | (s[32] >>> 19);
b17 = (s[32] << 13) | (s[33] >>> 19);
b48 = (s[42] << 2) | (s[43] >>> 30);
b49 = (s[43] << 2) | (s[42] >>> 30);
b40 = (s[5] << 30) | (s[4] >>> 2);
b41 = (s[4] << 30) | (s[5] >>> 2);
b22 = (s[14] << 6) | (s[15] >>> 26);
b23 = (s[15] << 6) | (s[14] >>> 26);
b4 = (s[25] << 11) | (s[24] >>> 21);
b5 = (s[24] << 11) | (s[25] >>> 21);
b36 = (s[34] << 15) | (s[35] >>> 17);
b37 = (s[35] << 15) | (s[34] >>> 17);
b18 = (s[45] << 29) | (s[44] >>> 3);
b19 = (s[44] << 29) | (s[45] >>> 3);
b10 = (s[6] << 28) | (s[7] >>> 4);
b11 = (s[7] << 28) | (s[6] >>> 4);
b42 = (s[17] << 23) | (s[16] >>> 9);
b43 = (s[16] << 23) | (s[17] >>> 9);
b24 = (s[26] << 25) | (s[27] >>> 7);
b25 = (s[27] << 25) | (s[26] >>> 7);
b6 = (s[36] << 21) | (s[37] >>> 11);
b7 = (s[37] << 21) | (s[36] >>> 11);
b38 = (s[47] << 24) | (s[46] >>> 8);
b39 = (s[46] << 24) | (s[47] >>> 8);
b30 = (s[8] << 27) | (s[9] >>> 5);
b31 = (s[9] << 27) | (s[8] >>> 5);
b12 = (s[18] << 20) | (s[19] >>> 12);
b13 = (s[19] << 20) | (s[18] >>> 12);
b44 = (s[29] << 7) | (s[28] >>> 25);
b45 = (s[28] << 7) | (s[29] >>> 25);
b26 = (s[38] << 8) | (s[39] >>> 24);
b27 = (s[39] << 8) | (s[38] >>> 24);
b8 = (s[48] << 14) | (s[49] >>> 18);
b9 = (s[49] << 14) | (s[48] >>> 18);
s[0] = b0 ^ (~b2 & b4);
s[1] = b1 ^ (~b3 & b5);
s[10] = b10 ^ (~b12 & b14);
s[11] = b11 ^ (~b13 & b15);
s[20] = b20 ^ (~b22 & b24);
s[21] = b21 ^ (~b23 & b25);
s[30] = b30 ^ (~b32 & b34);
s[31] = b31 ^ (~b33 & b35);
s[40] = b40 ^ (~b42 & b44);
s[41] = b41 ^ (~b43 & b45);
s[2] = b2 ^ (~b4 & b6);
s[3] = b3 ^ (~b5 & b7);
s[12] = b12 ^ (~b14 & b16);
s[13] = b13 ^ (~b15 & b17);
s[22] = b22 ^ (~b24 & b26);
s[23] = b23 ^ (~b25 & b27);
s[32] = b32 ^ (~b34 & b36);
s[33] = b33 ^ (~b35 & b37);
s[42] = b42 ^ (~b44 & b46);
s[43] = b43 ^ (~b45 & b47);
s[4] = b4 ^ (~b6 & b8);
s[5] = b5 ^ (~b7 & b9);
s[14] = b14 ^ (~b16 & b18);
s[15] = b15 ^ (~b17 & b19);
s[24] = b24 ^ (~b26 & b28);
s[25] = b25 ^ (~b27 & b29);
s[34] = b34 ^ (~b36 & b38);
s[35] = b35 ^ (~b37 & b39);
s[44] = b44 ^ (~b46 & b48);
s[45] = b45 ^ (~b47 & b49);
s[6] = b6 ^ (~b8 & b0);
s[7] = b7 ^ (~b9 & b1);
s[16] = b16 ^ (~b18 & b10);
s[17] = b17 ^ (~b19 & b11);
s[26] = b26 ^ (~b28 & b20);
s[27] = b27 ^ (~b29 & b21);
s[36] = b36 ^ (~b38 & b30);
s[37] = b37 ^ (~b39 & b31);
s[46] = b46 ^ (~b48 & b40);
s[47] = b47 ^ (~b49 & b41);
s[8] = b8 ^ (~b0 & b2);
s[9] = b9 ^ (~b1 & b3);
s[18] = b18 ^ (~b10 & b12);
s[19] = b19 ^ (~b11 & b13);
s[28] = b28 ^ (~b20 & b22);
s[29] = b29 ^ (~b21 & b23);
s[38] = b38 ^ (~b30 & b32);
s[39] = b39 ^ (~b31 & b33);
s[48] = b48 ^ (~b40 & b42);
s[49] = b49 ^ (~b41 & b43);
s[0] ^= RC[n];
s[1] ^= RC[n + 1];
}
};
function extractLast20Bytes(hexString, addPrefix) {
// Ensure the input hexString has '0x' prefix
if (!hexString.startsWith('0x')) {
hexString = '0x' + hexString;
}
// Remove '0x' prefix and parse the hex string to a BigInt
var bigIntValue = BigInt(hexString);
// Extract the last 20 bytes (160 bits) from the BigInt
var last20Bytes = bigIntValue & BigInt('0x' + 'f'.repeat(40)); // 0xf is 4 bits in hexadecimal, repeated 40 times for 160 bits
// Convert the result back to a hexadecimal string
var result = last20Bytes.toString(16).padStart(40, '0'); // 40 characters for 160 bits
// Add '0x' prefix if addPrefix is truthy
if (addPrefix) {
result = '0x' + result;
}
return result;
}
if (typeof root.keccak === 'object') {
Object.assign(root.keccak, methods);
}
if (COMMON_JS) {
module.exports = methods;
} else {
for (i = 0; i < methodNames.length; ++i) {
root[methodNames[i]] = methods[methodNames[i]];
}
if (AMD) {
define(function () {
return methods;
});
}
}
})();

File diff suppressed because it is too large Load Diff