@sudobility/contracts 0.14.0 → 0.15.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 (123) 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/onchain-mailer-client.d.ts +224 -139
  56. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  57. package/dist/unified/src/unified/onchain-mailer-client.js +577 -857
  58. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  59. package/dist/unified/src/unified/types.d.ts +9 -2
  60. package/dist/unified/src/unified/types.d.ts.map +1 -1
  61. package/dist/{unified/src/evm/mailer-client.d.ts → unified-esm/src/evm/evm-mailer-client.d.ts} +146 -50
  62. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +1 -0
  63. package/dist/unified-esm/src/evm/evm-mailer-client.js +920 -0
  64. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +1 -0
  65. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  66. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  67. package/dist/unified-esm/src/evm/index.js +2 -2
  68. package/dist/unified-esm/src/evm/index.js.map +1 -1
  69. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +26 -20
  70. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  71. package/dist/unified-esm/src/react/context/MailerProvider.js +25 -26
  72. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  73. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +225 -192
  74. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  75. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +254 -262
  76. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  77. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +117 -63
  78. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  79. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +232 -102
  80. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  81. package/dist/unified-esm/src/react/index.d.ts +5 -3
  82. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  83. package/dist/unified-esm/src/react/index.js +9 -5
  84. package/dist/unified-esm/src/react/index.js.map +1 -1
  85. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  86. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  87. package/dist/unified-esm/src/solana/index.js +2 -1
  88. package/dist/unified-esm/src/solana/index.js.map +1 -1
  89. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +209 -0
  90. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +1 -0
  91. package/dist/unified-esm/src/solana/solana-mailer-client.js +1000 -0
  92. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +1 -0
  93. package/dist/unified-esm/src/solana/types.d.ts +3 -2
  94. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  95. package/dist/unified-esm/src/solana/types.js.map +1 -1
  96. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +224 -139
  97. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  98. package/dist/unified-esm/src/unified/onchain-mailer-client.js +579 -859
  99. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  100. package/dist/unified-esm/src/unified/types.d.ts +9 -2
  101. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  102. package/package.json +3 -3
  103. package/dist/evm/src/evm/mailer-client.d.ts.map +0 -1
  104. package/dist/evm/src/evm/mailer-client.js +0 -619
  105. package/dist/evm/src/evm/mailer-client.js.map +0 -1
  106. package/dist/solana/solana/mailer-client.d.ts +0 -282
  107. package/dist/solana/solana/mailer-client.d.ts.map +0 -1
  108. package/dist/solana/solana/mailer-client.js +0 -989
  109. package/dist/solana/solana/mailer-client.js.map +0 -1
  110. package/dist/unified/src/evm/mailer-client.d.ts.map +0 -1
  111. package/dist/unified/src/evm/mailer-client.js +0 -619
  112. package/dist/unified/src/evm/mailer-client.js.map +0 -1
  113. package/dist/unified/src/solana/mailer-client.d.ts +0 -282
  114. package/dist/unified/src/solana/mailer-client.d.ts.map +0 -1
  115. package/dist/unified/src/solana/mailer-client.js +0 -989
  116. package/dist/unified/src/solana/mailer-client.js.map +0 -1
  117. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +0 -1
  118. package/dist/unified-esm/src/evm/mailer-client.js +0 -615
  119. package/dist/unified-esm/src/evm/mailer-client.js.map +0 -1
  120. package/dist/unified-esm/src/solana/mailer-client.d.ts +0 -282
  121. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +0 -1
  122. package/dist/unified-esm/src/solana/mailer-client.js +0 -985
  123. package/dist/unified-esm/src/solana/mailer-client.js.map +0 -1
