@sudobility/contracts 0.14.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 (322) hide show
  1. package/README.md +353 -0
  2. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +1146 -0
  3. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +4 -0
  4. package/artifacts/contracts/Mailer.sol/Mailer.json +1096 -0
  5. package/artifacts/contracts/Mailer.sol/artifacts.d.ts +21 -0
  6. package/artifacts/contracts/MockUSDC.sol/MockUSDC.d.ts +284 -0
  7. package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +4 -0
  8. package/artifacts/contracts/MockUSDC.sol/MockUSDC.json +234 -0
  9. package/artifacts/contracts/MockUSDC.sol/artifacts.d.ts +21 -0
  10. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.d.ts +157 -0
  11. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +4 -0
  12. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.json +107 -0
  13. package/artifacts/contracts/interfaces/IERC20.sol/artifacts.d.ts +21 -0
  14. package/dist/evm/src/evm/index.d.ts +4 -0
  15. package/dist/evm/src/evm/index.d.ts.map +1 -0
  16. package/dist/evm/src/evm/index.js +10 -0
  17. package/dist/evm/src/evm/index.js.map +1 -0
  18. package/dist/evm/src/evm/mailer-client.d.ts +966 -0
  19. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -0
  20. package/dist/evm/src/evm/mailer-client.js +619 -0
  21. package/dist/evm/src/evm/mailer-client.js.map +1 -0
  22. package/dist/evm/typechain-types/Mailer.d.ts +698 -0
  23. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -0
  24. package/dist/evm/typechain-types/Mailer.js +3 -0
  25. package/dist/evm/typechain-types/Mailer.js.map +1 -0
  26. package/dist/evm/typechain-types/MockUSDC.d.ts +118 -0
  27. package/dist/evm/typechain-types/MockUSDC.d.ts.map +1 -0
  28. package/dist/evm/typechain-types/MockUSDC.js +3 -0
  29. package/dist/evm/typechain-types/MockUSDC.js.map +1 -0
  30. package/dist/evm/typechain-types/common.d.ts +51 -0
  31. package/dist/evm/typechain-types/common.d.ts.map +1 -0
  32. package/dist/evm/typechain-types/common.js +3 -0
  33. package/dist/evm/typechain-types/common.js.map +1 -0
  34. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +875 -0
  35. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
  36. package/dist/evm/typechain-types/factories/Mailer__factory.js +1125 -0
  37. package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -0
  38. package/dist/evm/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
  39. package/dist/evm/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
  40. package/dist/evm/typechain-types/factories/MockUSDC__factory.js +263 -0
  41. package/dist/evm/typechain-types/factories/MockUSDC__factory.js.map +1 -0
  42. package/dist/evm/typechain-types/factories/index.d.ts +4 -0
  43. package/dist/evm/typechain-types/factories/index.d.ts.map +1 -0
  44. package/dist/evm/typechain-types/factories/index.js +45 -0
  45. package/dist/evm/typechain-types/factories/index.js.map +1 -0
  46. package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
  47. package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
  48. package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.js +116 -0
  49. package/dist/evm/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
  50. package/dist/evm/typechain-types/factories/interfaces/index.d.ts +2 -0
  51. package/dist/evm/typechain-types/factories/interfaces/index.d.ts.map +1 -0
  52. package/dist/evm/typechain-types/factories/interfaces/index.js +9 -0
  53. package/dist/evm/typechain-types/factories/interfaces/index.js.map +1 -0
  54. package/dist/evm/typechain-types/index.d.ts +10 -0
  55. package/dist/evm/typechain-types/index.d.ts.map +1 -0
  56. package/dist/evm/typechain-types/index.js +44 -0
  57. package/dist/evm/typechain-types/index.js.map +1 -0
  58. package/dist/evm/typechain-types/interfaces/IERC20.d.ts +70 -0
  59. package/dist/evm/typechain-types/interfaces/IERC20.d.ts.map +1 -0
  60. package/dist/evm/typechain-types/interfaces/IERC20.js +3 -0
  61. package/dist/evm/typechain-types/interfaces/IERC20.js.map +1 -0
  62. package/dist/evm/typechain-types/interfaces/index.d.ts +2 -0
  63. package/dist/evm/typechain-types/interfaces/index.d.ts.map +1 -0
  64. package/dist/evm/typechain-types/interfaces/index.js +3 -0
  65. package/dist/evm/typechain-types/interfaces/index.js.map +1 -0
  66. package/dist/solana/solana/index.d.ts +3 -0
  67. package/dist/solana/solana/index.d.ts.map +1 -0
  68. package/dist/solana/solana/index.js +21 -0
  69. package/dist/solana/solana/index.js.map +1 -0
  70. package/dist/solana/solana/mailer-client.d.ts +282 -0
  71. package/dist/solana/solana/mailer-client.d.ts.map +1 -0
  72. package/dist/solana/solana/mailer-client.js +989 -0
  73. package/dist/solana/solana/mailer-client.js.map +1 -0
  74. package/dist/solana/solana/types.d.ts +28 -0
  75. package/dist/solana/solana/types.d.ts.map +1 -0
  76. package/dist/solana/solana/types.js +23 -0
  77. package/dist/solana/solana/types.js.map +1 -0
  78. package/dist/solana/utils/currency.d.ts +26 -0
  79. package/dist/solana/utils/currency.d.ts.map +1 -0
  80. package/dist/solana/utils/currency.js +36 -0
  81. package/dist/solana/utils/currency.js.map +1 -0
  82. package/dist/unified/package.json +3 -0
  83. package/dist/unified/src/evm/index.d.ts +4 -0
  84. package/dist/unified/src/evm/index.d.ts.map +1 -0
  85. package/dist/unified/src/evm/index.js +10 -0
  86. package/dist/unified/src/evm/index.js.map +1 -0
  87. package/dist/unified/src/evm/mailer-client.d.ts +966 -0
  88. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -0
  89. package/dist/unified/src/evm/mailer-client.js +619 -0
  90. package/dist/unified/src/evm/mailer-client.js.map +1 -0
  91. package/dist/unified/src/react/context/MailerProvider.d.ts +102 -0
  92. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -0
  93. package/dist/unified/src/react/context/MailerProvider.js +160 -0
  94. package/dist/unified/src/react/context/MailerProvider.js.map +1 -0
  95. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +301 -0
  96. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -0
  97. package/dist/unified/src/react/hooks/useMailerMutations.js +417 -0
  98. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -0
  99. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +130 -0
  100. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -0
  101. package/dist/unified/src/react/hooks/useMailerQueries.js +197 -0
  102. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -0
  103. package/dist/unified/src/react/index.d.ts +37 -0
  104. package/dist/unified/src/react/index.d.ts.map +1 -0
  105. package/dist/unified/src/react/index.js +70 -0
  106. package/dist/unified/src/react/index.js.map +1 -0
  107. package/dist/unified/src/solana/index.d.ts +3 -0
  108. package/dist/unified/src/solana/index.d.ts.map +1 -0
  109. package/dist/unified/src/solana/index.js +21 -0
  110. package/dist/unified/src/solana/index.js.map +1 -0
  111. package/dist/unified/src/solana/mailer-client.d.ts +282 -0
  112. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -0
  113. package/dist/unified/src/solana/mailer-client.js +989 -0
  114. package/dist/unified/src/solana/mailer-client.js.map +1 -0
  115. package/dist/unified/src/solana/types.d.ts +28 -0
  116. package/dist/unified/src/solana/types.d.ts.map +1 -0
  117. package/dist/unified/src/solana/types.js +23 -0
  118. package/dist/unified/src/solana/types.js.map +1 -0
  119. package/dist/unified/src/unified/index.d.ts +4 -0
  120. package/dist/unified/src/unified/index.d.ts.map +1 -0
  121. package/dist/unified/src/unified/index.js +9 -0
  122. package/dist/unified/src/unified/index.js.map +1 -0
  123. package/dist/unified/src/unified/onchain-mailer-client.d.ts +173 -0
  124. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -0
  125. package/dist/unified/src/unified/onchain-mailer-client.js +1048 -0
  126. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -0
  127. package/dist/unified/src/unified/types.d.ts +47 -0
  128. package/dist/unified/src/unified/types.d.ts.map +1 -0
  129. package/dist/unified/src/unified/types.js +3 -0
  130. package/dist/unified/src/unified/types.js.map +1 -0
  131. package/dist/unified/src/unified/wallet-detector.d.ts +28 -0
  132. package/dist/unified/src/unified/wallet-detector.d.ts.map +1 -0
  133. package/dist/unified/src/unified/wallet-detector.js +63 -0
  134. package/dist/unified/src/unified/wallet-detector.js.map +1 -0
  135. package/dist/unified/src/utils/chain-config.d.ts +75 -0
  136. package/dist/unified/src/utils/chain-config.d.ts.map +1 -0
  137. package/dist/unified/src/utils/chain-config.js +203 -0
  138. package/dist/unified/src/utils/chain-config.js.map +1 -0
  139. package/dist/unified/src/utils/currency.d.ts +26 -0
  140. package/dist/unified/src/utils/currency.d.ts.map +1 -0
  141. package/dist/unified/src/utils/currency.js +36 -0
  142. package/dist/unified/src/utils/currency.js.map +1 -0
  143. package/dist/unified/src/utils/index.d.ts +4 -0
  144. package/dist/unified/src/utils/index.d.ts.map +1 -0
  145. package/dist/unified/src/utils/index.js +20 -0
  146. package/dist/unified/src/utils/index.js.map +1 -0
  147. package/dist/unified/src/utils/validation.d.ts +10 -0
  148. package/dist/unified/src/utils/validation.d.ts.map +1 -0
  149. package/dist/unified/src/utils/validation.js +102 -0
  150. package/dist/unified/src/utils/validation.js.map +1 -0
  151. package/dist/unified/typechain-types/Mailer.d.ts +698 -0
  152. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -0
  153. package/dist/unified/typechain-types/Mailer.js +3 -0
  154. package/dist/unified/typechain-types/Mailer.js.map +1 -0
  155. package/dist/unified/typechain-types/MockUSDC.d.ts +118 -0
  156. package/dist/unified/typechain-types/MockUSDC.d.ts.map +1 -0
  157. package/dist/unified/typechain-types/MockUSDC.js +3 -0
  158. package/dist/unified/typechain-types/MockUSDC.js.map +1 -0
  159. package/dist/unified/typechain-types/common.d.ts +51 -0
  160. package/dist/unified/typechain-types/common.d.ts.map +1 -0
  161. package/dist/unified/typechain-types/common.js +3 -0
  162. package/dist/unified/typechain-types/common.js.map +1 -0
  163. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +875 -0
  164. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
  165. package/dist/unified/typechain-types/factories/Mailer__factory.js +1125 -0
  166. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -0
  167. package/dist/unified/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
  168. package/dist/unified/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
  169. package/dist/unified/typechain-types/factories/MockUSDC__factory.js +263 -0
  170. package/dist/unified/typechain-types/factories/MockUSDC__factory.js.map +1 -0
  171. package/dist/unified/typechain-types/factories/index.d.ts +4 -0
  172. package/dist/unified/typechain-types/factories/index.d.ts.map +1 -0
  173. package/dist/unified/typechain-types/factories/index.js +45 -0
  174. package/dist/unified/typechain-types/factories/index.js.map +1 -0
  175. package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
  176. package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
  177. package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.js +116 -0
  178. package/dist/unified/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
  179. package/dist/unified/typechain-types/factories/interfaces/index.d.ts +2 -0
  180. package/dist/unified/typechain-types/factories/interfaces/index.d.ts.map +1 -0
  181. package/dist/unified/typechain-types/factories/interfaces/index.js +9 -0
  182. package/dist/unified/typechain-types/factories/interfaces/index.js.map +1 -0
  183. package/dist/unified/typechain-types/index.d.ts +10 -0
  184. package/dist/unified/typechain-types/index.d.ts.map +1 -0
  185. package/dist/unified/typechain-types/index.js +44 -0
  186. package/dist/unified/typechain-types/index.js.map +1 -0
  187. package/dist/unified/typechain-types/interfaces/IERC20.d.ts +70 -0
  188. package/dist/unified/typechain-types/interfaces/IERC20.d.ts.map +1 -0
  189. package/dist/unified/typechain-types/interfaces/IERC20.js +3 -0
  190. package/dist/unified/typechain-types/interfaces/IERC20.js.map +1 -0
  191. package/dist/unified/typechain-types/interfaces/index.d.ts +2 -0
  192. package/dist/unified/typechain-types/interfaces/index.d.ts.map +1 -0
  193. package/dist/unified/typechain-types/interfaces/index.js +3 -0
  194. package/dist/unified/typechain-types/interfaces/index.js.map +1 -0
  195. package/dist/unified-esm/src/evm/index.d.ts +4 -0
  196. package/dist/unified-esm/src/evm/index.d.ts.map +1 -0
  197. package/dist/unified-esm/src/evm/index.js +5 -0
  198. package/dist/unified-esm/src/evm/index.js.map +1 -0
  199. package/dist/unified-esm/src/evm/mailer-client.d.ts +966 -0
  200. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -0
  201. package/dist/unified-esm/src/evm/mailer-client.js +615 -0
  202. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -0
  203. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +102 -0
  204. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -0
  205. package/dist/unified-esm/src/react/context/MailerProvider.js +120 -0
  206. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -0
  207. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +301 -0
  208. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -0
  209. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +400 -0
  210. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -0
  211. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +130 -0
  212. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -0
  213. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +186 -0
  214. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -0
  215. package/dist/unified-esm/src/react/index.d.ts +37 -0
  216. package/dist/unified-esm/src/react/index.d.ts.map +1 -0
  217. package/dist/unified-esm/src/react/index.js +39 -0
  218. package/dist/unified-esm/src/react/index.js.map +1 -0
  219. package/dist/unified-esm/src/solana/index.d.ts +3 -0
  220. package/dist/unified-esm/src/solana/index.d.ts.map +1 -0
  221. package/dist/unified-esm/src/solana/index.js +3 -0
  222. package/dist/unified-esm/src/solana/index.js.map +1 -0
  223. package/dist/unified-esm/src/solana/mailer-client.d.ts +282 -0
  224. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -0
  225. package/dist/unified-esm/src/solana/mailer-client.js +985 -0
  226. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -0
  227. package/dist/unified-esm/src/solana/types.d.ts +28 -0
  228. package/dist/unified-esm/src/solana/types.d.ts.map +1 -0
  229. package/dist/unified-esm/src/solana/types.js +16 -0
  230. package/dist/unified-esm/src/solana/types.js.map +1 -0
  231. package/dist/unified-esm/src/unified/index.d.ts +4 -0
  232. package/dist/unified-esm/src/unified/index.d.ts.map +1 -0
  233. package/dist/unified-esm/src/unified/index.js +4 -0
  234. package/dist/unified-esm/src/unified/index.js.map +1 -0
  235. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +173 -0
  236. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -0
  237. package/dist/unified-esm/src/unified/onchain-mailer-client.js +1011 -0
  238. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -0
  239. package/dist/unified-esm/src/unified/types.d.ts +47 -0
  240. package/dist/unified-esm/src/unified/types.d.ts.map +1 -0
  241. package/dist/unified-esm/src/unified/types.js +2 -0
  242. package/dist/unified-esm/src/unified/types.js.map +1 -0
  243. package/dist/unified-esm/src/unified/wallet-detector.d.ts +28 -0
  244. package/dist/unified-esm/src/unified/wallet-detector.d.ts.map +1 -0
  245. package/dist/unified-esm/src/unified/wallet-detector.js +59 -0
  246. package/dist/unified-esm/src/unified/wallet-detector.js.map +1 -0
  247. package/dist/unified-esm/src/utils/chain-config.d.ts +75 -0
  248. package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -0
  249. package/dist/unified-esm/src/utils/chain-config.js +199 -0
  250. package/dist/unified-esm/src/utils/chain-config.js.map +1 -0
  251. package/dist/unified-esm/src/utils/currency.d.ts +26 -0
  252. package/dist/unified-esm/src/utils/currency.d.ts.map +1 -0
  253. package/dist/unified-esm/src/utils/currency.js +31 -0
  254. package/dist/unified-esm/src/utils/currency.js.map +1 -0
  255. package/dist/unified-esm/src/utils/index.d.ts +4 -0
  256. package/dist/unified-esm/src/utils/index.d.ts.map +1 -0
  257. package/dist/unified-esm/src/utils/index.js +4 -0
  258. package/dist/unified-esm/src/utils/index.js.map +1 -0
  259. package/dist/unified-esm/src/utils/validation.d.ts +10 -0
  260. package/dist/unified-esm/src/utils/validation.d.ts.map +1 -0
  261. package/dist/unified-esm/src/utils/validation.js +96 -0
  262. package/dist/unified-esm/src/utils/validation.js.map +1 -0
  263. package/dist/unified-esm/typechain-types/Mailer.d.ts +698 -0
  264. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -0
  265. package/dist/unified-esm/typechain-types/Mailer.js +2 -0
  266. package/dist/unified-esm/typechain-types/Mailer.js.map +1 -0
  267. package/dist/unified-esm/typechain-types/MockUSDC.d.ts +118 -0
  268. package/dist/unified-esm/typechain-types/MockUSDC.d.ts.map +1 -0
  269. package/dist/unified-esm/typechain-types/MockUSDC.js +2 -0
  270. package/dist/unified-esm/typechain-types/MockUSDC.js.map +1 -0
  271. package/dist/unified-esm/typechain-types/common.d.ts +51 -0
  272. package/dist/unified-esm/typechain-types/common.d.ts.map +1 -0
  273. package/dist/unified-esm/typechain-types/common.js +2 -0
  274. package/dist/unified-esm/typechain-types/common.js.map +1 -0
  275. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +875 -0
  276. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -0
  277. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1121 -0
  278. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -0
  279. package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.d.ts +193 -0
  280. package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.d.ts.map +1 -0
  281. package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.js +259 -0
  282. package/dist/unified-esm/typechain-types/factories/MockUSDC__factory.js.map +1 -0
  283. package/dist/unified-esm/typechain-types/factories/index.d.ts +4 -0
  284. package/dist/unified-esm/typechain-types/factories/index.d.ts.map +1 -0
  285. package/dist/unified-esm/typechain-types/factories/index.js +7 -0
  286. package/dist/unified-esm/typechain-types/factories/index.js.map +1 -0
  287. package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.d.ts +80 -0
  288. package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.d.ts.map +1 -0
  289. package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.js +112 -0
  290. package/dist/unified-esm/typechain-types/factories/interfaces/IERC20__factory.js.map +1 -0
  291. package/dist/unified-esm/typechain-types/factories/interfaces/index.d.ts +2 -0
  292. package/dist/unified-esm/typechain-types/factories/interfaces/index.d.ts.map +1 -0
  293. package/dist/unified-esm/typechain-types/factories/interfaces/index.js +5 -0
  294. package/dist/unified-esm/typechain-types/factories/interfaces/index.js.map +1 -0
  295. package/dist/unified-esm/typechain-types/index.d.ts +10 -0
  296. package/dist/unified-esm/typechain-types/index.d.ts.map +1 -0
  297. package/dist/unified-esm/typechain-types/index.js +5 -0
  298. package/dist/unified-esm/typechain-types/index.js.map +1 -0
  299. package/dist/unified-esm/typechain-types/interfaces/IERC20.d.ts +70 -0
  300. package/dist/unified-esm/typechain-types/interfaces/IERC20.d.ts.map +1 -0
  301. package/dist/unified-esm/typechain-types/interfaces/IERC20.js +2 -0
  302. package/dist/unified-esm/typechain-types/interfaces/IERC20.js.map +1 -0
  303. package/dist/unified-esm/typechain-types/interfaces/index.d.ts +2 -0
  304. package/dist/unified-esm/typechain-types/interfaces/index.d.ts.map +1 -0
  305. package/dist/unified-esm/typechain-types/interfaces/index.js +2 -0
  306. package/dist/unified-esm/typechain-types/interfaces/index.js.map +1 -0
  307. package/package.json +250 -0
  308. package/programs/mailer/Cargo.toml +29 -0
  309. package/programs/mailer/src/lib.rs +2034 -0
  310. package/programs/mailer/tests/integration_tests.rs +1236 -0
  311. package/typechain-types/Mailer.ts +1393 -0
  312. package/typechain-types/MockUSDC.ts +236 -0
  313. package/typechain-types/common.ts +131 -0
  314. package/typechain-types/factories/Mailer__factory.ts +1157 -0
  315. package/typechain-types/factories/MockUSDC__factory.ts +284 -0
  316. package/typechain-types/factories/index.ts +6 -0
  317. package/typechain-types/factories/interfaces/IERC20__factory.ts +115 -0
  318. package/typechain-types/factories/interfaces/index.ts +4 -0
  319. package/typechain-types/hardhat.d.ts +99 -0
  320. package/typechain-types/index.ts +12 -0
  321. package/typechain-types/interfaces/IERC20.ts +148 -0
  322. package/typechain-types/interfaces/index.ts +4 -0
