@sudobility/contracts 1.10.0 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/dist/solana/solana/mailer-client.d.ts +7 -0
  2. package/dist/solana/solana/mailer-client.d.ts.map +1 -1
  3. package/dist/solana/solana/mailer-client.js +30 -1
  4. package/dist/solana/solana/mailer-client.js.map +1 -1
  5. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +1 -1
  6. package/dist/unified/src/react/hooks/useMailerMutations.js +1 -1
  7. package/dist/unified/src/solana/mailer-client.d.ts +7 -0
  8. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -1
  9. package/dist/unified/src/solana/mailer-client.js +30 -1
  10. package/dist/unified/src/solana/mailer-client.js.map +1 -1
  11. package/dist/unified/src/unified/onchain-mailer-client.d.ts +2 -1
  12. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  13. package/dist/unified/src/unified/onchain-mailer-client.js +23 -2
  14. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  15. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +1 -1
  16. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +1 -1
  17. package/dist/unified-esm/src/solana/mailer-client.d.ts +7 -0
  18. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -1
  19. package/dist/unified-esm/src/solana/mailer-client.js +30 -1
  20. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -1
  21. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +2 -1
  22. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  23. package/dist/unified-esm/src/unified/onchain-mailer-client.js +23 -2
  24. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  25. package/package.json +6 -1
  26. package/programs/mailer/src/lib.rs +429 -102
  27. package/programs/mailer/tests/integration_tests.rs +387 -65
@@ -1,3 +1,4 @@
1
+ use borsh::BorshDeserialize;
1
2
  use solana_program::{
2
3
  instruction::{AccountMeta, Instruction},
3
4
  program_pack::Pack,
@@ -13,11 +14,10 @@ use spl_token::{
13
14
  instruction as spl_instruction,
14
15
  state::{Account as TokenAccount, Mint},
15
16
  };
16
- use borsh::BorshDeserialize;
17
17
  use std::str::FromStr;
18
18
 
19
19
  // Import our program
20
- use mailer::{MailerInstruction, MailerState, RecipientClaim, Delegation};
20
+ use mailer::{Delegation, MailerInstruction, MailerState, RecipientClaim};
21
21
 
22
22
  // Program ID for tests
23
23
  const PROGRAM_ID_STR: &str = "9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF";
@@ -51,7 +51,8 @@ async fn create_usdc_mint(
51
51
  &payer.pubkey(),
52
52
  None,
53
53
  6, // USDC has 6 decimals
54
- ).unwrap(),
54
+ )
55
+ .unwrap(),
55
56
  ],
56
57
  Some(&payer.pubkey()),
57
58
  );
@@ -82,12 +83,8 @@ async fn create_token_account(
82
83
  TokenAccount::LEN as u64,
83
84
  &spl_token::id(),
84
85
  ),
85
- spl_instruction::initialize_account(
86
- &spl_token::id(),
87
- &account.pubkey(),
88
- mint,
89
- owner,
90
- ).unwrap(),
86
+ spl_instruction::initialize_account(&spl_token::id(), &account.pubkey(), mint, owner)
87
+ .unwrap(),
91
88
  ],
92
89
  Some(&payer.pubkey()),
93
90
  );
@@ -114,7 +111,8 @@ async fn mint_to(
114
111
  &payer.pubkey(),
115
112
  &[],
116
113
  amount,
117
- ).unwrap()],
114
+ )
115
+ .unwrap()],
118
116
  Some(&payer.pubkey()),
119
117
  );
120
118
  transaction.sign(&[payer], recent_blockhash);
@@ -170,7 +168,7 @@ async fn test_initialize_program() {
170
168
  // Verify the mailer state was initialized correctly
171
169
  let account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
172
170
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &account.data[8..]).unwrap();
173
-
171
+
174
172
  assert_eq!(mailer_state.owner, payer.pubkey());
175
173
  assert_eq!(mailer_state.usdc_mint, usdc_mint);
176
174
  assert_eq!(mailer_state.send_fee, 100_000); // 0.1 USDC
