@sudobility/contracts 0.15.1 → 1.9.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 (171) hide show
  1. package/README.md +2 -3
  2. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
  3. package/artifacts/contracts/Mailer.sol/Mailer.json +2 -278
  4. package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +1 -1
  5. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +1 -1
  6. package/dist/evm/src/evm/index.d.ts +1 -1
  7. package/dist/evm/src/evm/index.d.ts.map +1 -1
  8. package/dist/evm/src/evm/index.js +4 -4
  9. package/dist/evm/src/evm/index.js.map +1 -1
  10. package/dist/evm/src/evm/mailer-client.d.ts +210 -0
  11. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -0
  12. package/dist/evm/src/evm/mailer-client.js +417 -0
  13. package/dist/evm/src/evm/mailer-client.js.map +1 -0
  14. package/dist/evm/typechain-types/Mailer.d.ts +10 -177
  15. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
  16. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +1 -216
  17. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  18. package/dist/evm/typechain-types/factories/Mailer__factory.js +1 -277
  19. package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -1
  20. package/dist/solana/solana/index.d.ts +1 -1
  21. package/dist/solana/solana/index.d.ts.map +1 -1
  22. package/dist/solana/solana/index.js +1 -4
  23. package/dist/solana/solana/index.js.map +1 -1
  24. package/dist/solana/solana/mailer-client.d.ts +209 -0
  25. package/dist/solana/solana/mailer-client.d.ts.map +1 -0
  26. package/dist/solana/solana/mailer-client.js +728 -0
  27. package/dist/solana/solana/mailer-client.js.map +1 -0
  28. package/dist/solana/solana/types.d.ts +2 -3
  29. package/dist/solana/solana/types.d.ts.map +1 -1
  30. package/dist/solana/solana/types.js.map +1 -1
  31. package/dist/unified/src/evm/index.d.ts +1 -1
  32. package/dist/unified/src/evm/index.d.ts.map +1 -1
  33. package/dist/unified/src/evm/index.js +4 -4
  34. package/dist/unified/src/evm/index.js.map +1 -1
  35. package/dist/unified/src/evm/mailer-client.d.ts +210 -0
  36. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -0
  37. package/dist/unified/src/evm/mailer-client.js +417 -0
  38. package/dist/unified/src/evm/mailer-client.js.map +1 -0
  39. package/dist/unified/src/react/context/MailerProvider.d.ts +20 -26
  40. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
  41. package/dist/unified/src/react/context/MailerProvider.js +26 -26
  42. package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
  43. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +192 -225
  44. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  45. package/dist/unified/src/react/hooks/useMailerMutations.js +266 -263
  46. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
  47. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +63 -117
  48. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  49. package/dist/unified/src/react/hooks/useMailerQueries.js +104 -239
  50. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
  51. package/dist/unified/src/react/index.d.ts +3 -5
  52. package/dist/unified/src/react/index.d.ts.map +1 -1
  53. package/dist/unified/src/react/index.js +26 -41
  54. package/dist/unified/src/react/index.js.map +1 -1
  55. package/dist/unified/src/solana/index.d.ts +1 -1
  56. package/dist/unified/src/solana/index.d.ts.map +1 -1
  57. package/dist/unified/src/solana/index.js +1 -4
  58. package/dist/unified/src/solana/index.js.map +1 -1
  59. package/dist/unified/src/solana/mailer-client.d.ts +209 -0
  60. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -0
  61. package/dist/unified/src/solana/mailer-client.js +728 -0
  62. package/dist/unified/src/solana/mailer-client.js.map +1 -0
  63. package/dist/unified/src/solana/types.d.ts +2 -3
  64. package/dist/unified/src/solana/types.d.ts.map +1 -1
  65. package/dist/unified/src/solana/types.js.map +1 -1
  66. package/dist/unified/src/unified/index.d.ts +1 -1
  67. package/dist/unified/src/unified/index.d.ts.map +1 -1
  68. package/dist/unified/src/unified/onchain-mailer-client.d.ts +247 -192
  69. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  70. package/dist/unified/src/unified/onchain-mailer-client.js +1462 -551
  71. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  72. package/dist/unified/src/unified/types.d.ts +6 -23
  73. package/dist/unified/src/unified/types.d.ts.map +1 -1
  74. package/dist/unified/src/utils/chain-config.d.ts +2 -4
  75. package/dist/unified/src/utils/chain-config.d.ts.map +1 -1
  76. package/dist/unified/src/utils/chain-config.js +36 -46
  77. package/dist/unified/src/utils/chain-config.js.map +1 -1
  78. package/dist/unified/typechain-types/Mailer.d.ts +10 -177
  79. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
  80. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +1 -216
  81. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  82. package/dist/unified/typechain-types/factories/Mailer__factory.js +1 -277
  83. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
  84. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  85. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  86. package/dist/unified-esm/src/evm/index.js +2 -2
  87. package/dist/unified-esm/src/evm/index.js.map +1 -1
  88. package/dist/unified-esm/src/evm/mailer-client.d.ts +210 -0
  89. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -0
  90. package/dist/unified-esm/src/evm/mailer-client.js +413 -0
  91. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -0
  92. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +20 -26
  93. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  94. package/dist/unified-esm/src/react/context/MailerProvider.js +26 -25
  95. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  96. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +192 -225
  97. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  98. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +262 -254
  99. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  100. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +63 -117
  101. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  102. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +102 -232
  103. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  104. package/dist/unified-esm/src/react/index.d.ts +3 -5
  105. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  106. package/dist/unified-esm/src/react/index.js +5 -9
  107. package/dist/unified-esm/src/react/index.js.map +1 -1
  108. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  109. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  110. package/dist/unified-esm/src/solana/index.js +1 -2
  111. package/dist/unified-esm/src/solana/index.js.map +1 -1
  112. package/dist/unified-esm/src/solana/mailer-client.d.ts +209 -0
  113. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -0
  114. package/dist/unified-esm/src/solana/mailer-client.js +724 -0
  115. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -0
  116. package/dist/unified-esm/src/solana/types.d.ts +2 -3
  117. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  118. package/dist/unified-esm/src/solana/types.js.map +1 -1
  119. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  120. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  121. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +247 -192
  122. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  123. package/dist/unified-esm/src/unified/onchain-mailer-client.js +1462 -551
  124. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  125. package/dist/unified-esm/src/unified/types.d.ts +6 -23
  126. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  127. package/dist/unified-esm/src/utils/chain-config.d.ts +2 -4
  128. package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -1
  129. package/dist/unified-esm/src/utils/chain-config.js +35 -46
  130. package/dist/unified-esm/src/utils/chain-config.js.map +1 -1
  131. package/dist/unified-esm/typechain-types/Mailer.d.ts +10 -177
  132. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
  133. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +1 -216
  134. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  135. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1 -277
  136. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
  137. package/package.json +11 -22
  138. package/programs/mailer/src/lib.rs +171 -1026
  139. package/programs/mailer/tests/integration_tests.rs +65 -586
  140. package/typechain-types/Mailer.ts +8 -319
  141. package/typechain-types/factories/Mailer__factory.ts +1 -277
  142. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +0 -1146
  143. package/artifacts/contracts/Mailer.sol/artifacts.d.ts +0 -21
  144. package/artifacts/contracts/MockUSDC.sol/MockUSDC.d.ts +0 -284
  145. package/artifacts/contracts/MockUSDC.sol/artifacts.d.ts +0 -21
  146. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.d.ts +0 -157
  147. package/artifacts/contracts/interfaces/IERC20.sol/artifacts.d.ts +0 -21
  148. package/dist/evm/src/evm/evm-mailer-client.d.ts +0 -1062
  149. package/dist/evm/src/evm/evm-mailer-client.d.ts.map +0 -1
  150. package/dist/evm/src/evm/evm-mailer-client.js +0 -924
  151. package/dist/evm/src/evm/evm-mailer-client.js.map +0 -1
  152. package/dist/solana/solana/solana-mailer-client.d.ts +0 -209
  153. package/dist/solana/solana/solana-mailer-client.d.ts.map +0 -1
  154. package/dist/solana/solana/solana-mailer-client.js +0 -1004
  155. package/dist/solana/solana/solana-mailer-client.js.map +0 -1
  156. package/dist/unified/src/evm/evm-mailer-client.d.ts +0 -1062
  157. package/dist/unified/src/evm/evm-mailer-client.d.ts.map +0 -1
  158. package/dist/unified/src/evm/evm-mailer-client.js +0 -924
  159. package/dist/unified/src/evm/evm-mailer-client.js.map +0 -1
  160. package/dist/unified/src/solana/solana-mailer-client.d.ts +0 -209
  161. package/dist/unified/src/solana/solana-mailer-client.d.ts.map +0 -1
  162. package/dist/unified/src/solana/solana-mailer-client.js +0 -1004
  163. package/dist/unified/src/solana/solana-mailer-client.js.map +0 -1
  164. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts +0 -1062
  165. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +0 -1
  166. package/dist/unified-esm/src/evm/evm-mailer-client.js +0 -920
  167. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +0 -1
  168. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +0 -209
  169. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +0 -1
  170. package/dist/unified-esm/src/solana/solana-mailer-client.js +0 -1000
  171. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +0 -1
