@sudobility/contracts 1.12.0 → 1.13.1

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 (128) hide show
  1. package/dist/evm/src/evm/{mailer-client.d.ts → evm-mailer-client.d.ts} +146 -50
  2. package/dist/evm/src/evm/evm-mailer-client.d.ts.map +1 -0
  3. package/dist/evm/src/evm/evm-mailer-client.js +924 -0
  4. package/dist/evm/src/evm/evm-mailer-client.js.map +1 -0
  5. package/dist/evm/src/evm/index.d.ts +1 -1
  6. package/dist/evm/src/evm/index.d.ts.map +1 -1
  7. package/dist/evm/src/evm/index.js +4 -4
  8. package/dist/evm/src/evm/index.js.map +1 -1
  9. package/dist/solana/solana/index.d.ts +1 -1
  10. package/dist/solana/solana/index.d.ts.map +1 -1
  11. package/dist/solana/solana/index.js +4 -3
  12. package/dist/solana/solana/index.js.map +1 -1
  13. package/dist/solana/solana/solana-mailer-client.d.ts +209 -0
  14. package/dist/solana/solana/solana-mailer-client.d.ts.map +1 -0
  15. package/dist/solana/solana/solana-mailer-client.js +1004 -0
  16. package/dist/solana/solana/solana-mailer-client.js.map +1 -0
  17. package/dist/solana/solana/types.d.ts +3 -2
  18. package/dist/solana/solana/types.d.ts.map +1 -1
  19. package/dist/solana/solana/types.js.map +1 -1
  20. package/dist/{unified-esm/src/evm/mailer-client.d.ts → unified/src/evm/evm-mailer-client.d.ts} +146 -50
  21. package/dist/unified/src/evm/evm-mailer-client.d.ts.map +1 -0
  22. package/dist/unified/src/evm/evm-mailer-client.js +924 -0
  23. package/dist/unified/src/evm/evm-mailer-client.js.map +1 -0
  24. package/dist/unified/src/evm/index.d.ts +1 -1
  25. package/dist/unified/src/evm/index.d.ts.map +1 -1
  26. package/dist/unified/src/evm/index.js +4 -4
  27. package/dist/unified/src/evm/index.js.map +1 -1
  28. package/dist/unified/src/react/context/MailerProvider.d.ts +26 -20
  29. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
  30. package/dist/unified/src/react/context/MailerProvider.js +26 -26
  31. package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
  32. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +225 -192
  33. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  34. package/dist/unified/src/react/hooks/useMailerMutations.js +263 -266
  35. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
  36. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +117 -63
  37. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  38. package/dist/unified/src/react/hooks/useMailerQueries.js +239 -104
  39. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
  40. package/dist/unified/src/react/index.d.ts +5 -3
  41. package/dist/unified/src/react/index.d.ts.map +1 -1
  42. package/dist/unified/src/react/index.js +41 -26
  43. package/dist/unified/src/react/index.js.map +1 -1
  44. package/dist/unified/src/solana/index.d.ts +1 -1
  45. package/dist/unified/src/solana/index.d.ts.map +1 -1
  46. package/dist/unified/src/solana/index.js +4 -3
  47. package/dist/unified/src/solana/index.js.map +1 -1
  48. package/dist/unified/src/solana/solana-mailer-client.d.ts +209 -0
  49. package/dist/unified/src/solana/solana-mailer-client.d.ts.map +1 -0
  50. package/dist/unified/src/solana/solana-mailer-client.js +1004 -0
  51. package/dist/unified/src/solana/solana-mailer-client.js.map +1 -0
  52. package/dist/unified/src/solana/types.d.ts +3 -2
  53. package/dist/unified/src/solana/types.d.ts.map +1 -1
  54. package/dist/unified/src/solana/types.js.map +1 -1
  55. package/dist/unified/src/unified/index.d.ts +1 -1
  56. package/dist/unified/src/unified/index.d.ts.map +1 -1
  57. package/dist/unified/src/unified/onchain-mailer-client.d.ts +187 -268
  58. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  59. package/dist/unified/src/unified/onchain-mailer-client.js +539 -1614
  60. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  61. package/dist/unified/src/unified/types.d.ts +23 -6
  62. package/dist/unified/src/unified/types.d.ts.map +1 -1
  63. package/dist/{unified/src/evm/mailer-client.d.ts → unified-esm/src/evm/evm-mailer-client.d.ts} +146 -50
  64. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +1 -0
  65. package/dist/unified-esm/src/evm/evm-mailer-client.js +920 -0
  66. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +1 -0
  67. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  68. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  69. package/dist/unified-esm/src/evm/index.js +2 -2
  70. package/dist/unified-esm/src/evm/index.js.map +1 -1
  71. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +26 -20
  72. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  73. package/dist/unified-esm/src/react/context/MailerProvider.js +25 -26
  74. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  75. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +225 -192
  76. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  77. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +254 -262
  78. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  79. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +117 -63
  80. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  81. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +232 -102
  82. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  83. package/dist/unified-esm/src/react/index.d.ts +5 -3
  84. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  85. package/dist/unified-esm/src/react/index.js +9 -5
  86. package/dist/unified-esm/src/react/index.js.map +1 -1
  87. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  88. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  89. package/dist/unified-esm/src/solana/index.js +2 -1
  90. package/dist/unified-esm/src/solana/index.js.map +1 -1
  91. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +209 -0
  92. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +1 -0
  93. package/dist/unified-esm/src/solana/solana-mailer-client.js +1000 -0
  94. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +1 -0
  95. package/dist/unified-esm/src/solana/types.d.ts +3 -2
  96. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  97. package/dist/unified-esm/src/solana/types.js.map +1 -1
  98. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  99. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  100. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +187 -268
  101. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  102. package/dist/unified-esm/src/unified/onchain-mailer-client.js +539 -1614
  103. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  104. package/dist/unified-esm/src/unified/types.d.ts +23 -6
  105. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  106. package/package.json +5 -4
  107. package/programs/mailer/Cargo.toml +1 -1
  108. package/dist/evm/src/evm/mailer-client.d.ts.map +0 -1
  109. package/dist/evm/src/evm/mailer-client.js +0 -619
  110. package/dist/evm/src/evm/mailer-client.js.map +0 -1
  111. package/dist/solana/solana/mailer-client.d.ts +0 -282
  112. package/dist/solana/solana/mailer-client.d.ts.map +0 -1
  113. package/dist/solana/solana/mailer-client.js +0 -989
  114. package/dist/solana/solana/mailer-client.js.map +0 -1
  115. package/dist/unified/src/evm/mailer-client.d.ts.map +0 -1
  116. package/dist/unified/src/evm/mailer-client.js +0 -619
  117. package/dist/unified/src/evm/mailer-client.js.map +0 -1
  118. package/dist/unified/src/solana/mailer-client.d.ts +0 -282
  119. package/dist/unified/src/solana/mailer-client.d.ts.map +0 -1
  120. package/dist/unified/src/solana/mailer-client.js +0 -989
  121. package/dist/unified/src/solana/mailer-client.js.map +0 -1
  122. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +0 -1
  123. package/dist/unified-esm/src/evm/mailer-client.js +0 -615
  124. package/dist/unified-esm/src/evm/mailer-client.js.map +0 -1
  125. package/dist/unified-esm/src/solana/mailer-client.d.ts +0 -282
  126. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +0 -1
  127. package/dist/unified-esm/src/solana/mailer-client.js +0 -985
  128. package/dist/unified-esm/src/solana/mailer-client.js.map +0 -1