@@ -190,7 +188,7 @@ async fn test_send_priority_message() {
190
188
  // Create USDC mint and accounts
191
189
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
192
190
  let (mailer_pda, _) = get_mailer_pda();
193
-
191
+
194
192
  // Initialize the program first
195
193
  let init_instruction = Instruction::new_with_borsh(
196
194
  program_id(),
@@ -207,11 +205,33 @@ async fn test_send_priority_message() {
207
205
  banks_client.process_transaction(transaction).await.unwrap();
208
206
 
209
207
  // Create token accounts
210
- let sender_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
211
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
212
-
208
+ let sender_usdc = create_token_account(
209
+ &mut banks_client,
210
+ &payer,
211
+ recent_blockhash,
212
+ &usdc_mint,
213
+ &payer.pubkey(),
214
+ )
215
+ .await;
216
+ let mailer_usdc = create_token_account(
217
+ &mut banks_client,
218
+ &payer,
219
+ recent_blockhash,
220
+ &usdc_mint,
221
+ &mailer_pda,
222
+ )
223
+ .await;
224
+
213
225
  // Mint USDC to sender
214
- mint_to(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &sender_usdc, 1_000_000).await; // 1 USDC
226
+ mint_to(
227
+ &mut banks_client,
228
+ &payer,
229
+ recent_blockhash,
230
+ &usdc_mint,
231
+ &sender_usdc,
232
+ 1_000_000,
233
+ )
234
+ .await; // 1 USDC
215
235
 
216
236
  // Get recipient claim PDA
217
237
  let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
@@ -247,16 +267,22 @@ async fn test_send_priority_message() {
247
267
  let _recent_blockhash = banks_client.get_latest_blockhash().await.unwrap();
248
268
 
249
269
  // Verify recipient claim was created with correct amount
250
- let claim_account = banks_client.get_account(recipient_claim_pda).await.unwrap().unwrap();
251
- let recipient_claim: RecipientClaim = BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
252
-
270
+ let claim_account = banks_client
271
+ .get_account(recipient_claim_pda)
272
+ .await
273
+ .unwrap()
274
+ .unwrap();
275
+ let recipient_claim: RecipientClaim =
276
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
277
+
253
278
  assert_eq!(recipient_claim.recipient, payer.pubkey());
254
279
  assert_eq!(recipient_claim.amount, 90_000); // 90% of send_fee (100,000)
255
280
 
256
281
  // Verify mailer state was updated with owner share
257
282
  let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
258
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
259
-
283
+ let mailer_state: MailerState =
284
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
285
+
260
286
  // Debug output
261
287
  println!("Debug - Mailer state:");
262
288
  println!(" owner: {}", mailer_state.owner);
@@ -265,7 +291,7 @@ async fn test_send_priority_message() {
265
291
  println!(" delegation_fee: {}", mailer_state.delegation_fee);
266
292
  println!(" owner_claimable: {}", mailer_state.owner_claimable);
267
293
  println!(" bump: {}", mailer_state.bump);
268
-
294
+
269
295
  assert_eq!(mailer_state.owner_claimable, 10_000); // 10% of send_fee
270
296
  }
271
297
 
@@ -281,7 +307,7 @@ async fn test_send_standard_message() {
281
307
  // Setup similar to priority test
282
308
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
283
309
  let (mailer_pda, _) = get_mailer_pda();
284
-
310
+
285
311
  // Initialize the program
286
312
  let init_instruction = Instruction::new_with_borsh(
287
313
  program_id(),
@@ -298,11 +324,33 @@ async fn test_send_standard_message() {
298
324
  banks_client.process_transaction(transaction).await.unwrap();
299
325
 
300
326
  // Create token accounts
301
- let sender_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
302
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
303
-
327
+ let sender_usdc = create_token_account(
328
+ &mut banks_client,
329
+ &payer,
330
+ recent_blockhash,
331
+ &usdc_mint,
332
+ &payer.pubkey(),
333
+ )
334
+ .await;
335
+ let mailer_usdc = create_token_account(
336
+ &mut banks_client,
337
+ &payer,
338
+ recent_blockhash,
339
+ &usdc_mint,
340
+ &mailer_pda,
341
+ )
342
+ .await;
343
+
304
344
  // Mint USDC to sender
305
- mint_to(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &sender_usdc, 1_000_000).await;
345
+ mint_to(
346
+ &mut banks_client,
347
+ &payer,
348
+ recent_blockhash,
349
+ &usdc_mint,
350
+ &sender_usdc,
351
+ 1_000_000,
352
+ )
353
+ .await;
306
354
 
307
355
  // Get recipient claim PDA (needed even if not used for standard send)
308
356
  let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
@@ -336,7 +384,8 @@ async fn test_send_standard_message() {
336
384
 
337
385
  // Verify only owner fee was charged (10% of send_fee = 10,000)
338
386
  let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
339
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
387
+ let mailer_state: MailerState =
388
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
340
389
  assert_eq!(mailer_state.owner_claimable, 10_000); // Only 10% fee
341
390
  }
342
391
 
@@ -352,7 +401,7 @@ async fn test_claim_recipient_share() {
352
401
  // Setup and send priority message first (similar to previous test)
353
402
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
354
403
  let (mailer_pda, _) = get_mailer_pda();
355
-
404
+
356
405
  // Initialize
357
406
  let init_instruction = Instruction::new_with_borsh(
358
407
  program_id(),
@@ -369,11 +418,33 @@ async fn test_claim_recipient_share() {
369
418
  banks_client.process_transaction(transaction).await.unwrap();
370
419
 
371
420
  // Create token accounts
372
- let sender_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
373
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
374
-
421
+ let sender_usdc = create_token_account(
422
+ &mut banks_client,
423
+ &payer,
424
+ recent_blockhash,
425
+ &usdc_mint,
426
+ &payer.pubkey(),
427
+ )
428
+ .await;
429
+ let mailer_usdc = create_token_account(
430
+ &mut banks_client,
431
+ &payer,
432
+ recent_blockhash,
433
+ &usdc_mint,
434
+ &mailer_pda,
435
+ )
436
+ .await;
437
+
375
438
  // Mint USDC
376
- mint_to(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &sender_usdc, 1_000_000).await;
439
+ mint_to(
440
+ &mut banks_client,
441
+ &payer,
442
+ recent_blockhash,
443
+ &usdc_mint,
444
+ &sender_usdc,
445
+ 1_000_000,
446
+ )
447
+ .await;
377
448
 
378
449
  let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
379
450
 
@@ -385,7 +456,7 @@ async fn test_claim_recipient_share() {
385
456
  subject: "Test".to_string(),
386
457
  _body: "Test".to_string(),
387
458
  revenue_share_to_receiver: true,
388
- resolve_sender_to_name: false,
459
+ resolve_sender_to_name: false,
389
460
  },
390
461
  vec![
391
462
  AccountMeta::new(payer.pubkey(), true),
@@ -403,7 +474,14 @@ async fn test_claim_recipient_share() {
403
474
  banks_client.process_transaction(transaction).await.unwrap();
404
475
 
405
476
  // Create recipient's own USDC account to receive the claim
406
- let recipient_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
477
+ let recipient_usdc = create_token_account(
478
+ &mut banks_client,
479
+ &payer,
480
+ recent_blockhash,
481
+ &usdc_mint,
482
+ &payer.pubkey(),
483
+ )
484
+ .await;
407
485
 
408
486
  // Now claim the recipient share
409
487
  let claim_instruction = Instruction::new_with_borsh(
@@ -424,12 +502,21 @@ async fn test_claim_recipient_share() {
424
502
  banks_client.process_transaction(transaction).await.unwrap();
425
503
 
426
504
  // Verify the claim was processed
427
- let claim_account = banks_client.get_account(recipient_claim_pda).await.unwrap().unwrap();
428
- let recipient_claim: RecipientClaim = BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
505
+ let claim_account = banks_client
506
+ .get_account(recipient_claim_pda)
507
+ .await
508
+ .unwrap()
509
+ .unwrap();
510
+ let recipient_claim: RecipientClaim =
511
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
429
512
  assert_eq!(recipient_claim.amount, 0); // Should be zero after claiming
430
513
 
431
514
  // Verify tokens were transferred to recipient
432
- let recipient_token_account = banks_client.get_account(recipient_usdc).await.unwrap().unwrap();
515
+ let recipient_token_account = banks_client
516
+ .get_account(recipient_usdc)
517
+ .await
518
+ .unwrap()
519
+ .unwrap();
433
520
  let token_account_data = TokenAccount::unpack(&recipient_token_account.data).unwrap();
434
521
  assert_eq!(token_account_data.amount, 90_000); // 90% of 100,000
435
522
  }
@@ -446,7 +533,7 @@ async fn test_claim_owner_share() {
446
533
  // Setup and send a message to accumulate owner fees
447
534
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
448
535
  let (mailer_pda, _) = get_mailer_pda();
449
-
536
+
450
537
  // Initialize
451
538
  let init_instruction = Instruction::new_with_borsh(
452
539
  program_id(),
@@ -463,11 +550,40 @@ async fn test_claim_owner_share() {
463
550
  banks_client.process_transaction(transaction).await.unwrap();
464
551
 
465
552
  // Setup token accounts and send standard message to accumulate owner fees
466
- let sender_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
467
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
468
- let owner_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
469
-
470
- mint_to(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &sender_usdc, 1_000_000).await;
553
+ let sender_usdc = create_token_account(
554
+ &mut banks_client,
555
+ &payer,
556
+ recent_blockhash,
557
+ &usdc_mint,
558
+ &payer.pubkey(),
559
+ )
560
+ .await;
561
+ let mailer_usdc = create_token_account(
562
+ &mut banks_client,
563
+ &payer,
564
+ recent_blockhash,
565
+ &usdc_mint,
566
+ &mailer_pda,
567
+ )
568
+ .await;
569
+ let owner_usdc = create_token_account(
570
+ &mut banks_client,
571
+ &payer,
572
+ recent_blockhash,
573
+ &usdc_mint,
574
+ &payer.pubkey(),
575
+ )
576
+ .await;
577
+
578
+ mint_to(
579
+ &mut banks_client,
580
+ &payer,
581
+ recent_blockhash,
582
+ &usdc_mint,
583
+ &sender_usdc,
584
+ 1_000_000,
585
+ )
586
+ .await;
471
587
 
472
588
  let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
473
589
 
@@ -479,7 +595,7 @@ async fn test_claim_owner_share() {
479
595
  subject: "Test".to_string(),
480
596
  _body: "Test".to_string(),
481
597
  revenue_share_to_receiver: false,
482
- resolve_sender_to_name: false,
598
+ resolve_sender_to_name: false,
483
599
  },
484
600
  vec![
485
601
  AccountMeta::new(payer.pubkey(), true),
@@ -515,7 +631,8 @@ async fn test_claim_owner_share() {
515
631
 
516
632
  // Verify owner claimable was reset
517
633
  let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
518
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
634
+ let mailer_state: MailerState =
635
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
519
636
  assert_eq!(mailer_state.owner_claimable, 0);
520
637
 
521
638
  // Verify tokens were transferred to owner
@@ -535,7 +652,7 @@ async fn test_set_fees() {
535
652
 
536
653
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
537
654
  let (mailer_pda, _) = get_mailer_pda();
538
-
655
+
539
656
  // Initialize
540
657
  let init_instruction = Instruction::new_with_borsh(
541
658
  program_id(),
@@ -561,32 +678,38 @@ async fn test_set_fees() {
561
678
  ],
562
679
  );
563
680
 
564
- let mut transaction = Transaction::new_with_payer(&[set_fee_instruction], Some(&payer.pubkey()));
681
+ let mut transaction =
682
+ Transaction::new_with_payer(&[set_fee_instruction], Some(&payer.pubkey()));
565
683
  transaction.sign(&[&payer], recent_blockhash);
566
684
  banks_client.process_transaction(transaction).await.unwrap();
567
685
 
568
686
  // Verify fee was updated
569
687
  let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
570
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
688
+ let mailer_state: MailerState =
689
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
571
690
  assert_eq!(mailer_state.send_fee, 200_000);
572
691
 
573
692
  // Test setting delegation fee
574
693
  let set_delegation_fee_instruction = Instruction::new_with_borsh(
575
694
  program_id(),
576
- &MailerInstruction::SetDelegationFee { new_fee: 20_000_000 },
695
+ &MailerInstruction::SetDelegationFee {
696
+ new_fee: 20_000_000,
697
+ },
577
698
  vec![
578
699
  AccountMeta::new(payer.pubkey(), true),
579
700
  AccountMeta::new(mailer_pda, false),
580
701
  ],
581
702
  );
582
703
 
583
- let mut transaction = Transaction::new_with_payer(&[set_delegation_fee_instruction], Some(&payer.pubkey()));
704
+ let mut transaction =
705
+ Transaction::new_with_payer(&[set_delegation_fee_instruction], Some(&payer.pubkey()));
584
706
  transaction.sign(&[&payer], recent_blockhash);
585
707
  banks_client.process_transaction(transaction).await.unwrap();
586
708
 
587
709
  // Verify delegation fee was updated
588
710
  let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
589
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
711
+ let mailer_state: MailerState =
712
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
590
713
  assert_eq!(mailer_state.delegation_fee, 20_000_000);
591
714
  }
592
715
 
@@ -601,7 +724,7 @@ async fn test_delegation_functionality() {
601
724
 
602
725
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
603
726
  let (mailer_pda, _) = get_mailer_pda();
604
-
727
+
605
728
  // Initialize
606
729
  let init_instruction = Instruction::new_with_borsh(
607
730
  program_id(),
@@ -618,10 +741,32 @@ async fn test_delegation_functionality() {
618
741
  banks_client.process_transaction(transaction).await.unwrap();
619
742
 
620
743
  // Setup token accounts
621
- let delegator_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
622
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
623
-
624
- mint_to(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &delegator_usdc, 50_000_000).await; // 50 USDC
744
+ let delegator_usdc = create_token_account(
745
+ &mut banks_client,
746
+ &payer,
747
+ recent_blockhash,
748
+ &usdc_mint,
749
+ &payer.pubkey(),
750
+ )
751
+ .await;
752
+ let mailer_usdc = create_token_account(
753
+ &mut banks_client,
754
+ &payer,
755
+ recent_blockhash,
756
+ &usdc_mint,
757
+ &mailer_pda,
758
+ )
759
+ .await;
760
+
761
+ mint_to(
762
+ &mut banks_client,
763
+ &payer,
764
+ recent_blockhash,
765
+ &usdc_mint,
766
+ &delegator_usdc,
767
+ 50_000_000,
768
+ )
769
+ .await; // 50 USDC
625
770
 
626
771
  let delegate = Keypair::new();
627
772
  let (delegation_pda, _) = get_delegation_pda(&payer.pubkey());
@@ -643,13 +788,19 @@ async fn test_delegation_functionality() {
643
788
  ],
644
789
  );
645
790
 
646
- let mut transaction = Transaction::new_with_payer(&[delegate_instruction], Some(&payer.pubkey()));
791
+ let mut transaction =
792
+ Transaction::new_with_payer(&[delegate_instruction], Some(&payer.pubkey()));
647
793
  transaction.sign(&[&payer], recent_blockhash);
648
794
  banks_client.process_transaction(transaction).await.unwrap();
649
795
 
650
796
  // Verify delegation was created
651
- let delegation_account = banks_client.get_account(delegation_pda).await.unwrap().unwrap();
652
- let delegation: Delegation = BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
797
+ let delegation_account = banks_client
798
+ .get_account(delegation_pda)
799
+ .await
800
+ .unwrap()
801
+ .unwrap();
802
+ let delegation: Delegation =
803
+ BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
653
804
  assert_eq!(delegation.delegator, payer.pubkey());
654
805
  assert_eq!(delegation.delegate, Some(delegate.pubkey()));
655
806
 
@@ -662,6 +813,7 @@ async fn test_delegation_functionality() {
662
813
  vec![
663
814
  AccountMeta::new(delegate.pubkey(), true),
664
815
  AccountMeta::new(delegation_pda, false),
816
+ AccountMeta::new_readonly(mailer_pda, false),
665
817
  ],
666
818
  );
667
819
 
@@ -687,11 +839,25 @@ async fn test_error_conditions() {
687
839
 
688
840
  let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
689
841
  let (mailer_pda, _) = get_mailer_pda();
690
-
842
+
691
843
  // Test claiming with no claimable amount (should fail)
692
844
  let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
693
- let recipient_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &payer.pubkey()).await;
694
- let mailer_usdc = create_token_account(&mut banks_client, &payer, recent_blockhash, &usdc_mint, &mailer_pda).await;
845
+ let recipient_usdc = create_token_account(
846
+ &mut banks_client,
847
+ &payer,
848
+ recent_blockhash,
849
+ &usdc_mint,
850
+ &payer.pubkey(),
851
+ )
852
+ .await;
853
+ let mailer_usdc = create_token_account(
854
+ &mut banks_client,
855
+ &payer,
856
+ recent_blockhash,
857
+ &usdc_mint,
858
+ &mailer_pda,
859
+ )
860
+ .await;
695
861
 
696
862
  let claim_instruction = Instruction::new_with_borsh(
697
863
  program_id(),
@@ -708,8 +874,164 @@ async fn test_error_conditions() {
708
874
 
709
875
  let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
710
876
  transaction.sign(&[&payer], recent_blockhash);
711
-
877
+
712
878
  // This should fail because no claim exists
713
879
  let result = banks_client.process_transaction(transaction).await;
714
880
  assert!(result.is_err());
715
- }
881
+ }
882
+
883
+ #[tokio::test]
884
+ async fn test_claim_expired_shares_moves_funds_to_owner() {
885
+ let program_test = ProgramTest::new(
886
+ "mailer",
887
+ program_id(),
888
+ processor!(mailer::process_instruction),
889
+ );
890
+ let mut context = program_test.start_with_context().await;
891
+
892
+ let mut recent_blockhash = context.last_blockhash;
893
+
894
+ // Create USDC mint and initialize the program
895
+ let usdc_mint =
896
+ create_usdc_mint(&mut context.banks_client, &context.payer, recent_blockhash).await;
897
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
898
+
899
+ let (mailer_pda, _) = get_mailer_pda();
900
+ let init_instruction = Instruction::new_with_borsh(
901
+ program_id(),
902
+ &MailerInstruction::Initialize { usdc_mint },
903
+ vec![
904
+ AccountMeta::new(context.payer.pubkey(), true),
905
+ AccountMeta::new(mailer_pda, false),
906
+ AccountMeta::new_readonly(system_program::id(), false),
907
+ ],
908
+ );
909
+
910
+ let mut transaction =
911
+ Transaction::new_with_payer(&[init_instruction], Some(&context.payer.pubkey()));
912
+ transaction.sign(&[&context.payer], recent_blockhash);
913
+ context
914
+ .banks_client
915
+ .process_transaction(transaction)
916
+ .await
917
+ .unwrap();
918
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
919
+
920
+ // Prepare token accounts and fund the sender
921
+ let sender_usdc = create_token_account(
922
+ &mut context.banks_client,
923
+ &context.payer,
924
+ recent_blockhash,
925
+ &usdc_mint,
926
+ &context.payer.pubkey(),
927
+ )
928
+ .await;
929
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
930
+
931
+ let mailer_usdc = create_token_account(
932
+ &mut context.banks_client,
933
+ &context.payer,
934
+ recent_blockhash,
935
+ &usdc_mint,
936
+ &mailer_pda,
937
+ )
938
+ .await;
939
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
940
+
941
+ mint_to(
942
+ &mut context.banks_client,
943
+ &context.payer,
944
+ recent_blockhash,
945
+ &usdc_mint,
946
+ &sender_usdc,
947
+ 1_000_000,
948
+ )
949
+ .await; // 1 USDC to cover priority message
950
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
951
+
952
+ let (recipient_claim_pda, _) = get_claim_pda(&context.payer.pubkey());
953
+
954
+ // Send a priority message to create the claim record
955
+ let send_instruction = Instruction::new_with_borsh(
956
+ program_id(),
957
+ &MailerInstruction::Send {
958
+ to: context.payer.pubkey(),
959
+ subject: "Expired claim".to_string(),
960
+ _body: "Body".to_string(),
961
+ revenue_share_to_receiver: true,
962
+ resolve_sender_to_name: false,
963
+ },
964
+ vec![
965
+ AccountMeta::new(context.payer.pubkey(), true),
966
+ AccountMeta::new(recipient_claim_pda, false),
967
+ AccountMeta::new(mailer_pda, false),
968
+ AccountMeta::new(sender_usdc, false),
969
+ AccountMeta::new(mailer_usdc, false),
970
+ AccountMeta::new_readonly(spl_token::id(), false),
971
+ AccountMeta::new_readonly(system_program::id(), false),
972
+ ],
973
+ );
974
+
975
+ let mut transaction =
976
+ Transaction::new_with_payer(&[send_instruction], Some(&context.payer.pubkey()));
977
+ transaction.sign(&[&context.payer], recent_blockhash);
978
+ context
979
+ .banks_client
980
+ .process_transaction(transaction)
981
+ .await
982
+ .unwrap();
983
+
984
+ // Warp forward so the claim expires (claim period is 60 days = 5,184,000 seconds)
985
+ // Manually set the clock to a future timestamp beyond the claim period
986
+ use solana_sdk::clock::Clock;
987
+ let mut clock = context.banks_client.get_sysvar::<Clock>().await.unwrap();
988
+ clock.unix_timestamp += 60 * 24 * 60 * 60 + 1; // 60 days + 1 second
989
+ context.set_sysvar(&clock);
990
+
991
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
992
+
993
+ // Owner reclaims expired shares
994
+ let claim_expired_instruction = Instruction::new_with_borsh(
995
+ program_id(),
996
+ &MailerInstruction::ClaimExpiredShares {
997
+ recipient: context.payer.pubkey(),
998
+ },
999
+ vec![
1000
+ AccountMeta::new(context.payer.pubkey(), true),
1001
+ AccountMeta::new(mailer_pda, false),
1002
+ AccountMeta::new(recipient_claim_pda, false),
1003
+ ],
1004
+ );
1005
+
1006
+ let mut transaction =
1007
+ Transaction::new_with_payer(&[claim_expired_instruction], Some(&context.payer.pubkey()));
1008
+ transaction.sign(&[&context.payer], recent_blockhash);
1009
+ context
1010
+ .banks_client
1011
+ .process_transaction(transaction)
1012
+ .await
1013
+ .unwrap();
1014
+
1015
+ // Recipient claim should be cleared
1016
+ let claim_account = context
1017
+ .banks_client
1018
+ .get_account(recipient_claim_pda)
1019
+ .await
1020
+ .unwrap()
1021
+ .unwrap();
1022
+ let claim_state: RecipientClaim =
1023
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
1024
+ assert_eq!(claim_state.amount, 0);
1025
+ assert_eq!(claim_state.timestamp, 0);
1026
+
1027
+ // Owner claimable should now include both original owner share and reclaimed amount (total 100,000)
1028
+ let mailer_account = context
1029
+ .banks_client
1030
+ .get_account(mailer_pda)
1031
+ .await
1032
+ .unwrap()
1033
+ .unwrap();
1034
+ let mailer_state: MailerState =
1035
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
1036
+ assert_eq!(mailer_state.owner_claimable, 100_000);
1037
+ }