Skip to content

Commit

Permalink
refactor: move invites vuex state to composable
Browse files Browse the repository at this point in the history
  • Loading branch information
peronczyk committed Oct 10, 2023
1 parent 815ce5e commit 18ea987
Show file tree
Hide file tree
Showing 11 changed files with 140 additions and 86 deletions.
1 change: 1 addition & 0 deletions src/composables/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from './copy';
export * from './connection';
export * from './currencies';
export * from './deepLinkApi';
export * from './invites';
export * from './latestTransactionList';
export * from './maxAmount';
export * from './middleware';
Expand Down
93 changes: 93 additions & 0 deletions src/composables/invites.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import {
AE_AMOUNT_FORMATS,
AeSdk,
Encoded,
Node,
} from '@aeternity/aepp-sdk';
import type { IInvite } from '@/types';
import { STORAGE_KEYS } from '@/constants';
import { tg } from '@/popup/plugins/i18n';
import { getAccountFromSecret } from '@/protocols/aeternity/helpers';
import migrateInvitesVuexToComposable from '@/migrations/006-invites-vuex-to-composable';
import { useStorageRef } from './storageRef';
import { useModals } from './modals';
import { useNetworks } from './networks';

const invites = useStorageRef<IInvite[]>(
[],
STORAGE_KEYS.invites,
{
migrations: [
migrateInvitesVuexToComposable,
],
},
);

export function useInvites() {
const { activeNetwork } = useNetworks();
const { openDefaultModal } = useModals();

function addInvite(secretKey: Buffer) {
invites.value.unshift({
secretKey: secretKey.toJSON(),
createdAt: Date.now(),
});
}

function removeInvite(secretKey: Buffer) {
invites.value = invites.value.filter((invite) => invite.secretKey !== secretKey);
}

async function claimInvite({
secretKey,
recipientId,
amount = '0',
isMax = false,
}: { secretKey: Buffer; recipientId: Encoded.AccountAddress; amount?: string; isMax: boolean }) {
const aeSdk = new AeSdk({
nodes: [{
name: activeNetwork.value.name,
instance: new Node(activeNetwork.value.protocols.aeternity.nodeUrl),
}],
accounts: [getAccountFromSecret(secretKey)],
});
if (!isMax) {
await aeSdk.spend(
amount,
recipientId,
// @ts-ignore
{ denomination: AE_AMOUNT_FORMATS.AE },
);
} else {
await aeSdk.transferFunds(
1, // Decimal percentage, 1 = 100%
recipientId,
{ verify: false },
);
}
}

async function handleInsufficientBalanceError(error: Error, isInviteError = false) {
if (
(!isInviteError && !error.message.includes('is not enough to execute'))
|| (isInviteError && !error.message.includes('Transaction build error'))
) {
return false;
}

await openDefaultModal({
msg: (isInviteError)
? tg('pages.invite.insufficient-invite-balance')
: tg('pages.invite.insufficient-balance'),
});
return true;
}

return {
invites,
addInvite,
removeInvite,
claimInvite,
handleInsufficientBalanceError,
};
}
1 change: 1 addition & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,7 @@ export const STORAGE_KEYS = {
hiddenCards: 'hidden-cards',
otherSettings: 'other-settings',
errorLog: 'error-log',
invites: 'invites',
} as const;

