@sudobility/contracts 0.15.1 → 1.10.0

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 (166) hide show
  1. package/README.md +2 -3
  2. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +2 -185
  3. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
  4. package/artifacts/contracts/Mailer.sol/Mailer.json +2 -185
  5. package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +1 -1
  6. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +1 -1
  7. package/dist/evm/src/evm/index.d.ts +1 -1
  8. package/dist/evm/src/evm/index.d.ts.map +1 -1
  9. package/dist/evm/src/evm/index.js +4 -4
  10. package/dist/evm/src/evm/index.js.map +1 -1
  11. package/dist/evm/src/evm/mailer-client.d.ts +210 -0
  12. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -0
  13. package/dist/evm/src/evm/mailer-client.js +417 -0
  14. package/dist/evm/src/evm/mailer-client.js.map +1 -0
  15. package/dist/evm/typechain-types/Mailer.d.ts +10 -128
  16. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
  17. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +1 -145
  18. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  19. package/dist/evm/typechain-types/factories/Mailer__factory.js +1 -184
  20. package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -1
  21. package/dist/solana/solana/index.d.ts +1 -1
  22. package/dist/solana/solana/index.d.ts.map +1 -1
  23. package/dist/solana/solana/index.js +1 -4
  24. package/dist/solana/solana/index.js.map +1 -1
  25. package/dist/solana/solana/mailer-client.d.ts +209 -0
  26. package/dist/solana/solana/mailer-client.d.ts.map +1 -0
  27. package/dist/solana/solana/mailer-client.js +728 -0
  28. package/dist/solana/solana/mailer-client.js.map +1 -0
  29. package/dist/solana/solana/types.d.ts +2 -3
  30. package/dist/solana/solana/types.d.ts.map +1 -1
  31. package/dist/solana/solana/types.js.map +1 -1
  32. package/dist/unified/src/evm/index.d.ts +1 -1
  33. package/dist/unified/src/evm/index.d.ts.map +1 -1
  34. package/dist/unified/src/evm/index.js +4 -4
  35. package/dist/unified/src/evm/index.js.map +1 -1
  36. package/dist/unified/src/evm/mailer-client.d.ts +210 -0
  37. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -0
  38. package/dist/unified/src/evm/mailer-client.js +417 -0
  39. package/dist/unified/src/evm/mailer-client.js.map +1 -0
  40. package/dist/unified/src/react/context/MailerProvider.d.ts +20 -26
  41. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
  42. package/dist/unified/src/react/context/MailerProvider.js +26 -26
  43. package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
  44. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +192 -225
  45. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  46. package/dist/unified/src/react/hooks/useMailerMutations.js +266 -263
  47. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
  48. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +63 -117
  49. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  50. package/dist/unified/src/react/hooks/useMailerQueries.js +104 -239
  51. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
  52. package/dist/unified/src/react/index.d.ts +3 -5
  53. package/dist/unified/src/react/index.d.ts.map +1 -1
  54. package/dist/unified/src/react/index.js +26 -41
  55. package/dist/unified/src/react/index.js.map +1 -1
  56. package/dist/unified/src/solana/index.d.ts +1 -1
  57. package/dist/unified/src/solana/index.d.ts.map +1 -1
  58. package/dist/unified/src/solana/index.js +1 -4
  59. package/dist/unified/src/solana/index.js.map +1 -1
  60. package/dist/unified/src/solana/mailer-client.d.ts +209 -0
  61. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -0
  62. package/dist/unified/src/solana/mailer-client.js +728 -0
  63. package/dist/unified/src/solana/mailer-client.js.map +1 -0
  64. package/dist/unified/src/solana/types.d.ts +2 -3
  65. package/dist/unified/src/solana/types.d.ts.map +1 -1
  66. package/dist/unified/src/solana/types.js.map +1 -1
  67. package/dist/unified/src/unified/index.d.ts +1 -1
  68. package/dist/unified/src/unified/index.d.ts.map +1 -1
  69. package/dist/unified/src/unified/onchain-mailer-client.d.ts +247 -192
  70. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  71. package/dist/unified/src/unified/onchain-mailer-client.js +1462 -551
  72. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  73. package/dist/unified/src/unified/types.d.ts +6 -23
  74. package/dist/unified/src/unified/types.d.ts.map +1 -1
  75. package/dist/unified/src/utils/chain-config.d.ts +2 -4
  76. package/dist/unified/src/utils/chain-config.d.ts.map +1 -1
  77. package/dist/unified/src/utils/chain-config.js +36 -46
  78. package/dist/unified/src/utils/chain-config.js.map +1 -1
  79. package/dist/unified/typechain-types/Mailer.d.ts +10 -128
  80. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
  81. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +1 -145
  82. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  83. package/dist/unified/typechain-types/factories/Mailer__factory.js +1 -184
  84. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
  85. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  86. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  87. package/dist/unified-esm/src/evm/index.js +2 -2
  88. package/dist/unified-esm/src/evm/index.js.map +1 -1
  89. package/dist/unified-esm/src/evm/mailer-client.d.ts +210 -0
  90. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -0
  91. package/dist/unified-esm/src/evm/mailer-client.js +413 -0
  92. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -0
  93. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +20 -26
  94. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  95. package/dist/unified-esm/src/react/context/MailerProvider.js +26 -25
  96. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  97. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +192 -225
  98. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  99. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +262 -254
  100. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  101. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +63 -117
  102. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  103. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +102 -232
  104. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  105. package/dist/unified-esm/src/react/index.d.ts +3 -5
  106. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  107. package/dist/unified-esm/src/react/index.js +5 -9
  108. package/dist/unified-esm/src/react/index.js.map +1 -1
  109. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  110. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  111. package/dist/unified-esm/src/solana/index.js +1 -2
  112. package/dist/unified-esm/src/solana/index.js.map +1 -1
  113. package/dist/unified-esm/src/solana/mailer-client.d.ts +209 -0
  114. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -0
  115. package/dist/unified-esm/src/solana/mailer-client.js +724 -0
  116. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -0
  117. package/dist/unified-esm/src/solana/types.d.ts +2 -3
  118. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  119. package/dist/unified-esm/src/solana/types.js.map +1 -1
  120. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  121. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  122. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +247 -192
  123. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  124. package/dist/unified-esm/src/unified/onchain-mailer-client.js +1462 -551
  125. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  126. package/dist/unified-esm/src/unified/types.d.ts +6 -23
  127. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  128. package/dist/unified-esm/src/utils/chain-config.d.ts +2 -4
  129. package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -1
  130. package/dist/unified-esm/src/utils/chain-config.js +35 -46
  131. package/dist/unified-esm/src/utils/chain-config.js.map +1 -1
  132. package/dist/unified-esm/typechain-types/Mailer.d.ts +10 -128
  133. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
  134. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +1 -145
  135. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  136. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1 -184
  137. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
  138. package/package.json +10 -17
  139. package/programs/mailer/src/lib.rs +145 -764
  140. package/programs/mailer/tests/integration_tests.rs +65 -586
  141. package/typechain-types/Mailer.ts +8 -215
  142. package/typechain-types/factories/Mailer__factory.ts +1 -184
  143. package/dist/evm/src/evm/evm-mailer-client.d.ts +0 -1062
  144. package/dist/evm/src/evm/evm-mailer-client.d.ts.map +0 -1
  145. package/dist/evm/src/evm/evm-mailer-client.js +0 -924
  146. package/dist/evm/src/evm/evm-mailer-client.js.map +0 -1
  147. package/dist/solana/solana/solana-mailer-client.d.ts +0 -209
  148. package/dist/solana/solana/solana-mailer-client.d.ts.map +0 -1
  149. package/dist/solana/solana/solana-mailer-client.js +0 -1004
  150. package/dist/solana/solana/solana-mailer-client.js.map +0 -1
  151. package/dist/unified/src/evm/evm-mailer-client.d.ts +0 -1062
  152. package/dist/unified/src/evm/evm-mailer-client.d.ts.map +0 -1
  153. package/dist/unified/src/evm/evm-mailer-client.js +0 -924
  154. package/dist/unified/src/evm/evm-mailer-client.js.map +0 -1
  155. package/dist/unified/src/solana/solana-mailer-client.d.ts +0 -209
  156. package/dist/unified/src/solana/solana-mailer-client.d.ts.map +0 -1
  157. package/dist/unified/src/solana/solana-mailer-client.js +0 -1004
  158. package/dist/unified/src/solana/solana-mailer-client.js.map +0 -1
  159. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts +0 -1062
  160. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +0 -1
  161. package/dist/unified-esm/src/evm/evm-mailer-client.js +0 -920
  162. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +0 -1
  163. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +0 -209
  164. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +0 -1
  165. package/dist/unified-esm/src/solana/solana-mailer-client.js +0 -1000
  166. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +0 -1
