mirror of
https://github.com/Instadapp/assembly.git
synced 2024-07-29 22:37:06 +00:00
closes #10
This commit is contained in:
parent
131bc04455
commit
0ad579c6e7
|
@ -31,7 +31,7 @@
|
|||
<toggle-button
|
||||
v-if="active && canSimulate"
|
||||
@change="checked => (checked ? startSimulation() : stopSimulation())"
|
||||
:checked="forkId"
|
||||
:checked="!! forkId"
|
||||
:loading="loading"
|
||||
class="ml-4 border-l pl-4"
|
||||
label="Simulation Mode"
|
||||
|
|
41
components/common/input/ButtonCTAOutlined.vue
Normal file
41
components/common/input/ButtonCTAOutlined.vue
Normal file
|
@ -0,0 +1,41 @@
|
|||
<template>
|
||||
<button
|
||||
class="flex items-center justify-center flex-shrink-0 py-2 font-semibold whitespace-no-wrap duration-75 ease-out transform rounded-[4px] select-none border border-ocean-blue-pure text-ocean-blue-pure shadow-cta focus:outline-none dark:shadow-none"
|
||||
:class="{
|
||||
'bg-opacity-50 pointer-events-none': disabled && !loading,
|
||||
'hover:-translate-y-px': !disabled && !loading,
|
||||
'active:translate-y-px': !disabled && !loading
|
||||
}"
|
||||
:disabled="disabled || loading"
|
||||
v-bind="$attrs"
|
||||
v-on="$listeners"
|
||||
>
|
||||
<slot v-if="!loading" />
|
||||
<CustomTransition
|
||||
enter-active-class="duration-200 ease-out"
|
||||
enter-class="w-0 ml-0 opacity-0"
|
||||
enter-to-class="w-4 opacity-100"
|
||||
after-enter-class="w-4 "
|
||||
leave-active-class="duration-100 ease-in"
|
||||
leave-class="w-4 opacity-100"
|
||||
leave-to-class="w-0 ml-0 opacity-0"
|
||||
>
|
||||
<SVGSpinner v-if="loading" class="h-4 animate-spin-loading" />
|
||||
</CustomTransition>
|
||||
</button>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from '@nuxtjs/composition-api'
|
||||
import SVGSpinner from '@/assets/icons/spinner.svg?inline'
|
||||
|
||||
export default defineComponent({
|
||||
components: {
|
||||
SVGSpinner,
|
||||
},
|
||||
props: {
|
||||
loading: { type: Boolean, default: false },
|
||||
disabled: { type: Boolean, default: false },
|
||||
},
|
||||
})
|
||||
</script>
|
74
components/modal/authority/AddAuthorityDialog.vue
Normal file
74
components/modal/authority/AddAuthorityDialog.vue
Normal file
|
@ -0,0 +1,74 @@
|
|||
<template>
|
||||
<div
|
||||
class="inline-block w-full max-w-md px-8 py-7 overflow-hidden text-left align-bottom transition-all transform bg-white border border-opacity-50 rounded-lg shadow-xl dark:bg-dark-400 sm:my-8 sm:align-middle sm:p-6 border-green-light"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-headline"
|
||||
>
|
||||
<div>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<h3 id="modal-headline" class="font-bold text-2xl">
|
||||
Add Authority
|
||||
</h3>
|
||||
</div>
|
||||
|
||||
<div class="my-10">
|
||||
<div class="relative">
|
||||
<Input class="mr-4" v-model="authority" />
|
||||
|
||||
<span
|
||||
v-if="!authority"
|
||||
class="absolute right-0 inset-y-0 mt-3 mr-4 uppercase text-[#1874FF] font-semibold text-xs"
|
||||
>Paste</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center mt-4 sm:mt-6">
|
||||
<ButtonCTAOutlined class="flex-1 px-8 rounded" @click="close">
|
||||
Cancel
|
||||
</ButtonCTAOutlined>
|
||||
|
||||
<ButtonCTA
|
||||
@click="createAuthorityHandler"
|
||||
class="ml-4 flex-1 px-8"
|
||||
:loading="creatingAuthority"
|
||||
:disabled="creatingAuthority"
|
||||
>
|
||||
create
|
||||
</ButtonCTA>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent, ref } from '@nuxtjs/composition-api'
|
||||
import Input from '~/components/common/input/Input.vue'
|
||||
import { useDSA } from '~/composables/useDSA'
|
||||
import { useModal } from '~/composables/useModal'
|
||||
import ButtonCTA from '../../common/input/ButtonCTA.vue'
|
||||
import ButtonCTAOutlined from '../../common/input/ButtonCTAOutlined.vue'
|
||||
|
||||
export default defineComponent({
|
||||
components: { ButtonCTA, ButtonCTAOutlined, Input },
|
||||
setup() {
|
||||
const { close } = useModal()
|
||||
const { createAuthority, creatingAuthority } = useDSA()
|
||||
|
||||
const authority = ref();
|
||||
|
||||
const createAuthorityHandler = async () => {
|
||||
await createAuthority(authority.value)
|
||||
close()
|
||||
}
|
||||
|
||||
return {
|
||||
authority,
|
||||
close,
|
||||
createAuthorityHandler,
|
||||
creatingAuthority,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
89
components/modal/authority/RemoveAuthorityDialog.vue
Normal file
89
components/modal/authority/RemoveAuthorityDialog.vue
Normal file
|
@ -0,0 +1,89 @@
|
|||
<template>
|
||||
<div
|
||||
class="inline-block w-full max-w-md px-4 py-6 overflow-hidden text-left align-bottom transition-all transform bg-white border border-opacity-50 rounded-lg shadow-xl dark:bg-dark-400 sm:my-8 sm:align-middle sm:p-6 border-green-light"
|
||||
role="dialog"
|
||||
aria-modal="true"
|
||||
aria-labelledby="modal-headline"
|
||||
>
|
||||
<div>
|
||||
<div class="mt-3 text-center sm:mt-5">
|
||||
<h3 id="modal-headline" class="font-bold text-2xl">
|
||||
Remove Authority
|
||||
</h3>
|
||||
<p class="px-6 mt-4 text-[#9FB0C9]">
|
||||
this action will remove this account as authority
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="border-b border-[#DBE5F4] py-4 text-sm text-center flex items-center justify-center"
|
||||
>
|
||||
<svg
|
||||
class="mr-2"
|
||||
width="12"
|
||||
height="14"
|
||||
viewBox="0 0 12 14"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M6 7C7.89375 7 9.42857 5.4332 9.42857 3.5C9.42857 1.5668 7.89375 0 6 0C4.10625 0 2.57143 1.5668 2.57143 3.5C2.57143 5.4332 4.10625 7 6 7ZM8.56607 7.89141L7.28571 13.125L6.42857 9.40625L7.28571 7.875H4.71429L5.57143 9.40625L4.71429 13.125L3.43393 7.89141C1.52411 7.98438 0 9.57852 0 11.55V12.6875C0 13.4121 0.575893 14 1.28571 14H10.7143C11.4241 14 12 13.4121 12 12.6875V11.55C12 9.57852 10.4759 7.98438 8.56607 7.89141Z"
|
||||
fill="#9FB0C9"
|
||||
/>
|
||||
</svg>
|
||||
|
||||
<div>
|
||||
{{ authority }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="flex justify-between items-center mt-4 sm:mt-6">
|
||||
<ButtonCTAOutlined class="flex-1 px-8 rounded" @click="close">
|
||||
Cancel
|
||||
</ButtonCTAOutlined>
|
||||
|
||||
<ButtonCTA
|
||||
@click="removeAuthorityHandler(authority)"
|
||||
class="ml-4 flex-1 px-8"
|
||||
:loading="removingAuthority"
|
||||
:disabled="removingAuthority"
|
||||
>
|
||||
Remove
|
||||
</ButtonCTA>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { defineComponent } from '@nuxtjs/composition-api'
|
||||
import { useDSA } from '~/composables/useDSA'
|
||||
import { useModal } from '~/composables/useModal'
|
||||
import ButtonCTA from '../../common/input/ButtonCTA.vue'
|
||||
import ButtonCTAOutlined from '../../common/input/ButtonCTAOutlined.vue'
|
||||
|
||||
export default defineComponent({
|
||||
props: {
|
||||
authority: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
components: { ButtonCTA, ButtonCTAOutlined },
|
||||
setup() {
|
||||
const { close } = useModal()
|
||||
const { removeAuthority, removingAuthority } = useDSA()
|
||||
|
||||
const removeAuthorityHandler = async (authority) => {
|
||||
await removeAuthority(authority)
|
||||
close()
|
||||
}
|
||||
|
||||
return {
|
||||
close,
|
||||
removeAuthorityHandler,
|
||||
removingAuthority,
|
||||
}
|
||||
},
|
||||
})
|
||||
</script>
|
|
@ -45,6 +45,7 @@ export function useBalances() {
|
|||
});
|
||||
const fetchBalances = async (refresh = false) => {
|
||||
if (!balances.user || refresh) {
|
||||
if (!account.value) return;
|
||||
balances.user = {
|
||||
mainnet:
|
||||
networkName.value === Network.Mainnet
|
||||
|
@ -58,6 +59,8 @@ export function useBalances() {
|
|||
}
|
||||
|
||||
if (!balances.dsa || refresh) {
|
||||
if (!activeAccount.value) return;
|
||||
|
||||
balances.dsa = {
|
||||
mainnet:
|
||||
networkName.value === Network.Mainnet
|
||||
|
@ -123,8 +126,6 @@ export function useBalances() {
|
|||
};
|
||||
|
||||
watch(web3, () => {
|
||||
console.log("Fetch balances");
|
||||
|
||||
fetchBalances(true);
|
||||
});
|
||||
return {
|
||||
|
@ -144,8 +145,6 @@ async function getBalances(
|
|||
web3: Web3,
|
||||
additionalTokens = []
|
||||
) {
|
||||
console.log("getBalances", owner, network, web3);
|
||||
|
||||
try {
|
||||
const tokenResolverABI = abis.resolver.balance;
|
||||
const tokenResolverAddr = addresses[network].resolver.balance;
|
||||
|
|
|
@ -2,58 +2,63 @@ import { computed, readonly, ref, watch } from "@nuxtjs/composition-api";
|
|||
import { useWeb3 } from "./useWeb3";
|
||||
//@ts-ignore
|
||||
import DSA from "dsa-connect";
|
||||
import addresses from "~/constant/addresses";
|
||||
import abis from "~/constant/abis";
|
||||
import { AbiItem } from "web3-utils";
|
||||
import { useNotification } from "./useNotification";
|
||||
|
||||
const dsa = ref<DSA>();
|
||||
const accounts = ref<any[]>([]);
|
||||
const activeAccount = ref<any>();
|
||||
const authorities = ref<string[]>();
|
||||
|
||||
export function useDSA() {
|
||||
const { web3, chainId } = useWeb3();
|
||||
const { web3, chainId, networkName, account } = useWeb3();
|
||||
const { showWarning } = useNotification();
|
||||
|
||||
watch(
|
||||
web3,
|
||||
() => {
|
||||
if (web3.value) {
|
||||
dsa.value = new DSA(web3.value, chainId.value);
|
||||
watch(web3, () => {
|
||||
if (web3.value) {
|
||||
dsa.value = new DSA(web3.value, chainId.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(chainId, () => {
|
||||
if (web3.value) {
|
||||
dsa.value = new DSA(web3.value, chainId.value);
|
||||
}
|
||||
});
|
||||
|
||||
watch(dsa, async () => {
|
||||
if (dsa.value) {
|
||||
accounts.value = await dsa.value.getAccounts();
|
||||
|
||||
if (accounts.value.length > 0) {
|
||||
activeAccount.value = accounts.value[0];
|
||||
} else {
|
||||
activeAccount.value = undefined;
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
chainId,
|
||||
() => {
|
||||
if (web3.value) {
|
||||
dsa.value = new DSA(web3.value, chainId.value);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
watch(
|
||||
dsa,
|
||||
async () => {
|
||||
if (dsa.value) {
|
||||
accounts.value = await dsa.value.getAccounts();
|
||||
|
||||
if (accounts.value.length > 0) {
|
||||
activeAccount.value = accounts.value[0];
|
||||
}
|
||||
}
|
||||
//@ts-ignore
|
||||
window.dsa = dsa.value
|
||||
}
|
||||
);
|
||||
//@ts-ignore
|
||||
window.dsa = dsa.value;
|
||||
});
|
||||
|
||||
watch(
|
||||
activeAccount,
|
||||
async () => {
|
||||
authorities.value = [];
|
||||
|
||||
if (activeAccount.value) {
|
||||
dsa.value.setAccount(activeAccount.value.id);
|
||||
|
||||
fethAuthorities();
|
||||
}
|
||||
},
|
||||
{ immediate: true }
|
||||
);
|
||||
|
||||
const creatingAccount = ref(false);
|
||||
const creatingAuthority = ref(false);
|
||||
const removingAuthority = ref(false);
|
||||
|
||||
async function createAccount() {
|
||||
creatingAccount.value = true;
|
||||
|
@ -72,6 +77,88 @@ export function useDSA() {
|
|||
activeAccount.value = account;
|
||||
}
|
||||
|
||||
async function fethAuthorities() {
|
||||
try {
|
||||
const accountsResolverInstance = new web3.value.eth.Contract(
|
||||
abis.resolver.accounts as AbiItem[],
|
||||
addresses[networkName.value].resolver.accounts
|
||||
);
|
||||
const rawData = await accountsResolverInstance.methods
|
||||
.getAccountAuthorities(activeAccount.value.address)
|
||||
.call();
|
||||
|
||||
authorities.value = rawData;
|
||||
} catch (error) {}
|
||||
}
|
||||
|
||||
async function createAuthority(newAuthority: string) {
|
||||
try {
|
||||
if (!newAuthority) {
|
||||
return;
|
||||
}
|
||||
|
||||
const owners = authorities.value.map(x => x.toLowerCase());
|
||||
|
||||
if (owners.includes(newAuthority.toLowerCase())) {
|
||||
showWarning("Create Authority", "Account is already an owner!");
|
||||
return;
|
||||
}
|
||||
creatingAuthority.value = true;
|
||||
|
||||
const spells = dsa.value.Spell();
|
||||
|
||||
spells.add({
|
||||
connector: "authority",
|
||||
method: "add",
|
||||
args: [newAuthority]
|
||||
});
|
||||
|
||||
const transactionHash = await dsa.value.cast({
|
||||
spells,
|
||||
from: account.value
|
||||
});
|
||||
|
||||
creatingAuthority.value = false;
|
||||
|
||||
fethAuthorities();
|
||||
|
||||
return transactionHash;
|
||||
} catch (error) {
|
||||
creatingAuthority.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function removeAuthority(authority) {
|
||||
try {
|
||||
if (authorities.value.length <= 1) {
|
||||
showWarning("Remove Authority", "Cannot remove all authorities!");
|
||||
return;
|
||||
}
|
||||
removingAuthority.value = true;
|
||||
|
||||
const spells = dsa.value.Spell();
|
||||
|
||||
spells.add({
|
||||
connector: "authority",
|
||||
method: "remove",
|
||||
args: [authority]
|
||||
});
|
||||
|
||||
const transactionHash = await dsa.value.cast({
|
||||
spells,
|
||||
from: account.value
|
||||
});
|
||||
|
||||
removingAuthority.value = false;
|
||||
|
||||
fethAuthorities();
|
||||
|
||||
return transactionHash;
|
||||
} catch (error) {
|
||||
removingAuthority.value = false;
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
dsa,
|
||||
activeAccount: readonly(activeAccount),
|
||||
|
@ -80,6 +167,11 @@ export function useDSA() {
|
|||
creatingAccount,
|
||||
setAccount,
|
||||
web3,
|
||||
chainId
|
||||
chainId,
|
||||
authorities,
|
||||
createAuthority,
|
||||
creatingAuthority,
|
||||
removeAuthority,
|
||||
removingAuthority
|
||||
};
|
||||
}
|
||||
|
|
|
@ -107,14 +107,14 @@ export function useFormatting() {
|
|||
return formatter.format(value);
|
||||
}
|
||||
|
||||
function shortenHash(hash: any) {
|
||||
function shortenHash(hash: any, size = 4) {
|
||||
if (!hash) return;
|
||||
|
||||
if (hash.length < 12) return hash;
|
||||
|
||||
const beginningChars = hash.startsWith("0x") ? 6 : 4;
|
||||
const beginningChars = hash.startsWith("0x") ? size + 2 : size;
|
||||
|
||||
const shortened = hash.substr(0, beginningChars) + "…" + hash.substr(-4);
|
||||
const shortened = hash.substr(0, beginningChars) + "…" + hash.substr(-size);
|
||||
|
||||
return shortened;
|
||||
}
|
||||
|
|
|
@ -23,12 +23,18 @@ export function useModal() {
|
|||
|
||||
const isShown = computed(() => !!modal.value);
|
||||
|
||||
function showComponent(component, componentProps = {}) {
|
||||
modal.value = component;
|
||||
props.value = componentProps;
|
||||
}
|
||||
|
||||
return {
|
||||
showNetworksMismatchDialog,
|
||||
close,
|
||||
closePersistent,
|
||||
isShown,
|
||||
modal: computed(() => modal.value),
|
||||
props: computed(() => props.value)
|
||||
props: computed(() => props.value),
|
||||
showComponent
|
||||
};
|
||||
}
|
||||
|
|
|
@ -43,7 +43,7 @@
|
|||
|
||||
<NotificationBar />
|
||||
|
||||
<div class="fixed bottom-0 right-0 mr-10 mb-40">
|
||||
<div class="fixed bottom-0 right-0 mr-10 mb-28">
|
||||
<button
|
||||
@click="showSidebarBalances"
|
||||
class="px-9 h-[56px] bg-primary-blue-dark hover:bg-primary-blue-hover text-white rounded-[28px] text-lg font-semibold shadow flex items-center"
|
||||
|
|
|
@ -55,18 +55,20 @@
|
|||
<div class="text-semibold text-sm text-grey-dark uppercase">
|
||||
#{{ activeAccount.id }}
|
||||
</div>
|
||||
<div v-if="false" class="mt-3 text-2xl font-semibold">Account Name</div>
|
||||
<div class="hidden mt-3 text-2xl font-semibold">Account Name</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div class="font-medium text-lg">
|
||||
Account address
|
||||
</div>
|
||||
<div class="mt-4 text-lg font-medium text-grey-dark flex items-center">
|
||||
<div
|
||||
class="mt-4 text-lg font-medium text-grey-dark flex items-center"
|
||||
>
|
||||
{{ activeAccount.address }}
|
||||
|
||||
<button
|
||||
class="ml-3"
|
||||
class="ml-3"
|
||||
v-tooltip.bottom="tooltip"
|
||||
v-clipboard:copy="activeAccount.address"
|
||||
v-clipboard:success="onCopy"
|
||||
|
@ -101,43 +103,108 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mt-12 hidden">
|
||||
<h3 class="text-semibold text-sm text-primary-gray-dark uppercase">
|
||||
Authorities
|
||||
</h3>
|
||||
<div class="mt-12">
|
||||
<div class="flex justify-between items-center">
|
||||
<h3 class="text-semibold text-sm text-primary-gray uppercase">
|
||||
Authorities
|
||||
</h3>
|
||||
|
||||
<ButtonCTA @click="addAuthority" class="h-8 w-52 text-xs uppercase font-semibold">
|
||||
Add authority
|
||||
</ButtonCTA>
|
||||
</div>
|
||||
|
||||
<div
|
||||
class="mt-4 p-8 border border-[#DBE5F4] rounded-[2px] grid grid-cols-1 md:grid-cols-2 gap-x-4 gap-y-6"
|
||||
>
|
||||
<div
|
||||
v-for="authority in authorities"
|
||||
:key="authority"
|
||||
class="border border-[#DBE5F4] text-[#9FB0C9] rounded-[2px] flex items-center px-6 py-7"
|
||||
>
|
||||
<div>
|
||||
<svg
|
||||
width="16"
|
||||
height="18"
|
||||
viewBox="0 0 16 18"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
>
|
||||
<path
|
||||
d="M8 9C10.525 9 12.5714 6.98555 12.5714 4.5C12.5714 2.01445 10.525 0 8 0C5.475 0 3.42857 2.01445 3.42857 4.5C3.42857 6.98555 5.475 9 8 9ZM11.4214 10.1461L9.71429 16.875L8.57143 12.0938L9.71429 10.125H6.28571L7.42857 12.0938L6.28571 16.875L4.57857 10.1461C2.03214 10.2656 0 12.3152 0 14.85V16.3125C0 17.2441 0.767857 18 1.71429 18H14.2857C15.2321 18 16 17.2441 16 16.3125V14.85C16 12.3152 13.9679 10.2656 11.4214 10.1461Z"
|
||||
fill="#9FB0C9"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
<a
|
||||
:href="`${addressDetailsLink}/${authority}`"
|
||||
target="_blank"
|
||||
class="hover:underline flex-1 text-center font-medium text-lg text-primary-black truncate px-4"
|
||||
>
|
||||
{{ shortenHash(authority, 16) }}
|
||||
</a>
|
||||
<button @click="deleteAuthority(authority)">
|
||||
<Icon name="trash" class="w-5"></Icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import { defineComponent, watch } from "@nuxtjs/composition-api";
|
||||
import ButtonCTA from "~/components/common/input/ButtonCTA.vue";
|
||||
import RemoveAuthorityDialog from "~/components/modal/authority/RemoveAuthorityDialog.vue";
|
||||
import AddAuthorityDialog from "~/components/modal/authority/AddAuthorityDialog.vue";
|
||||
import { useBalances } from "~/composables/useBalances";
|
||||
import { useCopiedToClipboardUx } from "~/composables/useCopiedToClipboardUx";
|
||||
import { useDSA } from "~/composables/useDSA";
|
||||
import { useFormatting } from "~/composables/useFormatting";
|
||||
import { useLink } from "~/composables/useLink";
|
||||
import { useModal } from "~/composables/useModal";
|
||||
|
||||
export default defineComponent({
|
||||
components: {},
|
||||
components: { ButtonCTA },
|
||||
setup() {
|
||||
const {
|
||||
accounts,
|
||||
activeAccount,
|
||||
setAccount,
|
||||
createAccount,
|
||||
creatingAccount
|
||||
creatingAccount,
|
||||
authorities
|
||||
} = useDSA();
|
||||
const { shortenHash } = useFormatting();
|
||||
const { fetchBalances } = useBalances();
|
||||
const { onCopy, tooltip, copied } = useCopiedToClipboardUx();
|
||||
const { addressDetailsLink } = useLink();
|
||||
const { showComponent } = useModal();
|
||||
|
||||
watch(activeAccount, val => val && fetchBalances(true));
|
||||
|
||||
const deleteAuthority = (authority: string) => {
|
||||
showComponent(RemoveAuthorityDialog, { authority });
|
||||
};
|
||||
|
||||
const addAuthority = () => {
|
||||
showComponent(AddAuthorityDialog);
|
||||
};
|
||||
|
||||
return {
|
||||
addressDetailsLink,
|
||||
shortenHash,
|
||||
accounts,
|
||||
activeAccount,
|
||||
setAccount,
|
||||
createAccount,
|
||||
creatingAccount,
|
||||
authorities,
|
||||
onCopy,
|
||||
tooltip,
|
||||
copied
|
||||
copied,
|
||||
deleteAuthority,
|
||||
addAuthority,
|
||||
};
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue
Block a user