Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Move vesting to its own module
Alexis Sellier committed 5 years ago
commit c168270c990bde34ad6d446b3592a4b7a136fcb8
parent 3a1625e7754a6f53fc5f63973ede972da5e15c25
9 files changed +196 -177
modified public/index.css
@@ -166,3 +166,40 @@ input[type="text"]::placeholder {
input.wide {
	width: 44ch;
}
+

+
.modal {
+
	padding: 2rem;
+
	border: 1px solid var(--color-secondary);
+
	box-shadow: 8px 8px 64px var(--color-secondary-2);
+
	min-width: 480px;
+
	text-align: center;
+
}
+
.modal-title {
+
	font-size: 1.75rem;
+
	margin-bottom: 1rem;
+
	color: var(--color-secondary);
+
	text-align: center;
+
}
+
.modal-body {
+
	margin: 3rem 0;
+
}
+
.modal-actions {
+
	margin-top: 2rem;
+
	text-align: center;
+
}
+

+
table {
+
	table-layout: fixed;
+
	border-collapse: collapse;
+
	width: 100%;
+
	max-width: 480px;
+
}
+
td {
+
	text-align: left;
+
}
+
td.label {
+
	color: var(--color-secondary);
+
}
+
td strong {
+
	font-weight: 600;
+
}
modified src/App.svelte
@@ -1,26 +1,21 @@
<script lang="javascript">
  import { ethers } from 'ethers';
  import { get } from 'svelte/store';
-
  import { STATE, state, error } from './state.js';
  import { getConfig } from './config.js';
  import { session } from './session.js';
-
  import { getInfo } from './vesting.js';
+

+
  import Vesting from './base/vesting/Vesting.svelte';
  import Header from './Header.svelte';

  let contractAddress = "";
  let info = null;
+
  let app = Vesting;

  function handleKeydown(event) {
    if (event.key === 'Enter') {
      document.querySelector('button.primary').click();
    }
  }
-

-
  async function loadContract(config) {
-
    state.set(STATE.LOADING);
-
    info = await getInfo(contractAddress, config);
-
    state.set(STATE.IDLE);
-
  }
</script>

<style>
@@ -35,116 +30,12 @@
    justify-content: center;
    height: 24rem;
  }
-
  .modal {
-
    padding: 2rem;
-
    border: 1px solid var(--color-secondary);
-
    box-shadow: 8px 8px 64px var(--color-secondary-2);
-
    min-width: 480px;
-
    text-align: center;
-
  }
-
  .modal-title {
-
    font-size: 1.75rem;
-
    margin-bottom: 1rem;
-
    color: var(--color-secondary);
-
    text-align: center;
-
  }
-
  .modal-body {
-
    margin: 3rem 0;
-
  }
-
  .modal-actions {
-
    margin-top: 2rem;
-
    text-align: center;
-
  }
-
  div.input-caption {
-
    font-size: 1.25rem;
-
    text-align: left;
-
    margin-left: 1.5rem;
-
    padding-left: 1.5rem;
-
    margin-bottom: 1rem;
-
    color: var(--color-secondary);
-
  }
-
  div.input-main {
-
    display: flex;
-
    align-items: center;
-
    flex-direction: row;
-
    margin-left: 1.5rem;
-
    color: var(--color-secondary);
-
  }
-

-
  table {
-
    table-layout: fixed;
-
    border-collapse: collapse;
-
    width: 100%;
-
    max-width: 480px;
-
  }
-
  td {
-
    text-align: left;
-
  }
-
  td.label {
-
    color: var(--color-secondary);
-
  }
-
  td strong {
-
    font-weight: 600;
-
  }
</style>

<svelte:window on:keydown={handleKeydown} />
<div class="app">
  <Header/>
