Skip to content

Commit

Permalink
updated transaction UI flow verify
Browse files Browse the repository at this point in the history
  • Loading branch information
zlayine committed Aug 7, 2023
1 parent cf01b89 commit 0621b68
Show file tree
Hide file tree
Showing 9 changed files with 142 additions and 34 deletions.
26 changes: 23 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
"@polkadot/api": "^10.9.1",
"@polkadot/keyring": "^12.3.2",
"@polkadot/types": "^10.9.1",
"@polkadot/ui-shared": "^3.5.1",
"@polkadot/util": "^12.3.2",
"@polkadot/util-crypto": "^10.4.2",
"@tailwindcss/forms": "^0.5.3",
Expand Down
30 changes: 30 additions & 0 deletions resources/js/components/Identicon.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<template>
<div class="relative">
<svg :height="44" viewBox="0 0 64 64" :width="44">
<circle
v-for="(circle, index) in circles"
:key="index"
:cx="circle.cx"
:cy="circle.cy"
:fill="circle.fill"
:r="circle.r"
/>
</svg>
</div>
</template>

<script setup>
import { polkadotIcon } from '@polkadot/ui-shared';
import { ref, h } from 'vue';
const props = defineProps({
address: {
type: String,
required: true,
},
});
const circles = polkadotIcon(props.address, {
isAlternative: false,
}).map(({ cx, cy, fill, r }) => ({ cx, cy, fill, r }));
</script>
24 changes: 18 additions & 6 deletions resources/js/components/SignTransaction.vue
Original file line number Diff line number Diff line change
@@ -1,20 +1,26 @@
<template>
<Btn primary @click="signTransaction()" class="ml-3">
<Btn primary @click="signTransaction" class="px-8" :disabled="isLoading">
<LoadingCircle v-if="isLoading" class="h-5 w-5 mx-1 ml-0.5 text-white" />
<span v-else> Sign </span>
</Btn>
<Modal :is-open="showAccountsModal" :close="closeModal" width="max-w-lg">
<DialogTitle as="h3" class="text-lg font-medium leading-6 text-gray-900 text-center">
Select Account
Select an account to sign
</DialogTitle>
<div class="flex flex-col space-y-2 mt-4">
<div
v-for="account in useAppStore().accounts"
:key="account.address"
class="px-4 py-3 border border-gray-300 rounded-md text-sm cursor-pointer hover:bg-primary/20 transition-all"
class="px-4 py-3 border border-gray-300 rounded-md cursor-pointer hover:bg-primary/20 transition-all flex items-center space-x-4"
@click="selectAccount(account)"
>
{{ publicKeyToAddress(account.address) }}
<Identicon :address="account.address" />
<div class="flex flex-col">
<span class="font-medium">{{ account.name }} </span>
<span class="text-sm">
{{ addressShortHex(account.address) }}
</span>
</div>
</div>
</div>
</Modal>
Expand All @@ -24,16 +30,19 @@
import { DialogTitle } from '@headlessui/vue';
import Btn from './Btn.vue';
import Modal from './Modal.vue';
import { publicKeyToAddress } from '~/util/address';
import { addressShortHex } from '~/util/address';
import { useAppStore } from '~/store';
import { ref } from 'vue';
import LoadingCircle from './LoadingCircle.vue';
import snackbar from '~/util/snackbar';
import Identicon from './Identicon.vue';
const props = defineProps<{
transaction: any;
}>();
const emit = defineEmits(['success']);
const isLoading = ref(false);
const showAccountsModal = ref(false);
Expand All @@ -51,7 +60,10 @@ const selectAccount = async (account) => {
isLoading.value = true;
useAppStore().setAccount(account);
showAccountsModal.value = false;
await useAppStore().signTransaction(props.transaction);
const res = await useAppStore().signTransaction(props.transaction);
if (res) {
emit('success');
}
} catch (e) {
snackbar.error({ title: 'Failed to sign transaction' });
} finally {
Expand Down
9 changes: 7 additions & 2 deletions resources/js/components/Slideover.vue
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,12 @@
>
<DialogPanel class="pointer-events-auto w-screen max-w-xs md:max-w-lg transition-all">
<div ref="initialFocusRef"></div>
<component :is="component" @close="emit('close')" :item="item" />
<component
:is="component"
:item="item"
@close="emit('close')"
@update="($event) => emit('update', $event)"
/>
</DialogPanel>
</TransitionChild>
</div>
Expand All @@ -30,7 +35,7 @@
import { Dialog, DialogPanel, TransitionChild, TransitionRoot } from '@headlessui/vue';
import { defineAsyncComponent, shallowRef, watch } from 'vue';
const emit = defineEmits(['close']);
const emit = defineEmits(['close', 'update']);
const component = shallowRef();
const initialFocusRef = shallowRef();
Expand Down
5 changes: 1 addition & 4 deletions resources/js/components/WalletConnectButton.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,6 @@
</MenuItems>
</ScaleTransition>
</Menu>

</template>

<script setup lang="ts">
Expand Down Expand Up @@ -90,8 +89,7 @@ const getSession = async () => {
try {
loading.value = true;
await appStore.getSession();
} catch (e){
console.log(e)
} catch (e) {
snackbar.error({ title: 'Failed to get session' });
} finally {
loading.value = false;
Expand All @@ -104,7 +102,6 @@ const disconnectWallet = async () => {
loading.value = false;
};
(async () => {
getSession();
})();
Expand Down
51 changes: 44 additions & 7 deletions resources/js/components/pages/Transactions.vue
Original file line number Diff line number Diff line change
Expand Up @@ -105,10 +105,6 @@
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
{{ transaction.state }}
<SignTransaction
v-if="transaction.state === 'PENDING'"
:transaction="transaction"
/>
</td>
<td class="whitespace-nowrap px-3 py-4 text-sm text-gray-500">
<TransactionResultChip v-if="transaction.result" :text="transaction.result" />
Expand All @@ -117,12 +113,23 @@
class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-3 flex justify-end"
>
<Btn
v-if="transaction.transactionId"
v-if="
transaction.transactionId ||
transaction.state === TransactionState.BROADCAST
"
primary
@click="openModalSlide('DetailsTransactionSlideover', transaction)"
>
{{ transaction.transactionId }}
<span v-if="transaction.transactionId">
{{ transaction.transactionId }}
</span>
<LoadingCircle v-else class="h-5 w-5 mx-5 text-white" />
</Btn>
<SignTransaction
v-if="transaction.state === TransactionState.PENDING"
:transaction="transaction"
@success="onSuccess(transaction.id)"
/>
</td>
</tr>
</tbody>
Expand All @@ -134,7 +141,7 @@
<div ref="paginatorRef"></div>
</div>
</div>
<Slideover :open="modalSlide" @close="closeModalSlide" :item="slideComponent" />
<Slideover :open="modalSlide" @close="closeModalSlide" :item="slideComponent" @update="updateTransaction" />
</div>
</template>

Expand Down Expand Up @@ -285,6 +292,36 @@ const getSearchInputs = () => {
return inputs;
};
const onSuccess = async (id) => {
const res = await getTransaction(id);
transactions.value.items.map((p) => {
if (p.id === id) {
p.state = res.state;
p.result = res.result;
p.transactionId = res.transactionId;
}
return p;
});
};
const getTransaction = async (id) => {
const res = await TransactionApi.getTransaction(id);
return res.data.GetTransaction;
};
const updateTransaction = (transaction) => {
transactions.value.items.map((p) => {
if (p.id === transaction.id) {
p.state = transaction.state;
p.result = transaction.result;
p.transactionId = transaction.transactionId;
}
return p;
});
};
const getTransactions = async () => {
try {
isLoading.value = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
<template>
<div class="flex h-full flex-col divide-y divide-gray-200 bg-white shadow-xl">
<h3 class="text-xl font-semibold px-4 sm:px-6 py-4 text-gray-900">
Transaction Details for {{ item?.transactionId }}
Transaction Details for {{ item?.transactionId ?? item?.id }}
</h3>
<div class="h-0 flex-1 overflow-y-auto">
<div class="flex flex-1 flex-col justify-between">
<div class="px-4 sm:px-6 divide-y divide-gray-200">
<div v-if="!item?.id">
<div>
<div v-if="!webSocketEvents && !transaction?.state">
<LoadingCircle :size="40" class="pt-10" />
<p class="text-center pt-2">Waiting for transaction...</p>
Expand All @@ -30,6 +30,9 @@
>
Get More Transaction Details
</Btn>
<div class="text-xs text-center mx-auto mt-4">
Usually it takes few seconds to finilize the transaction
</div>
</div>
</div>

Expand Down Expand Up @@ -145,6 +148,8 @@ const props = withDefaults(
}
);

const emit = defineEmits(['update']);

const appStore = useAppStore();

const isLoading = ref(false);
Expand All @@ -160,11 +165,13 @@ const isAddressKey = (key) => ['who', 'operator', 'account', 'owner'].includes(k

const getTransaction = async () => {
try {
if (!props.item?.transactionId) return;
isLoading.value = true;
const res = await TransactionApi.getTransaction(props.item.transactionId);
const res = await TransactionApi.getTransaction(props.item?.transactionId ?? props.item?.id ?? '');
const transactionData = res.data.GetTransaction;
transaction.value = transactionData;
if (transactionData.state === TransactionState.FINALIZED) {
emit('update', transactionData);
}
} catch (error) {
// Do notihing
}
Expand Down
15 changes: 7 additions & 8 deletions resources/js/store/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import { ApiPromise, WsProvider } from '@polkadot/api';
import { SignerPayloadJSON } from '@polkadot/types/types';
import { AccountInfoWithTripleRefCount } from '@polkadot/types/interfaces';
import { TransactionApi } from '~/api/transaction';
import router from '~/router';

const RPC_URLS = {
canary: 'wss://rpc.matrix.canary.enjin.io',
Expand Down Expand Up @@ -57,19 +56,17 @@ const updateTransaction = async ({
snackbar.success({
title: 'Transaction signed',
text: `The transaction was signed successfully`,
event: id,
});

// TODO: There is probably a better way to refresh it
setTimeout(() => router.go(0), 1000);

return;
return true;
}

snackbar.error({
title: 'Sign Transaction',
text: 'Signing transaction failed',
});

return false;
} catch (e) {
if (snackbarErrors(e)) return;
snackbar.error({
Expand Down Expand Up @@ -143,7 +140,6 @@ export const useAppStore = defineStore('app', {

return true;
} catch (error: any) {
console.log(error);
snackbar.error({ title: error });
}

Expand Down Expand Up @@ -330,6 +326,7 @@ export const useAppStore = defineStore('app', {
const pkjs = new PolkadotjsWallet();
if (pkjs.installed) {
await pkjs.enable('Platform');
this.wallet = true;
this.provider = 'polkadot.js';
}
},
Expand Down Expand Up @@ -375,7 +372,7 @@ export const useAppStore = defineStore('app', {
extrinsic.addSignature(this.account.address, signature, payloadToSign);

const transactionHash = await api.rpc.author.submitExtrinsic(extrinsic.toHex());
await updateTransaction({
return await updateTransaction({
id: transaction.id,
transactionHash: transactionHash.toHex(),
signingAccount: this.account.address,
Expand All @@ -397,9 +394,11 @@ export const useAppStore = defineStore('app', {
}

this.account = null;
this.wallet = false;
this.provider = '';
} catch {
this.account = null;
this.wallet = false;
this.provider = '';
}
},
Expand Down

0 comments on commit 0621b68

Please sign in to comment.