-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy path03_send_transaction.zig
More file actions
220 lines (187 loc) Β· 9.44 KB
/
Copy path03_send_transaction.zig
File metadata and controls
220 lines (187 loc) Β· 9.44 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
/// Example: Sending Transactions
/// This example demonstrates how to:
/// - Create transactions (Legacy, EIP-1559)
/// - Sign transactions
/// - Send transactions
/// - Wait for confirmations
/// - Check transaction status
/// - Use middleware for automation
const std = @import("std");
const zigeth = @import("zigeth");
pub fn main() !void {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
std.debug.print("\nπΈ Zigeth Transaction Examples\n", .{});
std.debug.print("βββββββββββββββββββββββββββββββ\n\n", .{});
// Setup: Create wallet and connect to network
std.debug.print("π‘ Setting up wallet and provider...\n", .{});
// IMPORTANT: Replace with your own private key in production!
const private_key = try zigeth.crypto.PrivateKey.fromBytes([_]u8{0x01} ** 32);
const signer_config = zigeth.middleware.SignerConfig.sepolia(); // Using Sepolia testnet
var signer_middleware = try zigeth.middleware.SignerMiddleware.init(
allocator,
private_key,
signer_config,
);
var provider = try zigeth.providers.Networks.sepolia(allocator);
defer provider.deinit();
const from_address = try signer_middleware.getAddress();
const from_hex = try from_address.toHex(allocator);
defer allocator.free(from_hex);
std.debug.print("β
Wallet address: {s}\n", .{from_hex});
std.debug.print("β
Connected to Sepolia testnet\n\n", .{});
// Example 1: Create a simple ETH transfer (Legacy)
std.debug.print("Example 1: Legacy Transaction\n", .{});
std.debug.print("βββββββββββββββββββββββββββββ\n", .{});
{
const to_address = try zigeth.primitives.Address.fromHex("0x9999999999999999999999999999999999999999");
const empty_data = try zigeth.primitives.Bytes.fromSlice(allocator, &[_]u8{});
var tx = zigeth.types.Transaction.newLegacy(
allocator,
to_address,
@as(u256, 1_000_000_000_000_000), // 0.001 ETH
empty_data,
0, // nonce
21000, // gas_limit
@as(u256, 20_000_000_000), // 20 gwei gas_price
);
tx.from = from_address;
std.debug.print("β
Created legacy transaction\n", .{});
std.debug.print(" To: {any}\n", .{tx.to.?});
std.debug.print(" Value: {d} wei\n", .{tx.value});
std.debug.print(" Gas limit: {d}\n", .{tx.gas_limit});
std.debug.print(" Gas price: {d} wei\n\n", .{tx.gas_price.?});
}
// Example 2: Create EIP-1559 transaction
std.debug.print("Example 2: EIP-1559 Transaction\n", .{});
std.debug.print("ββββββββββββββββββββββββββββββββ\n", .{});
{
const to_address = try zigeth.primitives.Address.fromHex("0x8888888888888888888888888888888888888888");
const empty_data = try zigeth.primitives.Bytes.fromSlice(allocator, &[_]u8{});
var tx = zigeth.types.Transaction.newEip1559(
allocator,
to_address,
@as(u256, 1_000_000_000_000_000), // 0.001 ETH
empty_data,
1, // nonce
21000, // gas_limit
@as(u256, 50_000_000_000), // 50 gwei max_fee
@as(u256, 2_000_000_000), // 2 gwei priority_fee
11155111, // chain_id (Sepolia)
null, // access_list
);
tx.from = from_address;
std.debug.print("β
Created EIP-1559 transaction\n", .{});
std.debug.print(" Type: EIP-1559\n", .{});
std.debug.print(" Max fee: {d} wei\n", .{tx.max_fee_per_gas.?});
std.debug.print(" Priority fee: {d} wei\n\n", .{tx.max_priority_fee_per_gas.?});
}
// Example 3: Using Middleware for Automatic Gas & Nonce
std.debug.print("Example 3: Transaction with Middleware\n", .{});
std.debug.print("βββββββββββββββββββββββββββββββββββββββ\n", .{});
{
// Setup middleware
const gas_config = zigeth.middleware.GasConfig.fast(); // Fast confirmation
var gas_middleware = zigeth.middleware.GasMiddleware.init(
allocator,
provider.getProvider(),
gas_config,
);
var nonce_middleware = try zigeth.middleware.NonceMiddleware.init(
allocator,
provider.getProvider(),
.hybrid, // Hybrid strategy for reliability
);
defer nonce_middleware.deinit();
// Create transaction with middleware
const to_address = try zigeth.primitives.Address.fromHex("0x7777777777777777777777777777777777777777");
const empty_data = try zigeth.primitives.Bytes.fromSlice(allocator, &[_]u8{});
const nonce = try nonce_middleware.reserveNonce(from_address);
// Create transaction with initial values
var tx = zigeth.types.Transaction.newEip1559(
allocator,
to_address,
@as(u256, 1_000_000_000_000_000), // 0.001 ETH
empty_data,
nonce,
21000, // initial gas_limit (will be estimated)
@as(u256, 50_000_000_000), // temp values
@as(u256, 2_000_000_000),
11155111, // Sepolia
null,
);
tx.from = from_address;
// Apply middleware to optimize gas settings
try gas_middleware.applyGasSettings(&tx);
std.debug.print("β
Transaction configured with middleware\n", .{});
std.debug.print(" Nonce: {d} (auto-managed)\n", .{tx.nonce});
std.debug.print(" Gas limit: {d}\n", .{tx.gas_limit});
std.debug.print(" Max fee: {any}\n", .{tx.max_fee_per_gas});
// Check if we have sufficient balance
const has_balance = try gas_middleware.checkSufficientBalance(
from_address,
tx.value,
tx.gas_limit,
);
std.debug.print(" Sufficient balance: {}\n\n", .{has_balance});
}
// Example 4: Sign transaction
std.debug.print("Example 4: Sign Transaction\n", .{});
std.debug.print("βββββββββββββββββββββββββββ\n", .{});
{
const to_address = try zigeth.primitives.Address.fromHex("0x6666666666666666666666666666666666666666");
const empty_data = try zigeth.primitives.Bytes.fromSlice(allocator, &[_]u8{});
var tx = zigeth.types.Transaction.newEip1559(
allocator,
to_address,
@as(u256, 1_000_000_000_000_000), // 0.001 ETH
empty_data,
0, // nonce
21000, // gas_limit
@as(u256, 50_000_000_000), // 50 gwei max_fee
@as(u256, 2_000_000_000), // 2 gwei priority_fee
11155111, // Sepolia
null, // access_list
);
tx.from = from_address;
// Sign the transaction
const signature = try signer_middleware.signTransaction(&tx);
std.debug.print("β
Transaction signed\n", .{});
std.debug.print(" Signature v: {}\n", .{signature.v});
std.debug.print(" Signature valid: {}\n", .{signature.isValid()});
// Sign and serialize for sending
const raw_tx = try signer_middleware.signAndSerialize(&tx);
defer allocator.free(raw_tx);
std.debug.print(" Serialized length: {} bytes\n", .{raw_tx.len});
std.debug.print(" Ready to send!\n\n", .{});
}
// Example 5: Complete transaction flow (simulated)
std.debug.print("Example 5: Complete Transaction Flow\n", .{});
std.debug.print("βββββββββββββββββββββββββββββββββββββ\n", .{});
{
std.debug.print("π Transaction flow:\n", .{});
std.debug.print(" 1. Create transaction β
\n", .{});
std.debug.print(" 2. Get nonce from network β
\n", .{});
std.debug.print(" 3. Estimate gas limit β
\n", .{});
std.debug.print(" 4. Get optimal gas price β
\n", .{});
std.debug.print(" 5. Check balance β
\n", .{});
std.debug.print(" 6. Sign transaction β
\n", .{});
std.debug.print(" 7. Serialize to raw bytes β
\n", .{});
std.debug.print(" 8. Send to network (would use provider.sendRawTransaction)\n", .{});
std.debug.print(" 9. Wait for confirmation (would use provider.waitForTransaction)\n", .{});
std.debug.print(" 10. Verify receipt (would check receipt.status)\n\n", .{});
std.debug.print("π‘ To actually send transactions:\n", .{});
std.debug.print(" 1. Ensure you have testnet ETH\n", .{});
std.debug.print(" 2. Use your own private key\n", .{});
std.debug.print(" 3. Uncomment the send code below:\n\n", .{});
std.debug.print(" // const tx_hash = try provider.sendRawTransaction(raw_tx);\n", .{});
std.debug.print(" // const receipt = try provider.waitForTransaction(tx_hash, 60000);\n", .{});
std.debug.print(" // defer receipt.deinit();\n", .{});
std.debug.print(" // if (receipt.status == .success) {{\n", .{});
std.debug.print(" // std.debug.print(\"Transaction successful!\\n\", .{{}});\n", .{});
std.debug.print(" // }}\n\n", .{});
}
std.debug.print("π All transaction examples completed!\n", .{});
std.debug.print("π‘ Tip: Use Sepolia testnet for actual testing\n\n", .{});
}