Skip to content

Commit

Permalink
initial setup of activity log listener and store. (#153)
Browse files Browse the repository at this point in the history
closes #132

---------

Co-authored-by: Claire Olmstead <[email protected]>
Co-authored-by: Wil Wade <[email protected]>
  • Loading branch information
3 people authored Mar 20, 2024
1 parent e12ab77 commit d263d30
Show file tree
Hide file tree
Showing 43 changed files with 556 additions and 693 deletions.
2 changes: 1 addition & 1 deletion src/app.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<link rel="apple-touch-icon" sizes="180x180" href="%sveltekit.assets%/apple-touch-icon.png?v=1" />
<link rel="icon" type="image/png" sizes="32x32" href="%sveltekit.assets%/favicon-32x32.png?v=1" />
<link rel="icon" type="image/png" sizes="16x16" href="%sveltekit.assets%/favicon-16x16.png?v=1" />
Expand Down
28 changes: 22 additions & 6 deletions src/components/ActivityLogPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,9 +1,25 @@
<script lang="ts">
import ActivityLogPreviewItem from './ActivityLogPreviewItem.svelte';
import { activityLog } from '$lib/stores/activityLogStore';
import type { Activity } from '$lib/storeTypes';
let recentActivityItem: Activity;
$: {
recentActivityItem = $activityLog[0];
}
</script>

<!-- TODO: Connect activities -->
<div></div>
<!-- <div class="min-w-[300px] border-l border-divider pl-5">
<div class="label border-b border-divider pb-5">Activity Log</div>
<div class="border-b border-divider py-2 text-sm">Activity_Log_Preview</div>
</div> -->
<div class="flex flex-col">
<div class="min-w-[300px] border-l border-divider pl-5" />
<div class="label border-b border-divider pb-3">Activity Log</div>

{#if recentActivityItem}
<ActivityLogPreviewItem activity={recentActivityItem} />
<a href="/activity-log" class="mt-4 self-end">
<button class="btn-primary">See all activity</button>
</a>
{:else}
<div class="py-2 text-sm">No activity.</div>
{/if}
</div>
27 changes: 27 additions & 0 deletions src/components/ActivityLogPreviewItem.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<script lang="ts">
import SuccessIcon from '$lib/assets/SuccessIcon.svelte';
import LoadingIcon from '$lib/assets/LoadingIcon.svelte';
import FailureIcon from '$lib/assets/FailureIcon.svelte';
import { TxnStatus, type Activity } from '$lib/storeTypes';
export let activity: Activity;
</script>

<div class="break-anywhere flex gap-2 text-wrap border-b border-divider py-2 text-sm">
{#if activity.txnStatus === TxnStatus.LOADING}
<LoadingIcon />
{:else if activity.txnStatus === TxnStatus.SUCCESS}
<SuccessIcon />
{:else if activity.txnStatus === TxnStatus.FAILURE}
<FailureIcon />
{/if}

<div class="text-wrap break-words">
<div>Hash: {activity.txnId}</div>
<ul class="unordered-list break-words text-sm">
{#each activity.txnStatusItems as item}
<li>{item}</li>
{/each}
</ul>
</div>
</div>
84 changes: 13 additions & 71 deletions src/components/AddControlKey.svelte
Original file line number Diff line number Diff line change
@@ -1,98 +1,41 @@
<script lang="ts">
import { dotApi } from '$lib/stores';
import type { ApiPromise } from '@polkadot/api';
import { submitAddControlKey, type SigningKey, type TxnFinishedCallback } from '$lib/connections';
import { onMount } from 'svelte';
import { isFunction } from '@polkadot/util';
import { isLocalhost } from '$lib/utils';
import TransactionStatus from './TransactionStatus.svelte';
import { submitAddControlKey } from '$lib/connections';
import { getExtension } from '$lib/utils';
import AddKeyRequirements from './AddKeyRequirements.svelte';
import Modal from './Modal.svelte';
import DropDownMenu from './DropDownMenu.svelte';
import type { web3Enable, web3FromSource } from '@polkadot/extension-dapp';
import { user } from '$lib/stores/userStore';
import { type Account, unusedKeyAccountsStore } from '$lib/stores/accountsStore';
import { formatAccount } from '$lib/utils';
export let isOpen: boolean;
export let close: () => void;
export let txnFinished: TxnFinishedCallback = (succeeded: boolean) => {};
export let txnStatuses: Array<string> = [];
let selectedAccount: Account | null;
let thisWeb3FromSource: typeof web3FromSource;
let thisWeb3Enable: typeof web3Enable;
let showTransactionStatus = false;
$: isSubmitDisabled = selectedAccount?.signingKey == null || showTransactionStatus;
onMount(async () => {
const extension = await import('@polkadot/extension-dapp');
thisWeb3FromSource = extension.web3FromSource;
thisWeb3Enable = extension.web3Enable;
});
const addNewTxnStatus = (txnStatus: string) => {
txnStatuses = [...txnStatuses, txnStatus];
};
const clearTxnStatuses = () => (txnStatuses = new Array<string>());
$: isSubmitDisabled = selectedAccount?.injectedAccount == null;
const addControlKey = async () => {
clearTxnStatuses();
let endpointURI: string = $dotApi.selectedEndpoint || '';
if (!selectedAccount || !selectedAccount.signingKey) {
if (!selectedAccount || !selectedAccount.injectedAccount) {
alert('Please choose a key to add.');
} else if (!$user.msaId || !$user.signingKey) {
} else if (!$user.msaId || !$user.injectedAccount) {
alert('Invalid provider.');
} else {
let newKeys: SigningKey = selectedAccount.signingKey;
let signingKeys: SigningKey = $user.signingKey;
showTransactionStatus = true;
if (isLocalhost(endpointURI)) {
await submitAddControlKey(
$dotApi.api as ApiPromise,
undefined,
newKeys,
signingKeys,
$user.msaId,
endpointURI as string,
addNewTxnStatus,
txnFinished
);
} else {
if (isFunction(thisWeb3FromSource) && isFunction(thisWeb3Enable)) {
const extensions = await thisWeb3Enable('Frequency parachain provider dashboard: Adding Keys');
if (extensions.length !== 0) {
const injectedExtension = await thisWeb3FromSource(signingKeys.meta.source!);
await submitAddControlKey(
$dotApi.api as ApiPromise,
injectedExtension,
newKeys,
signingKeys,
$user.msaId,
endpointURI as string,
addNewTxnStatus,
txnFinished
);
} else {
console.error('found no extensions');
return;
}
} else {
console.error('web3FromSource is function? ', isFunction(thisWeb3FromSource));
console.error('web3Enable is function? ', isFunction(thisWeb3Enable));
}
}
close();
await submitAddControlKey(
$dotApi.api as ApiPromise,
await getExtension($user),
selectedAccount,
$user,
$user.msaId
);
}
};
function onCancel() {
selectedAccount = null;
showTransactionStatus = false;
close();
}
</script>
Expand Down Expand Up @@ -127,6 +70,5 @@
<span class="border-1 border-b border-divider" />

<AddKeyRequirements />
<TransactionStatus bind:showSelf={showTransactionStatus} statuses={txnStatuses} />
</svelte:fragment>
</Modal>
26 changes: 8 additions & 18 deletions src/components/BecomeAProvider.svelte
Original file line number Diff line number Diff line change
@@ -1,49 +1,39 @@
<script lang="ts">
import { user } from '$lib/stores/userStore';
import { nonProviderAccountsStore, type Account } from '$lib/stores/accountsStore';
import { nonProviderAccountsStore } from '$lib/stores/accountsStore';
import BlockSection from './BlockSection.svelte';
import SelectNetworkAndAccount from './SelectNetworkAndAccount.svelte';
import CreateMsa from './CreateMsa.svelte';
import CreateProvider from './CreateProvider.svelte';
import EmailProviderRequest from './EmailProviderRequest.svelte';
import { pageContent } from '$lib/stores/pageContentStore';
let newUser: Account | undefined;
// a callback for when the user cancels this action
export let cancelAction = () => {
pageContent.login();
};
function updateUser() {
if (!newUser) {
alert('Invalid form values');
return;
}
$user = newUser;
}
</script>

<div id="become-a-provider" class="content-block column w-single-block">
<BlockSection title="Become a Provider">
<form class="column w-[320px]">
<SelectNetworkAndAccount
bind:newUser
bind:newUser={$user}
accounts={$nonProviderAccountsStore}
accountSelectorTitle="Wallet Address"
accountSelectorPlaceholder="Select a wallet address"
noAccountsFoundErrorMsg="No accounts found. Add an account to your wallet."
/>
{#if newUser?.network != null && newUser.network.name === 'MAINNET'}
{#if $user?.network != null && $user.network.name === 'MAINNET'}
<EmailProviderRequest />
{:else if newUser && newUser?.address !== ''}
{#if newUser?.msaId === 0}
<CreateMsa beforeCreate={updateUser} />
{:else if $user && $user?.address !== ''}
{#if $user?.msaId === 0}
<CreateMsa />
{:else}
<CreateProvider beforeCreate={updateUser} />
<CreateProvider />
{/if}
{:else}
<button on:click|preventDefault={cancelAction} class="btn-no-fill text-left">Cancel</button>
<button on:click|preventDefault={cancelAction} class="btn-no-fill text-left">Back</button>
{/if}
</form>
</BlockSection>
Expand Down
4 changes: 2 additions & 2 deletions src/components/Capacity.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
let errMsg: string = '';
$: {
if (!$user.signingKey) {
if (!$user.injectedAccount) {
errMsg = 'No transaction signing address selected';
} else if (!$user.msaId) {
errMsg = 'No MSA ID. Please create one.';
Expand All @@ -37,5 +37,5 @@

<ListCard title="Capacity" list={capacityList} errorMessage={errMsg}>
<button on:click|preventDefault={() => (showStakeToProvider = true)} class="btn-primary">Stake to Provider</button>
<Stake providerId={$user.msaId} isOpen={showStakeToProvider} close={() => (showStakeToProvider = false)} />
<Stake isOpen={showStakeToProvider} close={() => (showStakeToProvider = false)} />
</ListCard>
96 changes: 40 additions & 56 deletions src/components/CreateMsa.svelte
Original file line number Diff line number Diff line change
@@ -1,79 +1,55 @@
<script lang="ts">
import type { web3Enable, web3FromSource } from '@polkadot/extension-dapp';
import { dotApi } from '$lib/stores';
import type { MsaInfo } from '$lib/storeTypes';
import { TxnStatus, type Activity, type MsaInfo } from '$lib/storeTypes';
import type { ApiPromise } from '@polkadot/api';
import { isLocalhost } from '$lib/utils';
import { submitCreateMsa, type TxnFinishedCallback } from '$lib/connections';
import TransactionStatus from '$components/TransactionStatus.svelte';
import { isFunction } from '@polkadot/util';
import { onMount } from 'svelte';
import { getExtension } from '$lib/utils';
import { submitCreateMsa } from '$lib/connections';
import { user } from '$lib/stores/userStore';
import { getMsaInfo } from '$lib/polkadotApi';
import { pageContent } from '$lib/stores/pageContentStore';
import LoadingIcon from '$lib/assets/LoadingIcon.svelte';
import ActivityLogPreviewItem from './ActivityLogPreviewItem.svelte';
import { activityLog } from '$lib/stores/activityLogStore';
export let beforeCreate: () => Promise<void>;
export let txnStatuses: Array<string> = [];
// a callback for when the user cancels this action
export let cancelAction = () => {
pageContent.login();
};
let recentActivityItem: Activity | undefined;
let recentTxnId: Activity['txnId'] | undefined;
let isInProgress = false;
// a callback for when a transaction hits a final state
export let txnFinished: TxnFinishedCallback = async (succeeded: boolean) => {
let createMsaTxnFinished = async (succeeded: boolean) => {
if (succeeded) {
const apiPromise = $dotApi.api as ApiPromise;
const msaInfo: MsaInfo = await getMsaInfo(apiPromise, $user.address);
$user.msaId = msaInfo.msaId;
}
};
let thisWeb3FromSource: typeof web3FromSource;
let thisWeb3Enable: typeof web3Enable;
let showTransactionStatus = false;
onMount(async () => {
const extension = await import('@polkadot/extension-dapp');
thisWeb3FromSource = extension.web3FromSource;
thisWeb3Enable = extension.web3Enable;
});
const doCreateMsa = async (_evt: Event) => {
await beforeCreate();
const endpoint: string | undefined = $user.network?.endpoint;
if (!endpoint) {
alert('Error connecting to endpoint.');
isInProgress = false;
setTimeout(() => {
$user.msaId = msaInfo.msaId;
}, 1500);
return;
}
isInProgress = false;
};
clearTxnStatuses();
showTransactionStatus = true;
const apiPromise = $dotApi.api as ApiPromise;
if (isLocalhost(endpoint)) {
await submitCreateMsa(apiPromise, undefined, endpoint, $user.signingKey!, addNewTxnStatus, txnFinished);
} else {
if (isFunction(thisWeb3FromSource) && isFunction(thisWeb3Enable)) {
const extensions = await thisWeb3Enable('Frequency parachain provider dashboard: Creating provider');
if (extensions.length !== 0) {
const injectedExtension = await thisWeb3FromSource($user.signingKey!.meta.source!);
await submitCreateMsa(
apiPromise,
injectedExtension,
endpoint,
$user.signingKey!,
addNewTxnStatus,
txnFinished
);
}
}
const checkIsFinished = async () => {
if (recentActivityItem && recentActivityItem.txnStatus !== TxnStatus.LOADING) {
await createMsaTxnFinished(recentActivityItem.txnStatus === TxnStatus.SUCCESS);
}
};
const addNewTxnStatus = (txnStatus: string) => {
txnStatuses = [...txnStatuses, txnStatus];
return;
$: {
recentActivityItem = $activityLog.find((value) => value.txnId === recentTxnId);
checkIsFinished();
}
const doCreateMsa = async (_evt: Event) => {
isInProgress = true;
recentTxnId = await submitCreateMsa($dotApi.api, await getExtension($user), $user);
recentActivityItem = $activityLog.find((value) => value.txnId === recentTxnId);
};
const clearTxnStatuses = () => (txnStatuses = new Array<string>());
</script>

<div id="create-msa" class="flex flex-col gap-3.5 text-sm">
Expand All @@ -83,8 +59,16 @@
controlled by the selected Transaction Signing Address above. It is available only on Frequency Testnet.
</p>
<form class="flex w-[350px] items-end justify-between">
<button id="create-msa-btn" on:click|preventDefault={doCreateMsa} class="btn-primary">Create an MSA</button>
<button id="create-msa-btn" on:click|preventDefault={doCreateMsa} disabled={isInProgress} class="btn-primary">
{#if isInProgress}
<LoadingIcon />
{:else}
Create an MSA
{/if}
</button>
<button on:click|preventDefault={cancelAction} class="btn-no-fill">Cancel</button>
</form>
</div>
<TransactionStatus bind:showSelf={showTransactionStatus} statuses={txnStatuses} />
{#if recentActivityItem}
<ActivityLogPreviewItem activity={recentActivityItem} />
{/if}
Loading

0 comments on commit d263d30

Please sign in to comment.