@@ -1,6 +1,6 @@
1
1
  //! # Native Solana Mailer Program
2
2
  //!
3
- //! A native Solana program for decentralized messaging with delegation management,
3
+ //! A native Solana program for decentralized messaging with delegation management,
4
4
  //! USDC fees and revenue sharing - no Anchor dependencies.
5
5
  //!
6
6
  //! ## Key Features
@@ -25,6 +25,7 @@
25
25
  //! - Standard: Sender pays 10% fee only
26
26
  //! - Owner gets 10% of all fees
27
27
 
28
+
28
29
  use borsh::{BorshDeserialize, BorshSerialize};
29
30
  use solana_program::{
30
31
  account_info::{next_account_info, AccountInfo},
@@ -33,13 +34,11 @@ use solana_program::{
33
34
  msg,
34
35
  program::{invoke, invoke_signed},
35
36
  program_error::ProgramError,
36
- program_pack::Pack,
37
37
  pubkey::Pubkey,
38
38
  rent::Rent,
39
39
  system_instruction,
40
40
  sysvar::Sysvar,
41
41
  };
42
- use spl_token::state::Account as TokenAccount;
43
42
  use thiserror::Error;
44
43
 
45
44
  // Program ID for the Native Mailer program
@@ -139,22 +138,6 @@ pub enum MailerInstruction {
139
138
  resolve_sender_to_name: bool,
140
139
  },
141
140
 
142
- /// Send prepared message with optional revenue sharing (references off-chain content via mailId)
143
- /// Accounts:
144
- /// 0. `[signer]` Sender
145
- /// 1. `[writable]` Recipient claim account (PDA)
146
- /// 2. `[]` Mailer state account (PDA)
147
- /// 3. `[writable]` Sender USDC account
148
- /// 4. `[writable]` Mailer USDC account
149
- /// 5. `[]` Token program
150
- /// 6. `[]` System program
151
- SendPrepared {
152
- to: Pubkey,
153
- mail_id: String,
154
- revenue_share_to_receiver: bool,
155
- resolve_sender_to_name: bool,
156
- },
157
-
158
141
  /// Send message to email address (no wallet address known)
159
142
  /// Charges only 10% owner fee since recipient wallet is unknown
160
143
  /// Accounts:
@@ -177,22 +160,9 @@ pub enum MailerInstruction {
177
160
  /// 2. `[writable]` Sender USDC account
178
161
  /// 3. `[writable]` Mailer USDC account
179
162
  /// 4. `[]` Token program
180
- SendPreparedToEmail { to_email: String, mail_id: String },
181
-
182
- /// Send message through webhook (referenced by webhookId)
183
- /// Accounts:
184
- /// 0. `[signer]` Sender
185
- /// 1. `[writable]` Recipient claim account (PDA)
186
- /// 2. `[]` Mailer state account (PDA)
187
- /// 3. `[writable]` Sender USDC account
188
- /// 4. `[writable]` Mailer USDC account
189
- /// 5. `[]` Token program
190
- /// 6. `[]` System program
191
- SendThroughWebhook {
192
- to: Pubkey,
193
- webhook_id: String,
194
- revenue_share_to_receiver: bool,
195
- resolve_sender_to_name: bool,
163
+ SendPreparedToEmail {
164
+ to_email: String,
165
+ mail_id: String,
196
166
  },
197
167
 
198
168
  /// Claim recipient share
@@ -235,7 +205,6 @@ pub enum MailerInstruction {
235
205
  /// Accounts:
236
206
  /// 0. `[signer]` Rejector
237
207
  /// 1. `[writable]` Delegation account (PDA)
238
- /// 2. `[]` Mailer state account (PDA)
239
208
  RejectDelegation,
240
209
 
241
210
  /// Set delegation fee (owner only)
@@ -272,13 +241,13 @@ pub enum MailerInstruction {
272
241
  /// 3. `[writable]` Mailer USDC account
273
242
  /// 4. `[]` Token program
274
243
  Pause,
275
-
244
+
276
245
  /// Unpause the contract (owner only)
277
246
  /// Accounts:
278
247
  /// 0. `[signer]` Owner
279
248
  /// 1. `[writable]` Mailer state account (PDA)
280
249
  Unpause,
281
-
250
+
282
251
  /// Distribute claimable funds (when paused)
283
252
  /// Accounts:
284
253
  /// 0. `[signer]` Anyone can call
@@ -289,13 +258,6 @@ pub enum MailerInstruction {
289
258
  /// 5. `[]` Token program
290
259
  DistributeClaimableFunds { recipient: Pubkey },
291
260
 
292
- /// Claim expired recipient shares (owner only)
293
- /// Accounts:
294
- /// 0. `[signer]` Owner
295
- /// 1. `[writable]` Mailer state account (PDA)
296
- /// 2. `[writable]` Recipient claim account (PDA)
297
- ClaimExpiredShares { recipient: Pubkey },
298
-
299
261
  /// Emergency unpause without fund distribution (owner only)
300
262
  /// Accounts:
301
263
  /// 0. `[signer]` Owner
@@ -328,10 +290,6 @@ pub enum MailerError {
328
290
  InvalidPDA,
329
291
  #[error("Invalid account owner")]
330
292
  InvalidAccountOwner,
331
- #[error("Invalid token mint")]
332
- InvalidMint,
333
- #[error("Invalid token program")]
334
- InvalidTokenProgram,
335
293
  #[error("Contract is paused")]
336
294
  ContractPaused,
337
295
  #[error("Contract is not paused")]
@@ -358,55 +316,15 @@ pub fn process_instruction(
358
316
  MailerInstruction::Initialize { usdc_mint } => {
359
317
  process_initialize(program_id, accounts, usdc_mint)
360
318
  }
361
- MailerInstruction::Send {
362
- to,
363
- subject,
364
- _body,
365
- revenue_share_to_receiver,
366
- resolve_sender_to_name,
367
- } => process_send(
368
- program_id,
369
- accounts,
370
- to,
371
- subject,
372
- _body,
373
- revenue_share_to_receiver,
374
- resolve_sender_to_name,
375
- ),
376
- MailerInstruction::SendPrepared {
377
- to,
378
- mail_id,
379
- revenue_share_to_receiver,
380
- resolve_sender_to_name,
381
- } => process_send_prepared(
382
- program_id,
383
- accounts,
384
- to,
385
- mail_id,
386
- revenue_share_to_receiver,
387
- resolve_sender_to_name,
388
- ),
389
- MailerInstruction::SendToEmail {
390
- to_email,
391
- subject,
392
- _body,
393
- } => process_send_to_email(program_id, accounts, to_email, subject, _body),
319
+ MailerInstruction::Send { to, subject, _body, revenue_share_to_receiver, resolve_sender_to_name } => {
320
+ process_send(program_id, accounts, to, subject, _body, revenue_share_to_receiver, resolve_sender_to_name)
321
+ }
322
+ MailerInstruction::SendToEmail { to_email, subject, _body } => {
323
+ process_send_to_email(program_id, accounts, to_email, subject, _body)
324
+ }
394
325
  MailerInstruction::SendPreparedToEmail { to_email, mail_id } => {
395
326
  process_send_prepared_to_email(program_id, accounts, to_email, mail_id)
396
327
  }
397
- MailerInstruction::SendThroughWebhook {
398
- to,
399
- webhook_id,
400
- revenue_share_to_receiver,
401
- resolve_sender_to_name,
402
- } => process_send_through_webhook(
403
- program_id,
404
- accounts,
405
- to,
406
- webhook_id,
407
- revenue_share_to_receiver,
408
- resolve_sender_to_name,
409
- ),
410
328
  MailerInstruction::ClaimRecipientShare => {
411
329
  process_claim_recipient_share(program_id, accounts)
412
330
  }
@@ -419,22 +337,24 @@ pub fn process_instruction(
419
337
  MailerInstruction::SetDelegationFee { new_fee } => {
420
338
  process_set_delegation_fee(program_id, accounts, new_fee)
421
339
  }
422
- MailerInstruction::SetCustomFeePercentage {
423
- account,
424
- percentage,
425
- } => process_set_custom_fee_percentage(program_id, accounts, account, percentage),
340
+ MailerInstruction::SetCustomFeePercentage { account, percentage } => {
341
+ process_set_custom_fee_percentage(program_id, accounts, account, percentage)
342
+ }
426
343
  MailerInstruction::ClearCustomFeePercentage { account } => {
427
344
  process_clear_custom_fee_percentage(program_id, accounts, account)
428
345
  }
429
- MailerInstruction::Pause => process_pause(program_id, accounts),
430
- MailerInstruction::Unpause => process_unpause(program_id, accounts),
346
+ MailerInstruction::Pause => {
347
+ process_pause(program_id, accounts)
348
+ }
349
+ MailerInstruction::Unpause => {
350
+ process_unpause(program_id, accounts)
351
+ }
431
352
  MailerInstruction::DistributeClaimableFunds { recipient } => {
432
353
  process_distribute_claimable_funds(program_id, accounts, recipient)
433
354
  }
434
- MailerInstruction::ClaimExpiredShares { recipient } => {
435
- process_claim_expired_shares(program_id, accounts, recipient)
355
+ MailerInstruction::EmergencyUnpause => {
356
+ process_emergency_unpause(program_id, accounts)
436
357
  }
437
- MailerInstruction::EmergencyUnpause => process_emergency_unpause(program_id, accounts),
438
358
  }
439
359
  }
440
360
 
@@ -472,11 +392,7 @@ fn process_initialize(
472
392
  space as u64,
473
393
  program_id,
474
394
  ),
475
- &[
476
- owner.clone(),
477
- mailer_account.clone(),
478
- system_program.clone(),
479
- ],
395
+ &[owner.clone(), mailer_account.clone(), system_program.clone()],
480
396
  &[&[b"mailer", &[bump]]],
481
397
  )?;
482
398
 
@@ -524,187 +440,26 @@ fn process_send(
524
440
  }
525
441
 
526
442
  // Load mailer state
527
- let (mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
528
443
  let mailer_data = mailer_account.try_borrow_data()?;
529
444
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
530
445
  drop(mailer_data);
531
446
 
532
- assert_token_program(token_program)?;
533
- assert_token_account(sender_usdc, sender.key, &mailer_state.usdc_mint)?;
534
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
535
-
536
447
  // Check if contract is paused
537
448
  if mailer_state.paused {
538
449
  return Err(MailerError::ContractPaused.into());
539
450
  }
540
451
 
541
452
  // Calculate effective fee based on custom discount (if any)
542
- let effective_fee =
543
- calculate_fee_with_discount(program_id, sender.key, accounts, mailer_state.send_fee)?;
453
+ let effective_fee = calculate_fee_with_discount(program_id, sender.key, accounts, mailer_state.send_fee)?;
544
454
 
545
455
  if revenue_share_to_receiver {
546
456
  // Priority mode: full fee with revenue sharing
547
457
 
548
458
  // Create or load recipient claim account
549
- let (claim_pda, claim_bump) =
550
- Pubkey::find_program_address(&[b"claim", to.as_ref()], program_id);
551
-
552
- if recipient_claim.key != &claim_pda {
553
- return Err(MailerError::InvalidPDA.into());
554
- }
555
-
556
- // Create claim account if needed
557
- if recipient_claim.lamports() == 0 {
558
- let rent = Rent::get()?;
559
- let space = 8 + RecipientClaim::LEN;
560
- let lamports = rent.minimum_balance(space);
561
-
562
- invoke_signed(
563
- &system_instruction::create_account(
564
- sender.key,
565
- recipient_claim.key,
566
- lamports,
567
- space as u64,
568
- program_id,
569
- ),
570
- &[
571
- sender.clone(),
572
- recipient_claim.clone(),
573
- system_program.clone(),
574
- ],
575
- &[&[b"claim", to.as_ref(), &[claim_bump]]],
576
- )?;
577
-
578
- // Initialize claim account
579
- let mut claim_data = recipient_claim.try_borrow_mut_data()?;
580
- claim_data[0..8]
581
- .copy_from_slice(&hash_discriminator("account:RecipientClaim").to_le_bytes());
582
-
583
- let claim_state = RecipientClaim {
584
- recipient: to,
585
- amount: 0,
586
- timestamp: 0,
587
- bump: claim_bump,
588
- };
589
-
590
- claim_state.serialize(&mut &mut claim_data[8..])?;
591
- drop(claim_data);
592
- }
593
-
594
- // Transfer effective fee (may be discounted)
595
- if effective_fee > 0 {
596
- invoke(
597
- &spl_token::instruction::transfer(
598
- token_program.key,
599
- sender_usdc.key,
600
- mailer_usdc.key,
601
- sender.key,
602
- &[],
603
- effective_fee,
604
- )?,
605
- &[
606
- sender_usdc.clone(),
607
- mailer_usdc.clone(),
608
- sender.clone(),
609
- token_program.clone(),
610
- ],
611
- )?;
612
-
613
- // Record revenue shares (only if fee > 0)
614
- record_shares(recipient_claim, mailer_account, to, effective_fee)?;
615
- }
616
-
617
- msg!("Priority mail sent from {} to {}: {} (revenue share enabled, resolve sender: {}, effective fee: {})", sender.key, to, subject, _resolve_sender_to_name, effective_fee);
618
- } else {
619
- // Standard mode: 10% fee only, no revenue sharing
620
- let owner_fee = (effective_fee * 10) / 100; // 10% of effective fee
621
-
622
- // Transfer only owner fee (10%)
623
- if owner_fee > 0 {
624
- invoke(
625
- &spl_token::instruction::transfer(
626
- token_program.key,
627
- sender_usdc.key,
628
- mailer_usdc.key,
629
- sender.key,
630
- &[],
631
- owner_fee,
632
- )?,
633
- &[
634
- sender_usdc.clone(),
635
- mailer_usdc.clone(),
636
- sender.clone(),
637
- token_program.clone(),
638
- ],
639
- )?;
640
- }
641
-
642
- // Update owner claimable
643
- let mut mailer_data = mailer_account.try_borrow_mut_data()?;
644
- let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
645
- mailer_state.owner_claimable += owner_fee;
646
- mailer_state.serialize(&mut &mut mailer_data[8..])?;
647
-
648
- msg!(
649
- "Standard mail sent from {} to {}: {} (resolve sender: {}, effective fee: {})",
650
- sender.key,
651
- to,
652
- subject,
653
- _resolve_sender_to_name,
654
- effective_fee
459
+ let (claim_pda, claim_bump) = Pubkey::find_program_address(
460
+ &[b"claim", to.as_ref()],
461
+ program_id
655
462
  );
656
- }
657
-
658
- Ok(())
659
- }
660
-
661
- /// Send prepared message with optional revenue sharing (references off-chain content via mailId)
662
- fn process_send_prepared(
663
- program_id: &Pubkey,
664
- accounts: &[AccountInfo],
665
- to: Pubkey,
666
- mail_id: String,
667
- revenue_share_to_receiver: bool,
668
- _resolve_sender_to_name: bool,
669
- ) -> ProgramResult {
670
- let account_iter = &mut accounts.iter();
671
- let sender = next_account_info(account_iter)?;
672
- let recipient_claim = next_account_info(account_iter)?;
673
- let mailer_account = next_account_info(account_iter)?;
674
- let sender_usdc = next_account_info(account_iter)?;
675
- let mailer_usdc = next_account_info(account_iter)?;
676
- let token_program = next_account_info(account_iter)?;
677
- let system_program = next_account_info(account_iter)?;
678
-
679
- if !sender.is_signer {
680
- return Err(ProgramError::MissingRequiredSignature);
681
- }
682
-
683
- // Load mailer state
684
- let (mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
685
- let mailer_data = mailer_account.try_borrow_data()?;
686
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
687
- drop(mailer_data);
688
-
689
- assert_token_program(token_program)?;
690
- assert_token_account(sender_usdc, sender.key, &mailer_state.usdc_mint)?;
691
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
692
-
693
- // Check if contract is paused
694
- if mailer_state.paused {
695
- return Err(MailerError::ContractPaused.into());
696
- }
697
-
698
- // Calculate effective fee based on custom discount (if any)
699
- let effective_fee =
700
- calculate_fee_with_discount(program_id, sender.key, accounts, mailer_state.send_fee)?;
701
-
702
- if revenue_share_to_receiver {
703
- // Priority mode: full fee with revenue sharing
704
-
705
- // Create or load recipient claim account
706
- let (claim_pda, claim_bump) =
707
- Pubkey::find_program_address(&[b"claim", to.as_ref()], program_id);
708
463
 
709
464
  if recipient_claim.key != &claim_pda {
710
465
  return Err(MailerError::InvalidPDA.into());
@@ -724,18 +479,13 @@ fn process_send_prepared(
724
479
  space as u64,
725
480
  program_id,
726
481
  ),
727
- &[
728
- sender.clone(),
729
- recipient_claim.clone(),
730
- system_program.clone(),
731
- ],
482
+ &[sender.clone(), recipient_claim.clone(), system_program.clone()],
732
483
  &[&[b"claim", to.as_ref(), &[claim_bump]]],
733
484
  )?;
734
485
 
735
486
  // Initialize claim account
736
487
  let mut claim_data = recipient_claim.try_borrow_mut_data()?;
737
- claim_data[0..8]
738
- .copy_from_slice(&hash_discriminator("account:RecipientClaim").to_le_bytes());
488
+ claim_data[0..8].copy_from_slice(&hash_discriminator("account:RecipientClaim").to_le_bytes());
739
489
 
740
490
  let claim_state = RecipientClaim {
741
491
  recipient: to,
@@ -771,7 +521,7 @@ fn process_send_prepared(
771
521
  record_shares(recipient_claim, mailer_account, to, effective_fee)?;
772
522
  }
773
523
 
774
- msg!("Priority prepared mail sent from {} to {} (mailId: {}, revenue share enabled, resolve sender: {}, effective fee: {})", sender.key, to, mail_id, _resolve_sender_to_name, effective_fee);
524
+ msg!("Priority mail sent from {} to {}: {} (revenue share enabled, resolve sender: {}, effective fee: {})", sender.key, to, subject, _resolve_sender_to_name, effective_fee);
775
525
  } else {
776
526
  // Standard mode: 10% fee only, no revenue sharing
777
527
  let owner_fee = (effective_fee * 10) / 100; // 10% of effective fee
@@ -802,14 +552,7 @@ fn process_send_prepared(
802
552
  mailer_state.owner_claimable += owner_fee;
803
553
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
804
554
 
805
- msg!(
806
- "Standard prepared mail sent from {} to {} (mailId: {}, resolve sender: {}, effective fee: {})",
807
- sender.key,
808
- to,
809
- mail_id,
810
- _resolve_sender_to_name,
811
- effective_fee
812
- );
555
+ msg!("Standard mail sent from {} to {}: {} (resolve sender: {}, effective fee: {})", sender.key, to, subject, _resolve_sender_to_name, effective_fee);
813
556
  }
814
557
 
815
558
  Ok(())
@@ -835,23 +578,17 @@ fn process_send_to_email(
835
578
  }
836
579
 
837
580
  // Load mailer state
838
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
839
581
  let mailer_data = mailer_account.try_borrow_data()?;
840
582
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
841
583
  drop(mailer_data);
842
584
 
843
- assert_token_program(token_program)?;
844
- assert_token_account(sender_usdc, sender.key, &mailer_state.usdc_mint)?;
845
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
846
-
847
585
  // Check if contract is paused
848
586
  if mailer_state.paused {
849
587
  return Err(MailerError::ContractPaused.into());
850
588
  }
851
589
 
852
590
  // Calculate effective fee based on custom discount (if any)
853
- let effective_fee =
854
- calculate_fee_with_discount(_program_id, sender.key, accounts, mailer_state.send_fee)?;
591
+ let effective_fee = calculate_fee_with_discount(_program_id, sender.key, accounts, mailer_state.send_fee)?;
855
592
 
856
593
  // Calculate 10% owner fee (no revenue share since no wallet address)
857
594
  let owner_fee = (effective_fee * 10) / 100;
@@ -884,13 +621,7 @@ fn process_send_to_email(
884
621
  mailer_state.owner_claimable += owner_fee;
885
622
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
886
623
 
887
- msg!(
888
- "Mail sent from {} to email {}: {} (effective fee: {})",
889
- sender.key,
890
- to_email,
891
- subject,
892
- effective_fee
893
- );
624
+ msg!("Mail sent from {} to email {}: {} (effective fee: {})", sender.key, to_email, subject, effective_fee);
894
625
 
895
626
  Ok(())
896
627
  }
@@ -909,225 +640,56 @@ fn process_send_prepared_to_email(
909
640
  let mailer_usdc = next_account_info(account_iter)?;
910
641
  let token_program = next_account_info(account_iter)?;
911
642
 
912
- if !sender.is_signer {
913
- return Err(ProgramError::MissingRequiredSignature);
914
- }
915
-
916
- // Load mailer state
917
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
918
- let mailer_data = mailer_account.try_borrow_data()?;
919
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
920
- drop(mailer_data);
921
-
922
- assert_token_program(token_program)?;
923
- assert_token_account(sender_usdc, sender.key, &mailer_state.usdc_mint)?;
924
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
925
-
926
- // Check if contract is paused
927
- if mailer_state.paused {
928
- return Err(MailerError::ContractPaused.into());
929
- }
930
-
931
- // Calculate effective fee based on custom discount (if any)
932
- let effective_fee =
933
- calculate_fee_with_discount(_program_id, sender.key, accounts, mailer_state.send_fee)?;
934
-
935
- // Calculate 10% owner fee (no revenue share since no wallet address)
936
- let owner_fee = (effective_fee * 10) / 100;
937
-
938
- // Transfer fee from sender to mailer
939
- if owner_fee > 0 {
940
- let transfer_ix = spl_token::instruction::transfer(
941
- token_program.key,
942
- sender_usdc.key,
943
- mailer_usdc.key,
944
- sender.key,
945
- &[],
946
- owner_fee,
947
- )?;
948
-
949
- invoke(
950
- &transfer_ix,
951
- &[
952
- sender_usdc.clone(),
953
- mailer_usdc.clone(),
954
- sender.clone(),
955
- token_program.clone(),
956
- ],
957
- )?;
958
- }
959
-
960
- // Update owner claimable
961
- let mut mailer_data = mailer_account.try_borrow_mut_data()?;
962
- let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
963
- mailer_state.owner_claimable += owner_fee;
964
- mailer_state.serialize(&mut &mut mailer_data[8..])?;
965
-
966
- msg!(
967
- "Prepared mail sent from {} to email {} (mailId: {}, effective fee: {})",
968
- sender.key,
969
- to_email,
970
- mail_id,
971
- effective_fee
972
- );
973
-
974
- Ok(())
975
- }
976
-
977
- /// Send message through webhook (references webhook by webhookId)
978
- fn process_send_through_webhook(
979
- program_id: &Pubkey,
980
- accounts: &[AccountInfo],
981
- to: Pubkey,
982
- webhook_id: String,
983
- revenue_share_to_receiver: bool,
984
- _resolve_sender_to_name: bool,
985
- ) -> ProgramResult {
986
- let account_iter = &mut accounts.iter();
987
- let sender = next_account_info(account_iter)?;
988
- let recipient_claim = next_account_info(account_iter)?;
989
- let mailer_account = next_account_info(account_iter)?;
990
- let sender_usdc = next_account_info(account_iter)?;
991
- let mailer_usdc = next_account_info(account_iter)?;
992
- let token_program = next_account_info(account_iter)?;
993
- let system_program = next_account_info(account_iter)?;
994
-
995
- if !sender.is_signer {
996
- return Err(ProgramError::MissingRequiredSignature);
997
- }
998
-
999
- // Load mailer state
1000
- let (mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
1001
- let mailer_data = mailer_account.try_borrow_data()?;
1002
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1003
- drop(mailer_data);
1004
-
1005
- assert_token_program(token_program)?;
1006
- assert_token_account(sender_usdc, sender.key, &mailer_state.usdc_mint)?;
1007
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1008
-
1009
- // Check if contract is paused
1010
- if mailer_state.paused {
1011
- return Err(MailerError::ContractPaused.into());
1012
- }
1013
-
1014
- // Calculate effective fee based on custom discount (if any)
1015
- let effective_fee =
1016
- calculate_fee_with_discount(program_id, sender.key, accounts, mailer_state.send_fee)?;
1017
-
1018
- if revenue_share_to_receiver {
1019
- // Priority mode: full fee with revenue sharing
1020
-
1021
- // Create or load recipient claim account
1022
- let (claim_pda, claim_bump) =
1023
- Pubkey::find_program_address(&[b"claim", to.as_ref()], program_id);
1024
-
1025
- if recipient_claim.key != &claim_pda {
1026
- return Err(MailerError::InvalidPDA.into());
1027
- }
1028
-
1029
- // Create claim account if needed
1030
- if recipient_claim.lamports() == 0 {
1031
- let rent = Rent::get()?;
1032
- let space = 8 + RecipientClaim::LEN;
1033
- let lamports = rent.minimum_balance(space);
1034
-
1035
- invoke_signed(
1036
- &system_instruction::create_account(
1037
- sender.key,
1038
- recipient_claim.key,
1039
- lamports,
1040
- space as u64,
1041
- program_id,
1042
- ),
1043
- &[
1044
- sender.clone(),
1045
- recipient_claim.clone(),
1046
- system_program.clone(),
1047
- ],
1048
- &[&[b"claim", to.as_ref(), &[claim_bump]]],
1049
- )?;
1050
-
1051
- // Initialize claim account
1052
- let mut claim_data = recipient_claim.try_borrow_mut_data()?;
1053
- claim_data[0..8]
1054
- .copy_from_slice(&hash_discriminator("account:RecipientClaim").to_le_bytes());
1055
-
1056
- let claim_state = RecipientClaim {
1057
- recipient: to,
1058
- amount: 0,
1059
- timestamp: 0,
1060
- bump: claim_bump,
1061
- };
1062
-
1063
- claim_state.serialize(&mut &mut claim_data[8..])?;
1064
- drop(claim_data);
1065
- }
1066
-
1067
- // Transfer effective fee (may be discounted)
1068
- if effective_fee > 0 {
1069
- invoke(
1070
- &spl_token::instruction::transfer(
1071
- token_program.key,
1072
- sender_usdc.key,
1073
- mailer_usdc.key,
1074
- sender.key,
1075
- &[],
1076
- effective_fee,
1077
- )?,
1078
- &[
1079
- sender_usdc.clone(),
1080
- mailer_usdc.clone(),
1081
- sender.clone(),
1082
- token_program.clone(),
1083
- ],
1084
- )?;
643
+ if !sender.is_signer {
644
+ return Err(ProgramError::MissingRequiredSignature);
645
+ }
1085
646
 
1086
- // Record revenue shares (only if fee > 0)
1087
- record_shares(recipient_claim, mailer_account, to, effective_fee)?;
1088
- }
647
+ // Load mailer state
648
+ let mailer_data = mailer_account.try_borrow_data()?;
649
+ let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
650
+ drop(mailer_data);
1089
651
 
1090
- msg!("Webhook mail sent from {} to {} (webhookId: {}, revenue share enabled, resolve sender: {}, effective fee: {})", sender.key, to, webhook_id, _resolve_sender_to_name, effective_fee);
1091
- } else {
1092
- // Standard mode: 10% fee only, no revenue sharing
1093
- let owner_fee = (effective_fee * 10) / 100; // 10% of effective fee
652
+ // Check if contract is paused
653
+ if mailer_state.paused {
654
+ return Err(MailerError::ContractPaused.into());
655
+ }
1094
656
 
1095
- // Transfer only owner fee (10%)
1096
- if owner_fee > 0 {
1097
- invoke(
1098
- &spl_token::instruction::transfer(
1099
- token_program.key,
1100
- sender_usdc.key,
1101
- mailer_usdc.key,
1102
- sender.key,
1103
- &[],
1104
- owner_fee,
1105
- )?,
1106
- &[
1107
- sender_usdc.clone(),
1108
- mailer_usdc.clone(),
1109
- sender.clone(),
1110
- token_program.clone(),
1111
- ],
1112
- )?;
1113
- }
657
+ // Calculate effective fee based on custom discount (if any)
658
+ let effective_fee = calculate_fee_with_discount(_program_id, sender.key, accounts, mailer_state.send_fee)?;
1114
659
 
1115
- // Update owner claimable
1116
- let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1117
- let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1118
- mailer_state.owner_claimable += owner_fee;
1119
- mailer_state.serialize(&mut &mut mailer_data[8..])?;
660
+ // Calculate 10% owner fee (no revenue share since no wallet address)
661
+ let owner_fee = (effective_fee * 10) / 100;
1120
662
 
1121
- msg!(
1122
- "Webhook mail sent from {} to {} (webhookId: {}, resolve sender: {}, effective fee: {})",
663
+ // Transfer fee from sender to mailer
664
+ if owner_fee > 0 {
665
+ let transfer_ix = spl_token::instruction::transfer(
666
+ token_program.key,
667
+ sender_usdc.key,
668
+ mailer_usdc.key,
1123
669
  sender.key,
1124
- to,
1125
- webhook_id,
1126
- _resolve_sender_to_name,
1127
- effective_fee
1128
- );
670
+ &[],
671
+ owner_fee,
672
+ )?;
673
+
674
+ invoke(
675
+ &transfer_ix,
676
+ &[
677
+ sender_usdc.clone(),
678
+ mailer_usdc.clone(),
679
+ sender.clone(),
680
+ token_program.clone(),
681
+ ],
682
+ )?;
1129
683
  }
1130
684
 
685
+ // Update owner claimable
686
+ let mut mailer_data = mailer_account.try_borrow_mut_data()?;
687
+ let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
688
+ mailer_state.owner_claimable += owner_fee;
689
+ mailer_state.serialize(&mut &mut mailer_data[8..])?;
690
+
691
+ msg!("Prepared mail sent from {} to email {} (mailId: {}, effective fee: {})", sender.key, to_email, mail_id, effective_fee);
692
+
1131
693
  Ok(())
1132
694
  }
1133
695
 
@@ -1145,13 +707,6 @@ fn process_claim_recipient_share(_program_id: &Pubkey, accounts: &[AccountInfo])
1145
707
  return Err(ProgramError::MissingRequiredSignature);
1146
708
  }
1147
709
 
1148
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
1149
- let (claim_pda, _) =
1150
- Pubkey::find_program_address(&[b"claim", recipient.key.as_ref()], _program_id);
1151
- if recipient_claim.key != &claim_pda {
1152
- return Err(MailerError::InvalidPDA.into());
1153
- }
1154
-
1155
710
  // Load claim state
1156
711
  let mut claim_data = recipient_claim.try_borrow_mut_data()?;
1157
712
  let mut claim_state: RecipientClaim = BorshDeserialize::deserialize(&mut &claim_data[8..])?;
@@ -1178,11 +733,6 @@ fn process_claim_recipient_share(_program_id: &Pubkey, accounts: &[AccountInfo])
1178
733
  // Load mailer state for PDA signing
1179
734
  let mailer_data = mailer_account.try_borrow_data()?;
1180
735
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1181
- drop(mailer_data);
1182
-
1183
- assert_token_program(token_program)?;
1184
- assert_token_account(recipient_usdc, recipient.key, &mailer_state.usdc_mint)?;
1185
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1186
736
 
1187
737
  // Transfer USDC from mailer to recipient
1188
738
  invoke_signed(
@@ -1220,8 +770,6 @@ fn process_claim_owner_share(_program_id: &Pubkey, accounts: &[AccountInfo]) ->
1220
770
  return Err(ProgramError::MissingRequiredSignature);
1221
771
  }
1222
772
 
1223
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
1224
-
1225
773
  // Load and update mailer state
1226
774
  let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1227
775
  let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1239,10 +787,6 @@ fn process_claim_owner_share(_program_id: &Pubkey, accounts: &[AccountInfo]) ->
1239
787
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
1240
788
  drop(mailer_data);
1241
789
 
1242
- assert_token_program(token_program)?;
1243
- assert_token_account(owner_usdc, owner.key, &mailer_state.usdc_mint)?;
1244
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1245
-
1246
790
  // Transfer USDC from mailer to owner
1247
791
  invoke_signed(
1248
792
  &spl_token::instruction::transfer(
@@ -1276,8 +820,6 @@ fn process_set_fee(_program_id: &Pubkey, accounts: &[AccountInfo], new_fee: u64)
1276
820
  return Err(ProgramError::MissingRequiredSignature);
1277
821
  }
1278
822
 
1279
- assert_mailer_account(_program_id, mailer_account)?;
1280
-
1281
823
  // Load and update mailer state
1282
824
  let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1283
825
  let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1318,25 +860,21 @@ fn process_delegate_to(
1318
860
  return Err(ProgramError::MissingRequiredSignature);
1319
861
  }
1320
862
 
1321
- let (mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
1322
-
1323
863
  // Load mailer state
1324
864
  let mailer_data = mailer_account.try_borrow_data()?;
1325
865
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1326
866
  drop(mailer_data);
1327
867
 
1328
- assert_token_program(token_program)?;
1329
- assert_token_account(delegator_usdc, delegator.key, &mailer_state.usdc_mint)?;
1330
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1331
-
1332
868
  // Check if contract is paused
1333
869
  if mailer_state.paused {
1334
870
  return Err(MailerError::ContractPaused.into());
1335
871
  }
1336
872
 
1337
873
  // Verify delegation account PDA
1338
- let (delegation_pda, delegation_bump) =
1339
- Pubkey::find_program_address(&[b"delegation", delegator.key.as_ref()], program_id);
874
+ let (delegation_pda, delegation_bump) = Pubkey::find_program_address(
875
+ &[b"delegation", delegator.key.as_ref()],
876
+ program_id
877
+ );
1340
878
 
1341
879
  if delegation_account.key != &delegation_pda {
1342
880
  return Err(MailerError::InvalidPDA.into());
@@ -1366,8 +904,7 @@ fn process_delegate_to(
1366
904
 
1367
905
  // Initialize delegation account
1368
906
  let mut delegation_data = delegation_account.try_borrow_mut_data()?;
1369
- delegation_data[0..8]
1370
- .copy_from_slice(&hash_discriminator("account:Delegation").to_le_bytes());
907
+ delegation_data[0..8].copy_from_slice(&hash_discriminator("account:Delegation").to_le_bytes());
1371
908
 
1372
909
  let delegation_state = Delegation {
1373
910
  delegator: *delegator.key,
@@ -1403,8 +940,7 @@ fn process_delegate_to(
1403
940
 
1404
941
  // Update delegation
1405
942
  let mut delegation_data = delegation_account.try_borrow_mut_data()?;
1406
- let mut delegation_state: Delegation =
1407
- BorshDeserialize::deserialize(&mut &delegation_data[8..])?;
943
+ let mut delegation_state: Delegation = BorshDeserialize::deserialize(&mut &delegation_data[8..])?;
1408
944
  delegation_state.delegate = delegate;
1409
945
  delegation_state.serialize(&mut &mut delegation_data[8..])?;
1410
946
 
@@ -1413,31 +949,18 @@ fn process_delegate_to(
1413
949
  }
1414
950
 
1415
951
  /// Reject delegation
1416
- fn process_reject_delegation(program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
952
+ fn process_reject_delegation(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
1417
953
  let account_iter = &mut accounts.iter();
1418
954
  let rejector = next_account_info(account_iter)?;
1419
955
  let delegation_account = next_account_info(account_iter)?;
1420
- let mailer_account = next_account_info(account_iter)?;
1421
956
 
1422
957
  if !rejector.is_signer {
1423
958
  return Err(ProgramError::MissingRequiredSignature);
1424
959
  }
1425
960
 
1426
- // Verify mailer state PDA and ensure contract is not paused
1427
- let (_mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
1428
-
1429
- let mailer_data = mailer_account.try_borrow_data()?;
1430
- let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1431
- drop(mailer_data);
1432
-
1433
- if mailer_state.paused {
1434
- return Err(MailerError::ContractPaused.into());
1435
- }
1436
-
1437
961
  // Load and update delegation state
1438
962
  let mut delegation_data = delegation_account.try_borrow_mut_data()?;
1439
- let mut delegation_state: Delegation =
1440
- BorshDeserialize::deserialize(&mut &delegation_data[8..])?;
963
+ let mut delegation_state: Delegation = BorshDeserialize::deserialize(&mut &delegation_data[8..])?;
1441
964
 
1442
965
  // Verify the rejector is the current delegate
1443
966
  if delegation_state.delegate != Some(*rejector.key) {
@@ -1465,8 +988,6 @@ fn process_set_delegation_fee(
1465
988
  return Err(ProgramError::MissingRequiredSignature);
1466
989
  }
1467
990
 
1468
- assert_mailer_account(_program_id, mailer_account)?;
1469
-
1470
991
  // Load and update mailer state
1471
992
  let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1472
993
  let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1507,8 +1028,6 @@ fn process_set_custom_fee_percentage(
1507
1028
  return Err(ProgramError::MissingRequiredSignature);
1508
1029
  }
1509
1030
 
1510
- assert_mailer_account(program_id, mailer_account)?;
1511
-
1512
1031
  // Load mailer state and verify owner
1513
1032
  let mailer_data = mailer_account.try_borrow_data()?;
1514
1033
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1529,8 +1048,10 @@ fn process_set_custom_fee_percentage(
1529
1048
  }
1530
1049
 
1531
1050
  // Verify fee discount account PDA
1532
- let (discount_pda, bump) =
1533
- Pubkey::find_program_address(&[b"discount", account.as_ref()], program_id);
1051
+ let (discount_pda, bump) = Pubkey::find_program_address(
1052
+ &[b"discount", account.as_ref()],
1053
+ program_id
1054
+ );
1534
1055
 
1535
1056
  if fee_discount_account.key != &discount_pda {
1536
1057
  return Err(MailerError::InvalidPDA.into());
@@ -1550,18 +1071,13 @@ fn process_set_custom_fee_percentage(
1550
1071
  space as u64,
1551
1072
  program_id,
1552
1073
  ),
1553
- &[
1554
- payer.clone(),
1555
- fee_discount_account.clone(),
1556
- system_program.clone(),
1557
- ],
1074
+ &[payer.clone(), fee_discount_account.clone(), system_program.clone()],
1558
1075
  &[&[b"discount", account.as_ref(), &[bump]]],
1559
1076
  )?;
1560
1077
 
1561
1078
  // Initialize discount account
1562
1079
  let mut discount_data = fee_discount_account.try_borrow_mut_data()?;
1563
- discount_data[0..8]
1564
- .copy_from_slice(&hash_discriminator("account:FeeDiscount").to_le_bytes());
1080
+ discount_data[0..8].copy_from_slice(&hash_discriminator("account:FeeDiscount").to_le_bytes());
1565
1081
 
1566
1082
  let fee_discount = FeeDiscount {
1567
1083
  account,
@@ -1573,8 +1089,7 @@ fn process_set_custom_fee_percentage(
1573
1089
  } else {
1574
1090
  // Update existing discount account
1575
1091
  let mut discount_data = fee_discount_account.try_borrow_mut_data()?;
1576
- let mut fee_discount: FeeDiscount =
1577
- BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1092
+ let mut fee_discount: FeeDiscount = BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1578
1093
  fee_discount.discount = 100 - percentage; // Store as discount
1579
1094
  fee_discount.serialize(&mut &mut discount_data[8..])?;
1580
1095
  }
@@ -1598,8 +1113,6 @@ fn process_clear_custom_fee_percentage(
1598
1113
  return Err(ProgramError::MissingRequiredSignature);
1599
1114
  }
1600
1115
 
1601
- assert_mailer_account(program_id, mailer_account)?;
1602
-
1603
1116
  // Load mailer state and verify owner
1604
1117
  let mailer_data = mailer_account.try_borrow_data()?;
1605
1118
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1615,8 +1128,10 @@ fn process_clear_custom_fee_percentage(
1615
1128
  }
1616
1129
 
1617
1130
  // Verify fee discount account PDA
1618
- let (discount_pda, _) =
1619
- Pubkey::find_program_address(&[b"discount", account.as_ref()], program_id);
1131
+ let (discount_pda, _) = Pubkey::find_program_address(
1132
+ &[b"discount", account.as_ref()],
1133
+ program_id
1134
+ );
1620
1135
 
1621
1136
  if fee_discount_account.key != &discount_pda {
1622
1137
  return Err(MailerError::InvalidPDA.into());
@@ -1625,57 +1140,15 @@ fn process_clear_custom_fee_percentage(
1625
1140
  // Clear by setting discount to 0 (no discount = 100% fee = default behavior)
1626
1141
  if fee_discount_account.lamports() > 0 {
1627
1142
  let mut discount_data = fee_discount_account.try_borrow_mut_data()?;
1628
- let mut fee_discount: FeeDiscount =
1629
- BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1143
+ let mut fee_discount: FeeDiscount = BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1630
1144
  fee_discount.discount = 0; // 0 discount = 100% fee = default
1631
1145
  fee_discount.serialize(&mut &mut discount_data[8..])?;
1632
1146
  }
1633
1147
 
1634
- msg!(
1635
- "Custom fee percentage cleared for {} (reset to 100%)",
1636
- account
1637
- );
1638
- Ok(())
1639
- }
1640
-
1641
- fn assert_token_program(token_program: &AccountInfo) -> Result<(), ProgramError> {
1642
- if token_program.key != &spl_token::id() {
1643
- return Err(MailerError::InvalidTokenProgram.into());
1644
- }
1645
- Ok(())
1646
- }
1647
-
1648
- fn assert_token_account(
1649
- token_account_info: &AccountInfo,
1650
- expected_owner: &Pubkey,
1651
- expected_mint: &Pubkey,
1652
- ) -> Result<(), ProgramError> {
1653
- let data = token_account_info.try_borrow_data()?;
1654
- let token_account = TokenAccount::unpack(&data)?;
1655
- drop(data);
1656
-
1657
- if token_account.owner != *expected_owner {
1658
- return Err(MailerError::InvalidAccountOwner.into());
1659
- }
1660
-
1661
- if token_account.mint != *expected_mint {
1662
- return Err(MailerError::InvalidMint.into());
1663
- }
1664
-
1148
+ msg!("Custom fee percentage cleared for {} (reset to 100%)", account);
1665
1149
  Ok(())
1666
1150
  }
1667
1151
 
1668
- fn assert_mailer_account(
1669
- program_id: &Pubkey,
1670
- mailer_account: &AccountInfo,
1671
- ) -> Result<(Pubkey, u8), ProgramError> {
1672
- let (mailer_pda, bump) = Pubkey::find_program_address(&[b"mailer"], program_id);
1673
- if mailer_account.key != &mailer_pda {
1674
- return Err(MailerError::InvalidPDA.into());
1675
- }
1676
- Ok((mailer_pda, bump))
1677
- }
1678
-
1679
1152
  /// Record revenue shares for priority messages
1680
1153
  fn record_shares(
1681
1154
  recipient_claim: &AccountInfo,
@@ -1702,11 +1175,7 @@ fn record_shares(
1702
1175
  mailer_state.owner_claimable += owner_amount;
1703
1176
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
1704
1177
 
1705
- msg!(
1706
- "Shares recorded: recipient {}, owner {}",
1707
- recipient_amount,
1708
- owner_amount
1709
- );
1178
+ msg!("Shares recorded: recipient {}, owner {}", recipient_amount, owner_amount);
1710
1179
  Ok(())
1711
1180
  }
1712
1181
 
@@ -1720,8 +1189,10 @@ fn calculate_fee_with_discount(
1720
1189
  base_fee: u64,
1721
1190
  ) -> Result<u64, ProgramError> {
1722
1191
  // Try to find fee discount account
1723
- let (discount_pda, _) =
1724
- Pubkey::find_program_address(&[b"discount", account.as_ref()], program_id);
1192
+ let (discount_pda, _) = Pubkey::find_program_address(
1193
+ &[b"discount", account.as_ref()],
1194
+ program_id
1195
+ );
1725
1196
 
1726
1197
  // Check if any account in the accounts slice matches the discount PDA
1727
1198
  let discount_account = accounts.iter().find(|acc| acc.key == &discount_pda);
@@ -1731,8 +1202,7 @@ fn calculate_fee_with_discount(
1731
1202
  if discount_acc.lamports() > 0 {
1732
1203
  let discount_data = discount_acc.try_borrow_data()?;
1733
1204
  if discount_data.len() >= 8 + FeeDiscount::LEN {
1734
- let fee_discount: FeeDiscount =
1735
- BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1205
+ let fee_discount: FeeDiscount = BorshDeserialize::deserialize(&mut &discount_data[8..])?;
1736
1206
  let discount = fee_discount.discount as u64;
1737
1207
 
1738
1208
  // Apply discount: fee = base_fee * (100 - discount) / 100
@@ -1760,8 +1230,6 @@ fn process_pause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResul
1760
1230
  return Err(ProgramError::MissingRequiredSignature);
1761
1231
  }
1762
1232
 
1763
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
1764
-
1765
1233
  // Load and update mailer state
1766
1234
  let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1767
1235
  let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1779,17 +1247,13 @@ fn process_pause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResul
1779
1247
  // Set paused state
1780
1248
  mailer_state.paused = true;
1781
1249
 
1782
- assert_token_program(token_program)?;
1783
-
1784
1250
  // Distribute owner claimable funds if any
1785
1251
  if mailer_state.owner_claimable > 0 {
1786
1252
  let amount = mailer_state.owner_claimable;
1787
1253
  mailer_state.owner_claimable = 0;
1788
1254
 
1789
- assert_token_account(owner_usdc, owner.key, &mailer_state.usdc_mint)?;
1790
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1791
-
1792
1255
  // Transfer USDC from mailer to owner
1256
+ let (mailer_pda, bump) = Pubkey::find_program_address(&[b"mailer"], _program_id);
1793
1257
  invoke_signed(
1794
1258
  &spl_token::instruction::transfer(
1795
1259
  token_program.key,
@@ -1799,13 +1263,8 @@ fn process_pause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResul
1799
1263
  &[],
1800
1264
  amount,
1801
1265
  )?,
1802
- &[
1803
- mailer_usdc.clone(),
1804
- owner_usdc.clone(),
1805
- mailer_account.clone(),
1806
- token_program.clone(),
1807
- ],
1808
- &[&[b"mailer", &[mailer_state.bump]]],
1266
+ &[mailer_usdc.clone(), owner_usdc.clone(), token_program.clone()],
1267
+ &[&[b"mailer", &[bump]]],
1809
1268
  )?;
1810
1269
 
1811
1270
  msg!("Distributed owner funds during pause: {}", amount);
@@ -1813,7 +1272,7 @@ fn process_pause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResul
1813
1272
 
1814
1273
  // Save updated state
1815
1274
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
1816
-
1275
+
1817
1276
  msg!("Contract paused by owner: {}", owner.key);
1818
1277
  Ok(())
1819
1278
  }
@@ -1828,8 +1287,6 @@ fn process_unpause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramRes
1828
1287
  return Err(ProgramError::MissingRequiredSignature);
1829
1288
  }
1830
1289
 
1831
- assert_mailer_account(_program_id, mailer_account)?;
1832
-
1833
1290
  // Load and update mailer state
1834
1291
  let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1835
1292
  let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1847,11 +1304,43 @@ fn process_unpause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramRes
1847
1304
  // Set unpaused state
1848
1305
  mailer_state.paused = false;
1849
1306
  mailer_state.serialize(&mut &mut mailer_data[8..])?;
1850
-
1307
+
1851
1308
  msg!("Contract unpaused by owner: {}", owner.key);
1852
1309
  Ok(())
1853
1310
  }
1854
1311
 
1312
+ /// Emergency unpause without fund distribution (owner only)
1313
+ fn process_emergency_unpause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
1314
+ let account_iter = &mut accounts.iter();
1315
+ let owner = next_account_info(account_iter)?;
1316
+ let mailer_account = next_account_info(account_iter)?;
1317
+
1318
+ if !owner.is_signer {
1319
+ return Err(ProgramError::MissingRequiredSignature);
1320
+ }
1321
+
1322
+ // Load and update mailer state
1323
+ let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1324
+ let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1325
+
1326
+ // Verify owner
1327
+ if mailer_state.owner != *owner.key {
1328
+ return Err(MailerError::OnlyOwner.into());
1329
+ }
1330
+
1331
+ // Check if not paused
1332
+ if !mailer_state.paused {
1333
+ return Err(MailerError::ContractNotPaused.into());
1334
+ }
1335
+
1336
+ // Set unpaused state without fund distribution
1337
+ mailer_state.paused = false;
1338
+ mailer_state.serialize(&mut &mut mailer_data[8..])?;
1339
+
1340
+ msg!("Contract emergency unpaused by owner: {} - funds can be claimed manually", owner.key);
1341
+ Ok(())
1342
+ }
1343
+
1855
1344
  /// Distribute claimable funds when contract is paused
1856
1345
  fn process_distribute_claimable_funds(
1857
1346
  _program_id: &Pubkey,
@@ -1866,8 +1355,6 @@ fn process_distribute_claimable_funds(
1866
1355
  let mailer_usdc = next_account_info(account_iter)?;
1867
1356
  let token_program = next_account_info(account_iter)?;
1868
1357
 
1869
- let (mailer_pda, _) = assert_mailer_account(_program_id, mailer_account)?;
1870
-
1871
1358
  // Load mailer state to check if paused
1872
1359
  let mailer_data = mailer_account.try_borrow_data()?;
1873
1360
  let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
@@ -1884,8 +1371,6 @@ fn process_distribute_claimable_funds(
1884
1371
  return Err(MailerError::InvalidPDA.into());
1885
1372
  }
1886
1373
 
1887
- assert_token_program(token_program)?;
1888
-
1889
1374
  // Load and update recipient claim
1890
1375
  let mut claim_data = recipient_claim_account.try_borrow_mut_data()?;
1891
1376
  let mut claim_state: RecipientClaim = BorshDeserialize::deserialize(&mut &claim_data[8..])?;
@@ -1898,10 +1383,8 @@ fn process_distribute_claimable_funds(
1898
1383
  claim_state.amount = 0;
1899
1384
  claim_state.timestamp = 0;
1900
1385
 
1901
- assert_token_account(recipient_usdc, &recipient, &mailer_state.usdc_mint)?;
1902
- assert_token_account(mailer_usdc, &mailer_pda, &mailer_state.usdc_mint)?;
1903
-
1904
1386
  // Transfer USDC from mailer to recipient
1387
+ let (mailer_pda, bump) = Pubkey::find_program_address(&[b"mailer"], _program_id);
1905
1388
  invoke_signed(
1906
1389
  &spl_token::instruction::transfer(
1907
1390
  token_program.key,
@@ -1911,118 +1394,16 @@ fn process_distribute_claimable_funds(
1911
1394
  &[],
1912
1395
  amount,
1913
1396
  )?,
1914
- &[
1915
- mailer_usdc.clone(),
1916
- recipient_usdc.clone(),
1917
- mailer_account.clone(),
1918
- token_program.clone(),
1919
- ],
1920
- &[&[b"mailer", &[mailer_state.bump]]],
1397
+ &[mailer_usdc.clone(), recipient_usdc.clone(), token_program.clone()],
1398
+ &[&[b"mailer", &[bump]]],
1921
1399
  )?;
1922
1400
 
1923
1401
  claim_state.serialize(&mut &mut claim_data[8..])?;
1924
-
1402
+
1925
1403
  msg!("Distributed claimable funds to {}: {}", recipient, amount);
1926
1404
  Ok(())
1927
1405
  }
1928
1406
 
1929
- /// Claim expired shares and move them under owner control (owner only)
1930
- fn process_claim_expired_shares(
1931
- program_id: &Pubkey,
1932
- accounts: &[AccountInfo],
1933
- recipient: Pubkey,
1934
- ) -> ProgramResult {
1935
- let account_iter = &mut accounts.iter();
1936
- let owner = next_account_info(account_iter)?;
1937
- let mailer_account = next_account_info(account_iter)?;
1938
- let recipient_claim_account = next_account_info(account_iter)?;
1939
-
1940
- if !owner.is_signer {
1941
- return Err(ProgramError::MissingRequiredSignature);
1942
- }
1943
-
1944
- let (_mailer_pda, _) = assert_mailer_account(program_id, mailer_account)?;
1945
-
1946
- // Load and verify mailer state
1947
- let mut mailer_data = mailer_account.try_borrow_mut_data()?;
1948
- let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
1949
-
1950
- if mailer_state.owner != *owner.key {
1951
- return Err(MailerError::OnlyOwner.into());
1952
- }
1953
-
1954
- // Verify recipient claim PDA
1955
- let (claim_pda, _) = Pubkey::find_program_address(&[b"claim", recipient.as_ref()], program_id);
1956
- if recipient_claim_account.key != &claim_pda {
1957
- return Err(MailerError::InvalidPDA.into());
1958
- }
1959
-
1960
- // Load and validate claim state
1961
- let mut claim_data = recipient_claim_account.try_borrow_mut_data()?;
1962
- let mut claim_state: RecipientClaim = BorshDeserialize::deserialize(&mut &claim_data[8..])?;
1963
-
1964
- if claim_state.recipient != recipient {
1965
- return Err(MailerError::InvalidRecipient.into());
1966
- }
1967
- if claim_state.amount == 0 {
1968
- return Err(MailerError::NoClaimableAmount.into());
1969
- }
1970
-
1971
- let current_time = Clock::get()?.unix_timestamp;
1972
- if current_time <= claim_state.timestamp + CLAIM_PERIOD {
1973
- return Err(MailerError::ClaimPeriodNotExpired.into());
1974
- }
1975
-
1976
- let amount = claim_state.amount;
1977
- claim_state.amount = 0;
1978
- claim_state.timestamp = 0;
1979
- claim_state.serialize(&mut &mut claim_data[8..])?;
1980
- drop(claim_data);
1981
-
1982
- mailer_state.owner_claimable += amount;
1983
- mailer_state.serialize(&mut &mut mailer_data[8..])?;
1984
-
1985
- msg!("Expired shares claimed for {}: {}", recipient, amount);
1986
- Ok(())
1987
- }
1988
-
1989
- /// Emergency unpause without fund distribution (owner only)
1990
- fn process_emergency_unpause(_program_id: &Pubkey, accounts: &[AccountInfo]) -> ProgramResult {
1991
- let account_iter = &mut accounts.iter();
1992
- let owner = next_account_info(account_iter)?;
1993
- let mailer_account = next_account_info(account_iter)?;
1994
-
1995
- if !owner.is_signer {
1996
- return Err(ProgramError::MissingRequiredSignature);
1997
- }
1998
-
1999
- assert_mailer_account(_program_id, mailer_account)?;
2000
-
2001
- // Load and update mailer state
2002
- let mut mailer_data = mailer_account.try_borrow_mut_data()?;
2003
- let mut mailer_state: MailerState = BorshDeserialize::deserialize(&mut &mailer_data[8..])?;
2004
-
2005
- // Verify owner
2006
- if mailer_state.owner != *owner.key {
2007
- return Err(MailerError::OnlyOwner.into());
2008
- }
2009
-
2010
- // Check if not paused
2011
- if !mailer_state.paused {
2012
- return Err(MailerError::ContractNotPaused.into());
2013
- }
2014
-
2015
- // Set unpaused state without fund distribution
2016
- mailer_state.paused = false;
2017
- mailer_state.serialize(&mut &mut mailer_data[8..])?;
2018
-
2019
- msg!(
2020
- "Contract emergency unpaused by owner: {} - funds can be claimed manually",
2021
- owner.key
2022
- );
2023
- Ok(())
2024
- }
2025
-
2026
1407
  /// Simple hash function for account discriminators
2027
1408
  fn hash_discriminator(name: &str) -> u64 {
2028
1409
  use std::collections::hash_map::DefaultHasher;