1
- import 'package:starknet/starknet.dart' ;
2
- import 'package:starknet_provider/starknet_provider.dart' ;
3
- import 'package:test/test.dart' ;
4
1
import 'dart:convert' ;
2
+ import 'dart:async' ;
5
3
import 'package:http/http.dart' as http;
6
- import 'package:starknet_provider/src/model/get_transaction_status.dart' ;
4
+ import 'package:starknet_provider/starknet_provider.dart' ;
5
+ import 'package:test/test.dart' ;
6
+ import 'package:starknet/starknet.dart' ;
7
7
8
8
void main () {
9
- group ('starknet_getTransactionStatus' , () {
10
- late JsonRpcReadProvider provider;
11
- late Felt txHash;
9
+ // Constants for test configuration
10
+ const pollingInterval = Duration (seconds: 1 );
11
+ const timeout = Duration (seconds: 30 );
12
+ final transferAmount = Felt .fromInt (1000000 );
13
+ final maxFee = Felt .fromInt (10000000000000000 );
14
+ final devnetUri = Uri .parse ('http://127.0.0.1:5050' );
12
15
13
- setUp (() async {
14
- provider =
15
- JsonRpcReadProvider (nodeUri: Uri .parse ('http://127.0.0.1:5050' ));
16
+ // Shared variable to store transaction hash between tests
17
+ String ? successfulTxHash;
16
18
17
- // First verify the devnet is responding
18
- final chainIdResponse = await http.post (
19
- Uri .parse ('http://127.0.0.1:5050' ),
19
+ group ('starknet_getTransactionStatus' , () {
20
+ test ('should handle non-existent transaction hash' , () async {
21
+ final response = await http.post (
22
+ devnetUri,
20
23
headers: {'Content-Type' : 'application/json' },
21
24
body: jsonEncode ({
22
25
'jsonrpc' : '2.0' ,
23
- 'method' : 'starknet_chainId' ,
24
- 'params' : [],
26
+ 'method' : 'starknet_getTransactionStatus' ,
27
+ 'params' : [
28
+ '0x0000000000000000000000000000000000000000000000000000000000000001'
29
+ ],
25
30
'id' : 1 ,
26
31
}),
27
32
);
28
- print ('Chain ID response: ${chainIdResponse .body }' );
29
33
30
- // Use a known transaction hash for non-existent transaction test
31
- txHash = Felt . fromHexString (
32
- '0x03b2911796e0024f9e23d7337997538058eca267d5ddaa582d482cbe1fb64897' );
33
- print ( 'Using tx_hash: ${ txHash . toHexString ()} ' );
34
- });
34
+ print ( 'Raw response from getTransactionStatus: ${ response . body }' );
35
+ final result = jsonDecode (response.body);
36
+ expect (result[ 'error' ][ 'code' ], 29 );
37
+ expect (result[ 'error' ][ 'message' ], 'Transaction hash not found ' );
38
+ }, tags : [ 'integration' ] );
35
39
36
- test ('should handle non-existent transaction hash ' , () async {
37
- // Make a direct HTTP request to see the raw response
38
- final directResponse = await http.post (
39
- Uri . parse ( 'http://127.0.0.1:5050' ) ,
40
+ test ('should handle real transaction status ' , () async {
41
+ // Get chain ID
42
+ final chainIdResponse = await http.post (
43
+ devnetUri ,
40
44
headers: {'Content-Type' : 'application/json' },
41
45
body: jsonEncode ({
42
46
'jsonrpc' : '2.0' ,
43
- 'method' : 'starknet_getTransactionStatus ' ,
44
- 'params' : [txHash. toHexString () ],
47
+ 'method' : 'starknet_chainId ' ,
48
+ 'params' : [],
45
49
'id' : 1 ,
46
50
}),
47
51
);
48
- print ('Raw response from getTransactionStatus: ${directResponse .body }' );
49
-
50
- expect (directResponse.statusCode, equals (200 ));
51
- final result = jsonDecode (directResponse.body);
52
- expect (result['error' ], isNotNull);
53
- expect (result['error' ]['code' ], equals (29 ));
54
- expect (result['error' ]['message' ], equals ('Transaction hash not found' ));
55
- }, tags: ['integration' ]);
52
+ print ('Chain ID response: ${chainIdResponse .body }' );
56
53
57
- test ('should handle real transaction status' , () async {
58
- // Use the pre-funded account from .env.devnet
59
- final senderAddress = Felt .fromHexString (
60
- '0x64b48806902a367c8598f4f95c305e8c1a1acba5f082d294a43793113115691' );
61
- final recipientAddress = Felt .fromHexString (
62
- '0x78662e7352d062084b0010068b99288486c2d8b914f6e2a55ce945f8792c8b1' );
63
- final privateKey =
64
- Felt .fromHexString ('0x71d7bb07b9a64f6f78ac4c816aff4da9' );
54
+ // Get predeployed accounts
55
+ final accounts = await Devnet .getPredeployedAccounts (devnetUri);
56
+ expect (accounts, isNotEmpty,
57
+ reason: 'Devnet should have predeployed accounts' );
58
+ final account = accounts.first;
65
59
66
60
// Create a signer for the account
67
- final signer =
61
+ final privateKey = account.privateKey;
62
+ final senderAddress = account.address;
63
+ final accountSigner =
68
64
StarkAccountSigner (signer: StarkSigner (privateKey: privateKey));
69
65
70
- // First get the nonce for the sender
66
+ // Get the latest nonce before sending the transaction
71
67
final nonceResponse = await http.post (
72
- Uri . parse ( 'http://127.0.0.1:5050' ) ,
68
+ devnetUri ,
73
69
headers: {'Content-Type' : 'application/json' },
74
70
body: jsonEncode ({
75
71
'jsonrpc' : '2.0' ,
@@ -79,47 +75,46 @@ void main() {
79
75
}),
80
76
);
81
77
print ('Nonce response: ${nonceResponse .body }' );
82
- final nonce =
83
- Felt .fromHexString (jsonDecode (nonceResponse.body)['result' ]);
78
+ final nonceResult = jsonDecode (nonceResponse.body);
79
+ expect (nonceResult['error' ], isNull, reason: 'Failed to get nonce' );
80
+ final nonce = Felt .fromHexString (nonceResult['result' ]);
84
81
85
82
// Create the function call for the transfer
86
83
final functionCall = FunctionCall (
87
84
contractAddress: Felt .fromHexString (
88
85
'0x049d36570d4e46f48e99674bd3fcc84644ddd6b96f7c741b1562b82f9e004dc7' ),
89
86
entryPointSelector: getSelectorByName ('transfer' ),
90
87
calldata: [
91
- recipientAddress,
92
- Felt . fromInt ( 100 ), // Amount low
93
- Felt .fromInt (0 ), // Amount high
88
+ accounts[ 1 ].address, // Transfer to second account
89
+ transferAmount,
90
+ Felt .fromInt (0 ),
94
91
],
95
92
);
96
93
97
- // Sign the transaction
98
- final chainId =
99
- Felt .fromHexString ('0x534e5f5345504f4c4941' ); // SN_SEPOLIA
100
- final signature = await signer.signTransactions (
94
+ // Convert function call to calldata
95
+ final calldata = functionCallsToCalldata (functionCalls: [functionCall]);
96
+
97
+ // Create and sign the transaction
98
+ final signature = await accountSigner.signTransactions (
101
99
transactions: [functionCall],
102
100
contractAddress: senderAddress,
103
101
version: 1 ,
104
102
nonce: nonce,
105
- maxFee: Felt . fromHexString ( '0x1000000000000000' ) ,
106
- chainId: chainId ,
103
+ maxFee: maxFee ,
104
+ chainId: Felt . fromHexString ( jsonDecode (chainIdResponse.body)[ 'result' ]) ,
107
105
);
108
106
109
- // Convert function call to calldata
110
- final calldata = functionCallsToCalldata (functionCalls: [functionCall]);
111
-
112
- // Create and send a transfer transaction
107
+ // Send the transaction
113
108
final invokeResponse = await http.post (
114
- Uri . parse ( 'http://127.0.0.1:5050' ) ,
109
+ devnetUri ,
115
110
headers: {'Content-Type' : 'application/json' },
116
111
body: jsonEncode ({
117
112
'jsonrpc' : '2.0' ,
118
113
'method' : 'starknet_addInvokeTransaction' ,
119
114
'params' : [
120
115
{
121
116
'type' : 'INVOKE' ,
122
- 'max_fee' : '0x1000000000000000' ,
117
+ 'max_fee' : maxFee. toHexString () ,
123
118
'version' : '0x1' ,
124
119
'signature' : signature.map ((s) => s.toHexString ()).toList (),
125
120
'nonce' : nonce.toHexString (),
@@ -132,110 +127,95 @@ void main() {
132
127
);
133
128
print ('Invoke response: ${invokeResponse .body }' );
134
129
final invokeResult = jsonDecode (invokeResponse.body);
135
- expect (invokeResult['error' ], isNull);
136
- final transactionHash = invokeResult['result' ]['transaction_hash' ];
130
+ expect (invokeResult['error' ], isNull,
131
+ reason: 'Failed to send transaction' );
132
+ successfulTxHash = invokeResult['result' ]['transaction_hash' ];
133
+ print ('Transaction hash: $successfulTxHash ' );
134
+
135
+ // Poll for the transaction status
136
+ TransactionStatus ? status;
137
+ final stopwatch = Stopwatch ()..start ();
138
+
139
+ while (stopwatch.elapsed < timeout) {
140
+ try {
141
+ final statusResponse = await http.post (
142
+ devnetUri,
143
+ headers: {'Content-Type' : 'application/json' },
144
+ body: jsonEncode ({
145
+ 'jsonrpc' : '2.0' ,
146
+ 'method' : 'starknet_getTransactionStatus' ,
147
+ 'params' : [successfulTxHash],
148
+ 'id' : 1 ,
149
+ }),
150
+ );
151
+
152
+ final statusResult = jsonDecode (statusResponse.body);
153
+ if (statusResult['error' ] == null ) {
154
+ status = TransactionStatus .fromJson (statusResult['result' ]);
155
+ break ;
156
+ }
157
+ } catch (e) {
158
+ print ('Error polling for transaction status: $e ' );
159
+ }
160
+ await Future .delayed (pollingInterval);
161
+ }
162
+
163
+ expect (status, isNotNull,
164
+ reason: 'Transaction status should be available within timeout' );
165
+ expect (status! .finalityStatus, isNotNull,
166
+ reason: 'Transaction should have a finality status' );
167
+ expect (status! .executionStatus, isNotNull,
168
+ reason: 'Transaction should have an execution status' );
169
+ }, tags: ['integration' ]);
137
170
138
- // Wait a bit for the transaction to be processed
139
- await Future .delayed (Duration (seconds: 2 ));
171
+ test ('should return transaction status with required finality_status field' ,
172
+ () async {
173
+ expect (successfulTxHash, isNotNull,
174
+ reason: 'Previous test must succeed to get a valid transaction hash' );
140
175
141
- // Now check the transaction status
142
- final statusResponse = await http.post (
143
- Uri .parse ('http://127.0.0.1:5050' ),
176
+ final response = await http.post (
177
+ devnetUri,
144
178
headers: {'Content-Type' : 'application/json' },
145
179
body: jsonEncode ({
146
180
'jsonrpc' : '2.0' ,
147
181
'method' : 'starknet_getTransactionStatus' ,
148
- 'params' : [transactionHash ],
182
+ 'params' : [successfulTxHash ],
149
183
'id' : 1 ,
150
184
}),
151
185
);
152
- print ('Status response: ${statusResponse .body }' );
153
-
154
- final result = jsonDecode (statusResponse.body);
155
- expect (result['error' ], isNull);
156
- expect (result['result' ], isNotNull);
157
-
158
- final status =
159
- TransactionStatus .fromJson (result['result' ] as Map <String , dynamic >);
160
-
161
- // Verify the required finality_status field is present and valid
162
- expect (status.finalityStatus, isNotNull);
163
- expect (
164
- ['RECEIVED' , 'REJECTED' , 'ACCEPTED_ON_L2' , 'ACCEPTED_ON_L1' ]
165
- .contains (status.finalityStatus),
166
- isTrue,
167
- reason:
168
- 'finality_status should be one of: RECEIVED, REJECTED, ACCEPTED_ON_L2, ACCEPTED_ON_L1' );
169
-
170
- // Verify that execution_status is one of the expected values or null
171
- expect (
172
- status.executionStatus == null ||
173
- ['SUCCEEDED' , 'REVERTED' ].contains (status.executionStatus),
174
- isTrue,
175
- reason:
176
- 'execution_status should be null or one of: SUCCEEDED, REVERTED' );
177
- }, tags: ['integration' ]);
178
186
179
- test ('should return transaction status with required finality_status field' ,
180
- () async {
181
- // Mock response for a valid transaction
182
- final mockResponse = {
183
- 'jsonrpc' : '2.0' ,
184
- 'id' : 1 ,
185
- 'result' : {
186
- 'finality_status' : 'ACCEPTED_ON_L2' ,
187
- 'execution_status' : 'SUCCEEDED'
188
- }
189
- };
190
-
191
- // Test that the model can parse this response
192
- final status = TransactionStatus .fromJson (
193
- mockResponse['result' ] as Map <String , dynamic >);
194
-
195
- // Verify the required finality_status field is present
196
- expect (status.finalityStatus, isNotNull);
197
- expect (status.finalityStatus, equals ('ACCEPTED_ON_L2' ));
198
-
199
- // Verify the optional execution_status field is present
200
- expect (status.executionStatus, isNotNull);
201
- expect (status.executionStatus, equals ('SUCCEEDED' ));
202
-
203
- // Verify that finality_status is one of the expected values
204
- expect (
205
- ['RECEIVED' , 'REJECTED' , 'ACCEPTED_ON_L2' , 'ACCEPTED_ON_L1' ]
206
- .contains (status.finalityStatus),
207
- isTrue,
208
- reason:
209
- 'finality_status should be one of: RECEIVED, REJECTED, ACCEPTED_ON_L2, ACCEPTED_ON_L1' );
210
-
211
- // Verify that execution_status is one of the expected values or null
212
- expect (
213
- status.executionStatus == null ||
214
- ['SUCCEEDED' , 'REVERTED' ].contains (status.executionStatus),
215
- isTrue,
216
- reason:
217
- 'execution_status should be null or one of: SUCCEEDED, REVERTED' );
218
- });
187
+ final result = jsonDecode (response.body);
188
+ expect (result['error' ], isNull,
189
+ reason: 'Failed to get transaction status' );
190
+
191
+ final status = TransactionStatus .fromJson (result['result' ]);
192
+ expect (status.finalityStatus, isNotNull,
193
+ reason: 'Transaction status should have a finality status' );
194
+ }, tags: ['integration' ]);
219
195
220
196
test ('should handle transaction status with only finality_status field' ,
221
197
() async {
222
- // Mock response for a transaction with only finality_status
223
- final mockResponse = {
224
- 'jsonrpc' : '2.0' ,
225
- 'id' : 1 ,
226
- 'result' : {'finality_status' : 'RECEIVED' }
227
- };
228
-
229
- // Test that the model can parse this response
230
- final status = TransactionStatus .fromJson (
231
- mockResponse['result' ] as Map <String , dynamic >);
232
-
233
- // Verify the required finality_status field is present
234
- expect (status.finalityStatus, isNotNull);
235
- expect (status.finalityStatus, equals ('RECEIVED' ));
236
-
237
- // Verify the optional execution_status field is null
238
- expect (status.executionStatus, isNull);
239
- });
198
+ expect (successfulTxHash, isNotNull,
199
+ reason: 'Previous test must succeed to get a valid transaction hash' );
200
+
201
+ final response = await http.post (
202
+ devnetUri,
203
+ headers: {'Content-Type' : 'application/json' },
204
+ body: jsonEncode ({
205
+ 'jsonrpc' : '2.0' ,
206
+ 'method' : 'starknet_getTransactionStatus' ,
207
+ 'params' : [successfulTxHash],
208
+ 'id' : 1 ,
209
+ }),
210
+ );
211
+
212
+ final result = jsonDecode (response.body);
213
+ expect (result['error' ], isNull,
214
+ reason: 'Failed to get transaction status' );
215
+
216
+ final status = TransactionStatus .fromJson (result['result' ]);
217
+ expect (status.finalityStatus, isNotNull,
218
+ reason: 'Transaction status should have a finality status' );
219
+ }, tags: ['integration' ]);
240
220
});
241
221
}
0 commit comments