aboutsummaryrefslogtreecommitdiffstats
path: root/config/samples/config.sample.json
blob: f3cfd30915c36d8a2f45266acce84451ec75c60d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
{
  "development": {
    "username": "root",
    "password": "password",
    "database": "coinos",
    "host": "localhost",
    "dialect": "mariadb",
    "dialectOptions": { "multipleStatements": true, "timezone": "Etc/GMT+7" }
  },
  "test": {
    "username": "root",
    "password": null,
    "database": "database_test",
    "host": "127.0.0.1",
    "dialect": "mariadb",
    "dialectOptions": { "multipleStatements": true, "timezone": "Etc/GMT+7" }
  },
  "production": {
    "username": "root",
    "password": null,
    "database": "database_production",
    "host": "127.0.0.1",
    "dialect": "mariadb",
    "dialectOptions": { "multipleStatements": true, "timezone": "Etc/GMT+7" }
  }
}
ght: bold } /* Keyword.Constant */ .highlight .kd { color: #080; font-weight: bold } /* Keyword.Declaration */ .highlight .kn { color: #080; font-weight: bold } /* Keyword.Namespace */ .highlight .kp { color: #080 } /* Keyword.Pseudo */ .highlight .kr { color: #080; font-weight: bold } /* Keyword.Reserved */ .highlight .kt { color: #888; font-weight: bold } /* Keyword.Type */ .highlight .m { color: #00D; font-weight: bold } /* Literal.Number */ .highlight .s { color: #D20; background-color: #FFF0F0 } /* Literal.String */ .highlight .na { color: #369 } /* Name.Attribute */ .highlight .nb { color: #038 } /* Name.Builtin */ .highlight .nc { color: #B06; font-weight: bold } /* Name.Class */ .highlight .no { color: #036; font-weight: bold } /* Name.Constant */ .highlight .nd { color: #555 } /* Name.Decorator */ .highlight .ne { color: #B06; font-weight: bold } /* Name.Exception */ .highlight .nf { color: #06B; font-weight: bold } /* Name.Function */ .highlight .nl { color: #369; font-style: italic } /* Name.Label */ .highlight .nn { color: #B06; font-weight: bold } /* Name.Namespace */ .highlight .py { color: #369; font-weight: bold } /* Name.Property */ .highlight .nt { color: #B06; font-weight: bold } /* Name.Tag */ .highlight .nv { color: #369 } /* Name.Variable */ .highlight .ow { color: #080 } /* Operator.Word */ .highlight .w { color: #BBB } /* Text.Whitespace */ .highlight .mb { color: #00D; font-weight: bold } /* Literal.Number.Bin */ .highlight .mf { color: #00D; font-weight: bold } /* Literal.Number.Float */ .highlight .mh { color: #00D; font-weight: bold } /* Literal.Number.Hex */ .highlight .mi { color: #00D; font-weight: bold } /* Literal.Number.Integer */ .highlight .mo { color: #00D; font-weight: bold } /* Literal.Number.Oct */ .highlight .sa { color: #D20; background-color: #FFF0F0 } /* Literal.String.Affix */ .highlight .sb { color: #D20; background-color: #FFF0F0 } /* Literal.String.Backtick */ .highlight .sc { color: #D20; background-color: #FFF0F0 } /* Literal.String.Char */ .highlight .dl { color: #D20; background-color: #FFF0F0 } /* Literal.String.Delimiter */ .highlight .sd { color: #D20; background-color: #FFF0F0 } /* Literal.String.Doc */ .highlight .s2 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Double */ .highlight .se { color: #04D; background-color: #FFF0F0 } /* Literal.String.Escape */ .highlight .sh { color: #D20; background-color: #FFF0F0 } /* Literal.String.Heredoc */ .highlight .si { color: #33B; background-color: #FFF0F0 } /* Literal.String.Interpol */ .highlight .sx { color: #2B2; background-color: #F0FFF0 } /* Literal.String.Other */ .highlight .sr { color: #080; background-color: #FFF0FF } /* Literal.String.Regex */ .highlight .s1 { color: #D20; background-color: #FFF0F0 } /* Literal.String.Single */ .highlight .ss { color: #A60; background-color: #FFF0F0 } /* Literal.String.Symbol */ .highlight .bp { color: #038 } /* Name.Builtin.Pseudo */ .highlight .fm { color: #06B; font-weight: bold } /* Name.Function.Magic */ .highlight .vc { color: #369 } /* Name.Variable.Class */ .highlight .vg { color: #D70 } /* Name.Variable.Global */ .highlight .vi { color: #33B } /* Name.Variable.Instance */ .highlight .vm { color: #369 } /* Name.Variable.Magic */ .highlight .il { color: #00D; font-weight: bold } /* Literal.Number.Integer.Long */
<script>
  import { onMount } from "svelte";
  import { fiat } from "$lib/store";
  import Left from "$comp/Left.svelte";
  import Icon from "$comp/Icon.svelte";
  import { f, s, focus, warning, sat, sats } from "$lib/utils";
  import { t } from "$lib/translations";

  export let amount = 0,
    currency = "USD",
    element,
    rate,
    locale,
    submit = undefined;

  export let amountFiat = 0;

  let pasted = async () => {
    html = (await navigator.clipboard.readText()).replace(/,/g, "");
  };

  function getCurrencyInfo(locale = "en-US", currency) {
    const formatter = new Intl.NumberFormat(locale, {
      style: "currency",
      currency,
      currencyDisplay: "symbol",
      minimumFractionDigits: 2,
      maximumFractionDigits: 2,
    });

    const parts = formatter.formatToParts(123456.78);
    const { value: decimal } = parts.find((part) => part.type === "decimal");
    const currencyPart = parts.find((part) => part.type === "currency");
    const symbol = currencyPart ? currencyPart.value : "";

    const firstNumberIndex = parts.findIndex((part) => part.type === "integer");
    const currencyIndex = parts.findIndex((part) => part.type === "currency");
    const position = currencyIndex < firstNumberIndex ? "before" : "after";

    return { symbol, position, decimal };
  }

  function strip(input) {
    const regex = new RegExp(`[^0-9\.]`, "g");
    return input.replace(decimal, ".").replace(regex, "");
  }

  let { decimal, symbol, position } = getCurrencyInfo(locale, currency);

  let arrow = "<";

  $: update(amount, amountFiat);
  let update = (a, f) => {
    if ($fiat) {
      amount = f ? Math.round(strip(f) / (rate / sats)) : 0;
    } else {
      amountFiat = a ? ((a * rate) / sats).toFixed(2) : 0;
    }
  };

  let loading = false;

  const numPad = [
    "1",
    "2",
    "3",
    "4",
    "5",
    "6",
    "7",
    "8",
    "9",
    decimal,
    "0",
    "<",
  ];

  const handleInput = (value) => {
    if (value === "<") html = html.substr(0, html.length - 1);
    else html += value;
    input(null, true);
  };

  $: html = $fiat ? amountFiat : (amount || 0).toString();

  let prev = "";

  let input = (e, numpad = false) => {
    let d = decimal.replace(".", "\\.");

    if (!$fiat && html.includes(decimal)) {
      html = html.replace(new RegExp(d), "");
    }

    if (prev === "0" && html !== `0${decimal}`) {
      prev = "";
      html = html.replace("0", "");
    }

    let sel = getSelection();
    let i = sel.focusOffset;

    if (html[0] === "0") i = html.length;

    if (html.split(decimal)[0][0] === "0" && html.length > 1) {
      html = html.replace("0", "");
      i++;
    }

    if (html[0] === decimal) {
      html = `0${html}`;
      i = html.length;
    }

    if (html.includes(decimal) && html.split(decimal)[1].length > 2) {
      html = html.slice(0, html.indexOf(decimal) + 3);
      i = html.length;
    }

    let clean = html
      .substr(0, 15)
      .replace(new RegExp(`[^0-9${d}]+`, "g"), "")
      .replace(new RegExp(d), "X")
      .replace(new RegExp(d, "g"), "")
      .replace("X", decimal);

    if (clean !== html) {
      html = clean;
      i = html.length;
    }
    if (amount > sats && html.length > prev.length) {
      html = html.substr(0, html.length - 1);
      i = html.length;
      warning($t("user.receive.lessThan1BTCWarning"));
    }

    if ($fiat) {
      amountFiat = html;
    } else {
      amount = parseInt(html);
    }

    if (!amount) amount = null;

    if (!numpad) {
      setTimeout(() => {
        let node = element.childNodes[0];
        let range = document.createRange();

        if (node) {
          if (i > node.length) i = node.length;
          range.setStart(node, i);
          range.setEnd(node, i);

          let sel = getSelection();
          sel.removeAllRanges();
          sel.addRange(range);
          node.selectionStart = node.selectionEnd;
        }

        prev = html.toString();
      }, 0);
    }
  };

  let select = (e) => {
    let range = document.createRange();
    range.selectNodeContents(e.target);
    let sel = getSelection();
    sel.removeAllRanges();
    sel.addRange(range);
  };

  let blur = () => {
    if (!html) html = "0";
  };

  let keydown = (e) =>
    e.key === "Enter" && (e.preventDefault() || submit.click());

  let swap = () => {
    if ($fiat) {
      amount = parseInt((amountFiat / (rate / sats)).toFixed(0));
    } else {
      amountFiat =
        (amount * (rate / sats)).toFixed(2) > 0.0
          ? (amount * (rate / sats)).toFixed(2)
          : 0;
    }
    $fiat = !$fiat;
  };
</script>

<div class="flex justify-center items-center">
  <div class="space-y-5 w-full">
    <div class="text-center">
      <div
        class="text-5xl md:text-6xl font-semibold tracking-widest flex justify-center"
      >
        <div class="my-auto" class:text-5xl={!$fiat}>
          {#if $fiat}
            {#if position === "before"}
              {symbol}
            {/if}
          {:else}
            <iconify-icon
              noobserver
              icon="ph:lightning-fill"
              class="text-yellow-300"
            ></iconify-icon>
          {/if}
        </div>
        <div
          use:focus
          contenteditable
          bind:innerHTML={html}
          on:paste={pasted}
          on:focus={select}
          on:blur={blur}
          on:input={input}
          on:keydown={keydown}
          class="outline-none my-auto"
          bind:this={element}
        />
        {#if $fiat && position === "after"}
          {symbol}
        {/if}
      </div>
      <div
        class="flex items-center justify-center text-2xl cursor-pointer"
        on:click|preventDefault|stopPropagation={swap}
      >
        {#if $fiat}
          <iconify-icon
            noobserver
            icon="ph:lightning-fill"
            class="text-yellow-300"
          ></iconify-icon>
          {s(amount, locale)}
        {:else}
          {f(amountFiat, currency, locale)}
        {/if}
      </div>
    </div>

    <div class="grid grid-cols-3 gap-2 w-full mx-auto">
      {#each numPad as value}
        {#if value === arrow}
          <button
            type="button"
            class="btn"
            on:click|preventDefault|stopPropagation={() => handleInput(value)}
          >
            <Left />
          </button>
        {:else}
          <button
            type="button"
            class="btn"
            on:click|preventDefault|stopPropagation={() => handleInput(value)}
            >{value}</button
          >
        {/if}
      {/each}
    </div>
  </div>
</div>