@sudobility/contracts 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/artifacts/contracts/Mailer.sol/Mailer.d.ts +120 -2
- package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
- package/artifacts/contracts/Mailer.sol/Mailer.json +120 -2
- package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +1 -1
- package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +1 -1
- package/dist/evm/src/evm/index.d.ts +1 -1
- package/dist/evm/src/evm/index.d.ts.map +1 -1
- package/dist/evm/src/evm/index.js +1 -1
- package/dist/evm/src/evm/index.js.map +1 -1
- package/dist/evm/src/evm/mailer-client.d.ts +936 -180
- package/dist/evm/src/evm/mailer-client.d.ts.map +1 -1
- package/dist/evm/src/evm/mailer-client.js +451 -249
- package/dist/evm/src/evm/mailer-client.js.map +1 -1
- package/dist/evm/typechain-types/Mailer.d.ts +81 -11
- package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
- package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +93 -1
- package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
- package/dist/evm/typechain-types/factories/Mailer__factory.js +119 -1
- package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -1
- package/dist/solana/solana/index.d.ts +1 -1
- package/dist/solana/solana/index.d.ts.map +1 -1
- package/dist/solana/solana/index.js +3 -1
- package/dist/solana/solana/index.js.map +1 -1
- package/dist/solana/solana/mailer-client.d.ts +86 -20
- package/dist/solana/solana/mailer-client.d.ts.map +1 -1
- package/dist/solana/solana/mailer-client.js +290 -58
- package/dist/solana/solana/mailer-client.js.map +1 -1
- package/dist/unified/src/evm/index.d.ts +1 -1
- package/dist/unified/src/evm/index.d.ts.map +1 -1
- package/dist/unified/src/evm/index.js +1 -1
- package/dist/unified/src/evm/index.js.map +1 -1
- package/dist/unified/src/evm/mailer-client.d.ts +936 -180
- package/dist/unified/src/evm/mailer-client.d.ts.map +1 -1
- package/dist/unified/src/evm/mailer-client.js +451 -249
- package/dist/unified/src/evm/mailer-client.js.map +1 -1
- package/dist/unified/src/solana/index.d.ts +1 -1
- package/dist/unified/src/solana/index.d.ts.map +1 -1
- package/dist/unified/src/solana/index.js +3 -1
- package/dist/unified/src/solana/index.js.map +1 -1
- package/dist/unified/src/solana/mailer-client.d.ts +86 -20
- package/dist/unified/src/solana/mailer-client.d.ts.map +1 -1
- package/dist/unified/src/solana/mailer-client.js +290 -58
- package/dist/unified/src/solana/mailer-client.js.map +1 -1
- package/dist/unified/src/unified/onchain-mailer-client.d.ts +25 -0
- package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
- package/dist/unified/src/unified/onchain-mailer-client.js +147 -4
- package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
- package/dist/unified/typechain-types/Mailer.d.ts +81 -11
- package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
- package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +93 -1
- package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
- package/dist/unified/typechain-types/factories/Mailer__factory.js +119 -1
- package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
- package/dist/unified-esm/src/evm/index.d.ts +1 -1
- package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
- package/dist/unified-esm/src/evm/index.js +1 -1
- package/dist/unified-esm/src/evm/index.js.map +1 -1
- package/dist/unified-esm/src/evm/mailer-client.d.ts +936 -180
- package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -1
- package/dist/unified-esm/src/evm/mailer-client.js +453 -251
- package/dist/unified-esm/src/evm/mailer-client.js.map +1 -1
- package/dist/unified-esm/src/solana/index.d.ts +1 -1
- package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
- package/dist/unified-esm/src/solana/index.js +1 -1
- package/dist/unified-esm/src/solana/index.js.map +1 -1
- package/dist/unified-esm/src/solana/mailer-client.d.ts +86 -20
- package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -1
- package/dist/unified-esm/src/solana/mailer-client.js +291 -59
- package/dist/unified-esm/src/solana/mailer-client.js.map +1 -1
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +25 -0
- package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
- package/dist/unified-esm/src/unified/onchain-mailer-client.js +147 -4
- package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
- package/dist/unified-esm/typechain-types/Mailer.d.ts +81 -11
- package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +93 -1
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +119 -1
- package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
- package/package.json +1 -1
- package/typechain-types/Mailer.ts +137 -9
- package/typechain-types/factories/Mailer__factory.ts +119 -1
|
@@ -35,6 +35,23 @@ function encodeSend(to, subject, body, revenueShareToReceiver, resolveSenderToNa
|
|
|
35
35
|
data.writeUInt8(resolveSenderToName ? 1 : 0, offset);
|
|
36
36
|
return data;
|
|
37
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
|
+
}
|
|
38
55
|
function encodeSendToEmail(toEmail, subject, body) {
|
|
39
56
|
const emailBytes = Buffer.from(toEmail, 'utf8');
|
|
40
57
|
const subjectBytes = Buffer.from(subject, 'utf8');
|
|
@@ -72,6 +89,23 @@ function encodeSendPreparedToEmail(toEmail, mailId) {
|
|
|
72
89
|
mailIdBytes.copy(data, offset);
|
|
73
90
|
return data;
|
|
74
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
|
+
}
|
|
75
109
|
function encodeSimpleInstruction(instructionType) {
|
|
76
110
|
const data = Buffer.alloc(1);
|
|
77
111
|
data.writeUInt8(instructionType, 0);
|
|
@@ -89,6 +123,19 @@ function encodeSetDelegationFee(newFee) {
|
|
|
89
123
|
data.writeBigUInt64LE(newFee, 1);
|
|
90
124
|
return data;
|
|
91
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
|
+
}
|
|
92
139
|
function encodeDelegateTo(delegate) {
|
|
93
140
|
if (!delegate) {
|
|
94
141
|
// Clear delegation - just send the instruction type and a null option
|
|
@@ -172,26 +219,40 @@ function parseDelegation(data) {
|
|
|
172
219
|
bump,
|
|
173
220
|
};
|
|
174
221
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
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
|
+
}
|
|
178
235
|
var InstructionType;
|
|
179
236
|
(function (InstructionType) {
|
|
180
237
|
InstructionType[InstructionType["Initialize"] = 0] = "Initialize";
|
|
181
238
|
InstructionType[InstructionType["Send"] = 1] = "Send";
|
|
182
|
-
InstructionType[InstructionType["
|
|
183
|
-
InstructionType[InstructionType["
|
|
184
|
-
InstructionType[InstructionType["
|
|
185
|
-
InstructionType[InstructionType["
|
|
186
|
-
InstructionType[InstructionType["
|
|
187
|
-
InstructionType[InstructionType["
|
|
188
|
-
InstructionType[InstructionType["
|
|
189
|
-
InstructionType[InstructionType["
|
|
190
|
-
InstructionType[InstructionType["
|
|
191
|
-
InstructionType[InstructionType["
|
|
192
|
-
InstructionType[InstructionType["
|
|
193
|
-
InstructionType[InstructionType["
|
|
194
|
-
InstructionType[InstructionType["
|
|
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";
|
|
195
256
|
})(InstructionType || (InstructionType = {}));
|
|
196
257
|
/**
|
|
197
258
|
* @class MailerClient
|
|
@@ -229,6 +290,7 @@ var InstructionType;
|
|
|
229
290
|
*/
|
|
230
291
|
class MailerClient {
|
|
231
292
|
constructor(connection, wallet, programId, usdcMint) {
|
|
293
|
+
this.defaultComputeUnitMultiplier = 1.2; // 20% buffer by default
|
|
232
294
|
this.connection = connection;
|
|
233
295
|
this.wallet = wallet;
|
|
234
296
|
this.programId = programId;
|
|
@@ -238,10 +300,69 @@ class MailerClient {
|
|
|
238
300
|
this.mailerStatePda = mailerPda;
|
|
239
301
|
this.mailerBump = bump;
|
|
240
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
|
+
}
|
|
241
361
|
/**
|
|
242
362
|
* Initialize the mailer program (owner only)
|
|
363
|
+
* @param computeOptions Compute unit optimization options
|
|
243
364
|
*/
|
|
244
|
-
async initialize() {
|
|
365
|
+
async initialize(computeOptions) {
|
|
245
366
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
246
367
|
keys: [
|
|
247
368
|
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
@@ -252,7 +373,7 @@ class MailerClient {
|
|
|
252
373
|
data: encodeInitialize(this.usdcMint),
|
|
253
374
|
});
|
|
254
375
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
255
|
-
return await this.sendTransaction(transaction);
|
|
376
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
256
377
|
}
|
|
257
378
|
/**
|
|
258
379
|
* Send a message with optional revenue sharing
|
|
@@ -261,9 +382,10 @@ class MailerClient {
|
|
|
261
382
|
* @param body Message body
|
|
262
383
|
* @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
|
|
263
384
|
* @param resolveSenderToName If true, resolve sender address to name via off-chain service
|
|
264
|
-
* @
|
|
385
|
+
* @param computeOptions Compute unit optimization options
|
|
386
|
+
* @returns Transaction result with signature and compute details
|
|
265
387
|
*/
|
|
266
|
-
async send(to, subject, body, revenueShareToReceiver = false, resolveSenderToName = false) {
|
|
388
|
+
async send(to, subject, body, revenueShareToReceiver = false, resolveSenderToName = false, computeOptions) {
|
|
267
389
|
const recipientKey = typeof to === 'string' ? new web3_js_1.PublicKey(to) : to;
|
|
268
390
|
// Derive recipient claim PDA
|
|
269
391
|
const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
@@ -293,13 +415,13 @@ class MailerClient {
|
|
|
293
415
|
});
|
|
294
416
|
instructions.push(sendInstruction);
|
|
295
417
|
const transaction = new web3_js_1.Transaction().add(...instructions);
|
|
296
|
-
return await this.sendTransaction(transaction);
|
|
418
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
297
419
|
}
|
|
298
420
|
/**
|
|
299
421
|
* Claim recipient share of revenue
|
|
300
|
-
* @returns Transaction
|
|
422
|
+
* @returns Transaction result
|
|
301
423
|
*/
|
|
302
|
-
async claimRecipientShare() {
|
|
424
|
+
async claimRecipientShare(computeOptions) {
|
|
303
425
|
const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), this.wallet.publicKey.toBuffer()], this.programId);
|
|
304
426
|
const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
|
|
305
427
|
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
|
|
@@ -316,13 +438,13 @@ class MailerClient {
|
|
|
316
438
|
data: encodeSimpleInstruction(InstructionType.ClaimRecipientShare),
|
|
317
439
|
});
|
|
318
440
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
319
|
-
return await this.sendTransaction(transaction);
|
|
441
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
320
442
|
}
|
|
321
443
|
/**
|
|
322
444
|
* Claim owner share of fees (owner only)
|
|
323
|
-
* @returns Transaction
|
|
445
|
+
* @returns Transaction result
|
|
324
446
|
*/
|
|
325
|
-
async claimOwnerShare() {
|
|
447
|
+
async claimOwnerShare(computeOptions) {
|
|
326
448
|
const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
|
|
327
449
|
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
|
|
328
450
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
@@ -337,7 +459,7 @@ class MailerClient {
|
|
|
337
459
|
data: encodeSimpleInstruction(InstructionType.ClaimOwnerShare),
|
|
338
460
|
});
|
|
339
461
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
340
|
-
return await this.sendTransaction(transaction);
|
|
462
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
341
463
|
}
|
|
342
464
|
/**
|
|
343
465
|
* Claim expired recipient shares and move them under owner control
|
|
@@ -345,7 +467,7 @@ class MailerClient {
|
|
|
345
467
|
* @param options Transaction confirm options
|
|
346
468
|
* @returns Transaction signature
|
|
347
469
|
*/
|
|
348
|
-
async claimExpiredShares(recipient, options) {
|
|
470
|
+
async claimExpiredShares(recipient, options, computeOptions) {
|
|
349
471
|
const recipientKey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
|
|
350
472
|
const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
351
473
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
@@ -358,14 +480,14 @@ class MailerClient {
|
|
|
358
480
|
data: encodeClaimExpiredShares(recipientKey),
|
|
359
481
|
});
|
|
360
482
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
361
|
-
return await this.sendTransaction(transaction, options);
|
|
483
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
362
484
|
}
|
|
363
485
|
/**
|
|
364
486
|
* Delegate message handling to another address
|
|
365
487
|
* @param delegate Address to delegate to, or null to clear delegation
|
|
366
488
|
* @returns Transaction signature
|
|
367
489
|
*/
|
|
368
|
-
async delegateTo(delegate) {
|
|
490
|
+
async delegateTo(delegate, computeOptions) {
|
|
369
491
|
const delegateKey = delegate
|
|
370
492
|
? typeof delegate === 'string'
|
|
371
493
|
? new web3_js_1.PublicKey(delegate)
|
|
@@ -388,14 +510,14 @@ class MailerClient {
|
|
|
388
510
|
data: encodeDelegateTo(delegateKey),
|
|
389
511
|
});
|
|
390
512
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
391
|
-
return await this.sendTransaction(transaction);
|
|
513
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
392
514
|
}
|
|
393
515
|
/**
|
|
394
516
|
* Reject a delegation made to you
|
|
395
517
|
* @param delegator Address that delegated to you
|
|
396
518
|
* @returns Transaction signature
|
|
397
519
|
*/
|
|
398
|
-
async rejectDelegation(delegator) {
|
|
520
|
+
async rejectDelegation(delegator, computeOptions) {
|
|
399
521
|
const delegatorKey = typeof delegator === 'string' ? new web3_js_1.PublicKey(delegator) : delegator;
|
|
400
522
|
const [delegationPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('delegation'), delegatorKey.toBuffer()], this.programId);
|
|
401
523
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
@@ -408,14 +530,15 @@ class MailerClient {
|
|
|
408
530
|
data: encodeSimpleInstruction(InstructionType.RejectDelegation),
|
|
409
531
|
});
|
|
410
532
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
411
|
-
return await this.sendTransaction(transaction);
|
|
533
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
412
534
|
}
|
|
413
535
|
/**
|
|
414
536
|
* Set the send fee (owner only)
|
|
415
537
|
* @param newFee New fee in USDC micro-units (6 decimals)
|
|
416
|
-
* @
|
|
538
|
+
* @param computeOptions Compute unit optimization options
|
|
539
|
+
* @returns Transaction result
|
|
417
540
|
*/
|
|
418
|
-
async setFee(newFee) {
|
|
541
|
+
async setFee(newFee, computeOptions) {
|
|
419
542
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
420
543
|
keys: [
|
|
421
544
|
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
@@ -425,14 +548,14 @@ class MailerClient {
|
|
|
425
548
|
data: encodeSetFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
|
|
426
549
|
});
|
|
427
550
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
428
|
-
return await this.sendTransaction(transaction);
|
|
551
|
+
return await this.sendTransaction(transaction, undefined, computeOptions);
|
|
429
552
|
}
|
|
430
553
|
/**
|
|
431
554
|
* Set the delegation fee (owner only)
|
|
432
555
|
* @param newFee New delegation fee in USDC micro-units (6 decimals)
|
|
433
556
|
* @returns Transaction signature
|
|
434
557
|
*/
|
|
435
|
-
async setDelegationFee(newFee) {
|
|
558
|
+
async setDelegationFee(newFee, computeOptions) {
|
|
436
559
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
437
560
|
keys: [
|
|
438
561
|
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
@@ -442,7 +565,59 @@ class MailerClient {
|
|
|
442
565
|
data: encodeSetDelegationFee(typeof newFee === 'bigint' ? newFee : BigInt(newFee)),
|
|
443
566
|
});
|
|
444
567
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
445
|
-
return await this.sendTransaction(transaction);
|
|
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;
|
|
446
621
|
}
|
|
447
622
|
/**
|
|
448
623
|
* Get current fees from the mailer state
|
|
@@ -530,7 +705,7 @@ class MailerClient {
|
|
|
530
705
|
* @param options Transaction confirm options
|
|
531
706
|
* @returns Transaction signature
|
|
532
707
|
*/
|
|
533
|
-
async sendToEmail(toEmail, subject, body, options) {
|
|
708
|
+
async sendToEmail(toEmail, subject, body, options, computeOptions) {
|
|
534
709
|
// Get associated token accounts
|
|
535
710
|
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
|
|
536
711
|
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
|
|
@@ -556,7 +731,7 @@ class MailerClient {
|
|
|
556
731
|
data: instructionData,
|
|
557
732
|
}));
|
|
558
733
|
const transaction = new web3_js_1.Transaction().add(...instructions);
|
|
559
|
-
return this.sendTransaction(transaction, options);
|
|
734
|
+
return this.sendTransaction(transaction, options, computeOptions);
|
|
560
735
|
}
|
|
561
736
|
/**
|
|
562
737
|
* Send a prepared message to an email address (no wallet known)
|
|
@@ -566,7 +741,7 @@ class MailerClient {
|
|
|
566
741
|
* @param options Transaction confirm options
|
|
567
742
|
* @returns Transaction signature
|
|
568
743
|
*/
|
|
569
|
-
async sendPreparedToEmail(toEmail, mailId, options) {
|
|
744
|
+
async sendPreparedToEmail(toEmail, mailId, options, computeOptions) {
|
|
570
745
|
// Get associated token accounts
|
|
571
746
|
const senderTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
|
|
572
747
|
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
|
|
@@ -592,7 +767,7 @@ class MailerClient {
|
|
|
592
767
|
data: instructionData,
|
|
593
768
|
}));
|
|
594
769
|
const transaction = new web3_js_1.Transaction().add(...instructions);
|
|
595
|
-
return this.sendTransaction(transaction, options);
|
|
770
|
+
return this.sendTransaction(transaction, options, computeOptions);
|
|
596
771
|
}
|
|
597
772
|
/**
|
|
598
773
|
* Send a prepared message using a mailId (to match EVM behavior)
|
|
@@ -602,16 +777,66 @@ class MailerClient {
|
|
|
602
777
|
* @param resolveSenderToName If true, resolve sender address to name
|
|
603
778
|
* @returns Transaction signature
|
|
604
779
|
*/
|
|
605
|
-
async sendPrepared(to, mailId, revenueShareToReceiver = false, resolveSenderToName = false) {
|
|
606
|
-
|
|
607
|
-
|
|
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);
|
|
608
833
|
}
|
|
609
834
|
/**
|
|
610
835
|
* Pause the contract and distribute owner claimable funds (owner only)
|
|
611
836
|
* @param options Transaction confirm options
|
|
612
837
|
* @returns Transaction signature
|
|
613
838
|
*/
|
|
614
|
-
async pause(options) {
|
|
839
|
+
async pause(options, computeOptions) {
|
|
615
840
|
const ownerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.wallet.publicKey);
|
|
616
841
|
const mailerTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, this.mailerStatePda, true);
|
|
617
842
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
@@ -626,14 +851,14 @@ class MailerClient {
|
|
|
626
851
|
data: encodeSimpleInstruction(InstructionType.Pause),
|
|
627
852
|
});
|
|
628
853
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
629
|
-
return await this.sendTransaction(transaction, options);
|
|
854
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
630
855
|
}
|
|
631
856
|
/**
|
|
632
857
|
* Unpause the contract (owner only)
|
|
633
858
|
* @param options Transaction confirm options
|
|
634
859
|
* @returns Transaction signature
|
|
635
860
|
*/
|
|
636
|
-
async unpause(options) {
|
|
861
|
+
async unpause(options, computeOptions) {
|
|
637
862
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
638
863
|
keys: [
|
|
639
864
|
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
@@ -643,14 +868,14 @@ class MailerClient {
|
|
|
643
868
|
data: encodeSimpleInstruction(InstructionType.Unpause),
|
|
644
869
|
});
|
|
645
870
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
646
|
-
return await this.sendTransaction(transaction, options);
|
|
871
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
647
872
|
}
|
|
648
873
|
/**
|
|
649
874
|
* Emergency unpause without fund distribution (owner only)
|
|
650
875
|
* @param options Transaction confirm options
|
|
651
876
|
* @returns Transaction signature
|
|
652
877
|
*/
|
|
653
|
-
async emergencyUnpause(options) {
|
|
878
|
+
async emergencyUnpause(options, computeOptions) {
|
|
654
879
|
const instruction = new web3_js_1.TransactionInstruction({
|
|
655
880
|
keys: [
|
|
656
881
|
{ pubkey: this.wallet.publicKey, isSigner: true, isWritable: false },
|
|
@@ -660,7 +885,7 @@ class MailerClient {
|
|
|
660
885
|
data: encodeSimpleInstruction(InstructionType.EmergencyUnpause),
|
|
661
886
|
});
|
|
662
887
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
663
|
-
return await this.sendTransaction(transaction, options);
|
|
888
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
664
889
|
}
|
|
665
890
|
/**
|
|
666
891
|
* Distribute claimable funds to a recipient when contract is paused
|
|
@@ -668,7 +893,7 @@ class MailerClient {
|
|
|
668
893
|
* @param options Transaction confirm options
|
|
669
894
|
* @returns Transaction signature
|
|
670
895
|
*/
|
|
671
|
-
async distributeClaimableFunds(recipient, options) {
|
|
896
|
+
async distributeClaimableFunds(recipient, options, computeOptions) {
|
|
672
897
|
const recipientKey = typeof recipient === 'string' ? new web3_js_1.PublicKey(recipient) : recipient;
|
|
673
898
|
const [recipientClaimPda] = web3_js_1.PublicKey.findProgramAddressSync([Buffer.from('claim'), recipientKey.toBuffer()], this.programId);
|
|
674
899
|
const recipientTokenAccount = (0, spl_token_1.getAssociatedTokenAddressSync)(this.usdcMint, recipientKey);
|
|
@@ -690,7 +915,7 @@ class MailerClient {
|
|
|
690
915
|
data,
|
|
691
916
|
});
|
|
692
917
|
const transaction = new web3_js_1.Transaction().add(instruction);
|
|
693
|
-
return await this.sendTransaction(transaction, options);
|
|
918
|
+
return await this.sendTransaction(transaction, options, computeOptions);
|
|
694
919
|
}
|
|
695
920
|
/**
|
|
696
921
|
* Get the current send fee
|
|
@@ -719,17 +944,24 @@ class MailerClient {
|
|
|
719
944
|
* @param options Confirm options
|
|
720
945
|
* @returns Transaction signature
|
|
721
946
|
*/
|
|
722
|
-
async sendTransaction(transaction, options) {
|
|
947
|
+
async sendTransaction(transaction, options, computeOptions) {
|
|
948
|
+
// Optimize compute units if requested
|
|
949
|
+
const { transaction: optimizedTx, simulatedUnits } = await this.optimizeComputeUnits(transaction, computeOptions);
|
|
723
950
|
// Get recent blockhash
|
|
724
951
|
const { blockhash } = await this.connection.getLatestBlockhash();
|
|
725
|
-
|
|
726
|
-
|
|
952
|
+
optimizedTx.recentBlockhash = blockhash;
|
|
953
|
+
optimizedTx.feePayer = this.wallet.publicKey;
|
|
727
954
|
// Sign transaction
|
|
728
|
-
const signedTx = await this.wallet.signTransaction(
|
|
955
|
+
const signedTx = await this.wallet.signTransaction(optimizedTx);
|
|
729
956
|
// Send and confirm
|
|
730
957
|
const signature = await this.connection.sendRawTransaction(signedTx.serialize());
|
|
731
958
|
await this.connection.confirmTransaction(signature, options?.commitment || 'confirmed');
|
|
732
|
-
return
|
|
959
|
+
return {
|
|
960
|
+
signature,
|
|
961
|
+
simulatedUnits,
|
|
962
|
+
computeUnitLimit: computeOptions?.computeUnitLimit,
|
|
963
|
+
computeUnitPrice: computeOptions?.computeUnitPrice,
|
|
964
|
+
};
|
|
733
965
|
}
|
|
734
966
|
/**
|
|
735
967
|
* Create a simple wallet from a keypair for testing
|