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