@@ -0,0 +1,1004 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SolanaMailerClient = 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 types
8
+ */
9
+ var InstructionType;
10
+ (function (InstructionType) {
11
+ InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
12
+ InstructionType[InstructionType["Send"] = 1] = "Send";
13
+ InstructionType[InstructionType["SendPrepared"] = 2] = "SendPrepared";
14
+ InstructionType[InstructionType["SendThroughWebhook"] = 3] = "SendThroughWebhook";
15
+ InstructionType[InstructionType["SendToEmail"] = 4] = "SendToEmail";
16
+ InstructionType[InstructionType["SendPreparedToEmail"] = 5] = "SendPreparedToEmail";
17
+ InstructionType[InstructionType["ClaimRecipientShare"] = 6] = "ClaimRecipientShare";
18
+ InstructionType[InstructionType["ClaimOwnerShare"] = 7] = "ClaimOwnerShare";
19
+ InstructionType[InstructionType["ClaimExpiredShares"] = 8] = "ClaimExpiredShares";
20
+ InstructionType[InstructionType["SetFees"] = 9] = "SetFees";
21
+ InstructionType[InstructionType["DelegateTo"] = 10] = "DelegateTo";
22
+ InstructionType[InstructionType["RejectDelegation"] = 11] = "RejectDelegation";
23
+ InstructionType[InstructionType["SetCustomFeePercentage"] = 12] = "SetCustomFeePercentage";
24
+ InstructionType[InstructionType["ClearCustomFeePercentage"] = 13] = "ClearCustomFeePercentage";
25
+ InstructionType[InstructionType["Pause"] = 14] = "Pause";
26
+ InstructionType[InstructionType["Unpause"] = 15] = "Unpause";
27
+ InstructionType[InstructionType["EmergencyUnpause"] = 16] = "EmergencyUnpause";
28
+ InstructionType[InstructionType["DistributeClaimableFunds"] = 17] = "DistributeClaimableFunds";
29
+ })(InstructionType || (InstructionType = {}));
30
+ // Instruction data encoding functions
31
+ function encodeInitialize(usdcMint) {
32
+ const data = Buffer.alloc(1 + 32);
33
+ data.writeUInt8(InstructionType.Initialize, 0);
34
+ usdcMint.toBuffer().copy(data, 1);
35
+ return data;
36
+ }
37
+ function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToName = false) {
38
+ const subjectBytes = Buffer.from(subject, 'utf8');
39
+ const bodyBytes = Buffer.from(body, 'utf8');
40
+ const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 1 + 1);
41
+ let offset = 0;
42
+ data.writeUInt8(InstructionType.Send, offset);
43
+ offset += 1;
44
+ to.toBuffer().copy(data, offset);
45
+ offset += 32;
46
+ data.writeUInt32LE(subjectBytes.length, offset);
47
+ offset += 4;
48
+ subjectBytes.copy(data, offset);
49
+ offset += subjectBytes.length;
50
+ data.writeUInt32LE(bodyBytes.length, offset);
51
+ offset += 4;
52
+ bodyBytes.copy(data, offset);
53
+ offset += bodyBytes.length;
54
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
55
+ offset += 1;
56
+ data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
57
+ return data;
58
+ }
59
+ function encodeSendPrepared(to, mailId, revenueShareToReceiver, resolveSenderToName = false) {
60
+ const mailIdBytes = Buffer.from(mailId, 'utf8');
61
+ const data = Buffer.alloc(1 + 32 + 4 + mailIdBytes.length + 1 + 1);
62
+ let offset = 0;
63
+ data.writeUInt8(InstructionType.SendPrepared, offset);
64
+ offset += 1;
65
+ to.toBuffer().copy(data, offset);
66
+ offset += 32;
67
+ data.writeUInt32LE(mailIdBytes.length, offset);
68
+ offset += 4;
69
+ mailIdBytes.copy(data, offset);
70
+ offset += mailIdBytes.length;
71
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
72
+ offset += 1;
73
+ data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
74
+ return data;
75
+ }
76
+ function encodeSendThroughWebhook(to, subject, body, webhookId, revenueShareToReceiver) {
77
+ const subjectBytes = Buffer.from(subject, 'utf8');
78
+ const bodyBytes = Buffer.from(body, 'utf8');
79
+ const webhookIdBytes = Buffer.from(webhookId, 'utf8');
80
+ const data = Buffer.alloc(1 + 32 + 4 + subjectBytes.length + 4 + bodyBytes.length + 4 + webhookIdBytes.length + 1);
81
+ let offset = 0;
82
+ data.writeUInt8(InstructionType.SendThroughWebhook, offset);
83
+ offset += 1;
84
+ to.toBuffer().copy(data, offset);
85
+ offset += 32;
86
+ data.writeUInt32LE(subjectBytes.length, offset);
87
+ offset += 4;
88
+ subjectBytes.copy(data, offset);
89
+ offset += subjectBytes.length;
90
+ data.writeUInt32LE(bodyBytes.length, offset);
91
+ offset += 4;
92
+ bodyBytes.copy(data, offset);
93
+ offset += bodyBytes.length;
94
+ data.writeUInt32LE(webhookIdBytes.length, offset);
95
+ offset += 4;
96
+ webhookIdBytes.copy(data, offset);
97
+ offset += webhookIdBytes.length;
98
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
99
+ return data;
100
+ }
101
+ function encodeSendToEmail(emailHash, subject, body, payer, revenueShareToReceiver) {
102
+ const emailHashBytes = Buffer.from(emailHash, 'utf8');
103
+ const subjectBytes = Buffer.from(subject, 'utf8');
104
+ const bodyBytes = Buffer.from(body, 'utf8');
105
+ const data = Buffer.alloc(1 + 4 + emailHashBytes.length + 4 + subjectBytes.length + 4 + bodyBytes.length + 32 + 1);
106
+ let offset = 0;
107
+ data.writeUInt8(InstructionType.SendToEmail, offset);
108
+ offset += 1;
109
+ data.writeUInt32LE(emailHashBytes.length, offset);
110
+ offset += 4;
111
+ emailHashBytes.copy(data, offset);
112
+ offset += emailHashBytes.length;
113
+ data.writeUInt32LE(subjectBytes.length, offset);
114
+ offset += 4;
115
+ subjectBytes.copy(data, offset);
116
+ offset += subjectBytes.length;
117
+ data.writeUInt32LE(bodyBytes.length, offset);
118
+ offset += 4;
119
+ bodyBytes.copy(data, offset);
120
+ offset += bodyBytes.length;
121
+ payer.toBuffer().copy(data, offset);
122
+ offset += 32;
123
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
124
+ return data;
125
+ }
126
+ function encodeSendPreparedToEmail(emailHash, mailId, payer, revenueShareToReceiver) {
127
+ const emailHashBytes = Buffer.from(emailHash, 'utf8');
128
+ const mailIdBytes = Buffer.from(mailId, 'utf8');
129
+ const data = Buffer.alloc(1 + 4 + emailHashBytes.length + 4 + mailIdBytes.length + 32 + 1);
130
+ let offset = 0;
131
+ data.writeUInt8(InstructionType.SendPreparedToEmail, offset);
132
+ offset += 1;
133
+ data.writeUInt32LE(emailHashBytes.length, offset);
134
+ offset += 4;
135
+ emailHashBytes.copy(data, offset);
136
+ offset += emailHashBytes.length;
137
+ data.writeUInt32LE(mailIdBytes.length, offset);
138
+ offset += 4;
139
+ mailIdBytes.copy(data, offset);
140
+ offset += mailIdBytes.length;
141
+ payer.toBuffer().copy(data, offset);
142
+ offset += 32;
143
+ data.writeUInt8(revenueShareToReceiver ? 1 : 0, offset);
144
+ return data;
145
+ }
146
+ function encodeSetFees(sendFee, delegationFee) {
147
+ const data = Buffer.alloc(1 + 8 + 8);
148
+ data.writeUInt8(InstructionType.SetFees, 0);
149
+ data.writeBigUInt64LE(sendFee, 1);
150
+ data.writeBigUInt64LE(delegationFee, 9);
151
+ return data;
152
+ }
153
+ function encodeDelegateTo(delegate) {
154
+ const data = Buffer.alloc(1 + 1 + (delegate ? 32 : 0));
155
+ data.writeUInt8(InstructionType.DelegateTo, 0);
156
+ data.writeUInt8(delegate ? 1 : 0, 1);
157
+ if (delegate) {
158
+ delegate.toBuffer().copy(data, 2);
159
+ }
160
+ return data;
161
+ }
162
+ function encodeRejectDelegation(delegatingAddress) {
163
+ const data = Buffer.alloc(1 + 32);
164
+ data.writeUInt8(InstructionType.RejectDelegation, 0);
165
+ delegatingAddress.toBuffer().copy(data, 1);
166
+ return data;
167
+ }
168
+ function encodeSetCustomFeePercentage(account, percentage) {
169
+ if (percentage < 0 || percentage > 100) {
170
+ throw new Error('Percentage must be between 0 and 100');
171
+ }
172
+ const data = Buffer.alloc(1 + 32 + 1);
173
+ data.writeUInt8(InstructionType.SetCustomFeePercentage, 0);
174
+ account.toBuffer().copy(data, 1);
175
+ data.writeUInt8(percentage, 33);
176
+ return data;
177
+ }
178
+ function encodeClearCustomFeePercentage(account) {
179
+ const data = Buffer.alloc(1 + 32);
180
+ data.writeUInt8(InstructionType.ClearCustomFeePercentage, 0);
181
+ account.toBuffer().copy(data, 1);
182
+ return data;
183
+ }
184
+ function encodeClaimExpiredShares(recipient) {
185
+ const data = Buffer.alloc(1 + 32);
186
+ data.writeUInt8(InstructionType.ClaimExpiredShares, 0);
187
+ recipient.toBuffer().copy(data, 1);
188
+ return data;
189
+ }
190
+ function encodeDistributeClaimableFunds(recipients) {
191
+ const recipientCount = recipients.length;
192
+ const data = Buffer.alloc(1 + 4 + recipientCount * 32);
193
+ let offset = 0;
194
+ data.writeUInt8(InstructionType.DistributeClaimableFunds, offset);
195
+ offset += 1;
196
+ data.writeUInt32LE(recipientCount, offset);
197
+ offset += 4;
198
+ for (const recipient of recipients) {
199
+ recipient.toBuffer().copy(data, offset);
200
+ offset += 32;
201
+ }
202
+ return data;
203
+ }
204
+ /**
205
+ * Stateless Solana Mailer client.
206
+ * All methods take wallet and chainInfo as parameters.
207
+ * No state is stored in the instance.
208
+ */
209
+ class SolanaMailerClient {
210
+ constructor() {
211
+ this.defaultComputeUnitMultiplier = 1.2; // 20% buffer by default
212
+ // Default compute unit limits for common operations
213
+ this.defaultComputeUnits = {
214
+ send: 200000,
215
+ sendPrepared: 150000,
216
+ sendToEmail: 250000,
217
+ claimRevenue: 100000,
218
+ claimOwnerShare: 100000,
219
+ delegateTo: 80000,
220
+ setFees: 60000,
221
+ pause: 50000,
222
+ unpause: 50000,
223
+ initialize: 100000,
224
+ distributeClaimableFunds: 150000,
225
+ };
226
+ // Priority fee recommendations based on network congestion
227
+ this.priorityFeeRecommendations = {
228
+ low: 1000, // 1,000 microLamports - for low priority transactions
229
+ normal: 10000, // 10,000 microLamports - for normal priority
230
+ high: 50000, // 50,000 microLamports - for high priority
231
+ urgent: 100000, // 100,000 microLamports - for urgent transactions
232
+ };
233
+ }
234
+ /**
235
+ * Create or get connection from wallet/chainInfo
236
+ */
237
+ async getOrCreateConnection(chainInfo, connection) {
238
+ if (connection) {
239
+ return connection;
240
+ }
241
+ // Build RPC URL from ChainInfo
242
+ let rpcUrl;
243
+ if (chainInfo.alchemyNetwork) {
244
+ rpcUrl = `https://${chainInfo.alchemyNetwork}.g.alchemy.com/v2/demo`;
245
+ }
246
+ else if (chainInfo.ankrNetwork) {
247
+ rpcUrl = `https://rpc.ankr.com/${chainInfo.ankrNetwork}`;
248
+ }
249
+ else {
250
+ // Default Solana endpoints
251
+ rpcUrl = chainInfo.isDev
252
+ ? 'https://api.devnet.solana.com'
253
+ : 'https://api.mainnet-beta.solana.com';
254
+ }
255
+ return new web3_js_1.Connection(rpcUrl, 'confirmed');
256
+ }
257
+ /**
258
+ * Get program and state PDAs from chainInfo
259
+ */
260
+ getProgramAddresses(chainInfo) {
261
+ if (!chainInfo.mailerAddress) {
262
+ throw new Error(`No mailer program deployed on ${chainInfo.name}`);
263
+ }
264
+ const programId = new web3_js_1.PublicKey(chainInfo.mailerAddress);
265
+ const [mailerPda, bump] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('mailer')], programId);
266
+ return {
267
+ programId,
268
+ mailerStatePda: mailerPda,
269
+ mailerBump: bump,
270
+ };
271
+ }
272
+ /**
273
+ * Optimize compute units for a transaction
274
+ */
275
+ async optimizeComputeUnits(transaction, wallet, connection, options, defaultComputeUnits) {
276
+ // Skip if explicitly disabled
277
+ if (options?.skipComputeUnits) {
278
+ return { transaction };
279
+ }
280
+ let simulatedUnits;
281
+ let computeUnitLimit = options?.computeUnitLimit;
282
+ // Auto-optimize by simulating transaction
283
+ if (options?.autoOptimize && !computeUnitLimit) {
284
+ let retryCount = 0;
285
+ const maxRetries = 2;
286
+ while (retryCount <= maxRetries) {
287
+ try {
288
+ // Set a high limit for simulation
289
+ const simTransaction = new web3_js_1.Transaction().add(...transaction.instructions);
290
+ simTransaction.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
291
+ units: 1400000, // Max for simulation
292
+ }));
293
+ simTransaction.recentBlockhash = (await connection.getLatestBlockhash()).blockhash;
294
+ simTransaction.feePayer = wallet.publicKey;
295
+ const simulation = await connection.simulateTransaction(simTransaction);
296
+ if (simulation.value.err === null && simulation.value.unitsConsumed) {
297
+ simulatedUnits = simulation.value.unitsConsumed;
298
+ const multiplier = options.computeUnitMultiplier ?? this.defaultComputeUnitMultiplier;
299
+ computeUnitLimit = Math.min(Math.ceil(simulatedUnits * multiplier), 1400000);
300
+ break; // Success
301
+ }
302
+ else if (simulation.value.err) {
303
+ throw new Error(`Simulation failed: ${JSON.stringify(simulation.value.err)}`);
304
+ }
305
+ }
306
+ catch (error) {
307
+ retryCount++;
308
+ if (retryCount > maxRetries) {
309
+ console.warn(`Failed to auto-optimize compute units after ${maxRetries} retries:`, error);
310
+ // Use default if provided
311
+ if (defaultComputeUnits) {
312
+ computeUnitLimit = defaultComputeUnits;
313
+ }
314
+ }
315
+ else {
316
+ // Wait before retry
317
+ await new Promise(resolve => setTimeout(resolve, 1000 * retryCount));
318
+ }
319
+ }
320
+ }
321
+ }
322
+ // Use default compute units if no limit is set yet
323
+ if (!computeUnitLimit && defaultComputeUnits) {
324
+ computeUnitLimit = defaultComputeUnits;
325
+ }
326
+ // Apply compute budget instructions
327
+ const optimizedTx = new web3_js_1.Transaction();
328
+ // Add compute unit limit if specified
329
+ if (computeUnitLimit) {
330
+ optimizedTx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitLimit({
331
+ units: computeUnitLimit,
332
+ }));
333
+ }
334
+ // Add priority fee if specified (or use recommended normal priority)
335
+ const priorityFee = options?.computeUnitPrice ??
336
+ (options?.autoOptimize ? this.priorityFeeRecommendations.normal : undefined);
337
+ if (priorityFee) {
338
+ optimizedTx.add(web3_js_1.ComputeBudgetProgram.setComputeUnitPrice({
339
+ microLamports: priorityFee,
340
+ }));
341
+ }
342
+ // Add original instructions
343
+ optimizedTx.add(...transaction.instructions);
344
+ return {
345
+ transaction: optimizedTx,
346
+ simulatedUnits,
347
+ };
348
+ }
349
+ /**
350
+ * Send and confirm transaction
351
+ */
352
+ async sendTransaction(transaction, wallet, connection, options, computeOptions, defaultComputeUnits) {
353
+ // Optimize compute units
354
+ const { transaction: optimizedTx, simulatedUnits } = await this.optimizeComputeUnits(transaction, wallet, connection, computeOptions, defaultComputeUnits);
355
+ // Get latest blockhash
356
+ const { blockhash } = await connection.getLatestBlockhash();
357
+ optimizedTx.recentBlockhash = blockhash;
358
+ optimizedTx.feePayer = wallet.publicKey;
359
+ // Sign transaction
360
+ const signed = await wallet.signTransaction(optimizedTx);
361
+ // Send and confirm
362
+ const signature = await connection.sendRawTransaction(signed.serialize(), {
363
+ skipPreflight: options?.skipPreflight ?? false,
364
+ preflightCommitment: options?.preflightCommitment ?? 'confirmed',
365
+ });
366
+ await connection.confirmTransaction(signature, options?.commitment ?? 'confirmed');
367
+ return {
368
+ signature,
369
+ transactionHash: signature,
370
+ simulatedUnits,
371
+ computeUnitLimit: computeOptions?.computeUnitLimit,
372
+ computeUnitPrice: computeOptions?.computeUnitPrice,
373
+ };
374
+ }
375
+ /**
376
+ * Initialize the mailer program (owner only)
377
+ */
378
+ async initialize(connectedWallet, chainInfo, computeOptions) {
379
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
380
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
381
+ if (!chainInfo.usdcAddress) {
382
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
383
+ }
384
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
385
+ const instruction = new web3_js_1.TransactionInstruction({
386
+ programId,
387
+ keys: [
388
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
389
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
390
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
391
+ ],
392
+ data: encodeInitialize(usdcMint),
393
+ });
394
+ const transaction = new web3_js_1.Transaction().add(instruction);
395
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
396
+ }
397
+ /**
398
+ * Send a message with optional revenue sharing
399
+ */
400
+ async send(connectedWallet, chainInfo, to, subject, body, revenueShareToReceiver, computeOptions) {
401
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
402
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
403
+ if (!chainInfo.usdcAddress) {
404
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
405
+ }
406
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
407
+ const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
408
+ // Get token accounts
409
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
410
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
411
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
412
+ const keys = [
413
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
414
+ { pubkey: toPubkey, isSigner: false, isWritable: false },
415
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
416
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
417
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
418
+ { pubkey: recipientInfo, isSigner: false, isWritable: true },
419
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
420
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
421
+ ];
422
+ const instruction = new web3_js_1.TransactionInstruction({
423
+ programId,
424
+ keys,
425
+ data: encodeSend(toPubkey, subject, body, revenueShareToReceiver),
426
+ });
427
+ const transaction = new web3_js_1.Transaction().add(instruction);
428
+ // Check if mailer token account exists, create if not
429
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
430
+ if (!accountInfo) {
431
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
432
+ }
433
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
434
+ }
435
+ /**
436
+ * Send a prepared message
437
+ */
438
+ async sendPrepared(connectedWallet, chainInfo, to, mailId, revenueShareToReceiver, computeOptions) {
439
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
440
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
441
+ if (!chainInfo.usdcAddress) {
442
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
443
+ }
444
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
445
+ const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
446
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
447
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
448
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
449
+ const keys = [
450
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
451
+ { pubkey: toPubkey, isSigner: false, isWritable: false },
452
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
453
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
454
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
455
+ { pubkey: recipientInfo, isSigner: false, isWritable: true },
456
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
457
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
458
+ ];
459
+ const instruction = new web3_js_1.TransactionInstruction({
460
+ programId,
461
+ keys,
462
+ data: encodeSendPrepared(toPubkey, mailId, revenueShareToReceiver),
463
+ });
464
+ const transaction = new web3_js_1.Transaction().add(instruction);
465
+ // Check if mailer token account exists, create if not
466
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
467
+ if (!accountInfo) {
468
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
469
+ }
470
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
471
+ }
472
+ /**
473
+ * Send through webhook
474
+ */
475
+ async sendThroughWebhook(connectedWallet, chainInfo, to, subject, body, webhookId, revenueShareToReceiver, computeOptions) {
476
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
477
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
478
+ if (!chainInfo.usdcAddress) {
479
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
480
+ }
481
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
482
+ const toPubkey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
483
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
484
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
485
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), toPubkey.toBuffer()], programId);
486
+ const keys = [
487
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
488
+ { pubkey: toPubkey, isSigner: false, isWritable: false },
489
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
490
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
491
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
492
+ { pubkey: recipientInfo, isSigner: false, isWritable: true },
493
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
494
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
495
+ ];
496
+ const instruction = new web3_js_1.TransactionInstruction({
497
+ programId,
498
+ keys,
499
+ data: encodeSendThroughWebhook(toPubkey, subject, body, webhookId, revenueShareToReceiver),
500
+ });
501
+ const transaction = new web3_js_1.Transaction().add(instruction);
502
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
503
+ if (!accountInfo) {
504
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
505
+ }
506
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
507
+ }
508
+ /**
509
+ * Send to email address
510
+ */
511
+ async sendToEmail(emailHash, subject, body, payer, revenueShareToReceiver, connectedWallet, chainInfo, computeOptions) {
512
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
513
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
514
+ if (!chainInfo.usdcAddress) {
515
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
516
+ }
517
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
518
+ const payerPubkey = typeof payer === 'string' ? new web3_js_1.PublicKey(payer) : payer;
519
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
520
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
521
+ const keys = [
522
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
523
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
524
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
525
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
526
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
527
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
528
+ ];
529
+ const instruction = new web3_js_1.TransactionInstruction({
530
+ programId,
531
+ keys,
532
+ data: encodeSendToEmail(emailHash, subject, body, payerPubkey, revenueShareToReceiver),
533
+ });
534
+ const transaction = new web3_js_1.Transaction().add(instruction);
535
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
536
+ if (!accountInfo) {
537
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
538
+ }
539
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
540
+ }
541
+ /**
542
+ * Send prepared to email address
543
+ */
544
+ async sendPreparedToEmail(emailHash, mailId, payer, revenueShareToReceiver, connectedWallet, chainInfo, computeOptions) {
545
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
546
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
547
+ if (!chainInfo.usdcAddress) {
548
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
549
+ }
550
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
551
+ const payerPubkey = typeof payer === 'string' ? new web3_js_1.PublicKey(payer) : payer;
552
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
553
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
554
+ const keys = [
555
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
556
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
557
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
558
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
559
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
560
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
561
+ ];
562
+ const instruction = new web3_js_1.TransactionInstruction({
563
+ programId,
564
+ keys,
565
+ data: encodeSendPreparedToEmail(emailHash, mailId, payerPubkey, revenueShareToReceiver),
566
+ });
567
+ const transaction = new web3_js_1.Transaction().add(instruction);
568
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
569
+ if (!accountInfo) {
570
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
571
+ }
572
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
573
+ }
574
+ /**
575
+ * Claim recipient share
576
+ */
577
+ async claimRecipientShare(connectedWallet, chainInfo, computeOptions) {
578
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
579
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
580
+ if (!chainInfo.usdcAddress) {
581
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
582
+ }
583
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
584
+ const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
585
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
586
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), connectedWallet.wallet.publicKey.toBuffer()], programId);
587
+ const keys = [
588
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
589
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
590
+ { pubkey: recipientTokenAccount, isSigner: false, isWritable: true },
591
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
592
+ { pubkey: recipientInfo, isSigner: false, isWritable: true },
593
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
594
+ ];
595
+ const instruction = new web3_js_1.TransactionInstruction({
596
+ programId,
597
+ keys,
598
+ data: Buffer.from([InstructionType.ClaimRecipientShare]),
599
+ });
600
+ const transaction = new web3_js_1.Transaction().add(instruction);
601
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
602
+ }
603
+ /**
604
+ * Claim owner share (owner only)
605
+ */
606
+ async claimOwnerShare(connectedWallet, chainInfo, computeOptions) {
607
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
608
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
609
+ if (!chainInfo.usdcAddress) {
610
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
611
+ }
612
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
613
+ const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
614
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
615
+ const keys = [
616
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
617
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
618
+ { pubkey: ownerTokenAccount, isSigner: false, isWritable: true },
619
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
620
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
621
+ ];
622
+ const instruction = new web3_js_1.TransactionInstruction({
623
+ programId,
624
+ keys,
625
+ data: Buffer.from([InstructionType.ClaimOwnerShare]),
626
+ });
627
+ const transaction = new web3_js_1.Transaction().add(instruction);
628
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
629
+ }
630
+ /**
631
+ * Claim expired shares (owner only)
632
+ */
633
+ async claimExpiredShares(connectedWallet, chainInfo, recipient, computeOptions) {
634
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
635
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
636
+ const recipientPubkey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
637
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipientPubkey.toBuffer()], programId);
638
+ const keys = [
639
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
640
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
641
+ { pubkey: recipientInfo, isSigner: false, isWritable: true },
642
+ ];
643
+ const instruction = new web3_js_1.TransactionInstruction({
644
+ programId,
645
+ keys,
646
+ data: encodeClaimExpiredShares(recipientPubkey),
647
+ });
648
+ const transaction = new web3_js_1.Transaction().add(instruction);
649
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
650
+ }
651
+ /**
652
+ * Delegate to another address
653
+ */
654
+ async delegateTo(connectedWallet, chainInfo, delegate, computeOptions) {
655
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
656
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
657
+ if (!chainInfo.usdcAddress) {
658
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
659
+ }
660
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
661
+ const delegatePubkey = delegate
662
+ ? (typeof delegate === 'string' ? new web3_js_1.PublicKey(delegate) : delegate)
663
+ : null;
664
+ const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, connectedWallet.wallet.publicKey, false, spl_token_1.TOKEN_PROGRAM_ID);
665
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
666
+ const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), connectedWallet.wallet.publicKey.toBuffer()], programId);
667
+ const keys = [
668
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
669
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
670
+ { pubkey: senderTokenAccount, isSigner: false, isWritable: true },
671
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
672
+ { pubkey: delegatorInfo, isSigner: false, isWritable: true },
673
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
674
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
675
+ ];
676
+ const instruction = new web3_js_1.TransactionInstruction({
677
+ programId,
678
+ keys,
679
+ data: encodeDelegateTo(delegatePubkey),
680
+ });
681
+ const transaction = new web3_js_1.Transaction().add(instruction);
682
+ const accountInfo = await connection.getAccountInfo(mailerTokenAccount);
683
+ if (!accountInfo) {
684
+ transaction.add((0, spl_token_1.createAssociatedTokenAccountInstruction)(connectedWallet.wallet.publicKey, mailerTokenAccount, mailerStatePda, usdcMint));
685
+ }
686
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
687
+ }
688
+ /**
689
+ * Reject delegation
690
+ */
691
+ async rejectDelegation(connectedWallet, chainInfo, delegatingAddress, computeOptions) {
692
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
693
+ const { programId } = this.getProgramAddresses(chainInfo);
694
+ const delegatorPubkey = typeof delegatingAddress === 'string' ? new web3_js_1.PublicKey(delegatingAddress) : delegatingAddress;
695
+ const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), delegatorPubkey.toBuffer()], programId);
696
+ const keys = [
697
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
698
+ { pubkey: delegatorInfo, isSigner: false, isWritable: true },
699
+ ];
700
+ const instruction = new web3_js_1.TransactionInstruction({
701
+ programId,
702
+ keys,
703
+ data: encodeRejectDelegation(delegatorPubkey),
704
+ });
705
+ const transaction = new web3_js_1.Transaction().add(instruction);
706
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
707
+ }
708
+ /**
709
+ * Set fees (owner only)
710
+ */
711
+ async setFees(connectedWallet, chainInfo, sendFee, delegationFee, computeOptions) {
712
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
713
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
714
+ const keys = [
715
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
716
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
717
+ ];
718
+ const instruction = new web3_js_1.TransactionInstruction({
719
+ programId,
720
+ keys,
721
+ data: encodeSetFees(BigInt(sendFee), BigInt(delegationFee)),
722
+ });
723
+ const transaction = new web3_js_1.Transaction().add(instruction);
724
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
725
+ }
726
+ /**
727
+ * Set custom fee percentage
728
+ */
729
+ async setCustomFeePercentage(account, percentage, connectedWallet, chainInfo, computeOptions) {
730
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
731
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
732
+ const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
733
+ const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
734
+ const keys = [
735
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: true },
736
+ { pubkey: mailerStatePda, isSigner: false, isWritable: false },
737
+ { pubkey: customFeeInfo, isSigner: false, isWritable: true },
738
+ { pubkey: web3_js_1.SystemProgram.programId, isSigner: false, isWritable: false },
739
+ ];
740
+ const instruction = new web3_js_1.TransactionInstruction({
741
+ programId,
742
+ keys,
743
+ data: encodeSetCustomFeePercentage(accountPubkey, percentage),
744
+ });
745
+ const transaction = new web3_js_1.Transaction().add(instruction);
746
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
747
+ }
748
+ /**
749
+ * Clear custom fee percentage
750
+ */
751
+ async clearCustomFeePercentage(account, connectedWallet, chainInfo, computeOptions) {
752
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
753
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
754
+ const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
755
+ const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
756
+ const keys = [
757
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
758
+ { pubkey: mailerStatePda, isSigner: false, isWritable: false },
759
+ { pubkey: customFeeInfo, isSigner: false, isWritable: true },
760
+ ];
761
+ const instruction = new web3_js_1.TransactionInstruction({
762
+ programId,
763
+ keys,
764
+ data: encodeClearCustomFeePercentage(accountPubkey),
765
+ });
766
+ const transaction = new web3_js_1.Transaction().add(instruction);
767
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
768
+ }
769
+ /**
770
+ * Pause the program (owner only)
771
+ */
772
+ async pause(connectedWallet, chainInfo, computeOptions) {
773
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
774
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
775
+ const keys = [
776
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
777
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
778
+ ];
779
+ const instruction = new web3_js_1.TransactionInstruction({
780
+ programId,
781
+ keys,
782
+ data: Buffer.from([InstructionType.Pause]),
783
+ });
784
+ const transaction = new web3_js_1.Transaction().add(instruction);
785
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
786
+ }
787
+ /**
788
+ * Unpause the program (owner only)
789
+ */
790
+ async unpause(connectedWallet, chainInfo, computeOptions) {
791
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
792
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
793
+ const keys = [
794
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
795
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
796
+ ];
797
+ const instruction = new web3_js_1.TransactionInstruction({
798
+ programId,
799
+ keys,
800
+ data: Buffer.from([InstructionType.Unpause]),
801
+ });
802
+ const transaction = new web3_js_1.Transaction().add(instruction);
803
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
804
+ }
805
+ /**
806
+ * Emergency unpause (owner only)
807
+ */
808
+ async emergencyUnpause(connectedWallet, chainInfo, computeOptions) {
809
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
810
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
811
+ const keys = [
812
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
813
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
814
+ ];
815
+ const instruction = new web3_js_1.TransactionInstruction({
816
+ programId,
817
+ keys,
818
+ data: Buffer.from([InstructionType.EmergencyUnpause]),
819
+ });
820
+ const transaction = new web3_js_1.Transaction().add(instruction);
821
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
822
+ }
823
+ /**
824
+ * Distribute claimable funds when paused
825
+ */
826
+ async distributeClaimableFunds(connectedWallet, chainInfo, recipients, computeOptions) {
827
+ const connection = await this.getOrCreateConnection(chainInfo, connectedWallet.connection);
828
+ const { programId, mailerStatePda } = this.getProgramAddresses(chainInfo);
829
+ if (!chainInfo.usdcAddress) {
830
+ throw new Error(`No USDC mint configured for ${chainInfo.name}`);
831
+ }
832
+ const usdcMint = new web3_js_1.PublicKey(chainInfo.usdcAddress);
833
+ const recipientPubkeys = recipients.map(r => typeof r === 'string' ? new web3_js_1.PublicKey(r) : r);
834
+ const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, mailerStatePda, true, spl_token_1.TOKEN_PROGRAM_ID);
835
+ // Build keys array
836
+ const keys = [
837
+ { pubkey: connectedWallet.wallet.publicKey, isSigner: true, isWritable: false },
838
+ { pubkey: mailerStatePda, isSigner: false, isWritable: true },
839
+ { pubkey: mailerTokenAccount, isSigner: false, isWritable: true },
840
+ { pubkey: spl_token_1.TOKEN_PROGRAM_ID, isSigner: false, isWritable: false },
841
+ ];
842
+ // Add recipient info and token accounts
843
+ for (const recipient of recipientPubkeys) {
844
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipient.toBuffer()], programId);
845
+ const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(usdcMint, recipient, false, spl_token_1.TOKEN_PROGRAM_ID);
846
+ keys.push({ pubkey: recipientInfo, isSigner: false, isWritable: true });
847
+ keys.push({ pubkey: recipientTokenAccount, isSigner: false, isWritable: true });
848
+ }
849
+ const instruction = new web3_js_1.TransactionInstruction({
850
+ programId,
851
+ keys,
852
+ data: encodeDistributeClaimableFunds(recipientPubkeys),
853
+ });
854
+ const transaction = new web3_js_1.Transaction().add(instruction);
855
+ return await this.sendTransaction(transaction, connectedWallet.wallet, connection, undefined, computeOptions);
856
+ }
857
+ // ============= Read Methods =============
858
+ /**
859
+ * Get fees configuration
860
+ */
861
+ async getFees(chainInfo, connection) {
862
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
863
+ const { mailerStatePda } = this.getProgramAddresses(chainInfo);
864
+ const accountInfo = await conn.getAccountInfo(mailerStatePda);
865
+ if (!accountInfo || !accountInfo.data) {
866
+ throw new Error('Mailer not initialized');
867
+ }
868
+ // Parse the state data
869
+ const data = accountInfo.data;
870
+ const sendFee = data.readBigUInt64LE(41); // After discriminator(8) + owner(32) + paused(1)
871
+ const delegationFee = data.readBigUInt64LE(49);
872
+ return {
873
+ sendFee,
874
+ delegationFee,
875
+ };
876
+ }
877
+ /**
878
+ * Get send fee only
879
+ */
880
+ async getSendFee(chainInfo, connection) {
881
+ const fees = await this.getFees(chainInfo, connection);
882
+ return fees.sendFee;
883
+ }
884
+ /**
885
+ * Get delegation fee only
886
+ */
887
+ async getDelegationFee(chainInfo, connection) {
888
+ const fees = await this.getFees(chainInfo, connection);
889
+ return fees.delegationFee;
890
+ }
891
+ /**
892
+ * Get recipient claimable info
893
+ */
894
+ async getRecipientClaimable(recipient, chainInfo, connection) {
895
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
896
+ const { programId } = this.getProgramAddresses(chainInfo);
897
+ const recipientPubkey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
898
+ const [recipientInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('recipient_info'), recipientPubkey.toBuffer()], programId);
899
+ const accountInfo = await conn.getAccountInfo(recipientInfo);
900
+ if (!accountInfo || !accountInfo.data) {
901
+ return null;
902
+ }
903
+ // Parse the recipient info data
904
+ const data = accountInfo.data;
905
+ const amount = data.readBigUInt64LE(8); // After discriminator
906
+ const expiresAt = data.readBigInt64LE(16);
907
+ // Check if expired
908
+ const now = Math.floor(Date.now() / 1000);
909
+ const isExpired = Number(expiresAt) > 0 && Number(expiresAt) < now;
910
+ return {
911
+ amount: Number(amount),
912
+ timestamp: Number(expiresAt), // Using expiresAt as timestamp
913
+ expiresAt: Number(expiresAt),
914
+ recipient: recipient instanceof web3_js_1.PublicKey ? recipient.toBase58() : recipient,
915
+ isExpired,
916
+ };
917
+ }
918
+ /**
919
+ * Get owner claimable amount
920
+ */
921
+ async getOwnerClaimable(chainInfo, connection) {
922
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
923
+ const { mailerStatePda } = this.getProgramAddresses(chainInfo);
924
+ const accountInfo = await conn.getAccountInfo(mailerStatePda);
925
+ if (!accountInfo || !accountInfo.data) {
926
+ throw new Error('Mailer not initialized');
927
+ }
928
+ // Parse the state data
929
+ const data = accountInfo.data;
930
+ const ownerClaimable = data.readBigUInt64LE(57); // After discriminator(8) + owner(32) + paused(1) + sendFee(8) + delegationFee(8)
931
+ return Number(ownerClaimable);
932
+ }
933
+ /**
934
+ * Get delegation for an address
935
+ */
936
+ async getDelegation(address, chainInfo, connection) {
937
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
938
+ const { programId } = this.getProgramAddresses(chainInfo);
939
+ const addressPubkey = typeof address === 'string' ? new web3_js_1.PublicKey(address) : address;
940
+ const [delegatorInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegator_info'), addressPubkey.toBuffer()], programId);
941
+ const accountInfo = await conn.getAccountInfo(delegatorInfo);
942
+ if (!accountInfo || !accountInfo.data) {
943
+ return null;
944
+ }
945
+ // Parse the delegatingAddress info data
946
+ const data = accountInfo.data;
947
+ const hasDelegate = data.readUInt8(8) === 1; // After discriminator
948
+ if (!hasDelegate) {
949
+ return null;
950
+ }
951
+ // Read delegate pubkey
952
+ const delegateBytes = data.slice(9, 41); // 32 bytes for pubkey
953
+ return new web3_js_1.PublicKey(delegateBytes);
954
+ }
955
+ /**
956
+ * Get custom fee percentage for an account
957
+ */
958
+ async getCustomFeePercentage(account, chainInfo, connection) {
959
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
960
+ const { programId } = this.getProgramAddresses(chainInfo);
961
+ const accountPubkey = typeof account === 'string' ? new web3_js_1.PublicKey(account) : account;
962
+ const [customFeeInfo] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('custom_fee'), accountPubkey.toBuffer()], programId);
963
+ const accountInfo = await conn.getAccountInfo(customFeeInfo);
964
+ if (!accountInfo || !accountInfo.data) {
965
+ return 100; // Default to 100% if no custom fee set
966
+ }
967
+ // Parse the custom fee data
968
+ const data = accountInfo.data;
969
+ const percentage = data.readUInt8(8); // After discriminator
970
+ return percentage;
971
+ }
972
+ /**
973
+ * Check if the program is paused
974
+ */
975
+ async isPaused(chainInfo, connection) {
976
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
977
+ const { mailerStatePda } = this.getProgramAddresses(chainInfo);
978
+ const accountInfo = await conn.getAccountInfo(mailerStatePda);
979
+ if (!accountInfo || !accountInfo.data) {
980
+ throw new Error('Mailer not initialized');
981
+ }
982
+ // Parse the state data
983
+ const data = accountInfo.data;
984
+ const paused = data.readUInt8(40); // After discriminator(8) + owner(32)
985
+ return paused === 1;
986
+ }
987
+ /**
988
+ * Get the contract owner
989
+ */
990
+ async getOwner(chainInfo, connection) {
991
+ const conn = await this.getOrCreateConnection(chainInfo, connection);
992
+ const { mailerStatePda } = this.getProgramAddresses(chainInfo);
993
+ const accountInfo = await conn.getAccountInfo(mailerStatePda);
994
+ if (!accountInfo || !accountInfo.data) {
995
+ throw new Error('Mailer not initialized');
996
+ }
997
+ // Parse the state data
998
+ const data = accountInfo.data;
999
+ const ownerBytes = data.slice(8, 40); // After discriminator(8)
1000
+ return new web3_js_1.PublicKey(ownerBytes);
1001
+ }
1002
+ }
1003
+ exports.SolanaMailerClient = SolanaMailerClient;
1004
+ //# sourceMappingURL=solana-mailer-client.js.map