@@ -1,985 +0,0 @@
1
- import { PublicKey, Transaction, TransactionInstruction, SystemProgram, ComputeBudgetProgram, } from '@solana/web3.js';
2
- import { TOKEN_PROGRAM_ID, getAssociatedTokenAddressSync, createAssociatedTokenAccountInstruction, } from '@solana/spl-token';
3
- /**
4
- * Native Solana Program instruction data structures
5
- */
6
- // Instruction data encoding functions
7
- function encodeInitialize(usdcMint) {
8
- const data = Buffer.alloc(1 + 32);
9
- data.writeUInt8(InstructionType.Initialize, 0);
10
- usdcMint.toBuffer().copy(data, 1);
11
- return data;
12
- }
13
- function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToName = false) {
14
- const subjectBytes = Buffer.from(subject, 'utf8');
15
- const bodyBytes = Buffer.from(body, 'utf8');
16
- const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 1 + 1);
17
- let offset = 0;
18
- data.writeUInt8(InstructionType.Send, offset);
19
- offset += 1;
20
- to.toBuffer().copy(data, offset);
21
- offset += 32;
22
- data.writeUInt32LE(subjectBytes.length, offset);
23
- offset += 4;
24
- subjectBytes.copy(data, offset);
25
- offset += subjectBytes.length;
26
- data.writeUInt32LE(bodyBytes.length, offset);
27
- offset += 4;
28
- bodyBytes.copy(data, offset);
29
- offset += bodyBytes.length;
30
- data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
31
- offset += 1;
32
- data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
33
- return data;
34
- }
35
- function encodeSendPrepared(to, mailId, revenueShareToReceiver, resolveSenderToName = false) {
36
- const mailIdBytes = Buffer.from(mailId, 'utf8');
37
- const data = Buffer.alloc(1 + 32 + 4 + mailIdBytes.length + 1 + 1);
38
- let offset = 0;
39
- data.writeUInt8(InstructionType.SendPrepared, offset);
40
- offset += 1;
41
- to.toBuffer().copy(data, offset);
42
- offset += 32;
43
- data.writeUInt32LE(mailIdBytes.length, offset);
44
- offset += 4;
45
- mailIdBytes.copy(data, offset);
46
- offset += mailIdBytes.length;
47
- data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
48
- offset += 1;
49
- data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
50
- return data;
51
- }
52
- function encodeSendToEmail(toEmail, subject, body) {
53
- const emailBytes = Buffer.from(toEmail, 'utf8');
54
- const subjectBytes = Buffer.from(subject, 'utf8');
55
- const bodyBytes = Buffer.from(body, 'utf8');
56
- const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + subjectBytes.length + 4 + bodyBytes.length);
57
- let offset = 0;
58
- data.writeUInt8(InstructionType.SendToEmail, offset);
59
- offset += 1;
60
- data.writeUInt32LE(emailBytes.length, offset);
61
- offset += 4;
62
- emailBytes.copy(data, offset);
63
- offset += emailBytes.length;
64
- data.writeUInt32LE(subjectBytes.length, offset);
65
- offset += 4;
66
- subjectBytes.copy(data, offset);
67
- offset += subjectBytes.length;
68
- data.writeUInt32LE(bodyBytes.length, offset);
69
- offset += 4;
70
- bodyBytes.copy(data, offset);
71
- return data;
72
- }
73
- function encodeSendPreparedToEmail(toEmail, mailId) {
74
- const emailBytes = Buffer.from(toEmail, 'utf8');
75
- const mailIdBytes = Buffer.from(mailId, 'utf8');
76
- const data = Buffer.alloc(1 + 4 + emailBytes.length + 4 + mailIdBytes.length);
77
- let offset = 0;
78
- data.writeUInt8(InstructionType.SendPreparedToEmail, offset);
79
- offset += 1;
80
- data.writeUInt32LE(emailBytes.length, offset);
81
- offset += 4;
82
- emailBytes.copy(data, offset);
83
- offset += emailBytes.length;
84
- data.writeUInt32LE(mailIdBytes.length, offset);
85
- offset += 4;
86
- mailIdBytes.copy(data, offset);
87
- return data;
88
- }
89
- function encodeSendThroughWebhook(to, webhookId, revenueShareToReceiver, resolveSenderToName = false) {
90
- const webhookBytes = Buffer.from(webhookId, 'utf8');
91
- const data = Buffer.alloc(1 + 32 + 4 + webhookBytes.length + 1 + 1);
92
- let offset = 0;
93
- data.writeUInt8(InstructionType.SendThroughWebhook, offset);
94
- offset += 1;
95
- to.toBuffer().copy(data, offset);
96
- offset += 32;
97
- data.writeUInt32LE(webhookBytes.length, offset);
98
- offset += 4;
99
- webhookBytes.copy(data, offset);
100
- offset += webhookBytes.length;
101
- data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
102
- offset += 1;
103
- data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
104
- return data;
105
- }
106
- function encodeSimpleInstruction(instructionType) {
107
- const data = Buffer.alloc(1);
108
- data.writeUInt8(instructionType, 0);
109
- return data;
110
- }
111
- function encodeSetFee(newFee) {
112
- const data = Buffer.alloc(1 + 8);
113
- data.writeUInt8(InstructionType.SetFee, 0);
114
- data.writeBigUInt64LE(newFee, 1);
115
- return data;
116
- }
117
- function encodeSetDelegationFee(newFee) {
118
- const data = Buffer.alloc(1 + 8);
119
- data.writeUInt8(InstructionType.SetDelegationFee, 0);
120
- data.writeBigUInt64LE(newFee, 1);
121
- return data;
122
- }
123
- function encodeSetCustomFeePercentage(account, percentage) {
124
- const data = Buffer.alloc(1 + 32 + 1);
125
- data.writeUInt8(InstructionType.SetCustomFeePercentage, 0);
126
- account.toBuffer().copy(data, 1);
127
- data.writeUInt8(percentage, 33);
128
- return data;
129
- }
130
- function encodeClearCustomFeePercentage(account) {
131
- const data = Buffer.alloc(1 + 32);
132
- data.writeUInt8(InstructionType.ClearCustomFeePercentage, 0);
133
- account.toBuffer().copy(data, 1);
134
- return data;
135
- }
136
- function encodeDelegateTo(delegate) {
137
- if (!delegate) {
138
- // Clear delegation - just send the instruction type and a null option
139
- const data = Buffer.alloc(1 + 1);
140
- data.writeUInt8(InstructionType.DelegateTo, 0);
141
- data.writeUInt8(0, 1); // Option::None
142
- return data;
143
- }
144
- else {
145
- // Set delegation - send instruction type, Some option, and pubkey
146
- const data = Buffer.alloc(1 + 1 + 32);
147
- data.writeUInt8(InstructionType.DelegateTo, 0);
148
- data.writeUInt8(1, 1); // Option::Some
149
- delegate.toBuffer().copy(data, 2);
150
- return data;
151
- }
152
- }
153
- function encodeClaimExpiredShares(recipient) {
154
- const data = Buffer.alloc(1 + 32);
155
- data.writeUInt8(InstructionType.ClaimExpiredShares, 0);
156
- recipient.toBuffer().copy(data, 1);
157
- return data;
158
- }
159
- // Account data parsing functions
160
- function parseMailerState(data) {
161
- let offset = 0;
162
- const owner = new PublicKey(data.slice(offset, offset + 32));
163
- offset += 32;
164
- const usdcMint = new PublicKey(data.slice(offset, offset + 32));
165
- offset += 32;
166
- const sendFee = data.readBigUInt64LE(offset);
167
- offset += 8;
168
- const delegationFee = data.readBigUInt64LE(offset);
169
- offset += 8;
170
- const ownerClaimable = data.readBigUInt64LE(offset);
171
- offset += 8;
172
- const paused = data.readUInt8(offset) === 1;
173
- offset += 1;
174
- const bump = data.readUInt8(offset);
175
- return {
176
- owner,
177
- usdc_mint: usdcMint,
178
- send_fee: sendFee,
179
- delegation_fee: delegationFee,
180
- owner_claimable: ownerClaimable,
181
- paused,
182
- bump,
183
- };
184
- }
185
- function parseRecipientClaim(data) {
186
- let offset = 0;
187
- const recipient = new PublicKey(data.slice(offset, offset + 32));
188
- offset += 32;
189
- const amount = data.readBigUInt64LE(offset);
190
- offset += 8;
191
- const timestamp = data.readBigInt64LE(offset);
192
- offset += 8;
193
- const bump = data.readUInt8(offset);
194
- return {
195
- recipient,
196
- amount,
197
- timestamp,
198
- bump,
199
- };
200
- }
201
- function parseDelegation(data) {
202
- let offset = 0;
203
- const delegator = new PublicKey(data.slice(offset, offset + 32));
204
- offset += 32;
205
- const hasDelegate = data.readUInt8(offset) === 1;
206
- offset += 1;
207
- const delegate = hasDelegate
208
- ? new PublicKey(data.slice(offset, offset + 32))
209
- : null;
210
- if (hasDelegate)
211
- offset += 32;
212
- const bump = data.readUInt8(offset);
213
- return {
214
- delegator,
215
- delegate,
216
- bump,
217
- };
218
- }
219
- function parseFeeDiscount(data) {
220
- let offset = 0;
221
- const account = new PublicKey(data.slice(offset, offset + 32));
222
- offset += 32;
223
- const discount = data.readUInt8(offset);
224
- offset += 1;
225
- const bump = data.readUInt8(offset);
226
- return {
227
- account,
228
- discount,
229
- bump,
230
- };
231
- }
232
- var InstructionType;
233
- (function (InstructionType) {
234
- InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
235
- InstructionType[InstructionType["Send"] = 1] = "Send";
236
- InstructionType[InstructionType["SendPrepared"] = 2] = "SendPrepared";
237
- InstructionType[InstructionType["SendToEmail"] = 3] = "SendToEmail";
238
- InstructionType[InstructionType["SendPreparedToEmail"] = 4] = "SendPreparedToEmail";
239
- InstructionType[InstructionType["SendThroughWebhook"] = 5] = "SendThroughWebhook";
240
- InstructionType[InstructionType["ClaimRecipientShare"] = 6] = "ClaimRecipientShare";
241
- InstructionType[InstructionType["ClaimOwnerShare"] = 7] = "ClaimOwnerShare";
242
- InstructionType[InstructionType["SetFee"] = 8] = "SetFee";
243
- InstructionType[InstructionType["DelegateTo"] = 9] = "DelegateTo";
244
- InstructionType[InstructionType["RejectDelegation"] = 10] = "RejectDelegation";
245
- InstructionType[InstructionType["SetDelegationFee"] = 11] = "SetDelegationFee";
246
- InstructionType[InstructionType["SetCustomFeePercentage"] = 12] = "SetCustomFeePercentage";
247
- InstructionType[InstructionType["ClearCustomFeePercentage"] = 13] = "ClearCustomFeePercentage";
248
- InstructionType[InstructionType["Pause"] = 14] = "Pause";
249
- InstructionType[InstructionType["Unpause"] = 15] = "Unpause";
250
- InstructionType[InstructionType["DistributeClaimableFunds"] = 16] = "DistributeClaimableFunds";
251
- InstructionType[InstructionType["ClaimExpiredShares"] = 17] = "ClaimExpiredShares";
252
- InstructionType[InstructionType["EmergencyUnpause"] = 18] = "EmergencyUnpause";
253
- })(InstructionType || (InstructionType = {}));
254
- /**
255
- * @class MailerClient
256
- * @description Native Solana program client for the Mailer program
257
- * @notice Provides easy-to-use methods for sending messages with USDC fees and revenue sharing
258
- *
259
- * ## Key Features:
260
- * - **Priority Messages**: Full fee (0.1 USDC) with 90% revenue share to recipient
261
- * - **Standard Messages**: 10% fee only (0.01 USDC) with no revenue share
262
- * - **Revenue Claims**: 60-day claim period for priority message revenue shares
263
- * - **Delegation Management**: Delegate message handling with rejection capability
264
- *
265
- * ## Usage Examples:
266
- * ```typescript
267
- * // Connect to existing deployed program
268
- * const connection = new Connection('https://api.devnet.solana.com');
269
- * const wallet = new WalletAdapter(keypair);
270
- * const programId = new PublicKey('9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF');
271
- * const usdcMint = new PublicKey('EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v');
272
- * const client = new MailerClient(connection, wallet, programId, usdcMint);
273
- *
274
- * // Send message with revenue sharing to recipient
275
- * await client.send('recipient-address', 'Subject', 'Message body', true);
276
- *
277
- * // Claim your revenue share within 60 days (as recipient)
278
- * await client.claimRecipientShare();
279
- *
280
- * // Check claimable amount
281
- * const info = await client.getRecipientClaimable();
282
- * if (info) console.log(`Claimable: ${formatUSDC(info.amount)} USDC`);
283
- * ```
284
- *
285
- * @author Mailer Team
286
- * @version 2.0.0 - Native Solana Program (no Anchor)
287
- */
288
- export class MailerClient {
289
- constructor(connection, wallet, programId, usdcMint) {
290
- this.defaultComputeUnitMultiplier = 1.2; // 20% buffer by default
291
- this.connection = connection;
292
- this.wallet = wallet;
293
- this.programId = programId;
294
- this.usdcMint = usdcMint;
295
- // Derive the mailer state PDA
296
- const [mailerPda, bump] = PublicKey.findProgramAddressSync([Buffer.from('mailer')], this.programId);
297
- this.mailerStatePda = mailerPda;
298
- this.mailerBump = bump;
299
- }
300
- /**
301
- * Optimize compute units for a transaction
302
- * @param transaction Transaction to optimize
303
- * @param options Compute unit options
304
- * @returns Optimized transaction with compute budget instructions
305
- */
306
- async optimizeComputeUnits(transaction, options) {
307
- // Skip if explicitly disabled
308
- if (options?.skipComputeUnits) {
309
- return { transaction };
310
- }
311
- let simulatedUnits;
312
- let computeUnitLimit = options?.computeUnitLimit;
313
- // Auto-optimize by simulating transaction
314
- if (options?.autoOptimize && !computeUnitLimit) {
315
- try {
316
- // Set a high limit for simulation
317
- const simTransaction = new Transaction().add(...transaction.instructions);
318
- simTransaction.add(ComputeBudgetProgram.setComputeUnitLimit({
319
- units: 1400000, // Max for simulation
320
- }));
321
- simTransaction.recentBlockhash = (await this.connection.getLatestBlockhash()).blockhash;
322
- simTransaction.feePayer = this.wallet.publicKey;
323
- const simulation = await this.connection.simulateTransaction(simTransaction);
324
- if (simulation.value.err === null && simulation.value.unitsConsumed) {
325
- simulatedUnits = simulation.value.unitsConsumed;
326
- const multiplier = options.computeUnitMultiplier ?? this.defaultComputeUnitMultiplier;
327
- computeUnitLimit = Math.min(Math.ceil(simulatedUnits * multiplier), 1400000 // Max compute units
328
- );
329
- }
330
- }
331
- catch (error) {
332
- console.warn('Failed to simulate transaction for compute unit optimization:', error);
333
- // Fall back to default or specified limit
334
- computeUnitLimit = computeUnitLimit ?? 200000;
335
- }
336
- }
337
- // Create new transaction with compute budget instructions prepended
338
- const optimizedTx = new Transaction();
339
- // Add compute unit limit if specified or auto-optimized
340
- if (computeUnitLimit) {
341
- optimizedTx.add(ComputeBudgetProgram.setComputeUnitLimit({
342
- units: computeUnitLimit,
343
- }));
344
- }
345
- // Add priority fee if specified
346
- if (options?.computeUnitPrice) {
347
- optimizedTx.add(ComputeBudgetProgram.setComputeUnitPrice({
348
- microLamports: options.computeUnitPrice,
349
- }));
350
- }
351
- // Add original instructions
352
- optimizedTx.add(...transaction.instructions);
353
- return {
354
- transaction: optimizedTx,
355
- simulatedUnits,
356
- };
357
- }
358
- /**
359
- * Initialize the mailer program (owner only)
360
- * @param computeOptions Compute unit optimization options
361
- */
362
- async initialize(computeOptions) {
363
- const instruction = new TransactionInstruction({
364
- keys: [
365
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
366
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
367
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
368
- ],
369
- programId: this.programId,
370
- data: encodeInitialize(this.usdcMint),
371
- });
372
- const transaction = new Transaction().add(instruction);
373
- return await this.sendTransaction(transaction, undefined, computeOptions);
374
- }
375
- /**
376
- * Send a message with optional revenue sharing
377
- * @param to Recipient's public key or address string who receives message and potential revenue share
378
- * @param subject Message subject
379
- * @param body Message body
380
- * @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
381
- * @param resolveSenderToName If true, resolve sender address to name via off-chain service
382
- * @param computeOptions Compute unit optimization options
383
- * @returns Transaction result with signature and compute details
384
- */
385
- async send(to, subject, body, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
386
- const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
387
- // Derive recipient claim PDA
388
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
389
- // Get associated token accounts
390
- const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
391
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
392
- // Check if accounts need to be created
393
- const instructions = [];
394
- // Check if mailer token account exists
395
- const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
396
- if (!mailerTokenInfo) {
397
- instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
398
- }
399
- // Add the send instruction
400
- const sendInstruction = new TransactionInstruction({
401
- keys: [
402
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
403
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
404
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
405
- { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
406
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
407
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
408
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
409
- ],
410
- programId: this.programId,
411
- data: encodeSend(recipientKey, subject, body, revenueShareToReceiver, resolveSenderToName),
412
- });
413
- instructions.push(sendInstruction);
414
- const transaction = new Transaction().add(...instructions);
415
- return await this.sendTransaction(transaction, undefined, computeOptions);
416
- }
417
- /**
418
- * Claim recipient share of revenue
419
- * @returns Transaction result
420
- */
421
- async claimRecipientShare(computeOptions) {
422
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), this.wallet.publicKey.toBuffer()], this.programId);
423
- const recipientTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
424
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
425
- const instruction = new TransactionInstruction({
426
- keys: [
427
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
428
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
429
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
430
- { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
431
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
432
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
433
- ],
434
- programId: this.programId,
435
- data: encodeSimpleInstruction(InstructionType.ClaimRecipientShare),
436
- });
437
- const transaction = new Transaction().add(instruction);
438
- return await this.sendTransaction(transaction, undefined, computeOptions);
439
- }
440
- /**
441
- * Claim owner share of fees (owner only)
442
- * @returns Transaction result
443
- */
444
- async claimOwnerShare(computeOptions) {
445
- const ownerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
446
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
447
- const instruction = new TransactionInstruction({
448
- keys: [
449
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
450
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
451
- { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
452
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
453
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
454
- ],
455
- programId: this.programId,
456
- data: encodeSimpleInstruction(InstructionType.ClaimOwnerShare),
457
- });
458
- const transaction = new Transaction().add(instruction);
459
- return await this.sendTransaction(transaction, undefined, computeOptions);
460
- }
461
- /**
462
- * Claim expired recipient shares and move them under owner control
463
- * @param recipient Recipient whose expired shares to reclaim
464
- * @param options Transaction confirm options
465
- * @returns Transaction signature
466
- */
467
- async claimExpiredShares(recipient, options, computeOptions) {
468
- const recipientKey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
469
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
470
- const instruction = new TransactionInstruction({
471
- keys: [
472
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
473
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
474
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
475
- ],
476
- programId: this.programId,
477
- data: encodeClaimExpiredShares(recipientKey),
478
- });
479
- const transaction = new Transaction().add(instruction);
480
- return await this.sendTransaction(transaction, options, computeOptions);
481
- }
482
- /**
483
- * Delegate message handling to another address
484
- * @param delegate Address to delegate to, or null to clear delegation
485
- * @returns Transaction signature
486
- */
487
- async delegateTo(delegate, computeOptions) {
488
- const delegateKey = delegate
489
- ? typeof delegate === 'string'
490
- ? new PublicKey(delegate)
491
- : delegate
492
- : null;
493
- const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), this.wallet.publicKey.toBuffer()], this.programId);
494
- const delegatorTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
495
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
496
- const instruction = new TransactionInstruction({
497
- keys: [
498
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
499
- { pubkey: delegationPda, isSigner: false, isWritable: true },
500
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
501
- { pubkey: delegatorTokenAccount, isSigner: false, isWritable: true },
502
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
503
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
504
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
505
- ],
506
- programId: this.programId,
507
- data: encodeDelegateTo(delegateKey),
508
- });
509
- const transaction = new Transaction().add(instruction);
510
- return await this.sendTransaction(transaction, undefined, computeOptions);
511
- }
512
- /**
513
- * Reject a delegation made to you
514
- * @param delegator Address that delegated to you
515
- * @returns Transaction signature
516
- */
517
- async rejectDelegation(delegator, computeOptions) {
518
- const delegatorKey = typeof delegator === 'string' ? new PublicKey(delegator) : delegator;
519
- const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
520
- const instruction = new TransactionInstruction({
521
- keys: [
522
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
523
- { pubkey: delegationPda, isSigner: false, isWritable: true },
524
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
525
- ],
526
- programId: this.programId,
527
- data: encodeSimpleInstruction(InstructionType.RejectDelegation),
528
- });
529
- const transaction = new Transaction().add(instruction);
530
- return await this.sendTransaction(transaction, undefined, computeOptions);
531
- }
532
- /**
533
- * Set the send fee (owner only)
534
- * @param newFee New fee in USDC micro-units (6 decimals)
535
- * @param computeOptions Compute unit optimization options
536
- * @returns Transaction result
537
- */
538
- async setFee(newFee, computeOptions) {
539
- const instruction = new TransactionInstruction({
540
- keys: [
541
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
542
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
543
- ],
544
- programId: this.programId,
545
- data: encodeSetFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
546
- });
547
- const transaction = new Transaction().add(instruction);
548
- return await this.sendTransaction(transaction, undefined, computeOptions);
549
- }
550
- /**
551
- * Set the delegation fee (owner only)
552
- * @param newFee New delegation fee in USDC micro-units (6 decimals)
553
- * @returns Transaction signature
554
- */
555
- async setDelegationFee(newFee, computeOptions) {
556
- const instruction = new TransactionInstruction({
557
- keys: [
558
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
559
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
560
- ],
561
- programId: this.programId,
562
- data: encodeSetDelegationFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
563
- });
564
- const transaction = new Transaction().add(instruction);
565
- return await this.sendTransaction(transaction, undefined, computeOptions);
566
- }
567
- async setCustomFeePercentage(account, percentage, payer, computeOptions) {
568
- const normalizedPercentage = Math.trunc(percentage);
569
- if (normalizedPercentage < 0 || normalizedPercentage > 100) {
570
- throw new Error('Percentage must be between 0 and 100');
571
- }
572
- const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
573
- const payerKey = payer
574
- ? typeof payer === 'string'
575
- ? new PublicKey(payer)
576
- : payer
577
- : this.wallet.publicKey;
578
- const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
579
- const instruction = new TransactionInstruction({
580
- keys: [
581
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
582
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
583
- { pubkey: discountPda, isSigner: false, isWritable: true },
584
- { pubkey: accountKey, isSigner: false, isWritable: false },
585
- { pubkey: payerKey, isSigner: true, isWritable: true },
586
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
587
- ],
588
- programId: this.programId,
589
- data: encodeSetCustomFeePercentage(accountKey, normalizedPercentage),
590
- });
591
- const transaction = new Transaction().add(instruction);
592
- return this.sendTransaction(transaction, undefined, computeOptions);
593
- }
594
- async clearCustomFeePercentage(account, computeOptions) {
595
- const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
596
- const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
597
- const instruction = new TransactionInstruction({
598
- keys: [
599
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
600
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
601
- { pubkey: discountPda, isSigner: false, isWritable: true },
602
- ],
603
- programId: this.programId,
604
- data: encodeClearCustomFeePercentage(accountKey),
605
- });
606
- const transaction = new Transaction().add(instruction);
607
- return this.sendTransaction(transaction, undefined, computeOptions);
608
- }
609
- async getCustomFeePercentage(account) {
610
- const accountKey = typeof account === 'string' ? new PublicKey(account) : account;
611
- const [discountPda] = PublicKey.findProgramAddressSync([Buffer.from('discount'), accountKey.toBuffer()], this.programId);
612
- const accountInfo = await this.connection.getAccountInfo(discountPda);
613
- if (!accountInfo) {
614
- return 100;
615
- }
616
- const discountState = parseFeeDiscount(accountInfo.data);
617
- return 100 - discountState.discount;
618
- }
619
- /**
620
- * Get current fees from the mailer state
621
- * @returns MailerFees object with current fees
622
- */
623
- async getFees() {
624
- const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
625
- if (!accountInfo) {
626
- throw new Error('Mailer state account not found - program not initialized');
627
- }
628
- const stateData = parseMailerState(accountInfo.data);
629
- return {
630
- sendFee: Number(stateData.send_fee),
631
- delegationFee: Number(stateData.delegation_fee),
632
- };
633
- }
634
- /**
635
- * Get recipient claimable information
636
- * @param recipient Optional recipient address, defaults to wallet address
637
- * @returns ClaimableInfo or null if no claimable amount
638
- */
639
- async getRecipientClaimable(recipient) {
640
- const recipientKey = recipient || this.wallet.publicKey;
641
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
642
- const accountInfo = await this.connection.getAccountInfo(recipientClaimPda);
643
- if (!accountInfo) {
644
- return null;
645
- }
646
- const claimData = parseRecipientClaim(accountInfo.data);
647
- // Check if claim period has expired (60 days)
648
- const now = Math.floor(Date.now() / 1000);
649
- const isExpired = now > Number(claimData.timestamp) + 60 * 24 * 60 * 60;
650
- return {
651
- amount: Number(claimData.amount),
652
- timestamp: Number(claimData.timestamp),
653
- recipient: recipientKey.toBase58(),
654
- isExpired,
655
- };
656
- }
657
- /**
658
- * Get owner claimable amount
659
- * @returns Owner claimable amount in USDC micro-units
660
- */
661
- async getOwnerClaimable() {
662
- const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
663
- if (!accountInfo) {
664
- throw new Error('Mailer state account not found');
665
- }
666
- const stateData = parseMailerState(accountInfo.data);
667
- return Number(stateData.owner_claimable);
668
- }
669
- /**
670
- * Get delegation information for an address
671
- * @param delegator Address to check delegation for, defaults to wallet address
672
- * @returns Delegation info or null if no delegation
673
- */
674
- async getDelegation(delegator) {
675
- const delegatorKey = delegator || this.wallet.publicKey;
676
- const [delegationPda] = PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
677
- const accountInfo = await this.connection.getAccountInfo(delegationPda);
678
- if (!accountInfo) {
679
- return null;
680
- }
681
- const delegationData = parseDelegation(accountInfo.data);
682
- return {
683
- delegator: delegatorKey.toBase58(),
684
- delegate: delegationData.delegate
685
- ? delegationData.delegate.toBase58()
686
- : null,
687
- };
688
- }
689
- /**
690
- * Get the mailer state PDA address
691
- * @returns PublicKey of the mailer state PDA
692
- */
693
- getMailerStatePda() {
694
- return this.mailerStatePda;
695
- }
696
- /**
697
- * Send a message to an email address (no wallet known)
698
- * Charges only 10% owner fee since recipient wallet is unknown
699
- * @param toEmail Email address of the recipient
700
- * @param subject Message subject
701
- * @param body Message body
702
- * @param options Transaction confirm options
703
- * @returns Transaction signature
704
- */
705
- async sendToEmail(toEmail, subject, body, options, computeOptions) {
706
- // Get associated token accounts
707
- const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
708
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
709
- // Check if accounts need to be created
710
- const instructions = [];
711
- // Check if mailer token account exists
712
- const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
713
- if (!mailerTokenInfo) {
714
- instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
715
- }
716
- // Encode instruction data for SendToEmail
717
- const instructionData = encodeSendToEmail(toEmail, subject, body);
718
- // Create send instruction
719
- instructions.push(new TransactionInstruction({
720
- keys: [
721
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
722
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
723
- { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
724
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
725
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
726
- ],
727
- programId: this.programId,
728
- data: instructionData,
729
- }));
730
- const transaction = new Transaction().add(...instructions);
731
- return this.sendTransaction(transaction, options, computeOptions);
732
- }
733
- /**
734
- * Send a prepared message to an email address (no wallet known)
735
- * Charges only 10% owner fee since recipient wallet is unknown
736
- * @param toEmail Email address of the recipient
737
- * @param mailId Pre-prepared message ID
738
- * @param options Transaction confirm options
739
- * @returns Transaction signature
740
- */
741
- async sendPreparedToEmail(toEmail, mailId, options, computeOptions) {
742
- // Get associated token accounts
743
- const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
744
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
745
- // Check if accounts need to be created
746
- const instructions = [];
747
- // Check if mailer token account exists
748
- const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
749
- if (!mailerTokenInfo) {
750
- instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
751
- }
752
- // Encode instruction data for SendPreparedToEmail
753
- const instructionData = encodeSendPreparedToEmail(toEmail, mailId);
754
- // Create send instruction
755
- instructions.push(new TransactionInstruction({
756
- keys: [
757
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
758
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
759
- { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
760
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
761
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
762
- ],
763
- programId: this.programId,
764
- data: instructionData,
765
- }));
766
- const transaction = new Transaction().add(...instructions);
767
- return this.sendTransaction(transaction, options, computeOptions);
768
- }
769
- /**
770
- * Send a prepared message using a mailId (to match EVM behavior)
771
- * @param to Recipient's public key or address string
772
- * @param mailId Pre-prepared message identifier
773
- * @param revenueShareToReceiver If true, recipient gets 90% revenue share
774
- * @param resolveSenderToName If true, resolve sender address to name
775
- * @returns Transaction signature
776
- */
777
- async sendPrepared(to, mailId, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
778
- const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
779
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
780
- const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
781
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
782
- const instructions = [];
783
- const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
784
- if (!mailerTokenInfo) {
785
- instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
786
- }
787
- const sendInstruction = new TransactionInstruction({
788
- keys: [
789
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
790
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
791
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
792
- { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
793
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
794
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
795
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
796
- ],
797
- programId: this.programId,
798
- data: encodeSendPrepared(recipientKey, mailId, revenueShareToReceiver, resolveSenderToName),
799
- });
800
- instructions.push(sendInstruction);
801
- const transaction = new Transaction().add(...instructions);
802
- return this.sendTransaction(transaction, undefined, computeOptions);
803
- }
804
- async sendThroughWebhook(to, webhookId, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
805
- const recipientKey = typeof to === 'string' ? new PublicKey(to) : to;
806
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
807
- const senderTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
808
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
809
- const instructions = [];
810
- const mailerTokenInfo = await this.connection.getAccountInfo(mailerTokenAccount);
811
- if (!mailerTokenInfo) {
812
- instructions.push(createAssociatedTokenAccountInstruction(this.wallet.publicKey, mailerTokenAccount, this.mailerStatePda, this.usdcMint));
813
- }
814
- const sendInstruction = new TransactionInstruction({
815
- keys: [
816
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
817
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
818
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
819
- { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
820
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
821
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
822
- { pubkey: SystemProgram.programId, isSigner: false, isWritable: false },
823
- ],
824
- programId: this.programId,
825
- data: encodeSendThroughWebhook(recipientKey, webhookId, revenueShareToReceiver, resolveSenderToName),
826
- });
827
- instructions.push(sendInstruction);
828
- const transaction = new Transaction().add(...instructions);
829
- return this.sendTransaction(transaction, undefined, computeOptions);
830
- }
831
- /**
832
- * Pause the contract and distribute owner claimable funds (owner only)
833
- * @param options Transaction confirm options
834
- * @returns Transaction signature
835
- */
836
- async pause(options, computeOptions) {
837
- const ownerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.wallet.publicKey);
838
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
839
- const instruction = new TransactionInstruction({
840
- keys: [
841
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
842
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
843
- { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
844
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
845
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
846
- ],
847
- programId: this.programId,
848
- data: encodeSimpleInstruction(InstructionType.Pause),
849
- });
850
- const transaction = new Transaction().add(instruction);
851
- return await this.sendTransaction(transaction, options, computeOptions);
852
- }
853
- /**
854
- * Unpause the contract (owner only)
855
- * @param options Transaction confirm options
856
- * @returns Transaction signature
857
- */
858
- async unpause(options, computeOptions) {
859
- const instruction = new TransactionInstruction({
860
- keys: [
861
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
862
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
863
- ],
864
- programId: this.programId,
865
- data: encodeSimpleInstruction(InstructionType.Unpause),
866
- });
867
- const transaction = new Transaction().add(instruction);
868
- return await this.sendTransaction(transaction, options, computeOptions);
869
- }
870
- /**
871
- * Emergency unpause without fund distribution (owner only)
872
- * @param options Transaction confirm options
873
- * @returns Transaction signature
874
- */
875
- async emergencyUnpause(options, computeOptions) {
876
- const instruction = new TransactionInstruction({
877
- keys: [
878
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
879
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: true },
880
- ],
881
- programId: this.programId,
882
- data: encodeSimpleInstruction(InstructionType.EmergencyUnpause),
883
- });
884
- const transaction = new Transaction().add(instruction);
885
- return await this.sendTransaction(transaction, options, computeOptions);
886
- }
887
- /**
888
- * Distribute claimable funds to a recipient when contract is paused
889
- * @param recipient Recipient address to distribute funds for
890
- * @param options Transaction confirm options
891
- * @returns Transaction signature
892
- */
893
- async distributeClaimableFunds(recipient, options, computeOptions) {
894
- const recipientKey = typeof recipient === 'string' ? new PublicKey(recipient) : recipient;
895
- const [recipientClaimPda] = PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
896
- const recipientTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, recipientKey);
897
- const mailerTokenAccount = getAssociatedTokenAddressSync(this.usdcMint, this.mailerStatePda, true);
898
- // Encode the recipient parameter
899
- const data = Buffer.alloc(1 + 32);
900
- data.writeUInt8(InstructionType.DistributeClaimableFunds, 0);
901
- recipientKey.toBuffer().copy(data, 1);
902
- const instruction = new TransactionInstruction({
903
- keys: [
904
- { pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
905
- { pubkey: this.mailerStatePda, isSigner: false, isWritable: false },
906
- { pubkey: recipientClaimPda, isSigner: false, isWritable: true },
907
- { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
908
- { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
909
- { pubkey: TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
910
- ],
911
- programId: this.programId,
912
- data,
913
- });
914
- const transaction = new Transaction().add(instruction);
915
- return await this.sendTransaction(transaction, options, computeOptions);
916
- }
917
- /**
918
- * Get the current send fee
919
- * @returns Send fee in USDC micro-units (6 decimals)
920
- */
921
- async getSendFee() {
922
- const fees = await this.getFees();
923
- return BigInt(fees.sendFee);
924
- }
925
- /**
926
- * Check if contract is currently paused
927
- * @returns True if contract is paused, false otherwise
928
- */
929
- async isPaused() {
930
- const accountInfo = await this.connection.getAccountInfo(this.mailerStatePda);
931
- if (!accountInfo) {
932
- throw new Error('Mailer state account not found - program not initialized');
933
- }
934
- const stateData = parseMailerState(accountInfo.data);
935
- // paused field is at offset: 32 + 32 + 8 + 8 + 8 = 88 bytes
936
- return stateData.paused;
937
- }
938
- /**
939
- * Send and confirm a transaction
940
- * @param transaction Transaction to send
941
- * @param options Confirm options
942
- * @returns Transaction signature
943
- */
944
- async sendTransaction(transaction, options, computeOptions) {
945
- // Optimize compute units if requested
946
- const { transaction: optimizedTx, simulatedUnits } = await this.optimizeComputeUnits(transaction, computeOptions);
947
- // Get recent blockhash
948
- const { blockhash } = await this.connection.getLatestBlockhash();
949
- optimizedTx.recentBlockhash = blockhash;
950
- optimizedTx.feePayer = this.wallet.publicKey;
951
- // Sign transaction
952
- const signedTx = await this.wallet.signTransaction(optimizedTx);
953
- // Send and confirm
954
- const signature = await this.connection.sendRawTransaction(signedTx.serialize());
955
- await this.connection.confirmTransaction(signature, options?.commitment || 'confirmed');
956
- return {
957
- signature,
958
- simulatedUnits,
959
- computeUnitLimit: computeOptions?.computeUnitLimit,
960
- computeUnitPrice: computeOptions?.computeUnitPrice,
961
- };
962
- }
963
- /**
964
- * Create a simple wallet from a keypair for testing
965
- * @param keypair Solana keypair
966
- * @returns Wallet interface implementation
967
- */
968
- static createWallet(keypair) {
969
- return {
970
- publicKey: keypair.publicKey,
971
- async signTransaction(transaction) {
972
- transaction.partialSign(keypair);
973
- return transaction;
974
- },
975
- async signAllTransactions(transactions) {
976
- return transactions.map((tx) => {
977
- tx.partialSign(keypair);
978
- return tx;
979
- });
980
- },
981
- };
982
- }
983
- }
984
- // Wallet interface is exported above
985
- //# sourceMappingURL=mailer-client.js.map