export const CURRENCIES: ICurrency[] = [
Expand Down
14 changes: 14 additions & 0 deletions src/migrations/006-invites-vuex-to-composable.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import type { IInvite, Migration } from '@/types';
import { collectVuexState } from './migrationHelpers';

const migration: Migration<IInvite[]> = async (restoredValue: IInvite[]) => {
if (!restoredValue?.length) {
const invites = (await collectVuexState())?.invites?.invites;
if (invites?.length) {
return invites;
}
}
return restoredValue;
};

export default migration;
18 changes: 10 additions & 8 deletions src/popup/components/InviteItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -102,10 +102,11 @@ import {
import { ROUTE_INVITE_CLAIM } from '@/popup/router/routeNames';
import {
useAccounts,
useBalances,
useMaxAmount,
useAeSdk,
useBalances,
useCurrencies,
useInvites,
useMaxAmount,
} from '@/composables';
import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
Expand Down Expand Up @@ -134,6 +135,7 @@ export default defineComponent({
const { marketData } = useCurrencies();
const { balance } = useBalances();
const { getAeSdk } = useAeSdk({ store });
const { claimInvite, removeInvite, handleInsufficientBalanceError } = useInvites();
const formModel = ref<IFormModel>({
amount: '',
Expand All @@ -160,7 +162,7 @@ export default defineComponent({
const address = computed(() => getAccountFromSecret(props.secretKey).address);
function deleteItem() {
store.commit('invites/delete', props.secretKey);
removeInvite(props.secretKey);
}
async function updateBalance() {
Expand All @@ -177,14 +179,14 @@ export default defineComponent({
async function claim() {
emit('loading', true);
try {
await store.dispatch('invites/claim', {
await claimInvite({
secretKey: Buffer.from(props.secretKey),
recipientId: getLastActiveProtocolAccount(PROTOCOL_AETERNITY)?.address,
recipientId: getLastActiveProtocolAccount(PROTOCOL_AETERNITY)?.address!,
isMax: true,
});
await updateBalance();
} catch (error) {
if (await store.dispatch('invites/handleNotEnoughFoundsError', { error, isInviteError: true })) {
} catch (error: any) {
if (await handleInsufficientBalanceError(error, true)) {
return;
}
throw error;
Expand Down Expand Up @@ -215,7 +217,7 @@ export default defineComponent({
await updateBalance();
resetTopUpChanges();
} catch (error: any) {
if (await store.dispatch('invites/handleNotEnoughFoundsError', { error })) {
if (await handleInsufficientBalanceError(error)) {
return;
}
throw error;
Expand Down
6 changes: 4 additions & 2 deletions src/popup/components/Modals/ClaimGiftCard.vue
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ import {
useAccounts,
useAeSdk,
useCurrencies,
useInvites,
} from '@/composables';
import { AE_COIN_PRECISION, AE_SYMBOL } from '@/protocols/aeternity/config';
import { getAccountFromSecret } from '@/protocols/aeternity/helpers';
Expand Down Expand Up @@ -167,6 +168,7 @@ export default defineComponent({
const { getAeSdk } = useAeSdk({ store });
const { aeAccounts, aeAccountsSelectOptions } = useAccounts();
const { getFormattedFiat } = useCurrencies();
const { claimInvite } = useInvites();
const recipientId = ref<Encoded.AccountAddress>(aeAccounts.value[0].address);
const amount = ref('');
Expand Down Expand Up @@ -226,15 +228,15 @@ export default defineComponent({
switch (step.value) {
case STEPS.initial:
setMaxAmount();
await store.dispatch('invites/claim', {
await claimInvite({
secretKey: props.secretKey,
recipientId: recipientId.value,
isMax: true,
});
step.value = STEPS.redeemFull;
break;
case STEPS.form:
await store.dispatch('invites/claim', {
await claimInvite({
secretKey: props.secretKey,
recipientId: recipientId.value,
amount: amount.value,
Expand Down
17 changes: 9 additions & 8 deletions src/popup/pages/Invite.vue
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,14 @@ import { useStore } from 'vuex';
import type { IFormModel } from '@/types';
import { ProtocolAdapterFactory } from '@/lib/ProtocolAdapterFactory';
import { PROTOCOL_AETERNITY } from '@/constants';
import { useState } from '../../composables/vuex';
import {
useAccounts,
useAeSdk,
useBalances,
useMaxAmount,
useCurrencies,
} from '../../composables';
useInvites,
useMaxAmount,
} from '@/composables';
import AccountInfo from '../components/AccountInfo.vue';
import BalanceInfo from '../components/BalanceInfo.vue';
Expand Down Expand Up @@ -111,6 +111,7 @@ export default defineComponent({
const { marketData } = useCurrencies();
const { getAeSdk } = useAeSdk({ store });
const { balance } = useBalances();
const { invites, addInvite, handleInsufficientBalanceError } = useInvites();
const formModel = ref<IFormModel>({
amount: '',
Expand All @@ -121,8 +122,6 @@ export default defineComponent({
const { max, fee } = useMaxAmount({ formModel, store });
const invites = useState('invites', 'invites');
async function generate() {
loading.value = true;
const { publicKey, secretKey } = generateKeyPair();
Expand All @@ -135,14 +134,16 @@ export default defineComponent({
// @ts-ignore
{ denomination: AE_AMOUNT_FORMATS.AE },
);
} catch (error) {
if (await store.dispatch('invites/handleNotEnoughFoundsError', { error })) return;
} catch (error: any) {
if (await handleInsufficientBalanceError(error)) {
return;
}
throw error;
} finally {
loading.value = false;
}
store.commit('invites/add', Buffer.from(secretKey, 'hex').slice(0, 32));
addInvite(Buffer.from(secretKey, 'hex').slice(0, 32));
formModel.value.amount = '';
}
Expand Down
7 changes: 3 additions & 4 deletions src/popup/pages/InviteClaim.vue
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
<script lang="ts">
import { defineComponent, onMounted } from 'vue';
import { decode } from '@aeternity/aepp-sdk';
import { useStore } from 'vuex';
import { useRouter, useRoute } from 'vue-router';
import { MODAL_CLAIM_GIFT_CARD } from '@/constants';
import { useModals } from '../../composables';
import { useInvites, useModals } from '../../composables';
import { ROUTE_ACCOUNT } from '../router/routeNames';
export default defineComponent({
setup() {
const store = useStore();
const router = useRouter();
const route = useRoute();
const { openDefaultModal, openModal } = useModals();
const { handleInsufficientBalanceError } = useInvites();
onMounted(async () => {
router.push({ name: ROUTE_ACCOUNT });
Expand All @@ -33,7 +32,7 @@ export default defineComponent({
});
return;
}
if (await store.dispatch('invites/handleNotEnoughFoundsError', { error, isInviteError: true })) {
if (await handleInsufficientBalanceError(error, true)) {
return;
}
throw error;
Expand Down
2 changes: 0 additions & 2 deletions src/store/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import namesPlugin from './plugins/names';
import pollAccountInfo from './plugins/pollAccountInfo';
import runMigrations from './migrations';
import accountsModule from './modules/accounts';
import invitesModule from './modules/invites';
import permissionsModule from './modules/permissions';
import fungibleTokensPlugin from './plugins/fungibleTokens';
import stateReducer from './utils';
Expand Down Expand Up @@ -35,7 +34,6 @@ export default new Vuex.Store({
],
modules: {
accounts: accountsModule,
invites: invitesModule,
permissions: permissionsModule,
},
});
62 changes: 0 additions & 62 deletions src/store/modules/invites.js

This file was deleted.

5 changes: 5 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -679,3 +679,8 @@ export interface IFormSelectOption {
}

export type Migration<T = any> = (restoredValue: T | any) => Promise<T>;

export interface IInvite {
secretKey: object;
createdAt: number;
}

0 comments on commit 18ea987

Please sign in to comment.