Radish alpha
r
Radicle web interface
Radicle
Git (anonymous pull)
Log in to clone via SSH
Add setOwner safe tx proposal creation
Sebastian Martinez committed 4 years ago
commit 6588ccafff3379e963c9ea7a1576cd3249c09571
parent 7c3cfcac28b05d4f89a3e4fe9137930dccf1ca0f
3 files changed +74 -7
modified src/base/orgs/Org.ts
@@ -132,6 +132,35 @@ export class Org {
    return org.setOwner(address);
  }

+
  async setOwnerMultisig(owner: string, config: Config): Promise<void> {
+
    assert(config.signer);
+
    assert(config.safe.client);
+

+
    const safeAddress = ethers.utils.getAddress(this.owner);
+
    const orgAddress = ethers.utils.getAddress(this.address);
+
    const org = new ethers.Contract(
+
      this.address,
+
      config.abi.org,
+
      config.signer
+
    );
+
    const unsignedTx = await org.populateTransaction.setOwner(
+
      owner
+
    );
+

+
    const txData = unsignedTx.data;
+
    if (! txData) {
+
      throw new Error("Org::setOwnerMultisig: Could not generate transaction for `setOwner` call");
+
    }
+

+
    const safeTx = {
+
      to: orgAddress,
+
      value: ethers.constants.Zero.toString(),
+
      data: txData,
+
      operation: OperationType.Call,
+
    };
+
    await utils.proposeSafeTransaction(safeTx, safeAddress, config);
+
  }
+

  async getMembers(config: Config): Promise<Array<string>> {
    const safe = await utils.getSafe(this.owner, config);
    if (safe) {
modified src/base/orgs/TransferOwnership.svelte
@@ -5,6 +5,8 @@
  import { formatAddress, isAddress } from "@app/utils";
  import Loading from '@app/Loading.svelte';
  import { assert } from '@app/error';
+
  import * as utils from '@app/utils';
+
  import Address from '@app/Address.svelte';

  import type { Org } from './Org';

@@ -15,9 +17,16 @@

  enum State {
    Idle,
+

+
    // Single sig states.
    Signing,
    Pending,
    Success,
+

+
    // Multi sig states.
+
    Proposing,
+
    Proposed,
+

    Failed,
  }

@@ -43,12 +52,18 @@
      return;
    }

-
    state = State.Signing;
    try {
-
      let tx = await org.setOwner(newOwner, config);
-
      state = State.Pending;
-
      await tx.wait();
-
      state = State.Success;
+
      if (org && await utils.isSafe(org.owner, config)) {
+
        state = State.Proposing;
+
        await org.setOwnerMultisig(newOwner, config);
+
        state = State.Proposed;
+
      } else {
+
        state = State.Signing;
+
        let tx = await org.setOwner(newOwner, config);
+
        state = State.Pending;
+
        await tx.wait();
+
        state = State.Success;
+
      }
    } catch (e) {
      console.error(e);
      state = State.Failed;
@@ -74,6 +89,24 @@
      </button>
    </div>
  </Modal>
+
{:else if state === State.Proposed && org}
+
  <Modal floating>
+
    <div slot="title">
+
      🪴
+
    </div>
+

+
    <div slot="subtitle">
+
      <p>The transaction to set the owner of <strong>{formatAddress(org.address)}</strong>
+
      to <strong>{newOwner}</strong> was proposed to:</p>
+
      <p><Address address={org.owner} {config} compact /></p>
+
    </div>
+

+
    <div slot="actions">
+
      <button class="small" on:click={() => dispatch('close')}>
+
        Done
+
      </button>
+
    </div>
+
  </Modal>
{:else}
  <Modal floating error={state == State.Failed} small={state == State.Failed}>
    <div slot="title">
@@ -86,6 +119,10 @@
        Please confirm the transaction in your wallet.
      {:else if state == State.Pending}
        Waiting for transaction to be processed...
+
      {:else if state == State.Proposing && org}
+
        Proposal is being submitted to the safe
+
        <strong>{formatAddress(org.owner)}</strong>,
+
        please sign the transaction in your wallet.
      {:else if state == State.Idle}
        Transfer the ownership of Org <strong>{formatAddress(org.address)}</strong> to a new address.
      {:else if state == State.Failed}
@@ -98,7 +135,7 @@
    <div slot="body">
      {#if state == State.Idle}
        <input type="text" size="40" disabled={state !== State.Idle} bind:this={input} bind:value={newOwner} />
-
      {:else if state == State.Pending || state == State.Signing}
+
      {:else if state == State.Pending || state == State.Proposing || state == State.Signing}
        <Loading small center />
      {:else if state == State.Failed}
        <!-- ... -->
modified src/base/orgs/View.svelte
@@ -63,6 +63,7 @@
      }
    }
  };
+
  $: account = $session && $session.address;
  $: isOwner = (org: Org): boolean => $session
    ? utils.isAddressEqual(org.owner, $session.address)
    : false;
@@ -220,7 +221,7 @@
          <div class="label">Owner</div>
          <div><Address resolve {config} address={org.owner} /></div>
          <div>
-
            {#if isOwner(org)}
+
            {#if isOwner(org) || (account && org.isMember(account, config))}
              <button class="tiny secondary" on:click={transferOwnership}>
                Transfer
              </button>