Workflow updating files of btcmortgage

This commit is contained in:
RanchiMall Dev 2023-12-18 16:34:54 +00:00
parent 1859fd4783
commit ace27d4e14
19 changed files with 21902 additions and 0 deletions

21
btcmortgage/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.

3
btcmortgage/README.md Normal file
View File

@ -0,0 +1,3 @@
# BTC Mortgage
This is a decentralized mortage that enables users to borrow loan from a lender using BTC as collateral.

View File

@ -0,0 +1,63 @@
<svg xmlns="http://www.w3.org/2000/svg" width="413" height="469" viewBox="0 0 413 469" fill="none">
<path d="M217.888 248.144C222.564 243.102 230.133 245.274 232.025 247.333L234.788 250.296C227.542 255.127 232.621 254.09 227.622 260.797C223.623 266.162 216.266 267.388 213.088 267.331C213.688 266.213 214.917 263.669 215.033 262.432C215.179 260.885 212.042 254.447 217.888 248.144Z" fill="#34C186"/>
<path d="M294.157 255.265C294.157 255.265 294.157 255.265 294.157 255.264L293.525 255.46C286.401 249.184 288.919 254.243 280.451 250.861C273.677 248.156 267.266 240.395 266.434 237.031C266.434 237.031 279.509 231.318 287.79 235.706C294.414 239.215 295.426 242.013 294.157 255.264L294.158 255.264L294.157 255.265Z" fill="#34C186"/>
<path d="M336.154 254.664C336.155 254.664 336.155 254.664 336.155 254.663L335.711 254.609C333.055 248.767 333.208 252.584 328.923 248.155C325.495 244.611 323.69 238.052 324.108 235.748C324.108 235.748 333.752 235.844 337.643 240.842C340.756 244.839 340.605 246.844 336.155 254.663L336.155 254.663L336.154 254.664Z" fill="#34C186"/>
<path d="M296.846 209C301.105 210.311 302.212 214.187 302.212 216.115L302.745 219.71L302.397 219.895C297.538 217.025 299.572 219.698 294.251 218.667C289.994 217.843 285.386 214.027 284.525 212.156C284.525 212.156 291.522 207.362 296.846 209Z" fill="#34C186"/>
<path d="M241.035 303.575C254.386 300.174 263.427 308.26 264.373 313.782L267.205 323.34L269.387 325.853C251.94 326.106 259.365 329.596 243.664 335.448C231.102 340.13 217.389 334.197 212.103 330.645C214.327 329.417 219.161 326.471 220.702 324.516C222.627 322.072 224.347 307.826 241.035 303.575Z" fill="#34C186"/>
<path d="M275.503 361.916C273.946 346.205 271.211 315.431 281.16 289.386C292.191 260.512 310.233 210.63 298.951 186.33M271.256 359.369C271.256 357.107 271.61 316.457 257.598 284.186C246.388 258.369 232.704 249.134 229.096 241.142" stroke="#604941" stroke-width="4" stroke-linecap="round"/>
<path d="M314.505 292.355C300.682 290.579 292.622 300.507 290.023 305.675L284.609 316.197C302.158 314.31 292.908 319.289 309.392 323.237C322.58 326.396 340.638 321.489 345.509 317.274C345.509 317.274 331.784 294.575 314.505 292.355Z" fill="#34C186"/>
<g style="mix-blend-mode:multiply">
<rect x="151.556" y="445.993" width="261.149" height="22.8177" rx="11.4089" fill="#8F7A6E"/>
</g>
<g style="mix-blend-mode:multiply">
<rect x="42.3583" y="445.993" width="100.577" height="22.8177" rx="11.4089" fill="#8F7A6E"/>
</g>
<path d="M278.647 359.879C276.114 353.161 274.725 339.273 278.647 328.202C291.198 292.78 301.462 275.22 346.653 246.815M271.748 360.951C271.481 359.957 266.852 342.06 256.899 329.533C248.936 319.512 241.838 317.066 239.313 313.98" stroke="#604941" stroke-width="4" stroke-linecap="round"/>
<mask id="mask0_1_131" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="227" y="355" width="95" height="102">
<path d="M227.655 369.268V361.789C227.655 358.474 230.343 355.787 233.657 355.789L315.811 355.818C319.124 355.819 321.809 358.505 321.809 361.818V369.307C321.809 370.149 321.126 370.832 320.284 370.832C319.507 370.832 318.854 371.416 318.768 372.188L309.885 451.898C309.814 452.528 309.281 453.005 308.647 453.005C307.96 453.005 307.402 453.562 307.402 454.25V454.572C307.402 455.437 306.701 456.139 305.835 456.139H243.258C242.393 456.139 241.691 455.437 241.691 454.572V454.092C241.691 453.491 241.205 453.005 240.604 453.005C240.051 453.005 239.585 452.588 239.524 452.038L230.661 372.116C230.576 371.352 229.931 370.775 229.163 370.775C228.33 370.775 227.655 370.1 227.655 369.268Z" fill="#FBAE96"/>
</mask>
<g mask="url(#mask0_1_131)">
<path d="M227.655 369.268V361.789C227.655 358.474 230.343 355.787 233.657 355.789L315.811 355.818C319.124 355.819 321.809 358.505 321.809 361.818V369.307C321.809 370.149 321.126 370.832 320.284 370.832C319.507 370.832 318.854 371.416 318.768 372.188L309.885 451.898C309.814 452.528 309.281 453.005 308.647 453.005C307.96 453.005 307.402 453.562 307.402 454.25V454.572C307.402 455.437 306.701 456.139 305.835 456.139H243.258C242.393 456.139 241.691 455.437 241.691 454.572V454.092C241.691 453.491 241.205 453.005 240.604 453.005C240.051 453.005 239.585 452.588 239.524 452.038L230.661 372.116C230.576 371.352 229.931 370.775 229.163 370.775C228.33 370.775 227.655 370.1 227.655 369.268Z" fill="#F79678"/>
<g style="mix-blend-mode:multiply" opacity="0.4">
<path fill-rule="evenodd" clip-rule="evenodd" d="M226.332 373.11C226.332 371.823 227.375 370.779 228.662 370.779H320.546C320.625 370.779 320.688 370.843 320.688 370.921V370.921C320.688 370.999 320.751 371.063 320.83 371.063L320.873 371.063C320.975 371.063 321.057 371.145 321.057 371.247L321.057 447.083C321.057 452.882 316.356 457.583 310.557 457.583H301.034C299.506 457.583 298.267 458.821 298.267 460.35V460.35C298.267 461.878 297.029 463.116 295.501 463.116H235.969C233.167 463.116 230.896 460.845 230.896 458.044V458.044C230.896 455.242 233.167 452.971 235.969 452.971H284.725C290.524 452.971 295.225 448.27 295.225 442.471L295.225 385.94C295.225 380.141 290.524 375.44 284.725 375.44H228.662C227.375 375.44 226.332 374.397 226.332 373.11V373.11Z" fill="#EB4073"/>
</g>
</g>
<path d="M259.225 267.746C252.191 273.594 254.53 283.802 257.128 286.464L260.863 290.348C267.803 281.072 266.059 287.743 275.327 281.588C282.741 276.664 284.901 266.982 285.054 262.756C283.526 263.472 280.059 264.921 278.407 264.986C276.343 265.068 268.018 260.437 259.225 267.746Z" fill="#34C186"/>
<path d="M241.822 328.16C249.572 323.301 258.541 328.708 260.259 332.007L262.784 336.768C251.806 340.467 258.688 340.892 249.949 347.776C242.957 353.284 233.085 352.315 229.022 351.142C230.179 349.914 232.638 347.072 233.215 345.523C233.936 343.587 232.134 334.233 241.822 328.16Z" fill="#56DD84"/>
<path d="M287.09 273.67C295.642 276.916 296.747 287.33 295.154 290.692L292.883 295.578C283.306 289.059 287.122 294.802 276.358 291.992C267.746 289.743 262.559 281.287 261.042 277.341C262.719 277.522 266.469 277.766 268.052 277.291C270.031 276.697 276.4 269.613 287.09 273.67Z" fill="#56DD84"/>
<path d="M249.548 242.351C242.684 242.783 239.578 250.018 239.976 252.786L240.522 256.8C248.848 254.245 244.832 257.522 253.188 257.894C259.873 258.191 265.477 253.27 267.443 250.772C266.198 250.529 263.45 249.872 262.418 249.179C261.129 248.313 258.127 241.81 249.548 242.351Z" fill="#56DD84"/>
<path d="M303.997 242.629C293.467 245.87 290.729 255.453 290.729 260.221L289.413 269.108L290.272 269.565C302.287 262.469 297.256 269.077 310.412 266.53C320.938 264.493 332.332 255.058 334.46 250.431C334.46 250.431 317.16 238.579 303.997 242.629Z" fill="#56DD84"/>
<path d="M308.793 202.529C304.534 203.839 303.427 207.715 303.427 209.644L302.894 213.238L303.242 213.423C308.101 210.553 306.067 213.226 311.388 212.196C315.645 211.371 320.253 207.555 321.114 205.684C321.114 205.684 314.117 200.89 308.793 202.529Z" fill="#56DD84"/>
<path d="M333.469 258.517C323.282 256.942 317.063 263.889 315.115 267.902L310.376 274.844L310.913 275.579C323.924 274.516 316.99 278.023 329.104 281.254C338.795 283.839 352.24 280.553 355.922 277.529C355.922 277.529 346.203 260.485 333.469 258.517Z" fill="#56DD84"/>
<path d="M217.618 199.202C220.071 196.509 224.308 196.509 226.761 199.202V199.202C228.388 200.988 230.907 201.663 233.209 200.93V200.93C236.68 199.824 240.349 201.943 241.127 205.501V205.501C241.644 207.862 243.487 209.705 245.848 210.222V210.222C249.406 211 251.525 214.669 250.419 218.14V218.14C249.686 220.442 250.361 222.961 252.147 224.588V224.588C254.84 227.041 254.84 231.278 252.147 233.731V233.731C250.361 235.358 249.686 237.877 250.419 240.179V240.179C251.525 243.65 249.406 247.319 245.848 248.098V248.098C243.487 248.614 241.644 250.457 241.127 252.818V252.818C240.349 256.376 236.68 258.495 233.209 257.39V257.39C230.907 256.656 228.388 257.331 226.761 259.117V259.117C224.308 261.81 220.071 261.81 217.618 259.117V259.117C215.991 257.331 213.472 256.656 211.17 257.39V257.39C207.699 258.495 204.03 256.376 203.251 252.818V252.818C202.735 250.457 200.892 248.614 198.531 248.098V248.098C194.973 247.319 192.854 243.65 193.96 240.179V240.179C194.693 237.877 194.018 235.358 192.232 233.731V233.731C189.539 231.278 189.539 227.041 192.232 224.588V224.588C194.018 222.961 194.693 220.442 193.96 218.14V218.14C192.854 214.669 194.973 211 198.531 210.222V210.222C200.892 209.705 202.735 207.862 203.251 205.501V205.501C204.03 201.943 207.699 199.824 211.17 200.93V200.93C213.472 201.663 215.991 200.988 217.618 199.202V199.202Z" fill="#FFF1A6"/>
<circle cx="222.189" cy="229.16" r="19.8559" fill="#FFD260"/>
<path d="M217.864 233.633L219.926 233.08C220.224 234.194 221.89 234.763 223.57 234.313C225.25 233.863 226.408 232.536 226.11 231.423C225.806 230.289 224.624 230.164 222.21 230.226C219.878 230.265 216.975 230.314 216.207 227.448C215.713 225.603 216.808 223.631 218.76 222.544L218.158 220.297L221.25 219.469L221.852 221.716C224.085 221.681 226.02 222.841 226.515 224.686L224.453 225.239C224.155 224.126 222.489 223.556 220.809 224.006C219.128 224.456 217.97 225.783 218.269 226.896C218.573 228.03 219.755 228.155 222.169 228.094C224.5 228.054 227.404 228.005 228.172 230.871C228.666 232.716 227.571 234.689 225.619 235.775L226.221 238.022L223.129 238.85L222.527 236.603C220.294 236.638 218.359 235.478 217.864 233.633Z" fill="#CA7E46"/>
<path d="M217.021 299.598C216.824 297.28 218.663 295.295 220.989 295.315V295.315C222.532 295.327 223.941 294.44 224.597 293.044V293.044C225.586 290.938 228.171 290.139 230.175 291.318V291.318C231.505 292.101 233.169 292.038 234.435 291.156V291.156C236.344 289.827 238.983 290.427 240.129 292.451V292.451C240.889 293.794 242.362 294.571 243.899 294.44V294.44C246.217 294.243 248.202 296.082 248.183 298.408V298.408C248.17 299.951 249.057 301.361 250.454 302.016V302.016C252.559 303.005 253.359 305.59 252.179 307.595V307.595C251.396 308.925 251.46 310.588 252.341 311.855V311.855C253.671 313.764 253.07 316.402 251.046 317.548V317.548C249.704 318.309 248.927 319.781 249.057 321.319V321.319C249.254 323.637 247.415 325.622 245.089 325.602V325.602C243.546 325.589 242.137 326.476 241.481 327.873V327.873C240.492 329.979 237.907 330.778 235.903 329.598V329.598C234.573 328.816 232.909 328.879 231.643 329.761V329.761C229.734 331.09 227.095 330.49 225.949 328.466V328.466C225.189 327.123 223.716 326.346 222.178 326.477V326.477C219.861 326.673 217.876 324.834 217.895 322.508V322.508C217.908 320.965 217.021 319.556 215.624 318.9V318.9C213.519 317.912 212.719 315.327 213.899 313.322V313.322C214.682 311.992 214.618 310.328 213.736 309.062V309.062C212.407 307.153 213.007 304.515 215.031 303.368V303.368C216.374 302.608 217.151 301.135 217.021 299.598V299.598Z" fill="#FFF1A6"/>
<circle cx="233.039" cy="310.458" r="12.6803" transform="rotate(-47.1858 233.039 310.458)" fill="#FFD260"/>
<path d="M233.257 314.426L233.893 313.221C234.544 313.564 235.534 313.031 236.053 312.048C236.571 311.066 236.452 309.948 235.801 309.604C235.138 309.254 234.566 309.754 233.547 310.911C232.554 312.021 231.316 313.402 229.641 312.518C228.562 311.949 228.113 310.58 228.451 309.194L227.137 308.501L228.091 306.693L229.405 307.386C230.358 306.324 231.742 305.922 232.821 306.491L232.185 307.696C231.534 307.353 230.544 307.886 230.025 308.869C229.507 309.851 229.626 310.969 230.277 311.313C230.94 311.662 231.512 311.163 232.531 310.005C233.524 308.896 234.761 307.515 236.437 308.399C237.516 308.968 237.965 310.337 237.626 311.723L238.94 312.416L237.986 314.224L236.673 313.531C235.72 314.592 234.336 314.995 233.257 314.426Z" fill="#CA7E46"/>
<path d="M373.126 235.514C375.231 236.505 376.027 239.091 374.845 241.094V241.094C374.06 242.423 374.122 244.087 375.002 245.354V245.354C376.329 247.265 375.725 249.903 373.7 251.046V251.046C372.356 251.805 371.577 253.277 371.706 254.814V254.814C371.899 257.132 370.058 259.115 367.732 259.093V259.093C366.189 259.078 364.779 259.963 364.121 261.359V261.359C363.13 263.463 360.544 264.26 358.541 263.077V263.077C357.212 262.293 355.548 262.354 354.28 263.234V263.234C352.37 264.561 349.732 263.958 348.588 261.932V261.932C347.83 260.589 346.358 259.81 344.82 259.938V259.938C342.502 260.132 340.52 258.291 340.542 255.965V255.965C340.557 254.422 339.672 253.011 338.276 252.354V252.354C336.171 251.363 335.375 248.777 336.557 246.773V246.773C337.342 245.444 337.28 243.78 336.4 242.513V242.513C335.073 240.602 335.677 237.965 337.702 236.821V236.821C339.046 236.062 339.825 234.591 339.696 233.053V233.053C339.503 230.735 341.344 228.752 343.67 228.775V228.775C345.213 228.79 346.623 227.904 347.281 226.508V226.508C348.272 224.404 350.858 223.608 352.861 224.79V224.79C354.19 225.575 355.854 225.513 357.122 224.633V224.633C359.032 223.306 361.67 223.91 362.814 225.935V225.935C363.572 227.279 365.044 228.058 366.582 227.929V227.929C368.9 227.735 370.882 229.577 370.86 231.903V231.903C370.845 233.446 371.73 234.856 373.126 235.514V235.514Z" fill="#FFF1A6"/>
<circle cx="355.701" cy="243.934" r="12.6803" transform="rotate(72.8863 355.701 243.934)" fill="#FFD260"/>
<path d="M352.158 242.135L352.883 243.289C352.259 243.68 352.224 244.804 352.815 245.745C353.405 246.686 354.433 247.143 355.056 246.752C355.691 246.354 355.545 245.608 355.054 244.147C354.592 242.731 354.017 240.968 355.621 239.961C356.654 239.312 358.064 239.61 359.094 240.597L360.352 239.808L361.439 241.539L360.181 242.329C360.622 243.685 360.277 245.084 359.244 245.733L358.519 244.578C359.143 244.187 359.177 243.063 358.587 242.122C357.996 241.182 356.969 240.724 356.346 241.115C355.711 241.514 355.857 242.259 356.348 243.721C356.81 245.136 357.385 246.899 355.781 247.906C354.747 248.555 353.338 248.257 352.308 247.27L351.05 248.06L349.963 246.328L351.221 245.539C350.78 244.182 351.125 242.783 352.158 242.135Z" fill="#CA7E46"/>
<path d="M308.404 136.151C311.219 133.061 316.082 133.061 318.898 136.151V136.151C320.766 138.201 323.656 138.976 326.299 138.135V138.135C330.282 136.866 334.494 139.298 335.387 143.382V143.382C335.98 146.091 338.096 148.207 340.805 148.8V148.8C344.889 149.693 347.321 153.904 346.052 157.888V157.888C345.211 160.53 345.985 163.421 348.035 165.289V165.289C351.125 168.104 351.125 172.967 348.035 175.783V175.783C345.985 177.651 345.211 180.541 346.052 183.184V183.184C347.321 187.168 344.889 191.379 340.805 192.272V192.272C338.096 192.865 335.98 194.981 335.387 197.69V197.69C334.494 201.774 330.282 204.206 326.299 202.937V202.937C323.656 202.096 320.766 202.87 318.898 204.92V204.92C316.082 208.011 311.219 208.011 308.404 204.92V204.92C306.536 202.87 303.645 202.096 301.003 202.937V202.937C297.019 204.206 292.808 201.774 291.914 197.69V197.69C291.322 194.981 289.206 192.865 286.496 192.272V192.272C282.412 191.379 279.981 187.168 281.249 183.184V183.184C282.091 180.541 281.316 177.651 279.266 175.783V175.783C276.176 172.967 276.176 168.104 279.266 165.289V165.289C281.316 163.421 282.091 160.53 281.249 157.888V157.888C279.981 153.904 282.412 149.693 286.496 148.8V148.8C289.206 148.207 291.322 146.091 291.914 143.382V143.382C292.808 139.298 297.019 136.866 301.003 138.135V138.135C303.645 138.976 306.536 138.202 308.404 136.151V136.151Z" fill="#FFF1A6"/>
<circle cx="313.651" cy="171.797" r="25.1238" fill="#FFD260"/>
<path d="M307.574 175.77H310.223C310.223 177.2 312.037 178.419 314.196 178.419C316.355 178.419 318.169 177.2 318.169 175.77C318.169 174.313 316.792 173.784 313.878 173.082C311.07 172.38 307.574 171.506 307.574 167.824C307.574 165.453 309.521 163.44 312.209 162.765V159.878H316.182V162.765C318.871 163.44 320.818 165.453 320.818 167.824H318.169C318.169 166.394 316.355 165.175 314.196 165.175C312.037 165.175 310.223 166.394 310.223 167.824C310.223 169.281 311.6 169.811 314.514 170.512C317.321 171.214 320.818 172.088 320.818 175.77C320.818 178.141 318.871 180.154 316.182 180.829V183.716H312.209V180.829C309.521 180.154 307.574 178.141 307.574 175.77Z" fill="#CA7E46"/>
<path d="M184.826 136.661C211.059 137.492 252.108 151.871 267.918 209.986M183.635 124.926C204.942 117.091 240.285 114.481 267.918 139.835M180.082 141.405C201.448 149.477 211.074 165.619 215.917 186.985M185.556 130.578C206.134 126.322 220.341 133.018 235.954 139.119M246.529 144.128C258.902 150.063 266.364 159.597 268.452 166.474" stroke="#3FAEFF" stroke-width="3" stroke-linecap="round" stroke-dasharray="8 8"/>
<mask id="mask1_1_131" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="8" y="58" width="171" height="98">
<path fill-rule="evenodd" clip-rule="evenodd" d="M161.635 127.207C165.013 128.072 168.601 127.385 171.42 125.332L174.31 123.226C174.852 122.832 175.523 122.659 176.187 122.741V122.741C177.729 122.931 178.773 124.405 178.441 125.922L175.256 140.501C175.009 141.634 173.989 142.431 172.829 142.396V142.396C172.211 142.378 171.624 142.123 171.189 141.684L169.291 139.77C167.37 137.832 164.685 136.852 161.967 137.097L130.497 139.933C117.553 141.1 104.991 144.886 93.5721 151.049C92.6726 151.535 91.9342 152.269 91.4232 153.154V153.154C89.8528 155.874 86.3748 156.806 83.6548 155.236L14.9741 115.583C12.9411 114.409 12.2445 111.81 13.4183 109.777V109.777C14.3717 108.125 14.1087 106.041 12.775 104.678L10.4627 102.315C7.76195 99.5559 7.22943 95.3354 9.16006 91.9915L23.0394 67.9517C24.9566 64.631 28.8701 63.0184 32.5701 64.0243L35.7091 64.8776C37.5591 65.3806 39.5158 64.5743 40.4744 62.9139V62.9139C41.6406 60.894 44.2235 60.2019 46.2435 61.3681L49.213 63.0826C52.1859 64.799 55.9381 64.3255 58.3915 61.9245L58.9094 61.4176C61.669 58.7168 65.8894 58.1843 69.2334 60.1149L105.997 81.3401C109.317 83.2573 110.93 87.1707 109.924 90.8708L109.753 91.4979C108.848 94.8284 110.3 98.3509 113.289 100.077L114.859 100.983C117.628 102.582 118.577 106.123 116.978 108.892L116.562 109.612C115.585 111.304 115.78 113.429 117.049 114.914V114.914C117.666 115.637 118.492 116.151 119.412 116.387L161.635 127.207ZM17.0949 96.0127C18.4624 97.3772 20.7518 97.0745 21.7177 95.4015L32.1994 77.2467C33.1742 75.5583 32.2656 73.406 30.3758 72.9268V72.9268C29.1002 72.6034 27.765 73.167 27.107 74.3067L16.6254 92.4614C15.9594 93.6149 16.1521 95.0719 17.0949 96.0127V96.0127ZM99.6416 85.4077C100.781 86.0657 101.345 87.4008 101.021 88.6764V88.6764C100.542 90.5663 98.3899 91.4749 96.7015 90.5L65.8234 72.6726C64.1504 71.7066 63.8477 69.4173 65.2122 68.0497V68.0497C66.1529 67.1069 67.61 66.9143 68.7635 67.5802L99.6416 85.4077Z" fill="#55D77A"/>
</mask>
<g mask="url(#mask1_1_131)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M161.635 127.207C165.013 128.072 168.601 127.385 171.42 125.332L174.31 123.226C174.852 122.832 175.523 122.659 176.187 122.741V122.741C177.729 122.931 178.773 124.405 178.441 125.922L175.256 140.501C175.009 141.634 173.989 142.431 172.829 142.396V142.396C172.211 142.378 171.624 142.123 171.189 141.684L169.291 139.77C167.37 137.832 164.685 136.852 161.967 137.097L130.497 139.933C117.553 141.1 104.991 144.886 93.5721 151.049C92.6726 151.535 91.9342 152.269 91.4232 153.154V153.154C89.8528 155.874 86.3748 156.806 83.6548 155.236L14.9741 115.583C12.9411 114.409 12.2445 111.81 13.4183 109.777V109.777C14.3717 108.125 14.1087 106.041 12.775 104.678L10.4627 102.315C7.76195 99.5559 7.22943 95.3354 9.16006 91.9915L23.0394 67.9517C24.9566 64.631 28.8701 63.0184 32.5701 64.0243L35.7091 64.8776C37.5591 65.3806 39.5158 64.5743 40.4744 62.9139V62.9139C41.6406 60.894 44.2235 60.2019 46.2435 61.3681L49.213 63.0826C52.1859 64.799 55.9381 64.3255 58.3915 61.9245L58.9094 61.4176C61.669 58.7168 65.8894 58.1843 69.2334 60.1149L105.997 81.3401C109.317 83.2573 110.93 87.1707 109.924 90.8708L109.753 91.4979C108.848 94.8284 110.3 98.3509 113.289 100.077L114.859 100.983C117.628 102.582 118.577 106.123 116.978 108.892L116.562 109.612C115.585 111.304 115.78 113.429 117.049 114.914V114.914C117.666 115.637 118.492 116.151 119.412 116.387L161.635 127.207ZM17.0949 96.0127C18.4624 97.3772 20.7518 97.0745 21.7177 95.4015L32.1994 77.2467C33.1742 75.5583 32.2656 73.406 30.3758 72.9268V72.9268C29.1002 72.6034 27.765 73.167 27.107 74.3067L16.6254 92.4614C15.9594 93.6149 16.1521 95.0719 17.0949 96.0127V96.0127ZM99.6416 85.4077C100.781 86.0657 101.345 87.4008 101.021 88.6764V88.6764C100.542 90.5663 98.3899 91.4749 96.7015 90.5L65.8234 72.6726C64.1504 71.7066 63.8477 69.4173 65.2122 68.0497V68.0497C66.1529 67.1069 67.61 66.9143 68.7635 67.5802L99.6416 85.4077Z" fill="#55D77A"/>
<g style="mix-blend-mode:multiply" opacity="0.5">
<path d="M70.4809 108.434C68.8458 110.125 66.3495 107.345 65.5497 106.522L68.4322 103.554C69.2547 104.411 72.1871 106.657 70.4809 108.434ZM64.0888 108.059L60.9149 111.348C61.9195 112.332 64.8975 115.602 66.6908 113.747C68.5712 111.816 65.1025 109.027 64.0888 108.059ZM78.8186 121.451C71.7508 128.76 60.1128 128.969 52.8032 121.901C45.4936 114.833 45.29 103.198 52.353 95.8856C59.4207 88.576 71.055 88.374 78.3683 95.4353C85.662 102.494 85.8704 114.132 78.8186 121.451ZM72.7427 104.406L75.1162 101.952L73.5931 100.541L71.2999 102.893C70.9021 102.515 70.5043 102.136 70.0814 101.765L72.4114 99.3487L70.9134 97.9313L68.5491 100.37C68.2218 100.054 67.8853 99.7531 67.5899 99.4551L65.533 97.46L63.9782 99.0487C63.9782 99.0487 65.1103 100.106 65.0692 100.104C65.6852 100.693 65.5551 101.213 65.2931 101.593L58.7964 108.318C58.5879 108.495 58.1672 108.635 57.751 108.289C57.7578 108.314 56.66 107.234 56.66 107.234L54.6492 108.729L56.5811 110.609C56.947 110.969 57.297 111.32 57.6562 111.655L55.2483 114.133L56.7438 115.591L59.1265 113.12C59.531 113.524 59.9288 113.902 60.3015 114.287L57.9372 116.726L59.4327 118.185L61.8405 115.707C64.4669 117.967 66.8589 119.051 69.3384 116.891C71.3775 115.2 71.3168 113.464 70.1923 111.731C71.5146 112.091 72.7893 111.871 73.9302 110.447C75.4727 108.511 74.5004 106.441 72.7427 104.406Z" fill="black"/>
</g>
<g style="mix-blend-mode:multiply">
<path d="M40.8847 62.1758L12.2322 111.803L5.83085 106.059L40.8847 62.1758Z" fill="#58BAA8"/>
</g>
<g style="mix-blend-mode:multiply">
<path d="M115.221 101.171L49.1008 62.997L54.9359 57.6165L112.444 99.1652L115.221 101.171Z" fill="#58BAA8"/>
</g>
<g style="mix-blend-mode:multiply">
<path d="M106.767 169.005C96.2325 172.889 86.6104 161.47 92.2243 151.746L98.0996 141.57C100.149 138.02 103.869 135.762 107.964 135.581L164.655 133.084C167.26 132.969 169.714 134.311 171.023 136.566V136.566C173.207 140.329 171.469 145.153 167.387 146.658L106.767 169.005Z" fill="#58BAA8"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 22 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 17 KiB

