Skip to content

Commit

Permalink
feat: simplify get receipts
Browse files Browse the repository at this point in the history
  • Loading branch information
LuizAsFight committed Sep 24, 2024
1 parent 4807670 commit 473b6c5
Show file tree
Hide file tree
Showing 8 changed files with 131 additions and 48 deletions.
5 changes: 4 additions & 1 deletion packages/app-portal/src/systems/Bridge/events.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,10 @@ export function bridgeEvents(store: Store) {
store.send(Services.bridgeTxs, { type: 'FETCH_NEXT_PAGE' });
},
addTxEthToFuel(
input?: { ethTxId?: HexAddress } & BridgeInputs['fetchTxs'],
input?: {
ethTxId?: HexAddress;
inputEthTxNonce?: BigInt;
} & BridgeInputs['fetchTxs'],
) {
if (!input) return;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ export type BridgeTxsMachineEvents =
type: 'ADD_TX_ETH_TO_FUEL';
input: {
ethTxId?: HexAddress;
inputEthTxNonce?: BigInt;
} & BridgeInputs['fetchTxs'];
}
| {
Expand Down Expand Up @@ -203,16 +204,25 @@ export const bridgeTxsMachine = createMachine(
}),
assignTxEthToFuel: assign({
ethToFuelTxRefs: (ctx, ev) => {
const { ethTxId, fuelAddress, fuelProvider, ethPublicClient } =
ev.input || {};
const {
ethTxId,
fuelAddress,
fuelProvider,
ethPublicClient,
inputEthTxNonce,
} = ev.input || {};
if (!ethTxId || ctx.ethToFuelTxRefs?.[ethTxId])
return ctx.ethToFuelTxRefs;

const key = `${ethTxId}-${inputEthTxNonce}`;

console.log(`NEW: creating machine Fuel To Eth: ${ethTxId}`);
const newRef = {
[ethTxId]: spawn(
[key]: spawn(
txEthToFuelMachine.withContext({
ethTxId: ethTxId as HexAddress,
inputEthTxNonce: inputEthTxNonce,
machineId: key,
fuelAddress: fuelAddress,
fuelProvider: fuelProvider,
ethPublicClient: ethPublicClient,
Expand Down
14 changes: 9 additions & 5 deletions packages/app-portal/src/systems/Bridge/services/bridge.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -79,26 +79,30 @@ export class BridgeService {

const assetEth = getAssetEth(asset);
const amountEthUnits = bn.parseUnits(amountFormatted, assetEth.decimals);
const txId = await TxEthToFuelService.start({
const startedTxEthToFuel = await TxEthToFuelService.start({
amount: amountEthUnits.toHex(),
ethWalletClient,
fuelAddress,
ethAssetAddress: assetEth.address,
ethPublicClient,
});

if (txId) {
const { txHash, nonce } = startedTxEthToFuel || {};

if (txHash && nonce) {
if (fuelWallet) {
store.addTxEthToFuel({
ethTxId: txId,
ethTxId: txHash,
inputEthTxNonce: nonce,
fuelProvider,
ethPublicClient,
fuelAddress,
});
store.openTxEthToFuel({
txId,
txId: txHash,
messageSentEventNonce: nonce,
});
EthTxCache.setTxIsCreated(txId);
EthTxCache.setTxIsCreated(txHash);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -359,8 +359,8 @@ export const txEthToFuelMachine = createMachine(
fuelMessageStatus: (_, ev) => ev.data,
}),
clearTxCreated: (ctx) => {
if (ctx.machineId && EthTxCache.getTxIsCreated(ctx.machineId)) {
EthTxCache.removeTxCreated(ctx.machineId);
if (ctx.ethTxId && EthTxCache.getTxIsCreated(ctx.ethTxId)) {
EthTxCache.removeTxCreated(ctx.ethTxId);
}
},
setEthToFuelTxReceiptCached: (ctx) => {
Expand Down Expand Up @@ -400,7 +400,8 @@ export const txEthToFuelMachine = createMachine(
hasEthTxNonce: (ctx, ev) => !!ctx.ethTxNonce || !!ev?.data?.nonce,
hasAnalyzeTxInput: (ctx) =>
!!ctx.ethTxId &&
!!ctx.inputEthTxNonce &&
// inputEthTxNonce can be zero
ctx.inputEthTxNonce != null &&
!!ctx.machineId &&
!!ctx.fuelAddress &&
!!ctx.fuelProvider &&
Expand Down
82 changes: 64 additions & 18 deletions packages/app-portal/src/systems/Chains/eth/services/txEthToFuel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
FUEL_MESSAGE_PORTAL,
decodeMessageSentData,
} from '../contracts/FuelMessagePortal';
import { getBlockDate, isErc20Address } from '../utils';
import { getBlockDate, getTransactionReceipt, isErc20Address } from '../utils';

import {
type HexAddress,
Expand Down Expand Up @@ -126,8 +126,8 @@ export class TxEthToFuelService {
TxEthToFuelService.assertStartEth(input);

try {
const { ethWalletClient, fuelAddress, amount } = input;
if (fuelAddress && ethWalletClient) {
const { ethWalletClient, fuelAddress, amount, ethPublicClient } = input;
if (fuelAddress && ethWalletClient && ethPublicClient) {
const bridgeSolidityContracts = await getBridgeSolidityContracts();
const fuelPortal = EthConnectorService.connectToFuelMessagePortal({
walletClient: ethWalletClient,
Expand All @@ -142,7 +142,34 @@ export class TxEthToFuelService {
},
);

return txHash;
const receipt = await getTransactionReceipt({
ethPublicClient,
txHash,
});

if (receipt.status !== 'success') {
throw new Error('Failed to deposit ETH');
}

const nonce = receipt.logs.map((log) => {
try {
const messageSentEvent = decodeEventLog({
abi: FUEL_MESSAGE_PORTAL.abi,
data: log.data,
topics: log.topics,
}) as unknown as { args: FuelMessagePortalArgs['MessageSent'] };

return messageSentEvent?.args?.nonce;
} catch (_) {
/* empty */
}
})[0];

if (nonce == null) {
throw new Error('Failed to get nonce of ETH deposit');
}

return { txHash, nonce };
}
} catch (e) {
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Expand Down Expand Up @@ -185,19 +212,11 @@ export class TxEthToFuelService {
amount,
]);

let approveTxHashReceipt: TransactionReceipt;
try {
approveTxHashReceipt = await ethPublicClient.getTransactionReceipt({
hash: approveTxHash,
});
} catch (_err: unknown) {
// workaround in place because waitForTransactionReceipt stop working after first time using it
approveTxHashReceipt =
await ethPublicClient.waitForTransactionReceipt({
hash: approveTxHash,
confirmations: 2,
});
}
const approveTxHashReceipt = await getTransactionReceipt({
ethPublicClient,
txHash: approveTxHash,
waitOptions: { confirmations: 2 },
});

if (approveTxHashReceipt.status !== 'success') {
throw new Error('Failed to approve Token for transfer');
Expand All @@ -213,7 +232,34 @@ export class TxEthToFuelService {
amount,
]);

return depositTxHash;
const receipt = await getTransactionReceipt({
ethPublicClient,
txHash: depositTxHash,
});

if (receipt.status !== 'success') {
throw new Error('Failed to deposit ETH');
}

const nonce = receipt.logs.map((log) => {
try {
const messageSentEvent = decodeEventLog({
abi: FUEL_MESSAGE_PORTAL.abi,
data: log.data,
topics: log.topics,
}) as unknown as { args: FuelMessagePortalArgs['MessageSent'] };

return messageSentEvent?.args?.nonce;
} catch (_) {
/* empty */
}
})[0];

if (!nonce) {
throw new Error('Failed to get nonce of ETH deposit');
}

return { txHash: depositTxHash, nonce };
}
} catch (e) {
// biome-ignore lint/suspicious/noExplicitAny: <explanation>
Expand Down
1 change: 1 addition & 0 deletions packages/app-portal/src/systems/Chains/eth/utils/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from './block';
export * from './chain';
export * from './address';
export * from './txCache';
export * from './transaction';
29 changes: 29 additions & 0 deletions packages/app-portal/src/systems/Chains/eth/utils/transaction.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import {
PublicClient,
TransactionReceipt,
WaitForTransactionReceiptParameters,
} from 'viem';

export async function getTransactionReceipt({
ethPublicClient,
txHash,
waitOptions,
}: {
ethPublicClient: PublicClient;
txHash: `0x${string}`;
waitOptions?: Omit<WaitForTransactionReceiptParameters, 'hash'>;
}): Promise<TransactionReceipt> {
let receipt: TransactionReceipt;
try {
receipt = await ethPublicClient.getTransactionReceipt({
hash: txHash,
});
} catch (_err: unknown) {
// workaround in place because waitForTransactionReceipt stop working after first time using it
receipt = await ethPublicClient.waitForTransactionReceipt({
...(waitOptions ? waitOptions : {}),
hash: txHash,
});
}
return receipt;
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import { FUEL_MESSAGE_PORTAL } from '../../eth/contracts/FuelMessagePortal';
import { EthConnectorService } from '../../eth/services';
import { parseEthAddressToFuel } from '../../eth/utils/address';
import { createRelayMessageParams } from '../../eth/utils/relayMessage';
import { getTransactionReceipt } from '../../eth/utils/transaction';
import { getBlock } from '../utils';

export type TxFuelToEthInputs = {
Expand Down Expand Up @@ -439,28 +440,16 @@ export class TxFuelToEthService {

const { ethPublicClient, txHash } = input;

let txReceipts: Awaited<
ReturnType<
| typeof ethPublicClient.getTransactionReceipt
| typeof ethPublicClient.waitForTransactionReceipt
>
>;
try {
txReceipts = await ethPublicClient.getTransactionReceipt({
hash: txHash,
});
} catch (_err: unknown) {
// workaround in place because waitForTransactionReceipt stop working after first time using it
txReceipts = await ethPublicClient.waitForTransactionReceipt({
hash: txHash,
});
}
const txReceipt = await getTransactionReceipt({
ethPublicClient,
txHash,
});

if (txReceipts.status !== 'success') {
if (txReceipt.status !== 'success') {
throw new Error('Failed to relay message (transaction reverted)');
}

return !!txReceipts;
return !!txReceipt;
}

static async fetchTxs(input: TxFuelToEthInputs['fetchTxs']) {
Expand Down

0 comments on commit 473b6c5

Please sign in to comment.