Skip to content

Commit

Permalink
feat: use accounts machine instead of fetching accounts each time
Browse files Browse the repository at this point in the history
  • Loading branch information
arthurgeron committed Jan 22, 2025
1 parent c0cd4af commit a57bd40
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 87 deletions.
2 changes: 1 addition & 1 deletion packages/app/src/systems/Account/services/account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type AccountInputs = {
};
fetchBalance: {
providerUrl: string;
address: string | undefined;
account?: Maybe<Account>;
};
fetchAccount: {
address: string;
Expand Down
35 changes: 14 additions & 21 deletions packages/app/src/systems/DApp/hooks/useTransactionRequest.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -26,32 +26,26 @@ const selectors = {
proposedTxRequest(state: TransactionRequestState) {
return state.context.response?.proposedTxRequest;
},
isLoadingAccounts(state: TransactionRequestState) {
return state.matches('fetchingAccount');
},
errors(state: TransactionRequestState) {
if (!state.context.errors) return {};
const simulateTxErrors = state.context.errors?.simulateTxErrors;
const hasSimulateTxErrors = Boolean(simulateTxErrors);
const txApproveError = state.context.errors?.txApproveError;
return { txApproveError, simulateTxErrors, hasSimulateTxErrors };
},
status(externalLoading?: boolean) {
return useCallback(
(state: TransactionRequestState) => {
const isLoading = state.hasTag('loading');
const isClosed = state.matches('done') || state.matches('failed');

if (state.matches('idle')) return TxRequestStatus.idle;
if (externalLoading || isLoading) return TxRequestStatus.loading;
if (state.matches('txFailed')) return TxRequestStatus.failed;
if (state.matches('txSuccess')) return TxRequestStatus.success;
if (state.matches('sendingTx')) return TxRequestStatus.sending;
if (isClosed) return TxRequestStatus.inactive;
return TxRequestStatus.waitingApproval;
},
[externalLoading]
);
status() {
return useCallback((state: TransactionRequestState) => {
const isLoading = state.hasTag('loading');
const isClosed = state.matches('done') || state.matches('failed');

if (state.matches('idle')) return TxRequestStatus.idle;
if (isLoading) return TxRequestStatus.loading;
if (state.matches('txFailed')) return TxRequestStatus.failed;
if (state.matches('txSuccess')) return TxRequestStatus.success;
if (state.matches('sendingTx')) return TxRequestStatus.sending;
if (isClosed) return TxRequestStatus.inactive;
return TxRequestStatus.waitingApproval;
}, []);
},
title(state: TransactionRequestState) {
if (state.matches('txSuccess')) return 'Transaction sent';
Expand Down Expand Up @@ -95,12 +89,11 @@ export function useTransactionRequest(opts: UseTransactionRequestOpts = {}) {
},
});

const isLoadingAccounts = useSelector(service, selectors.isLoadingAccounts);
const account = useSelector(service, selectors.account);
const ctx = useSelector(service, selectors.context);
const errors = useSelector(service, selectors.errors);
const providerUrl = ctx.input.providerUrl;
const txStatusSelector = selectors.status(isLoadingAccounts);
const txStatusSelector = selectors.status();
const txStatus = useSelector(service, txStatusSelector);
const title = useSelector(service, selectors.title);
const txSummarySimulated = useSelector(service, selectors.txSummarySimulated);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import type { Account } from '@fuel-wallet/types';
import type { Account, AccountWithBalance } from '@fuel-wallet/types';
import type { BN, TransactionRequest, TransactionSummary } from 'fuels';
import type { InterpreterFrom, StateFrom } from 'xstate';
import { assign, createMachine } from 'xstate';
import { AccountService } from '~/systems/Account';
import { FetchMachine, assignErrorMessage, delay } from '~/systems/Core';
import type { GroupedErrors, VMApiError } from '~/systems/Transaction';
import type { TxInputs } from '~/systems/Transaction/services';
Expand All @@ -23,11 +22,10 @@ type MachineContext = {
origin?: string;
title?: string;
favIconUrl?: string;
address?: string;
isOriginRequired?: boolean;
providerUrl?: string;
transactionRequest?: TransactionRequest;
account?: Account;
account?: AccountWithBalance;
tip?: BN;
gasLimit?: BN;
skipCustomFee?: boolean;
Expand Down Expand Up @@ -78,9 +76,6 @@ type MachineServices = {
simulateTransaction: {
data: SimulateTransactionReturn;
};
fetchAccount: {
data: Account;
};
};

type MachineEvents =
Expand Down Expand Up @@ -143,32 +138,13 @@ export const transactionRequestMachine = createMachine(
},
{
actions: ['assignGasLimit'],
target: 'fetchingAccount',
},
],
},
},
fetchingAccount: {
entry: ['openDialog'],
tags: ['loading'],
invoke: {
src: 'fetchAccount',
data: {
input: (ctx: MachineContext) => ctx.input,
},
onDone: [
{
cond: FetchMachine.hasError,
target: 'failed',
},
{
actions: ['assignAccount'],
target: 'simulatingTransaction',
},
],
},
},
simulatingTransaction: {
entry: ['openDialog'],
tags: ['loading'],
invoke: {
src: 'simulateTransaction',
Expand Down Expand Up @@ -283,28 +259,25 @@ export const transactionRequestMachine = createMachine(
maxGasLimit: ev.data.maxGasLimit,
},
})),
assignAccount: assign({
input: (ctx, ev) => ({
...ctx.input,
account: ev.data,
}),
}),
assignTxRequestData: assign({
input: (ctx, ev) => {
const {
transactionRequest,
origin,
address,
providerUrl,
title,
favIconUrl,
skipCustomFee,
account,
} = ev.input || {};

if (!providerUrl) {
throw new Error('providerUrl is required');
}
if (!address) {
if (!account) {
throw new Error('account is required');
}
if (!account.address) {
throw new Error('address is required');
}
if (!transactionRequest) {
Expand All @@ -317,7 +290,7 @@ export const transactionRequestMachine = createMachine(
return {
transactionRequest,
origin,
address,
account,
providerUrl,
title,
favIconUrl,
Expand Down Expand Up @@ -443,30 +416,6 @@ export const transactionRequestMachine = createMachine(
};
},
}),
fetchAccount: FetchMachine.create<
{ address: string; providerUrl: string },
Account
>({
showError: true,
async fetch({ input }) {
if (!input?.address || !input?.providerUrl) {
throw new Error('Invalid fetchAccount input');
}
const [_, accountWithBalances] = await Promise.all([
AccountService.getCurrentAccount().then((res) => {
if (res?.address !== input.address) {
throw new Error('Current account does not match the address');
}
}),
AccountService.fetchBalance({
address: input.address,
providerUrl: input.providerUrl,
}),
]);

return accountWithBalances;
},
}),
},
}
);
Expand Down
8 changes: 8 additions & 0 deletions packages/app/src/systems/DApp/methods.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,11 +51,19 @@ export class RequestMethods extends ExtensionPageConnection {
const { origin, address, provider, transaction, title, favIconUrl } = input;
const providerUrl = provider.url;
const transactionRequest = transactionRequestify(JSON.parse(transaction));
const currentAccount = await store.getStateFrom(Services.accounts).context
.account;
if (currentAccount?.address !== origin) {
throw new Error(
`Origin: ${origin} does not match current account: ${currentAccount?.address}`
);
}
const state = await store
.requestTransaction({
origin,
transactionRequest,
address,
account: currentAccount,
providerUrl,
title,
favIconUrl,
Expand Down
9 changes: 8 additions & 1 deletion packages/app/src/systems/Send/hooks/useSend.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ import { useTransactionRequest } from '~/systems/DApp';
import { TxRequestStatus } from '~/systems/DApp/machines/transactionRequestMachine';
import type { TxInputs } from '~/systems/Transaction/services';

import { Services } from '~/store';
import { store } from '~/store';
import { AssetsCache } from '~/systems/Asset/cache/AssetsCache';
import { useProvider } from '~/systems/Network/hooks/useProvider';
import { formatGasLimit } from '~/systems/Transaction';
Expand Down Expand Up @@ -273,9 +275,13 @@ const DEFAULT_VALUES: SendFormValues = {
export function useSend() {
const navigate = useNavigate();
const txRequest = useTransactionRequest();
const { account } = useAccounts();
const provider = useProvider();

const account = store.useSelector(
Services.accounts,
(state) => state.context.account
);

const service = useInterpret(() =>
sendMachine.withConfig({
actions: {
Expand All @@ -299,6 +305,7 @@ export function useSend() {
txRequest.handlers.request({
providerUrl,
transactionRequest,
account,
address,
fees: {
baseFee,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ export default {

const Template: StoryFn<typeof TxApprove> = (_args, { loaded }) => {
const txRequest = useTransactionRequest();
const { transactionRequest, network, address } = loaded || {};
const { transactionRequest, network, account, address } = loaded || {};

// biome-ignore lint/correctness/useExhaustiveDependencies: <explanation>
useEffect(() => {
txRequest.handlers.request({
address,
account,
transactionRequest,
providerUrl: network?.url,
});
Expand Down
7 changes: 4 additions & 3 deletions packages/app/src/systems/Transaction/services/transaction.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Account } from '@fuel-wallet/types';
import type { Account, AccountWithBalance } from '@fuel-wallet/types';
import type { TransactionRequest, WalletLocked } from 'fuels';
import { clone } from 'ramda';

Expand Down Expand Up @@ -45,10 +45,11 @@ export type TxInputs = {
request: {
providerUrl: string;
transactionRequest: TransactionRequest;
address?: string;
origin?: string;
address: string | undefined;
origin?: string | undefined;
title?: string;
favIconUrl?: string;
account: AccountWithBalance | undefined;
skipCustomFee?: boolean;
fees?: {
baseFee?: BN;
Expand Down

0 comments on commit a57bd40

Please sign in to comment.