-
  {#await getConfig()}
-
    <!-- Loading wallet -->
-
  {:then config}
-
    <div class="wrapper">
-
      <main>
-
        {#if info}
-
          <div class="modal">
-
            <div class="modal-title">
-
              {contractAddress}
-
            </div>
-
            <div class="modal-body">
-
              <table>
-
                <tr><td class="label">Beneficiary</td><td>{info.beneficiary}</td></tr>
-
                <tr><td class="label">Allocation</td><td>{info.totalVesting} <strong>{info.symbol}</strong></td></tr>
-
                <tr><td class="label">Withdrawn</td><td>{info.withdrawn} <strong>{info.symbol}</strong></td></tr>
-
                <tr><td class="label">Withdrawable</td><td>{info.withdrawableBalance} <strong>{info.symbol}</strong></td></tr>
-
              </table>
-
            </div>
-
            <div class="modal-actions">
-
              <button on:click={() => info = null} class="small">
-
                Back
-
              </button>
-
            </div>
-
          </div>
-
        {:else}
-
          <div class="input-caption">
-
            Enter your Radicle <strong>vesting contract</strong> address
-
          </div>
-
          <div class="input-main">
-
            <span class="name">
-
              <div>
-
                <input
-
                  autofocus
-
                  size="40"
-
                  placeholder=""
-
                  class="subdomain"
-
                  disabled={$state === STATE.LOADING}
-
                  type="text" bind:value={contractAddress}
-
                />
-
              </div>
-
            </span>
-
            <button
-
              on:click={() => loadContract(config)}
-
              class="primary"
-
              data-waiting={$state === STATE.LOADING || null}
-
              disabled={$state === STATE.LOADING}
-
            >
-
              Load
-
            </button>
-
          </div>
-
        {/if}
-
      </main>
-
    </div>
-
  {:catch error}
-
    Ethereum wallet not available.
-
  {/await}
+
  <div class="wrapper">
+
    <svelte:component this={app}/>
+
  </div>
</div>
modified src/Header.svelte
@@ -2,9 +2,8 @@
  // TODO: Shorten tx hash
  // TODO: Link to correct network on etherscan
  import { ethers } from "ethers";
-
  import { STATE, state, error } from "./state.js";
-
  import { ERROR } from "./error.js";
  import { CONNECTION, session, connectWallet, disconnectWallet, shortAddress } from "./session.js";
+
  import { error } from './error.js';
  import Logo from './Logo.svelte';
  import Connect from './Connect.svelte';

added src/base/vesting/Vesting.svelte
@@ -0,0 +1,89 @@
+
<script lang="javascript">
+
  import { ethers } from 'ethers';
+
  import { get } from 'svelte/store';
+
  import { STATE, state } from './state.js';
+
  import { getConfig } from '../../config.js';
+
  import { getInfo } from './vesting.js';
+

+
  let contractAddress = "";
+
  let info = null;
+

+
  async function loadContract(config) {
+
    state.set(STATE.LOADING);
+
    info = await getInfo(contractAddress, config);
+
    state.set(STATE.IDLE);
+
  }
+
</script>
+

+
<style>
+
  div.input-caption {
+
    font-size: 1.25rem;
+
    text-align: left;
+
    margin-left: 1.5rem;
+
    padding-left: 1.5rem;
+
    margin-bottom: 1rem;
+
    color: var(--color-secondary);
+
  }
+
  div.input-main {
+
    display: flex;
+
    align-items: center;
+
    flex-direction: row;
+
    margin-left: 1.5rem;
+
    color: var(--color-secondary);
+
  }
+
</style>
+

+
{#await getConfig()}
+
  <!-- Loading wallet -->
+
{:then config}
+
  <main>
+
    {#if info}
+
      <div class="modal">
+
        <div class="modal-title">
+
          {contractAddress}
+
        </div>
+
        <div class="modal-body">
+
          <table>
+
            <tr><td class="label">Beneficiary</td><td>{info.beneficiary}</td></tr>
+
            <tr><td class="label">Allocation</td><td>{info.totalVesting} <strong>{info.symbol}</strong></td></tr>
+
            <tr><td class="label">Withdrawn</td><td>{info.withdrawn} <strong>{info.symbol}</strong></td></tr>
+
            <tr><td class="label">Withdrawable</td><td>{info.withdrawableBalance} <strong>{info.symbol}</strong></td></tr>
+
          </table>
+
        </div>
+
        <div class="modal-actions">
+
          <button on:click={() => info = null} class="small">
+
            Back
+
          </button>
+
        </div>
+
      </div>
+
    {:else}
+
      <div class="input-caption">
+
        Enter your Radicle <strong>vesting contract</strong> address
+
      </div>
+
      <div class="input-main">
+
        <span class="name">
+
          <div>
+
            <input
+
              autofocus
+
              size="40"
+
              placeholder=""
+
              class="subdomain"
+
              disabled={$state === STATE.LOADING}
+
              type="text" bind:value={contractAddress}
+
            />
+
          </div>
+
        </span>
+
        <button
+
          on:click={() => loadContract(config)}
+
          class="primary"
+
          data-waiting={$state === STATE.LOADING || null}
+
          disabled={$state === STATE.LOADING}
+
        >
+
          Load
+
        </button>
+
      </div>
+
    {/if}
+
  </main>
+
{:catch error}
+
  Ethereum wallet not available.
+
{/await}
added src/base/vesting/state.js
@@ -0,0 +1,13 @@
+
import { derived, writable } from "svelte/store";
+

+
export const STATE = {
+
  ERROR: -1,
+
  IDLE: 0,
+
  LOADING: 1,
+
  FOUND: 2,
+
  NOT_FOUND: 3,
+
  WITHDRAWING: 4,
+
  WITHDRAWN: 5,
+
};
+

+
export const state = writable(STATE.IDLE);
added src/base/vesting/vesting.js
@@ -0,0 +1,46 @@
+
import { ethers } from "ethers";
+

+
const abi = [
+
  "function token() view returns (address)",
+
  "function totalVestingAmount() view returns (uint256)",
+
  "function vestingStartTime() view returns (uint256)",
+
  "function vestingPeriod() view returns (uint256)",
+
  "function cliffPeriod() view returns (uint256)",
+
  "function beneficiary() view returns (address)",
+
  "function interrupted() view returns (bool)",
+
  "function withdrawn() view returns (uint256)",
+
  "function withdrawableBalance() view returns (uint256)",
+
  "function withdrawVested()",
+
];
+

+
const tokenAbi = [
+
  "function symbol() view returns (string)",
+
];
+

+
export async function getInfo(address, config) {
+
  const contract = new ethers.Contract(address, abi, config.provider);
+
  const signer = config.provider.getSigner();
+
  const userAddr = await signer.getAddress();
+

+
  const token = await contract.token();
+
  const beneficiary = await contract.beneficiary();
+
  const withdrawable = await contract.withdrawableBalance();
+
  const withdrawn = await contract.withdrawn();
+
  const total = await contract.totalVestingAmount();
+

+
  const tokenContract = new ethers.Contract(token, tokenAbi, config.provider);
+
  const symbol = await tokenContract.symbol();
+

+
  return {
+
    token: token,
+
    symbol: symbol,
+
    beneficiary: beneficiary,
+
    totalVesting: format(total),
+
    withdrawableBalance: format(withdrawable),
+
    withdrawn: format(withdrawn),
+
  };
+
}
+

+
function format(n) {
+
  return ethers.utils.commify(parseFloat(ethers.utils.formatUnits(n)).toFixed(2));
+
}
modified src/error.js
@@ -1,3 +1,7 @@
+
import { writable } from "svelte/store";
+

export const ERROR = {
  TRANSACTION_FAILED: 1,
};
+

+
export const error = writable(null);
deleted src/state.js
@@ -1,14 +0,0 @@
-
import { derived, writable } from "svelte/store";
-

-
export const STATE = {
-
  ERROR: -1,
-
  IDLE: 0,
-
  LOADING: 1,
-
  FOUND: 2,
-
  NOT_FOUND: 3,
-
  WITHDRAWING: 4,
-
  WITHDRAWN: 5,
-
};
-

-
export const state = writable(STATE.IDLE);
-
export const error = writable(null);
deleted src/vesting.js
@@ -1,46 +0,0 @@
-
import { ethers } from "ethers";
-

-
const abi = [
-
  "function token() view returns (address)",
-
  "function totalVestingAmount() view returns (uint256)",
-
  "function vestingStartTime() view returns (uint256)",
-
  "function vestingPeriod() view returns (uint256)",
-
  "function cliffPeriod() view returns (uint256)",
-
  "function beneficiary() view returns (address)",
-
  "function interrupted() view returns (bool)",
-
  "function withdrawn() view returns (uint256)",
-
  "function withdrawableBalance() view returns (uint256)",
-
  "function withdrawVested()",
-
];
-

-
const tokenAbi = [
-
  "function symbol() view returns (string)",
-
];
-

-
export async function getInfo(address, config) {
-
  const contract = new ethers.Contract(address, abi, config.provider);
-
  const signer = config.provider.getSigner();
-
  const userAddr = await signer.getAddress();
-

-
  const token = await contract.token();
-
  const beneficiary = await contract.beneficiary();
-
  const withdrawable = await contract.withdrawableBalance();
-
  const withdrawn = await contract.withdrawn();
-
  const total = await contract.totalVestingAmount();
-

-
  const tokenContract = new ethers.Contract(token, tokenAbi, config.provider);
-
  const symbol = await tokenContract.symbol();
-

-
  return {
-
    token: token,
-
    symbol: symbol,
-
    beneficiary: beneficiary,
-
    totalVesting: format(total),
-
    withdrawableBalance: format(withdrawable),
-
    withdrawn: format(withdrawn),
-
  };
-
}
-

-
function format(n) {
-
  return ethers.utils.commify(parseFloat(ethers.utils.formatUnits(n)).toFixed(2));
-
}