Skip to content

Commit c65ae94

Browse files
committed
- Adds ability to retrieve transaction receipts
1 parent 17b8f4c commit c65ae94

File tree

5 files changed

+98
-5
lines changed

5 files changed

+98
-5
lines changed

README.md

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,11 @@ const {
417417
- `sendTransaction(txParams)`: Send a privacy-preserving transaction through the session key
418418
- `txParams`: `{ to: string, value: string, data: string }`
419419
- Returns: `Promise<string>` (transaction hash)
420+
- `waitForReceipt(txHash, timeout?)`: Wait for transaction receipt and confirmation
421+
- `txHash`: Transaction hash from `sendTransaction`
422+
- `timeout`: Optional timeout in milliseconds (default: 30000)
423+
- Returns: `Promise<TransactionReceipt>` (full receipt with logs and status)
424+
- Throws: Error if transaction reverts or timeout is exceeded
420425
- `createSessionKey()`: Create a new session key
421426
- `fundSessionKey(address, amount, userAddress)`: Fund a session key with ETH
422427
- `deleteSessionKey()`: Delete the current session key
@@ -426,10 +431,10 @@ const {
426431
**Example:**
427432
```tsx
428433
import { useSessionKeyStore } from '@tenprotocol/ten-kit';
429-
import { encodeFunctionData, parseEther } from 'viem';
434+
import { encodeFunctionData, parseEther, parseEventLogs } from 'viem';
430435

431436
function MyComponent() {
432-
const { sessionKey, sendTransaction } = useSessionKeyStore();
437+
const { sessionKey, sendTransaction, waitForReceipt } = useSessionKeyStore();
433438

434439
const handleTransaction = async () => {
435440
const data = encodeFunctionData({
@@ -442,6 +447,17 @@ function MyComponent() {
442447
value: `0x${parseEther('0.01').toString(16)}`,
443448
data,
444449
});
450+
451+
// Wait for confirmation and get receipt
452+
const receipt = await waitForReceipt(txHash);
453+
console.log('Status:', receipt.status);
454+
455+
// Parse event logs
456+
const events = parseEventLogs({
457+
abi: MyContractABI,
458+
logs: receipt.logs,
459+
});
460+
console.log('Events:', events);
445461
};
446462

447463
return <button onClick={handleTransaction}>Send TX</button>;
@@ -624,6 +640,7 @@ import type {
624640
// Session Key Types
625641
SessionKeyStore,
626642
TransactionParams,
643+
TransactionReceipt,
627644

628645
// Public Clients
629646
TENPublicClients,
@@ -640,6 +657,12 @@ const txParams: TransactionParams = {
640657
data: '0x...',
641658
};
642659

660+
// Example: Working with receipts
661+
const receipt: TransactionReceipt = await waitForReceipt(txHash);
662+
console.log('Status:', receipt.status);
663+
console.log('Gas used:', receipt.gasUsed);
664+
console.log('Logs:', receipt.logs);
665+
643666
// Example: Custom Config
644667
const config: TenConfig = {
645668
id: 8443,

src/components/TENProvider/TENProvider.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { ReactNode } from 'react';
1+
import {ReactNode, useEffect} from 'react';
22
import {QueryClient, QueryClientProvider} from '@tanstack/react-query';
33
import { WagmiProvider, createConfig } from 'wagmi';
44
import { defineChain, http } from 'viem';
@@ -36,7 +36,9 @@ export function TENProvider({
3636
transports,
3737
});
3838

39-
setWagmiConfig(wagmiConfig);
39+
useEffect(() => {
40+
setWagmiConfig(wagmiConfig);
41+
}, []);
4042

4143
return (
4244
<WagmiProvider config={wagmiConfig}>

src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export type { TENPublicClients } from '@/lib/contractReadFunctions'
3333
export type {
3434
EIP1193Provider,
3535
TransactionParams,
36+
TransactionReceipt,
3637
StateSubscriber,
3738
SessionKeyStore,
3839
TenConfig,

src/lib/types.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,33 @@ export interface TransactionParams {
2929
maxPriorityFeePerGas?: string | bigint;
3030
}
3131

32+
export interface TransactionReceipt {
33+
transactionHash: string;
34+
transactionIndex: string;
35+
blockHash: string;
36+
blockNumber: string;
37+
from: string;
38+
to: string | null;
39+
cumulativeGasUsed: string;
40+
gasUsed: string;
41+
contractAddress: string | null;
42+
logs: Array<{
43+
address: string;
44+
topics: string[];
45+
data: string;
46+
blockNumber: string;
47+
transactionHash: string;
48+
transactionIndex: string;
49+
blockHash: string;
50+
logIndex: string;
51+
removed: boolean;
52+
}>;
53+
logsBloom: string;
54+
status: string; // '0x1' for success, '0x0' for failure
55+
effectiveGasPrice: string;
56+
type: string;
57+
}
58+
3259
export type StateSubscriber = (state: SessionKeyState) => void;
3360

3461
export interface SessionKeyStore {
@@ -51,6 +78,7 @@ export interface SessionKeyStore {
5178
cleanupSessionKey: () => Promise<void>;
5279
updateBalance: () => Promise<SessionBalanceObject>;
5380
sendTransaction: (txParams: TransactionParams) => Promise<string>;
81+
waitForReceipt: (txHash: string, timeout?: number) => Promise<TransactionReceipt>;
5482
setWagmiConfig: (config: Config) => void;
5583
}
5684

src/stores/sessionKey.store.ts

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { create } from 'zustand';
22
import { persist } from 'zustand/middleware';
33
import { encode as rlpEncode } from 'rlp';
44

5-
import type {SessionKeyStore, TransactionParams, SessionBalanceObject} from '@/lib/types';
5+
import type {SessionKeyStore, TransactionParams, SessionBalanceObject, TransactionReceipt} from '@/lib/types';
66
import { LOCAL_STORAGE_KEY, TEN_ADDRESSES } from '@/lib/constants';
77
import {
88
parseEther,
@@ -408,6 +408,45 @@ export const useSessionKeyStore = create<SessionKeyStore>()(
408408
}
409409
},
410410

411+
waitForReceipt: async (txHash: string, timeout: number = 30000): Promise<TransactionReceipt> => {
412+
try {
413+
const provider = get().provider;
414+
if (!provider) {
415+
throw new Error('No provider available');
416+
}
417+
418+
const startTime = Date.now();
419+
const pollInterval = 1000;
420+
421+
while (true) {
422+
if (Date.now() - startTime > timeout) {
423+
throw new Error(`Transaction receipt timeout after ${timeout}ms`);
424+
}
425+
426+
const receipt = await provider.request({
427+
method: 'eth_getTransactionReceipt',
428+
params: [txHash],
429+
});
430+
431+
if (receipt) {
432+
console.log('Transaction mined:', txHash);
433+
434+
if (receipt.status === '0x0') {
435+
throw new Error('Transaction reverted');
436+
}
437+
438+
get().updateBalance();
439+
return receipt as TransactionReceipt;
440+
}
441+
442+
await new Promise((resolve) => setTimeout(resolve, pollInterval));
443+
}
444+
} catch (error) {
445+
const err = error instanceof Error ? error : new Error('Failed to get receipt');
446+
throw err;
447+
}
448+
},
449+
411450
setWagmiConfig: (wagmiConfig) => {
412451
set({wagmiConfig});
413452
}

0 commit comments

Comments
 (0)