@@ -0,0 +1,1236 @@
1
+ use borsh::BorshDeserialize;
2
+ use solana_program::{
3
+ instruction::{AccountMeta, Instruction},
4
+ program_pack::Pack,
5
+ pubkey::Pubkey,
6
+ system_program,
7
+ };
8
+ use solana_program_test::*;
9
+ use solana_sdk::{
10
+ signature::{Keypair, Signer},
11
+ transaction::Transaction,
12
+ };
13
+ use spl_token::{
14
+ instruction as spl_instruction,
15
+ state::{Account as TokenAccount, Mint},
16
+ };
17
+ use std::str::FromStr;
18
+
19
+ // Import our program
20
+ use mailer::{Delegation, MailerInstruction, MailerState, RecipientClaim};
21
+
22
+ // Program ID for tests
23
+ const PROGRAM_ID_STR: &str = "9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF";
24
+
25
+ fn program_id() -> Pubkey {
26
+ Pubkey::from_str(PROGRAM_ID_STR).unwrap()
27
+ }
28
+
29
+ /// Test helper to create a test USDC mint
30
+ async fn create_usdc_mint(
31
+ banks_client: &mut BanksClient,
32
+ payer: &Keypair,
33
+ recent_blockhash: solana_program::hash::Hash,
34
+ ) -> Pubkey {
35
+ let mint = Keypair::new();
36
+ let rent = banks_client.get_rent().await.unwrap();
37
+ let mint_rent = rent.minimum_balance(Mint::LEN);
38
+
39
+ let mut transaction = Transaction::new_with_payer(
40
+ &[
41
+ solana_sdk::system_instruction::create_account(
42
+ &payer.pubkey(),
43
+ &mint.pubkey(),
44
+ mint_rent,
45
+ Mint::LEN as u64,
46
+ &spl_token::id(),
47
+ ),
48
+ spl_instruction::initialize_mint(
49
+ &spl_token::id(),
50
+ &mint.pubkey(),
51
+ &payer.pubkey(),
52
+ None,
53
+ 6, // USDC has 6 decimals
54
+ )
55
+ .unwrap(),
56
+ ],
57
+ Some(&payer.pubkey()),
58
+ );
59
+ transaction.sign(&[payer, &mint], recent_blockhash);
60
+ banks_client.process_transaction(transaction).await.unwrap();
61
+
62
+ mint.pubkey()
63
+ }
64
+
65
+ /// Test helper to create a token account for a user
66
+ async fn create_token_account(
67
+ banks_client: &mut BanksClient,
68
+ payer: &Keypair,
69
+ recent_blockhash: solana_program::hash::Hash,
70
+ mint: &Pubkey,
71
+ owner: &Pubkey,
72
+ ) -> Pubkey {
73
+ let account = Keypair::new();
74
+ let rent = banks_client.get_rent().await.unwrap();
75
+ let account_rent = rent.minimum_balance(TokenAccount::LEN);
76
+
77
+ let mut transaction = Transaction::new_with_payer(
78
+ &[
79
+ solana_sdk::system_instruction::create_account(
80
+ &payer.pubkey(),
81
+ &account.pubkey(),
82
+ account_rent,
83
+ TokenAccount::LEN as u64,
84
+ &spl_token::id(),
85
+ ),
86
+ spl_instruction::initialize_account(&spl_token::id(), &account.pubkey(), mint, owner)
87
+ .unwrap(),
88
+ ],
89
+ Some(&payer.pubkey()),
90
+ );
91
+ transaction.sign(&[payer, &account], recent_blockhash);
92
+ banks_client.process_transaction(transaction).await.unwrap();
93
+
94
+ account.pubkey()
95
+ }
96
+
97
+ /// Test helper to mint tokens to an account
98
+ async fn mint_to(
99
+ banks_client: &mut BanksClient,
100
+ payer: &Keypair,
101
+ recent_blockhash: solana_program::hash::Hash,
102
+ mint: &Pubkey,
103
+ account: &Pubkey,
104
+ amount: u64,
105
+ ) {
106
+ let mut transaction = Transaction::new_with_payer(
107
+ &[spl_instruction::mint_to(
108
+ &spl_token::id(),
109
+ mint,
110
+ account,
111
+ &payer.pubkey(),
112
+ &[],
113
+ amount,
114
+ )
115
+ .unwrap()],
116
+ Some(&payer.pubkey()),
117
+ );
118
+ transaction.sign(&[payer], recent_blockhash);
119
+ banks_client.process_transaction(transaction).await.unwrap();
120
+ }
121
+
122
+ /// Test helper to get mailer state PDA
123
+ fn get_mailer_pda() -> (Pubkey, u8) {
124
+ Pubkey::find_program_address(&[b"mailer"], &program_id())
125
+ }
126
+
127
+ /// Test helper to get recipient claim PDA
128
+ fn get_claim_pda(recipient: &Pubkey) -> (Pubkey, u8) {
129
+ Pubkey::find_program_address(&[b"claim", recipient.as_ref()], &program_id())
130
+ }
131
+
132
+ /// Test helper to get delegation PDA
133
+ fn get_delegation_pda(delegator: &Pubkey) -> (Pubkey, u8) {
134
+ Pubkey::find_program_address(&[b"delegation", delegator.as_ref()], &program_id())
135
+ }
136
+
137
+ #[tokio::test]
138
+ async fn test_initialize_program() {
139
+ let program_test = ProgramTest::new(
140
+ "mailer",
141
+ program_id(),
142
+ processor!(mailer::process_instruction),
143
+ );
144
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
145
+
146
+ // Create USDC mint
147
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
148
+
149
+ // Get mailer state PDA
150
+ let (mailer_pda, _) = get_mailer_pda();
151
+
152
+ // Initialize the program
153
+ let instruction_data = MailerInstruction::Initialize { usdc_mint };
154
+ let instruction = Instruction::new_with_borsh(
155
+ program_id(),
156
+ &instruction_data,
157
+ vec![
158
+ AccountMeta::new(payer.pubkey(), true),
159
+ AccountMeta::new(mailer_pda, false),
160
+ AccountMeta::new_readonly(system_program::id(), false),
161
+ ],
162
+ );
163
+
164
+ let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
165
+ transaction.sign(&[&payer], recent_blockhash);
166
+ banks_client.process_transaction(transaction).await.unwrap();
167
+
168
+ // Verify the mailer state was initialized correctly
169
+ let account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
170
+ let mailer_state: MailerState = BorshDeserialize::deserialize(&mut &account.data[8..]).unwrap();
171
+
172
+ assert_eq!(mailer_state.owner, payer.pubkey());
173
+ assert_eq!(mailer_state.usdc_mint, usdc_mint);
174
+ assert_eq!(mailer_state.send_fee, 100_000); // 0.1 USDC
175
+ assert_eq!(mailer_state.delegation_fee, 10_000_000); // 10 USDC
176
+ assert_eq!(mailer_state.owner_claimable, 0);
177
+ }
178
+
179
+ #[tokio::test]
180
+ async fn test_send_priority_message() {
181
+ let program_test = ProgramTest::new(
182
+ "mailer",
183
+ program_id(),
184
+ processor!(mailer::process_instruction),
185
+ );
186
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
187
+
188
+ // Create USDC mint and accounts
189
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
190
+ let (mailer_pda, _) = get_mailer_pda();
191
+
192
+ // Initialize the program first
193
+ let init_instruction = Instruction::new_with_borsh(
194
+ program_id(),
195
+ &MailerInstruction::Initialize { usdc_mint },
196
+ vec![
197
+ AccountMeta::new(payer.pubkey(), true),
198
+ AccountMeta::new(mailer_pda, false),
199
+ AccountMeta::new_readonly(system_program::id(), false),
200
+ ],
201
+ );
202
+
203
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
204
+ transaction.sign(&[&payer], recent_blockhash);
205
+ banks_client.process_transaction(transaction).await.unwrap();
206
+
207
+ // Create token accounts
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
+
225
+ // Mint USDC to sender
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
235
+
236
+ // Get recipient claim PDA
237
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
238
+
239
+ // Send message with revenue sharing (priority mode)
240
+ let instruction_data = MailerInstruction::Send {
241
+ to: payer.pubkey(),
242
+ subject: "Test Subject".to_string(),
243
+ _body: "Test message body".to_string(),
244
+ revenue_share_to_receiver: true,
245
+ resolve_sender_to_name: false,
246
+ };
247
+
248
+ let instruction = Instruction::new_with_borsh(
249
+ program_id(),
250
+ &instruction_data,
251
+ vec![
252
+ AccountMeta::new(payer.pubkey(), true),
253
+ AccountMeta::new(recipient_claim_pda, false),
254
+ AccountMeta::new(mailer_pda, false), // Must be writable for record_shares to update owner_claimable
255
+ AccountMeta::new(sender_usdc, false),
256
+ AccountMeta::new(mailer_usdc, false),
257
+ AccountMeta::new_readonly(spl_token::id(), false),
258
+ AccountMeta::new_readonly(system_program::id(), false),
259
+ ],
260
+ );
261
+
262
+ let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
263
+ transaction.sign(&[&payer], recent_blockhash);
264
+ banks_client.process_transaction(transaction).await.unwrap();
265
+
266
+ // Get the latest blockhash to ensure we're reading the most recent state
267
+ let _recent_blockhash = banks_client.get_latest_blockhash().await.unwrap();
268
+
269
+ // Verify recipient claim was created with correct amount
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
+
278
+ assert_eq!(recipient_claim.recipient, payer.pubkey());
279
+ assert_eq!(recipient_claim.amount, 90_000); // 90% of send_fee (100,000)
280
+
281
+ // Verify mailer state was updated with owner share
282
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
283
+ let mailer_state: MailerState =
284
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
285
+
286
+ // Debug output
287
+ println!("Debug - Mailer state:");
288
+ println!(" owner: {}", mailer_state.owner);
289
+ println!(" usdc_mint: {}", mailer_state.usdc_mint);
290
+ println!(" send_fee: {}", mailer_state.send_fee);
291
+ println!(" delegation_fee: {}", mailer_state.delegation_fee);
292
+ println!(" owner_claimable: {}", mailer_state.owner_claimable);
293
+ println!(" bump: {}", mailer_state.bump);
294
+
295
+ assert_eq!(mailer_state.owner_claimable, 10_000); // 10% of send_fee
296
+ }
297
+
298
+ #[tokio::test]
299
+ async fn test_send_standard_message() {
300
+ let program_test = ProgramTest::new(
301
+ "mailer",
302
+ program_id(),
303
+ processor!(mailer::process_instruction),
304
+ );
305
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
306
+
307
+ // Setup similar to priority test
308
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
309
+ let (mailer_pda, _) = get_mailer_pda();
310
+
311
+ // Initialize the program
312
+ let init_instruction = Instruction::new_with_borsh(
313
+ program_id(),
314
+ &MailerInstruction::Initialize { usdc_mint },
315
+ vec![
316
+ AccountMeta::new(payer.pubkey(), true),
317
+ AccountMeta::new(mailer_pda, false),
318
+ AccountMeta::new_readonly(system_program::id(), false),
319
+ ],
320
+ );
321
+
322
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
323
+ transaction.sign(&[&payer], recent_blockhash);
324
+ banks_client.process_transaction(transaction).await.unwrap();
325
+
326
+ // Create token accounts
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
+
344
+ // Mint USDC to sender
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;
354
+
355
+ // Get recipient claim PDA (needed even if not used for standard send)
356
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
357
+
358
+ // Send standard message (no revenue sharing)
359
+ let instruction_data = MailerInstruction::Send {
360
+ to: payer.pubkey(),
361
+ subject: "Test Standard Subject".to_string(),
362
+ _body: "Test standard message body".to_string(),
363
+ revenue_share_to_receiver: false,
364
+ resolve_sender_to_name: false,
365
+ };
366
+
367
+ let instruction = Instruction::new_with_borsh(
368
+ program_id(),
369
+ &instruction_data,
370
+ vec![
371
+ AccountMeta::new(payer.pubkey(), true),
372
+ AccountMeta::new_readonly(recipient_claim_pda, false), // Not used for standard send but required
373
+ AccountMeta::new(mailer_pda, false), // Needs to be writable to update owner_claimable
374
+ AccountMeta::new(sender_usdc, false),
375
+ AccountMeta::new(mailer_usdc, false),
376
+ AccountMeta::new_readonly(spl_token::id(), false),
377
+ AccountMeta::new_readonly(system_program::id(), false),
378
+ ],
379
+ );
380
+
381
+ let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
382
+ transaction.sign(&[&payer], recent_blockhash);
383
+ banks_client.process_transaction(transaction).await.unwrap();
384
+
385
+ // Verify only owner fee was charged (10% of send_fee = 10,000)
386
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
387
+ let mailer_state: MailerState =
388
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
389
+ assert_eq!(mailer_state.owner_claimable, 10_000); // Only 10% fee
390
+ }
391
+
392
+ #[tokio::test]
393
+ async fn test_send_through_webhook_priority() {
394
+ let program_test = ProgramTest::new(
395
+ "mailer",
396
+ program_id(),
397
+ processor!(mailer::process_instruction),
398
+ );
399
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
400
+
401
+ // Setup similar to priority test
402
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
403
+ let (mailer_pda, _) = get_mailer_pda();
404
+
405
+ // Initialize the program
406
+ let init_instruction = Instruction::new_with_borsh(
407
+ program_id(),
408
+ &MailerInstruction::Initialize { usdc_mint },
409
+ vec![
410
+ AccountMeta::new(payer.pubkey(), true),
411
+ AccountMeta::new(mailer_pda, false),
412
+ AccountMeta::new_readonly(system_program::id(), false),
413
+ ],
414
+ );
415
+
416
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
417
+ transaction.sign(&[&payer], recent_blockhash);
418
+ banks_client.process_transaction(transaction).await.unwrap();
419
+
420
+ // Create token accounts
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
+
438
+ // Mint USDC to sender
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; // 1 USDC
448
+
449
+ // Get recipient claim PDA
450
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
451
+
452
+ // Send message through webhook with revenue sharing (priority mode)
453
+ let instruction_data = MailerInstruction::SendThroughWebhook {
454
+ to: payer.pubkey(),
455
+ webhook_id: "webhook-123".to_string(),
456
+ revenue_share_to_receiver: true,
457
+ resolve_sender_to_name: false,
458
+ };
459
+
460
+ let instruction = Instruction::new_with_borsh(
461
+ program_id(),
462
+ &instruction_data,
463
+ vec![
464
+ AccountMeta::new(payer.pubkey(), true),
465
+ AccountMeta::new(recipient_claim_pda, false),
466
+ AccountMeta::new(mailer_pda, false), // Must be writable for record_shares to update owner_claimable
467
+ AccountMeta::new(sender_usdc, false),
468
+ AccountMeta::new(mailer_usdc, false),
469
+ AccountMeta::new_readonly(spl_token::id(), false),
470
+ AccountMeta::new_readonly(system_program::id(), false),
471
+ ],
472
+ );
473
+
474
+ let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
475
+ transaction.sign(&[&payer], recent_blockhash);
476
+ banks_client.process_transaction(transaction).await.unwrap();
477
+
478
+ // Verify recipient claim was created with correct amount
479
+ let claim_account = banks_client
480
+ .get_account(recipient_claim_pda)
481
+ .await
482
+ .unwrap()
483
+ .unwrap();
484
+ let recipient_claim: RecipientClaim =
485
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
486
+
487
+ assert_eq!(recipient_claim.recipient, payer.pubkey());
488
+ assert_eq!(recipient_claim.amount, 90_000); // 90% of send_fee (100,000)
489
+
490
+ // Verify mailer state was updated with owner share
491
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
492
+ let mailer_state: MailerState =
493
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
494
+
495
+ assert_eq!(mailer_state.owner_claimable, 10_000); // 10% of send_fee
496
+ }
497
+
498
+ #[tokio::test]
499
+ async fn test_send_through_webhook_standard() {
500
+ let program_test = ProgramTest::new(
501
+ "mailer",
502
+ program_id(),
503
+ processor!(mailer::process_instruction),
504
+ );
505
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
506
+
507
+ // Setup similar to standard test
508
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
509
+ let (mailer_pda, _) = get_mailer_pda();
510
+
511
+ // Initialize the program
512
+ let init_instruction = Instruction::new_with_borsh(
513
+ program_id(),
514
+ &MailerInstruction::Initialize { usdc_mint },
515
+ vec![
516
+ AccountMeta::new(payer.pubkey(), true),
517
+ AccountMeta::new(mailer_pda, false),
518
+ AccountMeta::new_readonly(system_program::id(), false),
519
+ ],
520
+ );
521
+
522
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
523
+ transaction.sign(&[&payer], recent_blockhash);
524
+ banks_client.process_transaction(transaction).await.unwrap();
525
+
526
+ // Create token accounts
527
+ let sender_usdc = create_token_account(
528
+ &mut banks_client,
529
+ &payer,
530
+ recent_blockhash,
531
+ &usdc_mint,
532
+ &payer.pubkey(),
533
+ )
534
+ .await;
535
+ let mailer_usdc = create_token_account(
536
+ &mut banks_client,
537
+ &payer,
538
+ recent_blockhash,
539
+ &usdc_mint,
540
+ &mailer_pda,
541
+ )
542
+ .await;
543
+
544
+ // Mint USDC to sender
545
+ mint_to(
546
+ &mut banks_client,
547
+ &payer,
548
+ recent_blockhash,
549
+ &usdc_mint,
550
+ &sender_usdc,
551
+ 1_000_000,
552
+ )
553
+ .await;
554
+
555
+ // Get recipient claim PDA (needed even if not used for standard send)
556
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
557
+
558
+ // Send webhook message (standard mode - no revenue sharing)
559
+ let instruction_data = MailerInstruction::SendThroughWebhook {
560
+ to: payer.pubkey(),
561
+ webhook_id: "webhook-456".to_string(),
562
+ revenue_share_to_receiver: false,
563
+ resolve_sender_to_name: false,
564
+ };
565
+
566
+ let instruction = Instruction::new_with_borsh(
567
+ program_id(),
568
+ &instruction_data,
569
+ vec![
570
+ AccountMeta::new(payer.pubkey(), true),
571
+ AccountMeta::new_readonly(recipient_claim_pda, false), // Not used for standard send but required
572
+ AccountMeta::new(mailer_pda, false), // Needs to be writable to update owner_claimable
573
+ AccountMeta::new(sender_usdc, false),
574
+ AccountMeta::new(mailer_usdc, false),
575
+ AccountMeta::new_readonly(spl_token::id(), false),
576
+ AccountMeta::new_readonly(system_program::id(), false),
577
+ ],
578
+ );
579
+
580
+ let mut transaction = Transaction::new_with_payer(&[instruction], Some(&payer.pubkey()));
581
+ transaction.sign(&[&payer], recent_blockhash);
582
+ banks_client.process_transaction(transaction).await.unwrap();
583
+
584
+ // Verify only owner fee was charged (10% of send_fee = 10,000)
585
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
586
+ let mailer_state: MailerState =
587
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
588
+ assert_eq!(mailer_state.owner_claimable, 10_000); // Only 10% fee
589
+ }
590
+
591
+ #[tokio::test]
592
+ async fn test_claim_recipient_share() {
593
+ let program_test = ProgramTest::new(
594
+ "mailer",
595
+ program_id(),
596
+ processor!(mailer::process_instruction),
597
+ );
598
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
599
+
600
+ // Setup and send priority message first (similar to previous test)
601
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
602
+ let (mailer_pda, _) = get_mailer_pda();
603
+
604
+ // Initialize
605
+ let init_instruction = Instruction::new_with_borsh(
606
+ program_id(),
607
+ &MailerInstruction::Initialize { usdc_mint },
608
+ vec![
609
+ AccountMeta::new(payer.pubkey(), true),
610
+ AccountMeta::new(mailer_pda, false),
611
+ AccountMeta::new_readonly(system_program::id(), false),
612
+ ],
613
+ );
614
+
615
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
616
+ transaction.sign(&[&payer], recent_blockhash);
617
+ banks_client.process_transaction(transaction).await.unwrap();
618
+
619
+ // Create token accounts
620
+ let sender_usdc = create_token_account(
621
+ &mut banks_client,
622
+ &payer,
623
+ recent_blockhash,
624
+ &usdc_mint,
625
+ &payer.pubkey(),
626
+ )
627
+ .await;
628
+ let mailer_usdc = create_token_account(
629
+ &mut banks_client,
630
+ &payer,
631
+ recent_blockhash,
632
+ &usdc_mint,
633
+ &mailer_pda,
634
+ )
635
+ .await;
636
+
637
+ // Mint USDC
638
+ mint_to(
639
+ &mut banks_client,
640
+ &payer,
641
+ recent_blockhash,
642
+ &usdc_mint,
643
+ &sender_usdc,
644
+ 1_000_000,
645
+ )
646
+ .await;
647
+
648
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
649
+
650
+ // Send message with revenue sharing to create a claim
651
+ let send_instruction = Instruction::new_with_borsh(
652
+ program_id(),
653
+ &MailerInstruction::Send {
654
+ to: payer.pubkey(),
655
+ subject: "Test".to_string(),
656
+ _body: "Test".to_string(),
657
+ revenue_share_to_receiver: true,
658
+ resolve_sender_to_name: false,
659
+ },
660
+ vec![
661
+ AccountMeta::new(payer.pubkey(), true),
662
+ AccountMeta::new(recipient_claim_pda, false),
663
+ AccountMeta::new_readonly(mailer_pda, false),
664
+ AccountMeta::new(sender_usdc, false),
665
+ AccountMeta::new(mailer_usdc, false),
666
+ AccountMeta::new_readonly(spl_token::id(), false),
667
+ AccountMeta::new_readonly(system_program::id(), false),
668
+ ],
669
+ );
670
+
671
+ let mut transaction = Transaction::new_with_payer(&[send_instruction], Some(&payer.pubkey()));
672
+ transaction.sign(&[&payer], recent_blockhash);
673
+ banks_client.process_transaction(transaction).await.unwrap();
674
+
675
+ // Create recipient's own USDC account to receive the claim
676
+ let recipient_usdc = create_token_account(
677
+ &mut banks_client,
678
+ &payer,
679
+ recent_blockhash,
680
+ &usdc_mint,
681
+ &payer.pubkey(),
682
+ )
683
+ .await;
684
+
685
+ // Now claim the recipient share
686
+ let claim_instruction = Instruction::new_with_borsh(
687
+ program_id(),
688
+ &MailerInstruction::ClaimRecipientShare,
689
+ vec![
690
+ AccountMeta::new(payer.pubkey(), true),
691
+ AccountMeta::new(recipient_claim_pda, false),
692
+ AccountMeta::new_readonly(mailer_pda, false),
693
+ AccountMeta::new(recipient_usdc, false),
694
+ AccountMeta::new(mailer_usdc, false),
695
+ AccountMeta::new_readonly(spl_token::id(), false),
696
+ ],
697
+ );
698
+
699
+ let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
700
+ transaction.sign(&[&payer], recent_blockhash);
701
+ banks_client.process_transaction(transaction).await.unwrap();
702
+
703
+ // Verify the claim was processed
704
+ let claim_account = banks_client
705
+ .get_account(recipient_claim_pda)
706
+ .await
707
+ .unwrap()
708
+ .unwrap();
709
+ let recipient_claim: RecipientClaim =
710
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
711
+ assert_eq!(recipient_claim.amount, 0); // Should be zero after claiming
712
+
713
+ // Verify tokens were transferred to recipient
714
+ let recipient_token_account = banks_client
715
+ .get_account(recipient_usdc)
716
+ .await
717
+ .unwrap()
718
+ .unwrap();
719
+ let token_account_data = TokenAccount::unpack(&recipient_token_account.data).unwrap();
720
+ assert_eq!(token_account_data.amount, 90_000); // 90% of 100,000
721
+ }
722
+
723
+ #[tokio::test]
724
+ async fn test_claim_owner_share() {
725
+ let program_test = ProgramTest::new(
726
+ "mailer",
727
+ program_id(),
728
+ processor!(mailer::process_instruction),
729
+ );
730
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
731
+
732
+ // Setup and send a message to accumulate owner fees
733
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
734
+ let (mailer_pda, _) = get_mailer_pda();
735
+
736
+ // Initialize
737
+ let init_instruction = Instruction::new_with_borsh(
738
+ program_id(),
739
+ &MailerInstruction::Initialize { usdc_mint },
740
+ vec![
741
+ AccountMeta::new(payer.pubkey(), true),
742
+ AccountMeta::new(mailer_pda, false),
743
+ AccountMeta::new_readonly(system_program::id(), false),
744
+ ],
745
+ );
746
+
747
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
748
+ transaction.sign(&[&payer], recent_blockhash);
749
+ banks_client.process_transaction(transaction).await.unwrap();
750
+
751
+ // Setup token accounts and send standard message to accumulate owner fees
752
+ let sender_usdc = create_token_account(
753
+ &mut banks_client,
754
+ &payer,
755
+ recent_blockhash,
756
+ &usdc_mint,
757
+ &payer.pubkey(),
758
+ )
759
+ .await;
760
+ let mailer_usdc = create_token_account(
761
+ &mut banks_client,
762
+ &payer,
763
+ recent_blockhash,
764
+ &usdc_mint,
765
+ &mailer_pda,
766
+ )
767
+ .await;
768
+ let owner_usdc = create_token_account(
769
+ &mut banks_client,
770
+ &payer,
771
+ recent_blockhash,
772
+ &usdc_mint,
773
+ &payer.pubkey(),
774
+ )
775
+ .await;
776
+
777
+ mint_to(
778
+ &mut banks_client,
779
+ &payer,
780
+ recent_blockhash,
781
+ &usdc_mint,
782
+ &sender_usdc,
783
+ 1_000_000,
784
+ )
785
+ .await;
786
+
787
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
788
+
789
+ // Send standard message to accumulate owner fees (no revenue sharing)
790
+ let send_instruction = Instruction::new_with_borsh(
791
+ program_id(),
792
+ &MailerInstruction::Send {
793
+ to: payer.pubkey(),
794
+ subject: "Test".to_string(),
795
+ _body: "Test".to_string(),
796
+ revenue_share_to_receiver: false,
797
+ resolve_sender_to_name: false,
798
+ },
799
+ vec![
800
+ AccountMeta::new(payer.pubkey(), true),
801
+ AccountMeta::new_readonly(recipient_claim_pda, false),
802
+ AccountMeta::new(mailer_pda, false),
803
+ AccountMeta::new(sender_usdc, false),
804
+ AccountMeta::new(mailer_usdc, false),
805
+ AccountMeta::new_readonly(spl_token::id(), false),
806
+ AccountMeta::new_readonly(system_program::id(), false),
807
+ ],
808
+ );
809
+
810
+ let mut transaction = Transaction::new_with_payer(&[send_instruction], Some(&payer.pubkey()));
811
+ transaction.sign(&[&payer], recent_blockhash);
812
+ banks_client.process_transaction(transaction).await.unwrap();
813
+
814
+ // Now claim owner share
815
+ let claim_instruction = Instruction::new_with_borsh(
816
+ program_id(),
817
+ &MailerInstruction::ClaimOwnerShare,
818
+ vec![
819
+ AccountMeta::new(payer.pubkey(), true),
820
+ AccountMeta::new(mailer_pda, false),
821
+ AccountMeta::new(owner_usdc, false),
822
+ AccountMeta::new(mailer_usdc, false),
823
+ AccountMeta::new_readonly(spl_token::id(), false),
824
+ ],
825
+ );
826
+
827
+ let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
828
+ transaction.sign(&[&payer], recent_blockhash);
829
+ banks_client.process_transaction(transaction).await.unwrap();
830
+
831
+ // Verify owner claimable was reset
832
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
833
+ let mailer_state: MailerState =
834
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
835
+ assert_eq!(mailer_state.owner_claimable, 0);
836
+
837
+ // Verify tokens were transferred to owner
838
+ let owner_token_account = banks_client.get_account(owner_usdc).await.unwrap().unwrap();
839
+ let token_account_data = TokenAccount::unpack(&owner_token_account.data).unwrap();
840
+ assert_eq!(token_account_data.amount, 10_000); // 10% of 100,000
841
+ }
842
+
843
+ #[tokio::test]
844
+ async fn test_set_fees() {
845
+ let program_test = ProgramTest::new(
846
+ "mailer",
847
+ program_id(),
848
+ processor!(mailer::process_instruction),
849
+ );
850
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
851
+
852
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
853
+ let (mailer_pda, _) = get_mailer_pda();
854
+
855
+ // Initialize
856
+ let init_instruction = Instruction::new_with_borsh(
857
+ program_id(),
858
+ &MailerInstruction::Initialize { usdc_mint },
859
+ vec![
860
+ AccountMeta::new(payer.pubkey(), true),
861
+ AccountMeta::new(mailer_pda, false),
862
+ AccountMeta::new_readonly(system_program::id(), false),
863
+ ],
864
+ );
865
+
866
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
867
+ transaction.sign(&[&payer], recent_blockhash);
868
+ banks_client.process_transaction(transaction).await.unwrap();
869
+
870
+ // Test setting send fee
871
+ let set_fee_instruction = Instruction::new_with_borsh(
872
+ program_id(),
873
+ &MailerInstruction::SetFee { new_fee: 200_000 },
874
+ vec![
875
+ AccountMeta::new(payer.pubkey(), true),
876
+ AccountMeta::new(mailer_pda, false),
877
+ ],
878
+ );
879
+
880
+ let mut transaction =
881
+ Transaction::new_with_payer(&[set_fee_instruction], Some(&payer.pubkey()));
882
+ transaction.sign(&[&payer], recent_blockhash);
883
+ banks_client.process_transaction(transaction).await.unwrap();
884
+
885
+ // Verify fee was updated
886
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
887
+ let mailer_state: MailerState =
888
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
889
+ assert_eq!(mailer_state.send_fee, 200_000);
890
+
891
+ // Test setting delegation fee
892
+ let set_delegation_fee_instruction = Instruction::new_with_borsh(
893
+ program_id(),
894
+ &MailerInstruction::SetDelegationFee {
895
+ new_fee: 20_000_000,
896
+ },
897
+ vec![
898
+ AccountMeta::new(payer.pubkey(), true),
899
+ AccountMeta::new(mailer_pda, false),
900
+ ],
901
+ );
902
+
903
+ let mut transaction =
904
+ Transaction::new_with_payer(&[set_delegation_fee_instruction], Some(&payer.pubkey()));
905
+ transaction.sign(&[&payer], recent_blockhash);
906
+ banks_client.process_transaction(transaction).await.unwrap();
907
+
908
+ // Verify delegation fee was updated
909
+ let mailer_account = banks_client.get_account(mailer_pda).await.unwrap().unwrap();
910
+ let mailer_state: MailerState =
911
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
912
+ assert_eq!(mailer_state.delegation_fee, 20_000_000);
913
+ }
914
+
915
+ #[tokio::test]
916
+ async fn test_delegation_functionality() {
917
+ let program_test = ProgramTest::new(
918
+ "mailer",
919
+ program_id(),
920
+ processor!(mailer::process_instruction),
921
+ );
922
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
923
+
924
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
925
+ let (mailer_pda, _) = get_mailer_pda();
926
+
927
+ // Initialize
928
+ let init_instruction = Instruction::new_with_borsh(
929
+ program_id(),
930
+ &MailerInstruction::Initialize { usdc_mint },
931
+ vec![
932
+ AccountMeta::new(payer.pubkey(), true),
933
+ AccountMeta::new(mailer_pda, false),
934
+ AccountMeta::new_readonly(system_program::id(), false),
935
+ ],
936
+ );
937
+
938
+ let mut transaction = Transaction::new_with_payer(&[init_instruction], Some(&payer.pubkey()));
939
+ transaction.sign(&[&payer], recent_blockhash);
940
+ banks_client.process_transaction(transaction).await.unwrap();
941
+
942
+ // Setup token accounts
943
+ let delegator_usdc = create_token_account(
944
+ &mut banks_client,
945
+ &payer,
946
+ recent_blockhash,
947
+ &usdc_mint,
948
+ &payer.pubkey(),
949
+ )
950
+ .await;
951
+ let mailer_usdc = create_token_account(
952
+ &mut banks_client,
953
+ &payer,
954
+ recent_blockhash,
955
+ &usdc_mint,
956
+ &mailer_pda,
957
+ )
958
+ .await;
959
+
960
+ mint_to(
961
+ &mut banks_client,
962
+ &payer,
963
+ recent_blockhash,
964
+ &usdc_mint,
965
+ &delegator_usdc,
966
+ 50_000_000,
967
+ )
968
+ .await; // 50 USDC
969
+
970
+ let delegate = Keypair::new();
971
+ let (delegation_pda, _) = get_delegation_pda(&payer.pubkey());
972
+
973
+ // Test delegation
974
+ let delegate_instruction = Instruction::new_with_borsh(
975
+ program_id(),
976
+ &MailerInstruction::DelegateTo {
977
+ delegate: Some(delegate.pubkey()),
978
+ },
979
+ vec![
980
+ AccountMeta::new(payer.pubkey(), true),
981
+ AccountMeta::new(delegation_pda, false),
982
+ AccountMeta::new(mailer_pda, false),
983
+ AccountMeta::new(delegator_usdc, false),
984
+ AccountMeta::new(mailer_usdc, false),
985
+ AccountMeta::new_readonly(spl_token::id(), false),
986
+ AccountMeta::new_readonly(system_program::id(), false),
987
+ ],
988
+ );
989
+
990
+ let mut transaction =
991
+ Transaction::new_with_payer(&[delegate_instruction], Some(&payer.pubkey()));
992
+ transaction.sign(&[&payer], recent_blockhash);
993
+ banks_client.process_transaction(transaction).await.unwrap();
994
+
995
+ // Verify delegation was created
996
+ let delegation_account = banks_client
997
+ .get_account(delegation_pda)
998
+ .await
999
+ .unwrap()
1000
+ .unwrap();
1001
+ let delegation: Delegation =
1002
+ BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
1003
+ assert_eq!(delegation.delegator, payer.pubkey());
1004
+ assert_eq!(delegation.delegate, Some(delegate.pubkey()));
1005
+
1006
+ // Test rejection - disabled due to timeout issue
1007
+ // TODO: Fix rejection timeout issue
1008
+ /*
1009
+ let reject_instruction = Instruction::new_with_borsh(
1010
+ program_id(),
1011
+ &MailerInstruction::RejectDelegation,
1012
+ vec![
1013
+ AccountMeta::new(delegate.pubkey(), true),
1014
+ AccountMeta::new(delegation_pda, false),
1015
+ AccountMeta::new_readonly(mailer_pda, false),
1016
+ ],
1017
+ );
1018
+
1019
+ let mut transaction = Transaction::new_with_payer(&[reject_instruction], Some(&delegate.pubkey()));
1020
+ transaction.sign(&[&delegate], recent_blockhash);
1021
+ banks_client.process_transaction(transaction).await.unwrap();
1022
+
1023
+ // Verify delegation was cleared
1024
+ let delegation_account = banks_client.get_account(delegation_pda).await.unwrap().unwrap();
1025
+ let delegation: Delegation = BorshDeserialize::deserialize(&mut &delegation_account.data[8..]).unwrap();
1026
+ assert_eq!(delegation.delegate, None);
1027
+ */
1028
+ }
1029
+
1030
+ #[tokio::test]
1031
+ async fn test_error_conditions() {
1032
+ let program_test = ProgramTest::new(
1033
+ "mailer",
1034
+ program_id(),
1035
+ processor!(mailer::process_instruction),
1036
+ );
1037
+ let (mut banks_client, payer, recent_blockhash) = program_test.start().await;
1038
+
1039
+ let usdc_mint = create_usdc_mint(&mut banks_client, &payer, recent_blockhash).await;
1040
+ let (mailer_pda, _) = get_mailer_pda();
1041
+
1042
+ // Test claiming with no claimable amount (should fail)
1043
+ let (recipient_claim_pda, _) = get_claim_pda(&payer.pubkey());
1044
+ let recipient_usdc = create_token_account(
1045
+ &mut banks_client,
1046
+ &payer,
1047
+ recent_blockhash,
1048
+ &usdc_mint,
1049
+ &payer.pubkey(),
1050
+ )
1051
+ .await;
1052
+ let mailer_usdc = create_token_account(
1053
+ &mut banks_client,
1054
+ &payer,
1055
+ recent_blockhash,
1056
+ &usdc_mint,
1057
+ &mailer_pda,
1058
+ )
1059
+ .await;
1060
+
1061
+ let claim_instruction = Instruction::new_with_borsh(
1062
+ program_id(),
1063
+ &MailerInstruction::ClaimRecipientShare,
1064
+ vec![
1065
+ AccountMeta::new(payer.pubkey(), true),
1066
+ AccountMeta::new(recipient_claim_pda, false),
1067
+ AccountMeta::new_readonly(mailer_pda, false),
1068
+ AccountMeta::new(recipient_usdc, false),
1069
+ AccountMeta::new(mailer_usdc, false),
1070
+ AccountMeta::new_readonly(spl_token::id(), false),
1071
+ ],
1072
+ );
1073
+
1074
+ let mut transaction = Transaction::new_with_payer(&[claim_instruction], Some(&payer.pubkey()));
1075
+ transaction.sign(&[&payer], recent_blockhash);
1076
+
1077
+ // This should fail because no claim exists
1078
+ let result = banks_client.process_transaction(transaction).await;
1079
+ assert!(result.is_err());
1080
+ }
1081
+
1082
+ #[tokio::test]
1083
+ async fn test_claim_expired_shares_moves_funds_to_owner() {
1084
+ let program_test = ProgramTest::new(
1085
+ "mailer",
1086
+ program_id(),
1087
+ processor!(mailer::process_instruction),
1088
+ );
1089
+ let mut context = program_test.start_with_context().await;
1090
+
1091
+ let mut recent_blockhash = context.last_blockhash;
1092
+
1093
+ // Create USDC mint and initialize the program
1094
+ let usdc_mint =
1095
+ create_usdc_mint(&mut context.banks_client, &context.payer, recent_blockhash).await;
1096
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1097
+
1098
+ let (mailer_pda, _) = get_mailer_pda();
1099
+ let init_instruction = Instruction::new_with_borsh(
1100
+ program_id(),
1101
+ &MailerInstruction::Initialize { usdc_mint },
1102
+ vec![
1103
+ AccountMeta::new(context.payer.pubkey(), true),
1104
+ AccountMeta::new(mailer_pda, false),
1105
+ AccountMeta::new_readonly(system_program::id(), false),
1106
+ ],
1107
+ );
1108
+
1109
+ let mut transaction =
1110
+ Transaction::new_with_payer(&[init_instruction], Some(&context.payer.pubkey()));
1111
+ transaction.sign(&[&context.payer], recent_blockhash);
1112
+ context
1113
+ .banks_client
1114
+ .process_transaction(transaction)
1115
+ .await
1116
+ .unwrap();
1117
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1118
+
1119
+ // Prepare token accounts and fund the sender
1120
+ let sender_usdc = create_token_account(
1121
+ &mut context.banks_client,
1122
+ &context.payer,
1123
+ recent_blockhash,
1124
+ &usdc_mint,
1125
+ &context.payer.pubkey(),
1126
+ )
1127
+ .await;
1128
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1129
+
1130
+ let mailer_usdc = create_token_account(
1131
+ &mut context.banks_client,
1132
+ &context.payer,
1133
+ recent_blockhash,
1134
+ &usdc_mint,
1135
+ &mailer_pda,
1136
+ )
1137
+ .await;
1138
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1139
+
1140
+ mint_to(
1141
+ &mut context.banks_client,
1142
+ &context.payer,
1143
+ recent_blockhash,
1144
+ &usdc_mint,
1145
+ &sender_usdc,
1146
+ 1_000_000,
1147
+ )
1148
+ .await; // 1 USDC to cover priority message
1149
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1150
+
1151
+ let (recipient_claim_pda, _) = get_claim_pda(&context.payer.pubkey());
1152
+
1153
+ // Send a priority message to create the claim record
1154
+ let send_instruction = Instruction::new_with_borsh(
1155
+ program_id(),
1156
+ &MailerInstruction::Send {
1157
+ to: context.payer.pubkey(),
1158
+ subject: "Expired claim".to_string(),
1159
+ _body: "Body".to_string(),
1160
+ revenue_share_to_receiver: true,
1161
+ resolve_sender_to_name: false,
1162
+ },
1163
+ vec![
1164
+ AccountMeta::new(context.payer.pubkey(), true),
1165
+ AccountMeta::new(recipient_claim_pda, false),
1166
+ AccountMeta::new(mailer_pda, false),
1167
+ AccountMeta::new(sender_usdc, false),
1168
+ AccountMeta::new(mailer_usdc, false),
1169
+ AccountMeta::new_readonly(spl_token::id(), false),
1170
+ AccountMeta::new_readonly(system_program::id(), false),
1171
+ ],
1172
+ );
1173
+
1174
+ let mut transaction =
1175
+ Transaction::new_with_payer(&[send_instruction], Some(&context.payer.pubkey()));
1176
+ transaction.sign(&[&context.payer], recent_blockhash);
1177
+ context
1178
+ .banks_client
1179
+ .process_transaction(transaction)
1180
+ .await
1181
+ .unwrap();
1182
+
1183
+ // Warp forward so the claim expires (claim period is 60 days = 5,184,000 seconds)
1184
+ // Manually set the clock to a future timestamp beyond the claim period
1185
+ use solana_sdk::clock::Clock;
1186
+ let mut clock = context.banks_client.get_sysvar::<Clock>().await.unwrap();
1187
+ clock.unix_timestamp += 60 * 24 * 60 * 60 + 1; // 60 days + 1 second
1188
+ context.set_sysvar(&clock);
1189
+
1190
+ recent_blockhash = context.banks_client.get_latest_blockhash().await.unwrap();
1191
+
1192
+ // Owner reclaims expired shares
1193
+ let claim_expired_instruction = Instruction::new_with_borsh(
1194
+ program_id(),
1195
+ &MailerInstruction::ClaimExpiredShares {
1196
+ recipient: context.payer.pubkey(),
1197
+ },
1198
+ vec![
1199
+ AccountMeta::new(context.payer.pubkey(), true),
1200
+ AccountMeta::new(mailer_pda, false),
1201
+ AccountMeta::new(recipient_claim_pda, false),
1202
+ ],
1203
+ );
1204
+
1205
+ let mut transaction =
1206
+ Transaction::new_with_payer(&[claim_expired_instruction], Some(&context.payer.pubkey()));
1207
+ transaction.sign(&[&context.payer], recent_blockhash);
1208
+ context
1209
+ .banks_client
1210
+ .process_transaction(transaction)
1211
+ .await
1212
+ .unwrap();
1213
+
1214
+ // Recipient claim should be cleared
1215
+ let claim_account = context
1216
+ .banks_client
1217
+ .get_account(recipient_claim_pda)
1218
+ .await
1219
+ .unwrap()
1220
+ .unwrap();
1221
+ let claim_state: RecipientClaim =
1222
+ BorshDeserialize::deserialize(&mut &claim_account.data[8..]).unwrap();
1223
+ assert_eq!(claim_state.amount, 0);
1224
+ assert_eq!(claim_state.timestamp, 0);
1225
+
1226
+ // Owner claimable should now include both original owner share and reclaimed amount (total 100,000)
1227
+ let mailer_account = context
1228
+ .banks_client
1229
+ .get_account(mailer_pda)
1230
+ .await
1231
+ .unwrap()
1232
+ .unwrap();
1233
+ let mailer_state: MailerState =
1234
+ BorshDeserialize::deserialize(&mut &mailer_account.data[8..]).unwrap();
1235
+ assert_eq!(mailer_state.owner_claimable, 100_000);
1236
+ }