@@ -0,0 +1,728 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MailerClient = void 0;
4
+ const web3_js_1 = require("@solana/web3.js");
5
+ const spl_token_1 = require("@solana/spl-token");
6
+ /**
7
+ * Native Solana Program instruction data structures
8
+ */
9
+ // Instruction data encoding functions
10
+ function encodeInitialize(usdcMint) {
11
+ const data = Buffer.alloc(1 + 32);
12
+ data.writeUInt8(InstructionType.Initialize, 0);
13
+ usdcMint.toBuffer().copy(data, 1);
14
+ return data;
15
+ }
16
+ function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToName = false) {
17
+ const subjectBytes = Buffer.from(subject, 'utf8');
18
+ const bodyBytes = Buffer.from(body, 'utf8');
19
+ const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 1 + 1);
20
+ let offset = 0;
21
+ data.writeUInt8(InstructionType.Send, offset);
22
+ offset += 1;
23
+ to.toBuffer().copy(data, offset);
24
+ offset += 32;
25
+ data.writeUInt32LE(subjectBytes.length, offset);
26
+ offset += 4;
27
+ subjectBytes.copy(data, offset);
28
+ offset += subjectBytes.length;
29
+ data.writeUInt32LE(bodyBytes.length, offset);
30
+ offset += 4;
31
+ bodyBytes.copy(data, offset);
32
+ offset += bodyBytes.length;
33
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
34
+ offset += 1;
35
+ data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
36
+ return data;
37
+ }
38
+ function encodeSendToEmail(toEmail, subject, body) {
39
+ const emailBytes = Buffer.from(toEmail, 'utf8');
40
+ const subjectBytes = Buffer.from(subject, 'utf8');
41
+ const bodyBytes = Buffer.from(body, 'utf8');
42
+ const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + subjectBytes.length + 4 + bodyBytes.length);
43
+ let offset = 0;
44
+ data.writeUInt8(InstructionType.SendToEmail, offset);
45
+ offset += 1;
46
+ data.writeUInt32LE(emailBytes.length, offset);
47
+ offset += 4;
48
+ emailBytes.copy(data, offset);
49
+ offset += emailBytes.length;
50
+ data.writeUInt32LE(subjectBytes.length, offset);
51
+ offset += 4;
52
+ subjectBytes.copy(data, offset);
53
+ offset += subjectBytes.length;
54
+ data.writeUInt32LE(bodyBytes.length, offset);
55
+ offset += 4;
56
+ bodyBytes.copy(data, offset);
57
+ return data;
58
+ }
59
+ function encodeSendPreparedToEmail(toEmail, mailId) {
60
+ const emailBytes = Buffer.from(toEmail, 'utf8');
61
+ const mailIdBytes = Buffer.from(mailId, 'utf8');
62
+ const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + mailIdBytes.length);
63
+ let offset = 0;
64
+ data.writeUInt8(InstructionType.SendPreparedToEmail, offset);
65
+ offset += 1;
66
+ data.writeUInt32LE(emailBytes.length, offset);
67
+ offset += 4;
68
+ emailBytes.copy(data, offset);
69
+ offset += emailBytes.length;
70
+ data.writeUInt32LE(mailIdBytes.length, offset);
71
+ offset += 4;
72
+ mailIdBytes.copy(data, offset);
73
+ return data;
74
+ }
75
+ function encodeSimpleInstruction(instructionType) {
76
+ const data = Buffer.alloc(1);
77
+ data.writeUInt8(instructionType, 0);
78
+ return data;
79
+ }
80
+ function encodeSetFee(newFee) {
81
+ const data = Buffer.alloc(1 + 8);
82
+ data.writeUInt8(InstructionType.SetFee, 0);
83
+ data.writeBigUInt64LE(newFee, 1);
84
+ return data;
85
+ }
86
+ function encodeSetDelegationFee(newFee) {
87
+ const data = Buffer.alloc(1 + 8);
88
+ data.writeUInt8(InstructionType.SetDelegationFee, 0);
89
+ data.writeBigUInt64LE(newFee, 1);
90
+ return data;
91
+ }
92
+ function encodeDelegateTo(delegate) {
93
+ if (!delegate) {
94
+ // Clear delegation - just send the instruction type and a null option
95
+ const data = Buffer.alloc(1 + 1);
96
+ data.writeUInt8(InstructionType.DelegateTo, 0);
97
+ data.writeUInt8(0, 1); // Option::None
98
+ return data;
99
+ }
100
+ else {
101
+ // Set delegation - send instruction type, Some option, and pubkey
102
+ const data = Buffer.alloc(1 + 1 + 32);
103
+ data.writeUInt8(InstructionType.DelegateTo, 0);
104
+ data.writeUInt8(1, 1); // Option::Some
105
+ delegate.toBuffer().copy(data, 2);
106
+ return data;
107
+ }
108
+ }
109
+ // Account data parsing functions
110
+ function parseMailerState(data) {
111
+ let offset = 0;
112
+ const owner = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
113
+ offset += 32;
114
+ const usdcMint = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
115
+ offset += 32;
116
+ const sendFee = data.readBigUInt64LE(offset);
117
+ offset += 8;
118
+ const delegationFee = data.readBigUInt64LE(offset);
119
+ offset += 8;
120
+ const ownerClaimable = data.readBigUInt64LE(offset);
121
+ offset += 8;
122
+ const paused = data.readUInt8(offset) === 1;
123
+ offset += 1;
124
+ const bump = data.readUInt8(offset);
125
+ return {
126
+ owner,
127
+ usdc_mint: usdcMint,
128
+ send_fee: sendFee,
129
+ delegation_fee: delegationFee,
130
+ owner_claimable: ownerClaimable,
131
+ paused,
132
+ bump,
133
+ };
134
+ }
135
+ function parseRecipientClaim(data) {
136
+ let offset = 0;
137
+ const recipient = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
138
+ offset += 32;
139
+ const amount = data.readBigUInt64LE(offset);
140
+ offset += 8;
141
+ const timestamp = data.readBigInt64LE(offset);
142
+ offset += 8;
143
+ const bump = data.readUInt8(offset);
144
+ return {
145
+ recipient,
146
+ amount,
147
+ timestamp,
148
+ bump,
149
+ };
150
+ }
151
+ function parseDelegation(data) {
152
+ let offset = 0;
153
+ const delegator = new web3_js_1.PublicKey(data.slice(offset, offset + 32));
154
+ offset += 32;
155
+ const hasDelegate = data.readUInt8(offset) === 1;
156
+ offset += 1;
157
+ const delegate = hasDelegate
158
+ ? new web3_js_1.PublicKey(data.slice(offset, offset + 32))
159
+ : null;
160
+ if (hasDelegate)
161
+ offset += 32;
162
+ const bump = data.readUInt8(offset);
163
+ return {
164
+ delegator,
165
+ delegate,
166
+ bump,
167
+ };
168
+ }
169
+ /**
170
+ * Instruction types for the native Solana program
171
+ */
172
+ var InstructionType;
173
+ (function (InstructionType) {
174
+ InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
175
+ InstructionType[InstructionType["Send"] = 1] = "Send";
176
+ InstructionType[InstructionType["SendToEmail"] = 2] = "SendToEmail";
177
+ InstructionType[InstructionType["SendPreparedToEmail"] = 3] = "SendPreparedToEmail";
178
+ InstructionType[InstructionType["ClaimRecipientShare"] = 4] = "ClaimRecipientShare";
179
+ InstructionType[InstructionType["ClaimOwnerShare"] = 5] = "ClaimOwnerShare";
180
+ InstructionType[InstructionType["SetFee"] = 6] = "SetFee";
181
+ InstructionType[InstructionType["DelegateTo"] = 7] = "DelegateTo";
182
+ InstructionType[InstructionType["RejectDelegation"] = 8] = "RejectDelegation";
183
+ InstructionType[InstructionType["SetDelegationFee"] = 9] = "SetDelegationFee";
184
+ InstructionType[InstructionType["Pause"] = 10] = "Pause";
185
+ InstructionType[InstructionType["Unpause"] = 11] = "Unpause";
186
+ InstructionType[InstructionType["DistributeClaimableFunds"] = 12] = "DistributeClaimableFunds";
187
+ InstructionType[InstructionType["EmergencyUnpause"] = 13] = "EmergencyUnpause";
188
+ })(InstructionType || (InstructionType = {}));
189
+ /**
190
+ * @class MailerClient
191
+ * @description Native Solana program client for the Mailer program
192
+ * @notice Provides easy-to-use methods for sending messages with USDC fees and revenue sharing
193
+ *
194
+ * ## Key Features:
195
+ * - **Priority Messages**: Full fee (0.1 USDC) with 90% revenue share to recipient
196
+ * - **Standard Messages**: 10% fee only (0.01 USDC) with no revenue share
197
+ * - **Revenue Claims**: 60-day claim period for priority message revenue shares
198
+ * - **Delegation Management**: Delegate message handling with rejection capability
199
+ *
200
+ * ## Usage Examples:
201
+ * ```typescript
202
+ * // Connect to existing deployed program
203
+ * const connection = new Connection('https://api.devnet.solana.com');
204
+ * const wallet = new WalletAdapter(keypair);
205
+ * const programId = new PublicKey('9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF');
206
+ * const usdcMint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
207
+ * const client = new MailerClient(connection, wallet, programId, usdcMint);
208
+ *
209
+ * // Send message with revenue sharing to recipient
210
+ * await client.send('recipient-address', 'Subject', 'Message body', true);
211
+ *
212
+ * // Claim your revenue share within 60 days (as recipient)
213
+ * await client.claimRecipientShare();
214
+ *
215
+ * // Check claimable amount
216
+ * const info = await client.getRecipientClaimable();
217
+ * if (info) console.log(`Claimable: ${formatUSDC(info.amount)} USDC`);
218
+ * ```
219
+ *
220
+ * @author Mailer Team
221
+ * @version 2.0.0 - Native Solana Program (no Anchor)
222
+ */
223
+ class MailerClient {
224
+ constructor(connection, wallet, programId, usdcMint) {
225
+ this.connection = connection;
226
+ this.wallet = wallet;
227
+ this.programId = programId;
228
+ this.usdcMint = usdcMint;
229
+ // Derive the mailer state PDA
230
+ const [mailerPda, bump] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('mailer')], this.programId);
231
+ this.mailerStatePda = mailerPda;
232
+ this.mailerBump = bump;
233
+ }
234
+ /**
235
+ * Initialize the mailer program (owner only)
236
+ */
237
+ async initialize() {
238
+ const instruction = new web3_js_1.TransactionInstruction({
239
+ keys: [
240
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
241
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
242
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
243
+ ],
244
+ programId: this.programId,
245
+ data: encodeInitialize(this.usdcMint),
246
+ });
247
+ const transaction = new web3_js_1.Transaction().add(instruction);
248
+ return await this.sendTransaction(transaction);
249
+ }
250
+ /**
251
+ * Send a message with optional revenue sharing
252
+ * @param to Recipient's public key or address string who receives message and potential revenue share
253
+ * @param subject Message subject
254
+ * @param body Message body
255
+ * @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
256
+ * @param resolveSenderToName If true, resolve sender address to name via off-chain service
257
+ * @returns Transaction signature
258
+ */
259
+ async send(to, subject, body, revenueShareToReceiver = false, resolveSenderToName = false) {
260
+ const recipientKey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
261
+ // Derive recipient claim PDA
262
+ const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
263
+ // Get associated token accounts
264
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
265
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
266
+ // Check if accounts need to be created
267
+ const instructions = [];
268
+ // Check if mailer token account exists
269
+ const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
270
+ if (!mailerTokenInfo) {
271
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
272
+ }
273
+ // Add the send instruction
274
+ const sendInstruction = new web3_js_1.TransactionInstruction({
275
+ keys: [
276
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
277
+ { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
278
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
279
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
280
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
281
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
282
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
283
+ ],
284
+ programId: this.programId,
285
+ data: encodeSend(recipientKey, subject, body, revenueShareToReceiver, resolveSenderToName),
286
+ });
287
+ instructions.push(sendInstruction);
288
+ const transaction = new web3_js_1.Transaction().add(...instructions);
289
+ return await this.sendTransaction(transaction);
290
+ }
291
+ /**
292
+ * Claim recipient share of revenue
293
+ * @returns Transaction signature
294
+ */
295
+ async claimRecipientShare() {
296
+ const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), this.wallet.publicKey.toBuffer()], this.programId);
297
+ const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
298
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
299
+ const instruction = new web3_js_1.TransactionInstruction({
300
+ keys: [
301
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
302
+ { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
303
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
304
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
305
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
306
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
307
+ ],
308
+ programId: this.programId,
309
+ data: encodeSimpleInstruction(InstructionType.ClaimRecipientShare),
310
+ });
311
+ const transaction = new web3_js_1.Transaction().add(instruction);
312
+ return await this.sendTransaction(transaction);
313
+ }
314
+ /**
315
+ * Claim owner share of fees (owner only)
316
+ * @returns Transaction signature
317
+ */
318
+ async claimOwnerShare() {
319
+ const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
320
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
321
+ const instruction = new web3_js_1.TransactionInstruction({
322
+ keys: [
323
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
324
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
325
+ { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
326
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
327
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
328
+ ],
329
+ programId: this.programId,
330
+ data: encodeSimpleInstruction(InstructionType.ClaimOwnerShare),
331
+ });
332
+ const transaction = new web3_js_1.Transaction().add(instruction);
333
+ return await this.sendTransaction(transaction);
334
+ }
335
+ /**
336
+ * Delegate message handling to another address
337
+ * @param delegate Address to delegate to, or null to clear delegation
338
+ * @returns Transaction signature
339
+ */
340
+ async delegateTo(delegate) {
341
+ const delegateKey = delegate
342
+ ? typeof delegate === 'string'
343
+ ? new web3_js_1.PublicKey(delegate)
344
+ : delegate
345
+ : null;
346
+ const [delegationPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegation'), this.wallet.publicKey.toBuffer()], this.programId);
347
+ const delegatorTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
348
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
349
+ const instruction = new web3_js_1.TransactionInstruction({
350
+ keys: [
351
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
352
+ { pubkey: delegationPda, isSigner: false, isWritable: true },
353
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
354
+ { pubkey: delegatorTokenAccount, isSigner: false, isWritable: true },
355
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
356
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
357
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
358
+ ],
359
+ programId: this.programId,
360
+ data: encodeDelegateTo(delegateKey),
361
+ });
362
+ const transaction = new web3_js_1.Transaction().add(instruction);
363
+ return await this.sendTransaction(transaction);
364
+ }
365
+ /**
366
+ * Reject a delegation made to you
367
+ * @param delegator Address that delegated to you
368
+ * @returns Transaction signature
369
+ */
370
+ async rejectDelegation(delegator) {
371
+ const delegatorKey = typeof delegator === 'string' ? new web3_js_1.PublicKey(delegator) : delegator;
372
+ const [delegationPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
373
+ const instruction = new web3_js_1.TransactionInstruction({
374
+ keys: [
375
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
376
+ { pubkey: delegationPda, isSigner: false, isWritable: true },
377
+ ],
378
+ programId: this.programId,
379
+ data: encodeSimpleInstruction(InstructionType.RejectDelegation),
380
+ });
381
+ const transaction = new web3_js_1.Transaction().add(instruction);
382
+ return await this.sendTransaction(transaction);
383
+ }
384
+ /**
385
+ * Set the send fee (owner only)
386
+ * @param newFee New fee in USDC micro-units (6 decimals)
387
+ * @returns Transaction signature
388
+ */
389
+ async setFee(newFee) {
390
+ const instruction = new web3_js_1.TransactionInstruction({
391
+ keys: [
392
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
393
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
394
+ ],
395
+ programId: this.programId,
396
+ data: encodeSetFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
397
+ });
398
+ const transaction = new web3_js_1.Transaction().add(instruction);
399
+ return await this.sendTransaction(transaction);
400
+ }
401
+ /**
402
+ * Set the delegation fee (owner only)
403
+ * @param newFee New delegation fee in USDC micro-units (6 decimals)
404
+ * @returns Transaction signature
405
+ */
406
+ async setDelegationFee(newFee) {
407
+ const instruction = new web3_js_1.TransactionInstruction({
408
+ keys: [
409
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
410
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
411
+ ],
412
+ programId: this.programId,
413
+ data: encodeSetDelegationFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
414
+ });
415
+ const transaction = new web3_js_1.Transaction().add(instruction);
416
+ return await this.sendTransaction(transaction);
417
+ }
418
+ /**
419
+ * Get current fees from the mailer state
420
+ * @returns MailerFees object with current fees
421
+ */
422
+ async getFees() {
423
+ const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
424
+ if (!accountInfo) {
425
+ throw new Error('Mailer state account not found - program not initialized');
426
+ }
427
+ const stateData = parseMailerState(accountInfo.data);
428
+ return {
429
+ sendFee: Number(stateData.send_fee),
430
+ delegationFee: Number(stateData.delegation_fee),
431
+ };
432
+ }
433
+ /**
434
+ * Get recipient claimable information
435
+ * @param recipient Optional recipient address, defaults to wallet address
436
+ * @returns ClaimableInfo or null if no claimable amount
437
+ */
438
+ async getRecipientClaimable(recipient) {
439
+ const recipientKey = recipient || this.wallet.publicKey;
440
+ const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
441
+ const accountInfo = await this.connection.getAccountInfo(recipientClaimPda);
442
+ if (!accountInfo) {
443
+ return null;
444
+ }
445
+ const claimData = parseRecipientClaim(accountInfo.data);
446
+ // Check if claim period has expired (60 days)
447
+ const now = Math.floor(Date.now() / 1000);
448
+ const isExpired = now > Number(claimData.timestamp) + 60 * 24 * 60 * 60;
449
+ return {
450
+ amount: Number(claimData.amount),
451
+ timestamp: Number(claimData.timestamp),
452
+ recipient: recipientKey.toBase58(),
453
+ isExpired,
454
+ };
455
+ }
456
+ /**
457
+ * Get owner claimable amount
458
+ * @returns Owner claimable amount in USDC micro-units
459
+ */
460
+ async getOwnerClaimable() {
461
+ const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
462
+ if (!accountInfo) {
463
+ throw new Error('Mailer state account not found');
464
+ }
465
+ const stateData = parseMailerState(accountInfo.data);
466
+ return Number(stateData.owner_claimable);
467
+ }
468
+ /**
469
+ * Get delegation information for an address
470
+ * @param delegator Address to check delegation for, defaults to wallet address
471
+ * @returns Delegation info or null if no delegation
472
+ */
473
+ async getDelegation(delegator) {
474
+ const delegatorKey = delegator || this.wallet.publicKey;
475
+ const [delegationPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
476
+ const accountInfo = await this.connection.getAccountInfo(delegationPda);
477
+ if (!accountInfo) {
478
+ return null;
479
+ }
480
+ const delegationData = parseDelegation(accountInfo.data);
481
+ return {
482
+ delegator: delegatorKey.toBase58(),
483
+ delegate: delegationData.delegate
484
+ ? delegationData.delegate.toBase58()
485
+ : null,
486
+ };
487
+ }
488
+ /**
489
+ * Get the mailer state PDA address
490
+ * @returns PublicKey of the mailer state PDA
491
+ */
492
+ getMailerStatePda() {
493
+ return this.mailerStatePda;
494
+ }
495
+ /**
496
+ * Send a message to an email address (no wallet known)
497
+ * Charges only 10% owner fee since recipient wallet is unknown
498
+ * @param toEmail Email address of the recipient
499
+ * @param subject Message subject
500
+ * @param body Message body
501
+ * @param options Transaction confirm options
502
+ * @returns Transaction signature
503
+ */
504
+ async sendToEmail(toEmail, subject, body, options) {
505
+ // Get associated token accounts
506
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
507
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
508
+ // Check if accounts need to be created
509
+ const instructions = [];
510
+ // Check if mailer token account exists
511
+ const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
512
+ if (!mailerTokenInfo) {
513
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
514
+ }
515
+ // Encode instruction data for SendToEmail
516
+ const instructionData = encodeSendToEmail(toEmail, subject, body);
517
+ // Create send instruction
518
+ instructions.push(new web3_js_1.TransactionInstruction({
519
+ keys: [
520
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
521
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
522
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
523
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
524
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
525
+ ],
526
+ programId: this.programId,
527
+ data: instructionData,
528
+ }));
529
+ const transaction = new web3_js_1.Transaction().add(...instructions);
530
+ return this.sendTransaction(transaction, options);
531
+ }
532
+ /**
533
+ * Send a prepared message to an email address (no wallet known)
534
+ * Charges only 10% owner fee since recipient wallet is unknown
535
+ * @param toEmail Email address of the recipient
536
+ * @param mailId Pre-prepared message ID
537
+ * @param options Transaction confirm options
538
+ * @returns Transaction signature
539
+ */
540
+ async sendPreparedToEmail(toEmail, mailId, options) {
541
+ // Get associated token accounts
542
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
543
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
544
+ // Check if accounts need to be created
545
+ const instructions = [];
546
+ // Check if mailer token account exists
547
+ const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
548
+ if (!mailerTokenInfo) {
549
+ instructions.push((0, spl_token_1.createAssociatedTokenAccountInstruction)(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
550
+ }
551
+ // Encode instruction data for SendPreparedToEmail
552
+ const instructionData = encodeSendPreparedToEmail(toEmail, mailId);
553
+ // Create send instruction
554
+ instructions.push(new web3_js_1.TransactionInstruction({
555
+ keys: [
556
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
557
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
558
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
559
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
560
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
561
+ ],
562
+ programId: this.programId,
563
+ data: instructionData,
564
+ }));
565
+ const transaction = new web3_js_1.Transaction().add(...instructions);
566
+ return this.sendTransaction(transaction, options);
567
+ }
568
+ /**
569
+ * Send a prepared message using a mailId (to match EVM behavior)
570
+ * @param to Recipient's public key or address string
571
+ * @param mailId Pre-prepared message identifier
572
+ * @param revenueShareToReceiver If true, recipient gets 90% revenue share
573
+ * @param resolveSenderToName If true, resolve sender address to name
574
+ * @returns Transaction signature
575
+ */
576
+ async sendPrepared(to, mailId, revenueShareToReceiver = false, resolveSenderToName = false) {
577
+ // For Solana, we send the mailId as both subject and body to indicate it's a prepared message
578
+ return this.send(to, mailId, '', revenueShareToReceiver, resolveSenderToName);
579
+ }
580
+ /**
581
+ * Pause the contract and distribute owner claimable funds (owner only)
582
+ * @param options Transaction confirm options
583
+ * @returns Transaction signature
584
+ */
585
+ async pause(options) {
586
+ const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
587
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
588
+ const instruction = new web3_js_1.TransactionInstruction({
589
+ keys: [
590
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
591
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
592
+ { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
593
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
594
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
595
+ ],
596
+ programId: this.programId,
597
+ data: encodeSimpleInstruction(InstructionType.Pause),
598
+ });
599
+ const transaction = new web3_js_1.Transaction().add(instruction);
600
+ return await this.sendTransaction(transaction, options);
601
+ }
602
+ /**
603
+ * Unpause the contract (owner only)
604
+ * @param options Transaction confirm options
605
+ * @returns Transaction signature
606
+ */
607
+ async unpause(options) {
608
+ const instruction = new web3_js_1.TransactionInstruction({
609
+ keys: [
610
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
611
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
612
+ ],
613
+ programId: this.programId,
614
+ data: encodeSimpleInstruction(InstructionType.Unpause),
615
+ });
616
+ const transaction = new web3_js_1.Transaction().add(instruction);
617
+ return await this.sendTransaction(transaction, options);
618
+ }
619
+ /**
620
+ * Emergency unpause without fund distribution (owner only)
621
+ * @param options Transaction confirm options
622
+ * @returns Transaction signature
623
+ */
624
+ async emergencyUnpause(options) {
625
+ const instruction = new web3_js_1.TransactionInstruction({
626
+ keys: [
627
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
628
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
629
+ ],
630
+ programId: this.programId,
631
+ data: encodeSimpleInstruction(InstructionType.EmergencyUnpause),
632
+ });
633
+ const transaction = new web3_js_1.Transaction().add(instruction);
634
+ return await this.sendTransaction(transaction, options);
635
+ }
636
+ /**
637
+ * Distribute claimable funds to a recipient when contract is paused
638
+ * @param recipient Recipient address to distribute funds for
639
+ * @param options Transaction confirm options
640
+ * @returns Transaction signature
641
+ */
642
+ async distributeClaimableFunds(recipient, options) {
643
+ const recipientKey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
644
+ const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
645
+ const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, recipientKey);
646
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
647
+ // Encode the recipient parameter
648
+ const data = Buffer.alloc(1 + 32);
649
+ data.writeUInt8(InstructionType.DistributeClaimableFunds, 0);
650
+ recipientKey.toBuffer().copy(data, 1);
651
+ const instruction = new web3_js_1.TransactionInstruction({
652
+ keys: [
653
+ { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
654
+ { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
655
+ { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
656
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
657
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
658
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
659
+ ],
660
+ programId: this.programId,
661
+ data,
662
+ });
663
+ const transaction = new web3_js_1.Transaction().add(instruction);
664
+ return await this.sendTransaction(transaction, options);
665
+ }
666
+ /**
667
+ * Get the current send fee
668
+ * @returns Send fee in USDC micro-units (6 decimals)
669
+ */
670
+ async getSendFee() {
671
+ const fees = await this.getFees();
672
+ return BigInt(fees.sendFee);
673
+ }
674
+ /**
675
+ * Check if contract is currently paused
676
+ * @returns True if contract is paused, false otherwise
677
+ */
678
+ async isPaused() {
679
+ const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
680
+ if (!accountInfo) {
681
+ throw new Error('Mailer state account not found - program not initialized');
682
+ }
683
+ const stateData = parseMailerState(accountInfo.data);
684
+ // paused field is at offset: 32 + 32 + 8 + 8 + 8 = 88 bytes
685
+ return stateData.paused;
686
+ }
687
+ /**
688
+ * Send and confirm a transaction
689
+ * @param transaction Transaction to send
690
+ * @param options Confirm options
691
+ * @returns Transaction signature
692
+ */
693
+ async sendTransaction(transaction, options) {
694
+ // Get recent blockhash
695
+ const { blockhash } = await this.connection.getLatestBlockhash();
696
+ transaction.recentBlockhash = blockhash;
697
+ transaction.feePayer = this.wallet.publicKey;
698
+ // Sign transaction
699
+ const signedTx = await this.wallet.signTransaction(transaction);
700
+ // Send and confirm
701
+ const signature = await this.connection.sendRawTransaction(signedTx.serialize());
702
+ await this.connection.confirmTransaction(signature, options?.commitment || 'confirmed');
703
+ return signature;
704
+ }
705
+ /**
706
+ * Create a simple wallet from a keypair for testing
707
+ * @param keypair Solana keypair
708
+ * @returns Wallet interface implementation
709
+ */
710
+ static createWallet(keypair) {
711
+ return {
712
+ publicKey: keypair.publicKey,
713
+ async signTransaction(transaction) {
714
+ transaction.partialSign(keypair);
715
+ return transaction;
716
+ },
717
+ async signAllTransactions(transactions) {
718
+ return transactions.map((tx) => {
719
+ tx.partialSign(keypair);
720
+ return tx;
721
+ });
722
+ },
723
+ };
724
+ }
725
+ }
726
+ exports.MailerClient = MailerClient;
727
+ // Wallet interface is exported above
728
+ //# sourceMappingURL=mailer-client.js.map