Skip to content

Commit d22d73a

Browse files
authored
chore: additional confirmation of UserOperation (#54)
* chore: added additional confirmation of UO on RPC side before the processing * chore: changeset * chore: fix
1 parent a1329c8 commit d22d73a

File tree

4 files changed

+50
-11
lines changed

4 files changed

+50
-11
lines changed

.changeset/frank-dragons-poke.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
'@mycelium-sdk/core': major
3+
---
4+
5+
## What was changed?
6+
7+
- Added additional confirmation of a transaction for `send()` adn `sendBatch()` methods via RPC request using wait `waitForTransactionReceipt` method
8+
9+
## Why was changed/added?
10+
11+
- Bundler sometimes go ahead in state that RPC node. It cause an issue when RPC try to fetch a wallet balance, but got zero result as a node still work with an old block
12+
13+
## How to use the change?
14+
15+
- It will be used by default under the hood for `send()` and `sendBatch()` methods of the SDK

packages/sdk/src/test/mocks/ChainManagerMock.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export const createMockChainManager = (): ChainManager => {
1111
const mockPublicClient = {
1212
readContract: vi.fn(),
1313
getBalance: vi.fn(),
14+
waitForTransactionReceipt: vi.fn(),
1415
} as unknown as PublicClient;
1516

1617
const mockBundlerClient = {

packages/sdk/src/wallet/DefaultSmartWallet.spec.ts

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -172,12 +172,16 @@ describe('DefaultSmartWallet integration tests', () => {
172172
};
173173
vi.mocked(bundlerClient.estimateUserOperationGas).mockResolvedValue(mockGasEstimate);
174174
vi.mocked(bundlerClient.sendUserOperation).mockResolvedValue('0xTransactionHash');
175-
// vi.mocked(bundlerClient.waitForUserOperationReceipt).mockResolvedValue({
176-
// receipt: {} as unknown as TransactionReceipt,
177-
// });
175+
vi.mocked(bundlerClient.waitForUserOperationReceipt).mockResolvedValue({
176+
receipt: { transactionHash: '0xTransactionHash' },
177+
});
178178

179179
const result = await wallet.send(transactionData, chainId);
180180

181+
expect(
182+
mockChainManager.getPublicClient(chainId).waitForTransactionReceipt,
183+
).toHaveBeenCalledWith({ hash: '0xTransactionHash' });
184+
181185
expect(mockChainManager.getBundlerClient).toHaveBeenCalledWith(chainId, mockAccount);
182186
expect(bundlerClient.estimateUserOperationGas).toHaveBeenCalledWith({
183187
account: mockAccount,
@@ -264,9 +268,16 @@ describe('DefaultSmartWallet integration tests', () => {
264268
};
265269
vi.mocked(bundlerClient.estimateUserOperationGas).mockResolvedValue(mockGasEstimate);
266270
vi.mocked(bundlerClient.sendUserOperation).mockResolvedValue('0xTransactionHash');
271+
vi.mocked(bundlerClient.waitForUserOperationReceipt).mockResolvedValue({
272+
receipt: { transactionHash: '0xTransactionHash' },
273+
});
267274

268275
const result = await wallet.sendBatch(transactionData, chainId);
269276

277+
expect(
278+
mockChainManager.getPublicClient(chainId).waitForTransactionReceipt,
279+
).toHaveBeenCalledWith({ hash: '0xTransactionHash' });
280+
270281
expect(mockChainManager.getBundlerClient).toHaveBeenCalledWith(chainId, mockAccount);
271282
expect(bundlerClient.estimateUserOperationGas).toHaveBeenCalledWith({
272283
account: mockAccount,

packages/sdk/src/wallet/DefaultSmartWallet.ts

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -286,25 +286,31 @@ export class DefaultSmartWallet extends SmartWallet {
286286
}
287287

288288
const bundlerClient = this.chainManager.getBundlerClient(chainId, account);
289+
const publicClient = this.chainManager.getPublicClient(chainId);
289290

290291
const gas = await bundlerClient.estimateUserOperationGas({
291292
account,
292293
calls: [transactionData],
293294
});
294295

295-
const hash = await bundlerClient.sendUserOperation({
296+
const userOperationHash = await bundlerClient.sendUserOperation({
296297
account,
297298
calls: [transactionData],
298299
callGasLimit: this.bumpGasLimits(gas.callGasLimit),
299300
verificationGasLimit: this.bumpGasLimits(gas.verificationGasLimit),
300301
preVerificationGas: this.bumpGasLimits(gas.preVerificationGas),
301302
});
302303

303-
await bundlerClient.waitForUserOperationReceipt({
304-
hash,
304+
const userOperationReceipt = await bundlerClient.waitForUserOperationReceipt({
305+
hash: userOperationHash,
305306
});
306307

307-
return hash;
308+
// Extra check that RPC node has included the transaction in the block
309+
await publicClient.waitForTransactionReceipt({
310+
hash: userOperationReceipt.receipt.transactionHash,
311+
});
312+
313+
return userOperationHash;
308314
} catch (error) {
309315
throw new Error(
310316
`Failed to send transaction: ${error instanceof Error ? error.message.toString().slice(0, 100) : 'Unknown error'}`,
@@ -346,25 +352,31 @@ export class DefaultSmartWallet extends SmartWallet {
346352
}
347353

348354
const bundlerClient = this.chainManager.getBundlerClient(chainId, account);
355+
const publicClient = this.chainManager.getPublicClient(chainId);
349356

350357
const gas = await bundlerClient.estimateUserOperationGas({
351358
account,
352359
calls: transactionData,
353360
});
354361

355-
const hash = await bundlerClient.sendUserOperation({
362+
const userOperationHash = await bundlerClient.sendUserOperation({
356363
account,
357364
calls: transactionData,
358365
callGasLimit: this.bumpGasLimits(gas.callGasLimit),
359366
verificationGasLimit: this.bumpGasLimits(gas.verificationGasLimit),
360367
preVerificationGas: this.bumpGasLimits(gas.preVerificationGas),
361368
});
362369

363-
await bundlerClient.waitForUserOperationReceipt({
364-
hash,
370+
const userOperationReceipt = await bundlerClient.waitForUserOperationReceipt({
371+
hash: userOperationHash,
372+
});
373+
374+
// Extra check that RPC node has included the transaction in the block
375+
await publicClient.waitForTransactionReceipt({
376+
hash: userOperationReceipt.receipt.transactionHash,
365377
});
366378

367-
return hash;
379+
return userOperationHash;
368380
} catch (error) {
369381
throw new Error(
370382
`Failed to send transaction: ${error instanceof Error ? error.message : 'Unknown error'}`,

0 commit comments

Comments
 (0)