1197
btcmortgage/css/main.css Normal file

File diff suppressed because it is too large Load Diff

1
btcmortgage/css/main.min.css vendored Normal file

File diff suppressed because one or more lines are too long

1135
btcmortgage/css/main.scss Normal file

File diff suppressed because it is too large Load Diff

2512
btcmortgage/index.html Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,257 @@
(function (EXPORTS) { //compactIDB v2.1.2
/* Compact IndexedDB operations */
'use strict';
const compactIDB = EXPORTS;
var defaultDB;
const indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB;
const IDBTransaction = window.IDBTransaction || window.webkitIDBTransaction || window.msIDBTransaction;
const IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange || window.msIDBKeyRange;
if (!indexedDB) {
console.error("Your browser doesn't support a stable version of IndexedDB.");
return;
}
compactIDB.setDefaultDB = dbName => defaultDB = dbName;
Object.defineProperty(compactIDB, 'default', {
get: () => defaultDB,
set: dbName => defaultDB = dbName
});
function getDBversion(dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
resolve(db.version)
db.close()
}).catch(error => reject(error))
})
}
function upgradeDB(dbName, createList = null, deleteList = null) {
return new Promise((resolve, reject) => {
getDBversion(dbName).then(version => {
var idb = indexedDB.open(dbName, version + 1);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onupgradeneeded = (event) => {
let db = event.target.result;
if (createList instanceof Object) {
if (Array.isArray(createList)) {
let tmp = {}
createList.forEach(o => tmp[o] = {})
createList = tmp
}
for (let o in createList) {
let obs = db.createObjectStore(o, createList[o].options || {});
if (createList[o].indexes instanceof Object)
for (let i in createList[o].indexes)
obs.createIndex(i, i, createList[o].indexes || {});
}
}
if (Array.isArray(deleteList))
deleteList.forEach(o => db.deleteObjectStore(o));
resolve('Database upgraded')
}
idb.onsuccess = (event) => event.target.result.close();
}).catch(error => reject(error))
})
}
compactIDB.initDB = function (dbName, objectStores = {}) {
return new Promise((resolve, reject) => {
if (!(objectStores instanceof Object))
return reject('ObjectStores must be an object or array')
defaultDB = defaultDB || dbName;
var idb = indexedDB.open(dbName);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onsuccess = (event) => {
var db = event.target.result;
let cList = Object.values(db.objectStoreNames);
var obs = {},
a_obs = {},
d_obs = [];
if (!Array.isArray(objectStores))
var obs = objectStores
else
objectStores.forEach(o => obs[o] = {})
let nList = Object.keys(obs)
for (let o of nList)
if (!cList.includes(o))
a_obs[o] = obs[o]
for (let o of cList)
if (!nList.includes(o))
d_obs.push(o)
if (!Object.keys(a_obs).length && !d_obs.length)
resolve("Initiated IndexedDB");
else
upgradeDB(dbName, a_obs, d_obs)
.then(result => resolve(result))
.catch(error => reject(error))
db.close();
}
});
}
const openDB = compactIDB.openDB = function (dbName = defaultDB) {
return new Promise((resolve, reject) => {
var idb = indexedDB.open(dbName);
idb.onerror = (event) => reject("Error in opening IndexedDB");
idb.onupgradeneeded = (event) => {
event.target.result.close();
deleteDB(dbName).then(_ => null).catch(_ => null).finally(_ => reject("Datebase not found"))
}
idb.onsuccess = (event) => resolve(event.target.result);
});
}
const deleteDB = compactIDB.deleteDB = function (dbName = defaultDB) {
return new Promise((resolve, reject) => {
var deleteReq = indexedDB.deleteDatabase(dbName);;
deleteReq.onerror = (event) => reject("Error deleting database!");
deleteReq.onsuccess = (event) => resolve("Database deleted successfully");
});
}
compactIDB.writeData = function (obsName, data, key = false, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let writeReq = (key ? obs.put(data, key) : obs.put(data));
writeReq.onsuccess = (evt) => resolve(`Write data Successful`);
writeReq.onerror = (evt) => reject(
`Write data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.addData = function (obsName, data, key = false, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let addReq = (key ? obs.add(data, key) : obs.add(data));
addReq.onsuccess = (evt) => resolve(`Add data successful`);
addReq.onerror = (evt) => reject(
`Add data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.removeData = function (obsName, key, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let delReq = obs.delete(key);
delReq.onsuccess = (evt) => resolve(`Removed Data ${key}`);
delReq.onerror = (evt) => reject(
`Remove data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.clearData = function (obsName, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readwrite").objectStore(obsName);
let clearReq = obs.clear();
clearReq.onsuccess = (evt) => resolve(`Clear data Successful`);
clearReq.onerror = (evt) => reject(`Clear data Unsuccessful`);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.readData = function (obsName, key, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
let getReq = obs.get(key);
getReq.onsuccess = (evt) => resolve(evt.target.result);
getReq.onerror = (evt) => reject(
`Read data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
compactIDB.readAllData = function (obsName, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var tmpResult = {}
let curReq = obs.openCursor();
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (cursor) {
tmpResult[cursor.primaryKey] = cursor.value;
cursor.continue();
} else
resolve(tmpResult);
}
curReq.onerror = (evt) => reject(
`Read-All data unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`
);
db.close();
}).catch(error => reject(error));
});
}
/* compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var filteredResult = {}
let keyRange;
if(options.lowerKey!==null && options.upperKey!==null)
keyRange = IDBKeyRange.bound(options.lowerKey, options.upperKey);
else if(options.lowerKey!==null)
keyRange = IDBKeyRange.lowerBound(options.lowerKey);
else if (options.upperKey!==null)
keyRange = IDBKeyRange.upperBound(options.upperBound);
else if (options.atKey)
let curReq = obs.openCursor(keyRange, )
}).catch(error => reject(error))
})
}*/
compactIDB.searchData = function (obsName, options = {}, dbName = defaultDB) {
options.lowerKey = options.atKey || options.lowerKey || 0
options.upperKey = options.atKey || options.upperKey || false
options.patternEval = options.patternEval || ((k, v) => true);
options.limit = options.limit || false;
options.reverse = options.reverse || false;
options.lastOnly = options.lastOnly || false
return new Promise((resolve, reject) => {
openDB(dbName).then(db => {
var obs = db.transaction(obsName, "readonly").objectStore(obsName);
var filteredResult = {}
let curReq = obs.openCursor(
options.upperKey ? IDBKeyRange.bound(options.lowerKey, options.upperKey) : IDBKeyRange.lowerBound(options.lowerKey),
options.lastOnly || options.reverse ? "prev" : "next");
curReq.onsuccess = (evt) => {
var cursor = evt.target.result;
if (!cursor || (options.limit && options.limit <= Object.keys(filteredResult).length))
return resolve(filteredResult); //reached end of key list or limit reached
else if (options.patternEval(cursor.primaryKey, cursor.value)) {
filteredResult[cursor.primaryKey] = cursor.value;
options.lastOnly ? resolve(filteredResult) : cursor.continue();
} else
cursor.continue();
}
curReq.onerror = (evt) => reject(`Search unsuccessful [${evt.target.error.name}] ${evt.target.error.message}`);
db.close();
}).catch(error => reject(error));
});
}
})(window.compactIDB = {});

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,531 @@
(function (EXPORTS) { //floCrypto v2.3.6b
/* 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) {
if (typeof privateKeyHex !== "string") throw new Error("No private key found.");
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 = {});

View File

@ -0,0 +1,843 @@
(function (EXPORTS) { //floDapps v2.4.1
/* General functions for FLO Dapps*/
'use strict';
const floDapps = EXPORTS;
const DEFAULT = {
root: "floDapps",
application: floGlobals.application,
adminID: floGlobals.adminID
};
Object.defineProperties(floDapps, {
application: {
get: () => DEFAULT.application
},
adminID: {
get: () => DEFAULT.adminID
},
root: {
get: () => DEFAULT.root
}
});
var user_priv_raw, aes_key, user_priv_wrap; //private variable inside capsule
const raw_user = {
get private() {
if (!user_priv_raw)
throw "User not logged in";
return Crypto.AES.decrypt(user_priv_raw, aes_key);
}
}
var user_id, user_public, user_private;
const user = floDapps.user = {
get id() {
if (!user_id)
throw "User not logged in";
return user_id;
},
get public() {
if (!user_public)
throw "User not logged in";
return user_public;
},
get private() {
if (!user_private)
throw "User not logged in";
else if (user_private instanceof Function)
return user_private();
else
return Crypto.AES.decrypt(user_private, aes_key);
},
sign(message) {
return floCrypto.signData(message, raw_user.private);
},
decrypt(data) {
return floCrypto.decryptData(data, raw_user.private);
},
encipher(message) {
return Crypto.AES.encrypt(message, raw_user.private);
},
decipher(data) {
return Crypto.AES.decrypt(data, raw_user.private);
},
get db_name() {
return "floDapps#" + floCrypto.toFloID(user.id);
},
lock() {
user_private = user_priv_wrap;
},
async unlock() {
if (await user.private === raw_user.private)
user_private = user_priv_raw;
},
get_contact(id) {
if (!user.contacts)
throw "Contacts not available";
else if (user.contacts[id])
return user.contacts[id];
else {
let id_raw = floCrypto.decodeAddr(id).hex;
for (let i in user.contacts)
if (floCrypto.decodeAddr(i).hex == id_raw)
return user.contacts[i];
}
},
get_pubKey(id) {
if (!user.pubKeys)
throw "Contacts not available";
else if (user.pubKeys[id])
return user.pubKeys[id];
else {
let id_raw = floCrypto.decodeAddr(id).hex;
for (let i in user.pubKeys)
if (floCrypto.decodeAddr(i).hex == id_raw)
return user.pubKeys[i];
}
},
clear() {
user_id = user_public = user_private = undefined;
user_priv_raw = aes_key = undefined;
delete user.contacts;
delete user.pubKeys;
delete user.messages;
}
};
Object.defineProperties(window, {
myFloID: {
get: () => {
try {
return user.id;
} catch {
return;
}
}
},
myUserID: {
get: () => {
try {
return user.id;
} catch {
return;
}
}
},
myPubKey: {
get: () => {
try {
return user.public;
} catch {
return;
}
}
},
myPrivKey: {
get: () => {
try {
return user.private;
} catch {
return;
}
}
}
});
var subAdmins, trustedIDs, settings;
Object.defineProperties(floGlobals, {
subAdmins: {
get: () => subAdmins
},
trustedIDs: {
get: () => trustedIDs
},
settings: {
get: () => settings
},
contacts: {
get: () => user.contacts
},
pubKeys: {
get: () => user.pubKeys
},
messages: {
get: () => user.messages
}
})
function initIndexedDB() {
return new Promise((resolve, reject) => {
var obs_g = {
//general
lastTx: {},
//supernode (cloud list)
supernodes: {}
}
var obs_a = {
//login credentials
credentials: {},
//for Dapps
subAdmins: {},
trustedIDs: {},
settings: {},
appObjects: {},
generalData: {},
lastVC: {}
}
//add other given objectStores
initIndexedDB.appObs = initIndexedDB.appObs || {}
for (let o in initIndexedDB.appObs)
if (!(o in obs_a))
obs_a[o] = initIndexedDB.appObs[o]
Promise.all([
compactIDB.initDB(DEFAULT.application, obs_a),
compactIDB.initDB(DEFAULT.root, obs_g)
]).then(result => {
compactIDB.setDefaultDB(DEFAULT.application)
resolve("IndexedDB App Storage Initated Successfully")
}).catch(error => reject(error));
})
}
function initUserDB() {
return new Promise((resolve, reject) => {
var obs = {
contacts: {},
pubKeys: {},
messages: {}
}
compactIDB.initDB(user.db_name, obs).then(result => {
resolve("UserDB Initated Successfully")
}).catch(error => reject('Init userDB failed'));
})
}
function loadUserDB() {
return new Promise((resolve, reject) => {
var loadData = ["contacts", "pubKeys", "messages"]
var promises = []
for (var i = 0; i < loadData.length; i++)
promises[i] = compactIDB.readAllData(loadData[i], user.db_name)
Promise.all(promises).then(results => {
for (var i = 0; i < loadData.length; i++)
user[loadData[i]] = results[i]
resolve("Loaded Data from userDB")
}).catch(error => reject('Load userDB failed'))
})
}
const startUpOptions = {
cloud: true,
app_config: true,
}
floDapps.startUpOptions = {
set app_config(val) {
if (val === true || val === false)
startUpOptions.app_config = val;
},
get app_config() { return startUpOptions.app_config },
set cloud(val) {
if (val === true || val === false)
startUpOptions.cloud = val;
},
get cloud() { return startUpOptions.cloud },
}
const startUpFunctions = [];
startUpFunctions.push(function readSupernodeListFromAPI() {
return new Promise((resolve, reject) => {
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
const CLOUD_KEY = "floCloudAPI#" + floCloudAPI.SNStorageID;
compactIDB.readData("lastTx", CLOUD_KEY, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: floCloudAPI.SNStorageName };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
//fetch data from flosight
floBlockchainAPI.readData(floCloudAPI.SNStorageID, query_options).then(result => {
compactIDB.readData("supernodes", CLOUD_KEY, DEFAULT.root).then(nodes => {
nodes = nodes || {};
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[floCloudAPI.SNStorageName];
for (let sn in content.removeNodes)
delete nodes[sn];
for (let sn in content.newNodes)
nodes[sn] = content.newNodes[sn];
for (let sn in content.updateNodes)
if (sn in nodes) //check if node is listed
nodes[sn].uri = content.updateNodes[sn];
}
Promise.all([
compactIDB.writeData("lastTx", result.lastItem, CLOUD_KEY, DEFAULT.root),
compactIDB.writeData("supernodes", nodes, CLOUD_KEY, DEFAULT.root)
]).then(_ => {
floCloudAPI.init(nodes)
.then(result => resolve("Loaded Supernode list\n" + result))
.catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function readAppConfigFromAPI() {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return resolve("No configs for this app");
compactIDB.readData("lastTx", `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root).then(lastTx => {
var query_options = { sentOnly: true, pattern: DEFAULT.application };
if (typeof lastTx == 'number') //lastTx is tx count (*backward support)
query_options.ignoreOld = lastTx;
else if (typeof lastTx == 'string') //lastTx is txid of last tx
query_options.after = lastTx;
//fetch data from flosight
floBlockchainAPI.readData(DEFAULT.adminID, query_options).then(result => {
for (var i = result.data.length - 1; i >= 0; i--) {
var content = JSON.parse(result.data[i])[DEFAULT.application];
if (!content || typeof content !== "object")
continue;
if (Array.isArray(content.removeSubAdmin))
for (var j = 0; j < content.removeSubAdmin.length; j++)
compactIDB.removeData("subAdmins", content.removeSubAdmin[j]);
if (Array.isArray(content.addSubAdmin))
for (var k = 0; k < content.addSubAdmin.length; k++)
compactIDB.writeData("subAdmins", true, content.addSubAdmin[k]);
if (Array.isArray(content.removeTrustedID))
for (var j = 0; j < content.removeTrustedID.length; j++)
compactIDB.removeData("trustedIDs", content.removeTrustedID[j]);
if (Array.isArray(content.addTrustedID))
for (var k = 0; k < content.addTrustedID.length; k++)
compactIDB.writeData("trustedIDs", true, content.addTrustedID[k]);
if (content.settings)
for (let l in content.settings)
compactIDB.writeData("settings", content.settings[l], l)
}
compactIDB.writeData("lastTx", result.lastItem, `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root);
compactIDB.readAllData("subAdmins").then(result => {
subAdmins = Object.keys(result);
compactIDB.readAllData("trustedIDs").then(result => {
trustedIDs = Object.keys(result);
compactIDB.readAllData("settings").then(result => {
settings = result;
resolve("Read app configuration from blockchain");
})
})
})
})
}).catch(error => reject(error))
})
});
startUpFunctions.push(function loadDataFromAppIDB() {
return new Promise((resolve, reject) => {
if (!startUpOptions.cloud)
return resolve("No cloud for this app");
var loadData = ["appObjects", "generalData", "lastVC"]
var promises = []
for (var i = 0; i < loadData.length; i++)
promises[i] = compactIDB.readAllData(loadData[i])
Promise.all(promises).then(results => {
for (var i = 0; i < loadData.length; i++)
floGlobals[loadData[i]] = results[i]
resolve("Loaded Data from app IDB")
}).catch(error => reject(error))
})
});
var keyInput = type => new Promise((resolve, reject) => {
let inputVal = prompt(`Enter ${type}: `)
if (inputVal === null)
reject(null)
else
resolve(inputVal)
});
function getCredentials() {
const readSharesFromIDB = indexArr => new Promise((resolve, reject) => {
var promises = []
for (var i = 0; i < indexArr.length; i++)
promises.push(compactIDB.readData('credentials', indexArr[i]))
Promise.all(promises).then(shares => {
var secret = floCrypto.retrieveShamirSecret(shares)
if (secret)
resolve(secret)
else
reject("Shares are insufficient or incorrect")
}).catch(error => {
clearCredentials();
location.reload();
})
});
const writeSharesToIDB = (shares, i = 0, resultIndexes = []) => new Promise(resolve => {
if (i >= shares.length)
return resolve(resultIndexes)
var n = floCrypto.randInt(0, 100000)
compactIDB.addData("credentials", shares[i], n).then(res => {
resultIndexes.push(n)
writeSharesToIDB(shares, i + 1, resultIndexes)
.then(result => resolve(result))
}).catch(error => {
writeSharesToIDB(shares, i, resultIndexes)
.then(result => resolve(result))
})
});
const getPrivateKeyCredentials = () => new Promise((resolve, reject) => {
var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
if (indexArr) {
readSharesFromIDB(JSON.parse(indexArr))
.then(result => resolve(result))
.catch(error => reject(error))
} else {
var privKey;
keyInput("PRIVATE_KEY").then(result => {
if (!result)
return reject("Empty Private Key")
var floID = floCrypto.getFloID(result)
if (!floID || !floCrypto.validateFloID(floID))
return reject("Invalid Private Key")
privKey = result;
}).catch(error => {
console.log(error, "Generating Random Keys")
privKey = floCrypto.generateNewID().privKey
}).finally(_ => {
if (!privKey)
return;
var threshold = floCrypto.randInt(10, 20)
var shares = floCrypto.createShamirsSecretShares(privKey, threshold, threshold)
writeSharesToIDB(shares).then(resultIndexes => {
//store index keys in localStorage
localStorage.setItem(`${DEFAULT.application}#privKey`, JSON.stringify(resultIndexes))
//also add a dummy privatekey to the IDB
var randomPrivKey = floCrypto.generateNewID().privKey
var randomThreshold = floCrypto.randInt(10, 20)
var randomShares = floCrypto.createShamirsSecretShares(randomPrivKey, randomThreshold, randomThreshold)
writeSharesToIDB(randomShares)
//resolve private Key
resolve(privKey)
})
})
}
});
const checkIfPinRequired = key => new Promise((resolve, reject) => {
if (key.length == 52)
resolve(key)
else {
keyInput("PIN/Password").then(pwd => {
try {
let privKey = Crypto.AES.decrypt(key, pwd);
resolve(privKey)
} catch (error) {
reject("Access Denied: Incorrect PIN/Password")
}
}).catch(error => reject("Access Denied: PIN/Password required"))
}
});
return new Promise((resolve, reject) => {
getPrivateKeyCredentials().then(key => {
checkIfPinRequired(key).then(privKey => {
try {
user_public = floCrypto.getPubKeyHex(privKey);
user_id = floCrypto.getAddress(privKey);
if (startUpOptions.cloud)
floCloudAPI.user(user_id, privKey); //Set user for floCloudAPI
user_priv_wrap = () => checkIfPinRequired(key);
let n = floCrypto.randInt(12, 20);
aes_key = floCrypto.randString(n);
user_priv_raw = Crypto.AES.encrypt(privKey, aes_key);
user_private = user_priv_wrap;
resolve('Login Credentials loaded successful')
} catch (error) {
console.log(error)
reject("Corrupted Private Key")
}
}).catch(error => reject(error))
}).catch(error => reject(error))
})
}
var startUpLog = (status, log) => status ? console.log(log) : console.error(log);
const callStartUpFunction = i => new Promise((resolve, reject) => {
startUpFunctions[i]().then(result => {
callStartUpFunction.completed += 1;
startUpLog(true, `${result}\nCompleted ${callStartUpFunction.completed}/${callStartUpFunction.total} Startup functions`)
resolve(true)
}).catch(error => {
callStartUpFunction.failed += 1;
startUpLog(false, `${error}\nFailed ${callStartUpFunction.failed}/${callStartUpFunction.total} Startup functions`)
reject(false)
})
});
var _midFunction;
const midStartUp = () => new Promise((res, rej) => {
if (_midFunction instanceof Function) {
_midFunction()
.then(r => res("Mid startup function completed"))
.catch(e => rej("Mid startup function failed"))
} else
res("No mid startup function")
});
const callAndLog = p => new Promise((res, rej) => {
p.then(r => {
startUpLog(true, r)
res(r)
}).catch(e => {
startUpLog(false, e)
rej(e)
})
});
floDapps.launchStartUp = function () {
return new Promise((resolve, reject) => {
initIndexedDB().then(log => {
console.log(log)
callStartUpFunction.total = startUpFunctions.length;
callStartUpFunction.completed = 0;
callStartUpFunction.failed = 0;
let p1 = new Promise((res, rej) => {
Promise.all(startUpFunctions.map((f, i) => callStartUpFunction(i))).then(r => {
callAndLog(midStartUp())
.then(r => res(true))
.catch(e => rej(false))
})
});
let p2 = new Promise((res, rej) => {
callAndLog(getCredentials()).then(r => {
callAndLog(initUserDB()).then(r => {
callAndLog(loadUserDB())
.then(r => res(true))
.catch(e => rej(false))
}).catch(e => rej(false))
}).catch(e => rej(false))
})
Promise.all([p1, p2])
.then(r => resolve('App Startup finished successful'))
.catch(e => reject('App Startup failed'))
}).catch(error => {
startUpLog(false, error);
reject("App database initiation failed")
})
})
}
floDapps.addStartUpFunction = fn => fn instanceof Function && !startUpFunctions.includes(fn) ? startUpFunctions.push(fn) : false;
floDapps.setMidStartup = fn => fn instanceof Function ? _midFunction = fn : false;
floDapps.setCustomStartupLogger = fn => fn instanceof Function ? startUpLog = fn : false;
floDapps.setCustomPrivKeyInput = fn => fn instanceof Function ? keyInput = fn : false;
floDapps.setAppObjectStores = appObs => initIndexedDB.appObs = appObs;
floDapps.storeContact = function (floID, name) {
return new Promise((resolve, reject) => {
if (!floCrypto.validateAddr(floID))
return reject("Invalid floID!")
compactIDB.writeData("contacts", name, floID, user.db_name).then(result => {
user.contacts[floID] = name;
resolve("Contact stored")
}).catch(error => reject(error))
});
}
floDapps.storePubKey = function (floID, pubKey) {
return new Promise((resolve, reject) => {
if (floID in user.pubKeys)
return resolve("pubKey already stored")
if (!floCrypto.validateAddr(floID))
return reject("Invalid floID!")
if (!floCrypto.verifyPubKey(pubKey, floID))
return reject("Incorrect pubKey")
compactIDB.writeData("pubKeys", pubKey, floID, user.db_name).then(result => {
user.pubKeys[floID] = pubKey;
resolve("pubKey stored")
}).catch(error => reject(error))
});
}
floDapps.sendMessage = function (floID, message) {
return new Promise((resolve, reject) => {
let options = {
receiverID: floID,
application: DEFAULT.root,
comment: DEFAULT.application
}
if (floID in user.pubKeys)
message = floCrypto.encryptData(JSON.stringify(message), user.pubKeys[floID])
floCloudAPI.sendApplicationData(message, "Message", options)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
floDapps.requestInbox = function (callback) {
return new Promise((resolve, reject) => {
let lastVC = Object.keys(user.messages).sort().pop()
let options = {
receiverID: user.id,
application: DEFAULT.root,
lowerVectorClock: lastVC + 1
}
let privKey = raw_user.private;
options.callback = (d, e) => {
for (let v in d) {
try {
if (d[v].message instanceof Object && "secret" in d[v].message)
d[v].message = floCrypto.decryptData(d[v].message, privKey)
} catch (error) { }
compactIDB.writeData("messages", d[v], v, user.db_name)
user.messages[v] = d[v]
}
if (callback instanceof Function)
callback(d, e)
}
floCloudAPI.requestApplicationData("Message", options)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
floDapps.manageAppConfig = function (adminPrivKey, addList, rmList, settings) {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return reject("No configs for this app");
if (!Array.isArray(addList) || !addList.length) addList = undefined;
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
if (!settings || typeof settings !== "object" || !Object.keys(settings).length) settings = undefined;
if (!addList && !rmList && !settings)
return reject("No configuration change")
var floData = {
[DEFAULT.application]: {
addSubAdmin: addList,
removeSubAdmin: rmList,
settings: settings
}
}
var floID = floCrypto.getFloID(adminPrivKey)
if (floID != DEFAULT.adminID)
reject('Access Denied for Admin privilege')
else
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
.then(result => resolve(['Updated App Configuration', result]))
.catch(error => reject(error))
})
}
floDapps.manageAppTrustedIDs = function (adminPrivKey, addList, rmList) {
return new Promise((resolve, reject) => {
if (!startUpOptions.app_config)
return reject("No configs for this app");
if (!Array.isArray(addList) || !addList.length) addList = undefined;
if (!Array.isArray(rmList) || !rmList.length) rmList = undefined;
if (!addList && !rmList)
return reject("No change in list")
var floData = {
[DEFAULT.application]: {
addTrustedID: addList,
removeTrustedID: rmList
}
}
var floID = floCrypto.getFloID(adminPrivKey)
if (floID != DEFAULT.adminID)
reject('Access Denied for Admin privilege')
else
floBlockchainAPI.writeData(floID, JSON.stringify(floData), adminPrivKey)
.then(result => resolve(['Updated App Configuration', result]))
.catch(error => reject(error))
})
}
const clearCredentials = floDapps.clearCredentials = function () {
return new Promise((resolve, reject) => {
compactIDB.clearData('credentials', DEFAULT.application).then(result => {
localStorage.removeItem(`${DEFAULT.application}#privKey`);
user.clear();
resolve("privKey credentials deleted!")
}).catch(error => reject(error))
})
}
floDapps.deleteUserData = function (credentials = false) {
return new Promise((resolve, reject) => {
let p = []
p.push(compactIDB.deleteDB(user.db_name))
if (credentials)
p.push(clearCredentials())
Promise.all(p)
.then(result => resolve('User database(local) deleted'))
.catch(error => reject(error))
})
}
floDapps.deleteAppData = function () {
return new Promise((resolve, reject) => {
compactIDB.deleteDB(DEFAULT.application).then(result => {
localStorage.removeItem(`${DEFAULT.application}#privKey`)
user.clear();
compactIDB.removeData('lastTx', `${DEFAULT.application}|${DEFAULT.adminID}`, DEFAULT.root)
.then(result => resolve("App database(local) deleted"))
.catch(error => reject(error))
}).catch(error => reject(error))
})
}
floDapps.securePrivKey = function (pwd) {
return new Promise(async (resolve, reject) => {
let indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
if (!indexArr)
return reject("PrivKey not found");
indexArr = JSON.parse(indexArr)
let encryptedKey = Crypto.AES.encrypt(await user.private, pwd);
let threshold = indexArr.length;
let shares = floCrypto.createShamirsSecretShares(encryptedKey, threshold, threshold)
let promises = [];
let overwriteFn = (share, index) =>
compactIDB.writeData("credentials", share, index, DEFAULT.application);
for (var i = 0; i < threshold; i++)
promises.push(overwriteFn(shares[i], indexArr[i]));
Promise.all(promises)
.then(results => resolve("Private Key Secured"))
.catch(error => reject(error))
})
}
floDapps.verifyPin = function (pin = null) {
const readSharesFromIDB = function (indexArr) {
return new Promise((resolve, reject) => {
var promises = []
for (var i = 0; i < indexArr.length; i++)
promises.push(compactIDB.readData('credentials', indexArr[i]))
Promise.all(promises).then(shares => {
var secret = floCrypto.retrieveShamirSecret(shares)
console.info(shares, secret)
if (secret)
resolve(secret)
else
reject("Shares are insufficient or incorrect")
}).catch(error => {
clearCredentials();
location.reload();
})
})
}
return new Promise((resolve, reject) => {
var indexArr = localStorage.getItem(`${DEFAULT.application}#privKey`)
console.info(indexArr)
if (!indexArr)
reject('No login credentials found')
readSharesFromIDB(JSON.parse(indexArr)).then(key => {
if (key.length == 52) {
if (pin === null)
resolve("Private key not secured")
else
reject("Private key not secured")
} else {
if (pin === null)
return reject("PIN/Password required")
try {
let privKey = Crypto.AES.decrypt(key, pin);
resolve("PIN/Password verified")
} catch (error) {
reject("Incorrect PIN/Password")
}
}
}).catch(error => reject(error))
})
}
const getNextGeneralData = floDapps.getNextGeneralData = function (type, vectorClock = null, options = {}) {
var fk = floCloudAPI.util.filterKey(type, options)
vectorClock = vectorClock || getNextGeneralData[fk] || '0';
var filteredResult = {}
if (floGlobals.generalData[fk]) {
for (let d in floGlobals.generalData[fk])
if (d > vectorClock)
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
} else if (options.comment) {
let comment = options.comment;
delete options.comment;
let fk = floCloudAPI.util.filterKey(type, options);
for (let d in floGlobals.generalData[fk])
if (d > vectorClock && floGlobals.generalData[fk][d].comment == comment)
filteredResult[d] = JSON.parse(JSON.stringify(floGlobals.generalData[fk][d]))
}
if (options.decrypt) {
let decryptionKey = (options.decrypt === true) ? raw_user.private : options.decrypt;
if (!Array.isArray(decryptionKey))
decryptionKey = [decryptionKey];
for (let f in filteredResult) {
let data = filteredResult[f]
try {
if (data.message instanceof Object && "secret" in data.message) {
for (let key of decryptionKey) {
try {
let tmp = floCrypto.decryptData(data.message, key)
data.message = JSON.parse(tmp)
break;
} catch (error) { }
}
}
} catch (error) { }
}
}
getNextGeneralData[fk] = Object.keys(filteredResult).sort().pop();
return filteredResult;
}
const syncData = floDapps.syncData = {};
syncData.oldDevice = () => new Promise((resolve, reject) => {
let sync = {
contacts: user.contacts,
pubKeys: user.pubKeys,
messages: user.messages
}
let message = Crypto.AES.encrypt(JSON.stringify(sync), raw_user.private)
let options = {
receiverID: user.id,
application: DEFAULT.root
}
floCloudAPI.sendApplicationData(message, "syncData", options)
.then(result => resolve(result))
.catch(error => reject(error))
});
syncData.newDevice = () => new Promise((resolve, reject) => {
var options = {
receiverID: user.id,
senderID: user.id,
application: DEFAULT.root,
mostRecent: true,
}
floCloudAPI.requestApplicationData("syncData", options).then(response => {
let vc = Object.keys(response).sort().pop()
let sync = JSON.parse(Crypto.AES.decrypt(response[vc].message, raw_user.private))
let promises = []
let store = (key, val, obs) => promises.push(compactIDB.writeData(obs, val, key, user.db_name));
["contacts", "pubKeys", "messages"].forEach(c => {
for (let i in sync[c]) {
store(i, sync[c][i], c)
user[c][i] = sync[c][i]
}
})
Promise.all(promises)
.then(results => resolve("Sync data successful"))
.catch(error => reject(error))
}).catch(error => reject(error))
});
})('object' === typeof module ? module.exports : window.floDapps = {});

View File

@ -0,0 +1,166 @@
(function (EXPORTS) { //floTokenAPI v1.0.4a
/* Token Operator to send/receive tokens via blockchain using API calls*/
'use strict';
const tokenAPI = EXPORTS;
const DEFAULT = {
apiURL: floGlobals.tokenURL || "https://ranchimallflo.duckdns.org/",
currency: floGlobals.currency || "rupee"
}
Object.defineProperties(tokenAPI, {
URL: {
get: () => DEFAULT.apiURL
},
currency: {
get: () => DEFAULT.currency,
set: currency => DEFAULT.currency = currency
}
});
if (floGlobals.currency) tokenAPI.currency = floGlobals.currency;
Object.defineProperties(floGlobals, {
currency: {
get: () => DEFAULT.currency,
set: currency => DEFAULT.currency = currency
}
});
const fetch_api = tokenAPI.fetch = function (apicall) {
return new Promise((resolve, reject) => {
console.debug(DEFAULT.apiURL + apicall);
fetch(DEFAULT.apiURL + apicall).then(response => {
if (response.ok)
response.json().then(data => resolve(data));
else
reject(response)
}).catch(error => reject(error))
})
}
const getBalance = tokenAPI.getBalance = function (floID, token = DEFAULT.currency) {
return new Promise((resolve, reject) => {
fetch_api(`api/v1.0/getFloAddressBalance?token=${token}&floAddress=${floID}`)
.then(result => resolve(result.balance || 0))
.catch(error => reject(error))
})
}
tokenAPI.getTx = function (txID) {
return new Promise((resolve, reject) => {
fetch_api(`api/v1.0/getTransactionDetails/${txID}`).then(res => {
if (res.result === "error")
reject(res.description);
else if (!res.parsedFloData)
reject("Data piece (parsedFloData) missing");
else if (!res.transactionDetails)
reject("Data piece (transactionDetails) missing");
else
resolve(res);
}).catch(error => reject(error))
})
}
tokenAPI.sendToken = function (privKey, amount, receiverID, message = "", token = DEFAULT.currency, options = {}) {
return new Promise((resolve, reject) => {
let senderID = floCrypto.getFloID(privKey);
if (typeof amount !== "number" || isNaN(amount) || amount <= 0)
return reject("Invalid amount");
getBalance(senderID, token).then(bal => {
if (amount > bal)
return reject(`Insufficient ${token}# balance`);
floBlockchainAPI.writeData(senderID, `send ${amount} ${token}# ${message}`, privKey, receiverID, options)
.then(txid => resolve(txid))
.catch(error => reject(error))
}).catch(error => reject(error))
});
}
function sendTokens_raw(privKey, receiverID, token, amount, utxo, vout, scriptPubKey) {
return new Promise((resolve, reject) => {
var trx = bitjs.transaction();
trx.addinput(utxo, vout, scriptPubKey)
trx.addoutput(receiverID, floBlockchainAPI.sendAmt);
trx.addflodata(`send ${amount} ${token}#`);
var signedTxHash = trx.sign(privKey, 1);
floBlockchainAPI.broadcastTx(signedTxHash)
.then(txid => resolve([receiverID, txid]))
.catch(error => reject([receiverID, error]))
})
}
//bulk transfer tokens
tokenAPI.bulkTransferTokens = function (sender, privKey, token, receivers) {
return new Promise((resolve, reject) => {
if (typeof receivers !== 'object')
return reject("receivers must be object in format {receiver1: amount1, receiver2:amount2...}")
let receiver_list = Object.keys(receivers), amount_list = Object.values(receivers);
let invalidReceivers = receiver_list.filter(id => !floCrypto.validateFloID(id));
let invalidAmount = amount_list.filter(val => typeof val !== 'number' || val <= 0);
if (invalidReceivers.length)
return reject(`Invalid receivers: ${invalidReceivers}`);
else if (invalidAmount.length)
return reject(`Invalid amounts: ${invalidAmount}`);
if (receiver_list.length == 0)
return reject("Receivers cannot be empty");
if (receiver_list.length == 1) {
let receiver = receiver_list[0], amount = amount_list[0];
floTokenAPI.sendToken(privKey, amount, receiver, "", token)
.then(txid => resolve({ success: { [receiver]: txid } }))
.catch(error => reject(error))
} else {
//check for token balance
floTokenAPI.getBalance(sender, token).then(token_balance => {
let total_token_amout = amount_list.reduce((a, e) => a + e, 0);
if (total_token_amout > token_balance)
return reject(`Insufficient ${token}# balance`);
//split utxos
floBlockchainAPI.splitUTXOs(sender, privKey, receiver_list.length).then(split_txid => {
//wait for the split utxo to get confirmation
floBlockchainAPI.waitForConfirmation(split_txid).then(split_tx => {
//send tokens using the split-utxo
var scriptPubKey = split_tx.vout[0].scriptPubKey.hex;
let promises = [];
for (let i in receiver_list)
promises.push(sendTokens_raw(privKey, receiver_list[i], token, amount_list[i], split_txid, i, scriptPubKey));
Promise.allSettled(promises).then(results => {
let success = Object.fromEntries(results.filter(r => r.status == 'fulfilled').map(r => r.value));
let failed = Object.fromEntries(results.filter(r => r.status == 'rejected').map(r => r.reason));
resolve({ success, failed });
})
}).catch(error => reject(error))
}).catch(error => reject(error))
}).catch(error => reject(error))
}
})
}
tokenAPI.getAllTxs = function (floID, token = DEFAULT.currency) {
return new Promise((resolve, reject) => {
fetch_api(`api/v1.0/getFloAddressTransactions?token=${token}&floAddress=${floID}`)
.then(result => resolve(result))
.catch(error => reject(error))
})
}
const util = tokenAPI.util = {};
util.parseTxData = function (txData) {
let parsedData = {};
for (let p in txData.parsedFloData)
parsedData[p] = txData.parsedFloData[p];
parsedData.sender = txData.transactionDetails.vin[0].addr;
for (let vout of txData.transactionDetails.vout)
if (vout.scriptPubKey.addresses[0] !== parsedData.sender)
parsedData.receiver = vout.scriptPubKey.addresses[0];
parsedData.time = txData.transactionDetails.time;
return parsedData;
}
})('object' === typeof module ? module.exports : window.floTokenAPI = {});

9975
btcmortgage/scripts/lib.js Normal file

File diff suppressed because it is too large Load Diff

2
btcmortgage/scripts/neverland.min.js vendored Normal file

File diff suppressed because one or more lines are too long