Skip to content

Commit d7b5030

Browse files
authored
Merge branch 'main' into 20240908-addl-transient-error-detection
2 parents 1056cb1 + 76f5575 commit d7b5030

9 files changed

+608
-34
lines changed

examples/token_airdrop.rs

+268-19
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ use std::iter::repeat;
2222

2323
use clap::Parser;
2424
use hedera::{
25-
AccountBalanceQuery, AccountCreateTransaction, AccountId, Client, Hbar, PrivateKey, TokenAirdropTransaction, TokenAssociateTransaction, TokenCreateTransaction, TokenDeleteTransaction, TokenGrantKycTransaction, TokenMintTransaction, TokenWipeTransaction, TransferTransaction
25+
AccountBalanceQuery, AccountCreateTransaction, AccountId, Client, Hbar, PrivateKey, TokenAirdropTransaction, TokenCancelAirdropTransaction, TokenClaimAirdropTransaction, TokenCreateTransaction, TokenMintTransaction, TokenRejectTransaction
2626
};
2727
use time::{Duration, OffsetDateTime};
2828

@@ -50,8 +50,8 @@ async fn main() -> anyhow::Result<()> {
5050
let client = Client::for_name(&hedera_network)?;
5151

5252
client.set_operator(operator_account_id, operator_key.clone());
53-
let private_key_1 = PrivateKey::generate_ed25519();
54-
let alice = AccountCreateTransaction::new()
53+
let private_key_1 = PrivateKey::generate_ecdsa();
54+
let alice_id = AccountCreateTransaction::new()
5555
.key(private_key_1.public_key())
5656
.initial_balance(Hbar::new(10))
5757
.max_automatic_token_associations(-1)
@@ -62,8 +62,8 @@ async fn main() -> anyhow::Result<()> {
6262
.account_id
6363
.unwrap();
6464

65-
let private_key_2 = PrivateKey::generate_ed25519();
66-
let bob = AccountCreateTransaction::new()
65+
let private_key_2 = PrivateKey::generate_ecdsa();
66+
let bob_id = AccountCreateTransaction::new()
6767
.key(private_key_2.public_key())
6868
.max_automatic_token_associations(1)
6969
.execute(&client)
@@ -73,8 +73,8 @@ async fn main() -> anyhow::Result<()> {
7373
.account_id
7474
.unwrap();
7575

76-
let private_key_3 = PrivateKey::generate_ed25519();
77-
let carol = AccountCreateTransaction::new()
76+
let private_key_3 = PrivateKey::generate_ecdsa();
77+
let carol_id = AccountCreateTransaction::new()
7878
.key(private_key_3.public_key())
7979
.max_automatic_token_associations(0)
8080
.execute(&client)
@@ -84,7 +84,7 @@ async fn main() -> anyhow::Result<()> {
8484
.account_id
8585
.unwrap();
8686

87-
let treasury_key = PrivateKey::generate_ed25519();
87+
let treasury_key = PrivateKey::generate_ecdsa();
8888
let treasury_account_id = AccountCreateTransaction::new()
8989
.key(treasury_key.public_key())
9090
.initial_balance(Hbar::new(10))
@@ -124,7 +124,6 @@ async fn main() -> anyhow::Result<()> {
124124
let nft_id = TokenCreateTransaction::new()
125125
.name("example NFT")
126126
.symbol("F")
127-
.decimals(3)
128127
.max_supply(10)
129128
.treasury_account_id(treasury_account_id)
130129
.token_supply_type(hedera::TokenSupplyType::Finite)
@@ -135,7 +134,7 @@ async fn main() -> anyhow::Result<()> {
135134
.pause_key(operator_key.clone().public_key())
136135
.expiration_time(OffsetDateTime::now_utc() + Duration::hours(2))
137136
.freeze_with(&client)?
138-
.sign(treasury_key)
137+
.sign(treasury_key.clone())
139138
.execute(&client)
140139
.await?
141140
.get_receipt(&client)
@@ -157,13 +156,15 @@ async fn main() -> anyhow::Result<()> {
157156
*/
158157
println!("Airdropping tokens to all accounts");
159158

160-
let airdrop_record = TokenAirdropTransaction::new()
161-
.token_transfer(token_id, alice, 10)
159+
let tx_record = TokenAirdropTransaction::new()
160+
.token_transfer(token_id, alice_id, 10)
162161
.token_transfer(token_id, treasury_account_id, -10)
163-
.token_transfer(token_id, bob, 10)
162+
.token_transfer(token_id, bob_id, 10)
164163
.token_transfer(token_id, treasury_account_id, -10)
165-
.token_transfer(token_id, carol, 10)
164+
.token_transfer(token_id, carol_id, 10)
166165
.token_transfer(token_id, treasury_account_id, -10)
166+
.freeze_with(&client)?
167+
.sign(treasury_key.clone())
167168
.execute(&client)
168169
.await?
169170
.get_record(&client)
@@ -175,29 +176,29 @@ async fn main() -> anyhow::Result<()> {
175176
*/
176177
println!(
177178
"Pending airdrop length: {}",
178-
airdrop_record.pending_airdrop_records.len()
179+
tx_record.pending_airdrop_records.len()
179180
);
180181
println!(
181182
"Pending airdrops: {:?}",
182-
airdrop_record.pending_airdrop_records.get(0)
183+
tx_record.pending_airdrop_records.get(0)
183184
);
184185

185186
/*
186187
* Step 5:
187188
* Query to verify alice and bob received the airdrops and carol did not
188189
*/
189190
let alice_balance = AccountBalanceQuery::new()
190-
.account_id(alice)
191+
.account_id(alice_id)
191192
.execute(&client)
192193
.await?;
193194

194195
let bob_balance = AccountBalanceQuery::new()
195-
.account_id(bob)
196+
.account_id(bob_id)
196197
.execute(&client)
197198
.await?;
198199

199200
let carol_balance = AccountBalanceQuery::new()
200-
.account_id(carol)
201+
.account_id(carol_id)
201202
.execute(&client)
202203
.await?;
203204

@@ -209,10 +210,258 @@ async fn main() -> anyhow::Result<()> {
209210
"Bob ft balance after airdrop: {}",
210211
bob_balance.tokens.get(&token_id).unwrap()
211212
);
213+
println!(
214+
"Carol ft balance after airdrop: {:?}",
215+
carol_balance.tokens.get(&token_id)
216+
);
217+
218+
/*
219+
* Step 6:
220+
* Claim the airdrop for carol
221+
*/
222+
println!("Claiming ft with Carol");
223+
224+
_ = TokenClaimAirdropTransaction::new()
225+
.add_pending_airdrop_id(
226+
tx_record
227+
.pending_airdrop_records
228+
.get(0)
229+
.unwrap()
230+
.pending_airdrop_id,
231+
)
232+
.freeze_with(&client)?
233+
.sign(private_key_3.clone())
234+
.execute(&client)
235+
.await?
236+
.get_receipt(&client)
237+
.await?;
238+
239+
let carol_balance = AccountBalanceQuery::new()
240+
.account_id(carol_id)
241+
.execute(&client)
242+
.await?;
243+
212244
println!(
213245
"Carol ft balance after airdrop: {}",
214246
carol_balance.tokens.get(&token_id).unwrap()
215247
);
216248

249+
/*
250+
* Step 7:
251+
* Airdrop the NFTs to all three accounts
252+
*/
253+
println!("Airdropping nfts");
254+
let tx_record = TokenAirdropTransaction::new()
255+
.nft_transfer(nft_id.nft(1), treasury_account_id, alice_id)
256+
.nft_transfer(nft_id.nft(2), treasury_account_id, bob_id)
257+
.nft_transfer(nft_id.nft(3), treasury_account_id, carol_id)
258+
.freeze_with(&client)?
259+
.sign(treasury_key.clone())
260+
.execute(&client)
261+
.await?
262+
.get_record(&client)
263+
.await?;
264+
265+
/*
266+
* Step 8:
267+
* Get the transaction record and verify two pending airdrops (for bob & carol)
268+
*/
269+
println!(
270+
"Pending airdrops length: {}",
271+
tx_record.pending_airdrop_records.len()
272+
);
273+
println!(
274+
"Pending airdrops for Bob: {}",
275+
tx_record.pending_airdrop_records.get(0).unwrap()
276+
);
277+
println!(
278+
"Pending airdrops for Carol: {}",
279+
tx_record.pending_airdrop_records.get(1).unwrap()
280+
);
281+
282+
/*
283+
* Step 9:
284+
* Query to verify alice received the airdrop and bob and carol did not
285+
*/
286+
let alice_balance = AccountBalanceQuery::new()
287+
.account_id(alice_id)
288+
.execute(&client)
289+
.await?;
290+
291+
let bob_balance = AccountBalanceQuery::new()
292+
.account_id(bob_id)
293+
.execute(&client)
294+
.await?;
295+
296+
let carol_balance = AccountBalanceQuery::new()
297+
.account_id(carol_id)
298+
.execute(&client)
299+
.await?;
300+
301+
println!(
302+
"Alice nft balance after airdrop: {}",
303+
alice_balance.tokens.get(&nft_id).unwrap()
304+
);
305+
306+
println!(
307+
"Bob nft balance after airdrop: {:?}",
308+
bob_balance.tokens.get(&nft_id)
309+
);
310+
311+
println!(
312+
"Carol nft balance after airdrop: {:?}",
313+
carol_balance.tokens.get(&nft_id)
314+
);
315+
316+
/*
317+
* Step 10:
318+
* Claim the airdrop for bob
319+
*/
320+
println!("Claiming nft with Bob");
321+
_ = TokenClaimAirdropTransaction::new()
322+
.add_pending_airdrop_id(
323+
tx_record
324+
.pending_airdrop_records
325+
.get(0)
326+
.unwrap()
327+
.pending_airdrop_id,
328+
)
329+
.freeze_with(&client)?
330+
.sign(private_key_2.clone())
331+
.execute(&client)
332+
.await?
333+
.get_receipt(&client)
334+
.await?;
335+
336+
let bob_balance = AccountBalanceQuery::new()
337+
.account_id(bob_id)
338+
.execute(&client)
339+
.await?;
340+
341+
println!(
342+
"Bob nft balance after claim: {}",
343+
bob_balance.tokens.get(&nft_id).unwrap()
344+
);
345+
346+
/*
347+
* Step 11:
348+
* Cancel the airdrop for carol
349+
*/
350+
println!("Cancelling nft for Carol");
351+
352+
_ = TokenCancelAirdropTransaction::new()
353+
.add_pending_airdrop_id(
354+
tx_record
355+
.pending_airdrop_records
356+
.get(1)
357+
.unwrap()
358+
.pending_airdrop_id,
359+
)
360+
.freeze_with(&client)?
361+
.sign(treasury_key.clone())
362+
.execute(&client)
363+
.await?
364+
.get_receipt(&client)
365+
.await?;
366+
367+
let carol_balance = AccountBalanceQuery::new()
368+
.account_id(carol_id)
369+
.execute(&client)
370+
.await?;
371+
372+
println!(
373+
"Carol nft balance after cancel: {:?}",
374+
carol_balance.tokens.get(&nft_id)
375+
);
376+
377+
/*
378+
* Step 12:
379+
* Reject the NFT for bob
380+
*/
381+
println!("Rejecting nft with Bob");
382+
383+
_ = TokenRejectTransaction::new()
384+
.owner(bob_id)
385+
.add_nft_id(nft_id.nft(2))
386+
.freeze_with(&client)?
387+
.sign(private_key_2)
388+
.execute(&client)
389+
.await?
390+
.get_receipt(&client)
391+
.await?;
392+
393+
/*
394+
* Step 13:
395+
* Query to verify bob no longer has the NFT
396+
*/
397+
let bob_balance = AccountBalanceQuery::new()
398+
.account_id(bob_id)
399+
.execute(&client)
400+
.await?;
401+
402+
println!(
403+
"Bob nft balance after reject: {}",
404+
bob_balance.tokens.get(&nft_id).unwrap()
405+
);
406+
407+
/*
408+
* Step 13:
409+
* Query to verify the NFT was returned to the Treasury
410+
*/
411+
let treasury_balance = AccountBalanceQuery::new()
412+
.account_id(treasury_account_id)
413+
.execute(&client)
414+
.await?;
415+
416+
println!(
417+
"Treasury nft balance after reject: {}",
418+
treasury_balance.tokens.get(&nft_id).unwrap()
419+
);
420+
421+
/*
422+
* Step 14:
423+
* Reject the Fungible token for carol
424+
*/
425+
println!("Rejecting ft with Carol");
426+
427+
_ = TokenRejectTransaction::new()
428+
.owner(carol_id)
429+
.add_token_id(token_id)
430+
.freeze_with(&client)?
431+
.sign(private_key_3.clone())
432+
.execute(&client)
433+
.await?
434+
.get_receipt(&client)
435+
.await?;
436+
437+
/*
438+
* Step 14:
439+
* Query to verify Carol no longer has the fungible tokens
440+
*/
441+
let carol_balance = AccountBalanceQuery::new()
442+
.account_id(carol_id)
443+
.execute(&client)
444+
.await?;
445+
446+
println!(
447+
"Carol ft balance after reject: {}",
448+
carol_balance.tokens.get(&token_id).unwrap()
449+
);
450+
451+
/*
452+
* Step 15:
453+
* Query to verify Treasury received the rejected fungible tokens
454+
*/
455+
let treasury_balance = AccountBalanceQuery::new()
456+
.account_id(treasury_account_id)
457+
.execute(&client)
458+
.await?;
459+
460+
println!(
461+
"Treasury ft balance after reject: {}",
462+
treasury_balance.tokens.get(&token_id).unwrap()
463+
);
464+
465+
println!("Token airdrop example completed successfully");
217466
Ok(())
218467
}

src/mirror_query/any.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,10 @@ impl MirrorQueryExecute for AnyMirrorQueryData {
5959

6060
type Response = AnyMirrorQueryResponse;
6161

62-
type ItemStream<'a> = BoxStream<'a, crate::Result<Self::Item>>
63-
where
64-
Self: 'a;
62+
type ItemStream<'a>
63+
= BoxStream<'a, crate::Result<Self::Item>>
64+
where
65+
Self: 'a;
6566

6667
fn subscribe_with_optional_timeout<'a>(
6768
&self,

0 commit comments

Comments
 (0)