Skip to content

Commit a5df7c6

Browse files
committed
txop
1 parent 188419e commit a5df7c6

File tree

3 files changed

+269
-49
lines changed

3 files changed

+269
-49
lines changed

packages/app/src/systems/CRX/background/services/types.ts

+3-15
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,5 @@
1-
import type {
2-
AssetData,
3-
FuelProviderConfig,
4-
NetworkData,
5-
} from '@fuel-wallet/types';
6-
import type { AbiMap, SelectNetworkArguments } from 'fuels';
1+
import type { AssetData, NetworkData } from '@fuel-wallet/types';
2+
import type { AbiMap, FuelConnectorSendTxParams } from 'fuels';
73

84
export type MessageInputs = {
95
signMessage: {
@@ -13,15 +9,7 @@ export type MessageInputs = {
139
title?: string;
1410
favIconUrl?: string;
1511
};
16-
sendTransaction: {
17-
address: string;
18-
origin: string;
19-
title?: string;
20-
favIconUrl?: string;
21-
provider: FuelProviderConfig;
22-
transaction: string;
23-
skipCustomFee?: boolean;
24-
};
12+
sendTransaction: FuelConnectorSendTxParams;
2513
addAssets: {
2614
assets: AssetData[];
2715
origin: string;

packages/app/src/systems/DApp/machines/transactionRequestMachine.tsx

+206-22
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { Account, AccountWithBalance } from '@fuel-wallet/types';
2-
import type { BN, TransactionRequest, TransactionSummary } from 'fuels';
2+
import type { TransactionRequest, TransactionSummary } from 'fuels';
3+
import { BN } from 'fuels';
34
import type { InterpreterFrom, StateFrom } from 'xstate';
45
import { assign, createMachine } from 'xstate';
56
import { AccountService } from '~/systems/Account';
@@ -32,11 +33,48 @@ type MachineContext = {
3233
tip?: BN;
3334
gasLimit?: BN;
3435
skipCustomFee?: boolean;
36+
isPrepareOnly?: boolean;
37+
state?: {
38+
state?: 'funded' | 'immutable';
39+
};
40+
providerCache?: {
41+
consensusParameterTimestamp?: string;
42+
chain?: {
43+
name?: string;
44+
consensusParameters?: Record<string, unknown>;
45+
daHeight?: string;
46+
[key: string]: unknown;
47+
};
48+
chainInfo?: {
49+
name?: string;
50+
consensusParameters?: Record<string, unknown>;
51+
latestBlockHeight?: string;
52+
[key: string]: unknown;
53+
};
54+
nodeInfo?: {
55+
maxDepth?: string;
56+
maxTx?: string;
57+
nodeVersion?: string;
58+
utxoValidation?: boolean;
59+
vmBacktrace?: boolean;
60+
[key: string]: unknown;
61+
};
62+
};
63+
transactionData?: {
64+
latestGasPrice?: string;
65+
estimatedGasPrice?: string;
66+
summary?: {
67+
operations?: unknown[];
68+
changes?: unknown[];
69+
[key: string]: unknown;
70+
};
71+
};
3572
};
3673
response?: {
3774
txSummarySimulated?: TransactionSummary;
3875
txSummaryExecuted?: TransactionSummary;
3976
proposedTxRequest?: TransactionRequest;
77+
preparedTransaction?: TransactionRequest;
4078
};
4179
fees: {
4280
baseFee?: BN;
@@ -79,7 +117,14 @@ type MachineServices = {
79117
};
80118

81119
type MachineEvents =
82-
| { type: 'START'; input?: TxInputs['request'] }
120+
| {
121+
type: 'START';
122+
input?: TxInputs['request'] & {
123+
state?: MachineContext['input']['state'];
124+
providerCache?: MachineContext['input']['providerCache'];
125+
transactionData?: MachineContext['input']['transactionData'];
126+
};
127+
}
83128
| { type: 'SET_CUSTOM_FEES'; input: TxInputs['setCustomFees'] }
84129
| { type: 'RESET'; input?: null }
85130
| { type: 'APPROVE'; input?: null }
@@ -130,6 +175,8 @@ export const transactionRequestMachine = createMachine(
130175
input: (ctx: MachineContext) => ({
131176
address: ctx.input.address,
132177
account: ctx.input.account,
178+
providerCache: ctx.input.providerCache,
179+
transactionData: ctx.input.transactionData,
133180
}),
134181
},
135182
onDone: [
@@ -150,7 +197,12 @@ export const transactionRequestMachine = createMachine(
150197
invoke: {
151198
src: 'simulateTransaction',
152199
data: {
153-
input: (ctx: MachineContext) => ctx.input,
200+
input: (ctx: MachineContext) => ({
201+
...ctx.input,
202+
providerCache: ctx.input.providerCache,
203+
transactionData: ctx.input.transactionData,
204+
state: ctx.input.state,
205+
}),
154206
},
155207
onDone: [
156208
{
@@ -267,8 +319,24 @@ export const transactionRequestMachine = createMachine(
267319
account,
268320
address,
269321
fees,
322+
state,
323+
providerCache,
324+
transactionData,
270325
} = ev.input || {};
271326

327+
// Log if we received rich data with the transaction
328+
if (state || providerCache || transactionData) {
329+
console.log(
330+
'🎁 Rich data received with transaction:',
331+
'state',
332+
state,
333+
'providerCache',
334+
providerCache,
335+
'transactionData',
336+
transactionData
337+
);
338+
}
339+
272340
if (!providerUrl) {
273341
throw new Error('providerUrl is required');
274342
}
@@ -292,6 +360,9 @@ export const transactionRequestMachine = createMachine(
292360
favIconUrl,
293361
skipCustomFee,
294362
fees,
363+
state,
364+
providerCache,
365+
transactionData,
295366
};
296367
},
297368
fees: (_ctx, ev) => {
@@ -316,10 +387,12 @@ export const transactionRequestMachine = createMachine(
316387
},
317388
}),
318389
assignApprovedTx: assign({
319-
response: (ctx, ev) => ({
320-
...ctx.response,
321-
txSummaryExecuted: ev.data,
322-
}),
390+
response: (ctx, ev) => {
391+
return {
392+
...ctx.response,
393+
txSummaryExecuted: ev.data,
394+
};
395+
},
323396
}),
324397
assignSimulateResult: assign({
325398
response: (ctx, ev) => ({
@@ -356,7 +429,12 @@ export const transactionRequestMachine = createMachine(
356429
},
357430
services: {
358431
prepareInputForSimulateTransaction: FetchMachine.create<
359-
{ address?: string; account?: AccountWithBalance },
432+
{
433+
address?: string;
434+
account?: AccountWithBalance;
435+
providerCache?: MachineContext['input']['providerCache'];
436+
transactionData?: MachineContext['input']['transactionData'];
437+
},
360438
{
361439
estimated: PrepareInputForSimulateTransactionReturn['estimated'];
362440
account: AccountWithBalance;
@@ -365,24 +443,68 @@ export const transactionRequestMachine = createMachine(
365443
showError: false,
366444
maxAttempts: 1,
367445
async fetch({ input }) {
368-
const [estimated, acc] = await Promise.all([
369-
TxService.estimateGasLimitAndDefaultTips(),
370-
input?.account ||
371-
AccountService.fetchAccount({
372-
address: input?.address as string,
373-
}).then(async (_account) => {
374-
const network = await NetworkService.getSelectedNetwork();
375-
return await AccountService.fetchBalance({
376-
account: _account,
377-
providerUrl: network?.url as string,
378-
});
379-
}),
380-
]);
446+
let acc = input?.account;
447+
if (!acc) {
448+
acc = await AccountService.fetchAccount({
449+
address: input?.address as string,
450+
}).then(async (_account) => {
451+
const network = await NetworkService.getSelectedNetwork();
452+
return await AccountService.fetchBalance({
453+
account: _account,
454+
providerUrl: network?.url as string,
455+
});
456+
});
457+
}
458+
459+
if (!acc) {
460+
throw new Error('Could not retrieve account information');
461+
}
462+
463+
// Check if we have cached gas prices from the SDK - now directly from input
464+
const hasEstimatedGasPrice =
465+
!!input?.transactionData?.estimatedGasPrice;
466+
const hasLatestGasPrice = !!input?.transactionData?.latestGasPrice;
467+
468+
if (hasEstimatedGasPrice && hasLatestGasPrice) {
469+
try {
470+
const estimatedGasPrice = input?.transactionData
471+
?.estimatedGasPrice as string;
472+
const latestGasPrice = input?.transactionData
473+
?.latestGasPrice as string;
474+
475+
// We need maxGasLimit in any case
476+
const { maxGasLimit } =
477+
await TxService.estimateGasLimitAndDefaultTips();
478+
479+
return {
480+
estimated: {
481+
// Using constructor to parse strings
482+
regularTip: new BN(latestGasPrice),
483+
fastTip: new BN(estimatedGasPrice),
484+
maxGasLimit,
485+
},
486+
account: acc,
487+
};
488+
} catch (error) {
489+
console.warn(
490+
'Failed to use cached gas prices, falling back',
491+
error
492+
);
493+
// Fall through to regular estimation
494+
}
495+
}
496+
497+
// Standard implementation if no cached data or any errors
498+
const estimated = await TxService.estimateGasLimitAndDefaultTips();
381499
return { estimated, account: acc };
382500
},
383501
}),
384502
simulateTransaction: FetchMachine.create<
385-
TxInputs['simulateTransaction'],
503+
TxInputs['simulateTransaction'] & {
504+
state?: MachineContext['input']['state'];
505+
providerCache?: MachineContext['input']['providerCache'];
506+
transactionData?: MachineContext['input']['transactionData'];
507+
},
386508
SimulateTransactionReturn
387509
>({
388510
showError: false,
@@ -391,6 +513,68 @@ export const transactionRequestMachine = createMachine(
391513
throw new Error('Invalid simulateTransaction input');
392514
}
393515

516+
console.log('🚀 Simulation input:', input);
517+
518+
// Now access rich data directly from input instead of accessing machine context
519+
const hasTransactionData = !!input.transactionData;
520+
const hasState = !!input.state;
521+
const hasProviderCache = !!input.providerCache;
522+
523+
// Log for debugging
524+
if (hasTransactionData || hasState || hasProviderCache) {
525+
console.log('🚀 Rich transaction data found in input:', {
526+
hasTransactionData,
527+
hasState,
528+
hasProviderCache,
529+
});
530+
531+
// Check if we have cached provider info we can use
532+
if (
533+
hasProviderCache &&
534+
(input.providerCache?.chain || input.providerCache?.chainInfo)
535+
) {
536+
// TODO: Use cached provider info
537+
}
538+
539+
// Check if we can skip simulation because the transaction is already funded
540+
const isFunded = input.state?.state === 'funded';
541+
const hasSummary = !!input.transactionData?.summary;
542+
543+
if (isFunded && hasSummary) {
544+
try {
545+
// Just create a transaction summary from the cached data
546+
const summary = input.transactionData?.summary || {};
547+
const txSummary = {
548+
id: summary.id,
549+
gasUsed: summary.gasUsed,
550+
fee: new BN(summary.fee ? summary.fee.toString() : '0'),
551+
receipts: summary.receipts || [],
552+
} as TransactionSummary;
553+
554+
// Return the mocked simulation result
555+
return {
556+
txSummary,
557+
baseFee: input.transactionData?.estimatedGasPrice
558+
? new BN(input.transactionData.estimatedGasPrice)
559+
: undefined,
560+
proposedTxRequest: input.transactionRequest,
561+
};
562+
} catch (error) {
563+
console.warn(
564+
'Failed to use cached transaction summary, falling back to simulation',
565+
error
566+
);
567+
// Fall through to regular simulation if anything goes wrong
568+
}
569+
}
570+
} else {
571+
console.log(
572+
'No rich data found in input, continuing with simulation'
573+
);
574+
}
575+
576+
// Standard implementation if we couldn't use cached data
577+
console.log('Running standard transaction simulation...');
394578
const simulatedInfo = await TxService.simulateTransaction(input);
395579
return simulatedInfo;
396580
},

0 commit comments

Comments
 (0)