@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.
Files changed (82) hide show
  1. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +120 -2
  2. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
  3. package/artifacts/contracts/Mailer.sol/Mailer.json +120 -2
  4. package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +1 -1
  5. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +1 -1
  6. package/dist/evm/src/evm/index.d.ts +1 -1
  7. package/dist/evm/src/evm/index.d.ts.map +1 -1
  8. package/dist/evm/src/evm/index.js +1 -1
  9. package/dist/evm/src/evm/index.js.map +1 -1
  10. package/dist/evm/src/evm/mailer-client.d.ts +936 -180
  11. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -1
  12. package/dist/evm/src/evm/mailer-client.js +451 -249
  13. package/dist/evm/src/evm/mailer-client.js.map +1 -1
  14. package/dist/evm/typechain-types/Mailer.d.ts +81 -11
  15. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
  16. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +93 -1
  17. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  18. package/dist/evm/typechain-types/factories/Mailer__factory.js +119 -1
  19. package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -1
  20. package/dist/solana/solana/index.d.ts +1 -1
  21. package/dist/solana/solana/index.d.ts.map +1 -1
  22. package/dist/solana/solana/index.js +3 -1
  23. package/dist/solana/solana/index.js.map +1 -1
  24. package/dist/solana/solana/mailer-client.d.ts +86 -20
  25. package/dist/solana/solana/mailer-client.d.ts.map +1 -1
  26. package/dist/solana/solana/mailer-client.js +290 -58
  27. package/dist/solana/solana/mailer-client.js.map +1 -1
  28. package/dist/unified/src/evm/index.d.ts +1 -1
  29. package/dist/unified/src/evm/index.d.ts.map +1 -1
  30. package/dist/unified/src/evm/index.js +1 -1
  31. package/dist/unified/src/evm/index.js.map +1 -1
  32. package/dist/unified/src/evm/mailer-client.d.ts +936 -180
  33. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -1
  34. package/dist/unified/src/evm/mailer-client.js +451 -249
  35. package/dist/unified/src/evm/mailer-client.js.map +1 -1
  36. package/dist/unified/src/solana/index.d.ts +1 -1
  37. package/dist/unified/src/solana/index.d.ts.map +1 -1
  38. package/dist/unified/src/solana/index.js +3 -1
  39. package/dist/unified/src/solana/index.js.map +1 -1
  40. package/dist/unified/src/solana/mailer-client.d.ts +86 -20
  41. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -1
  42. package/dist/unified/src/solana/mailer-client.js +290 -58
  43. package/dist/unified/src/solana/mailer-client.js.map +1 -1
  44. package/dist/unified/src/unified/onchain-mailer-client.d.ts +25 -0
  45. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  46. package/dist/unified/src/unified/onchain-mailer-client.js +147 -4
  47. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  48. package/dist/unified/typechain-types/Mailer.d.ts +81 -11
  49. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
  50. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +93 -1
  51. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  52. package/dist/unified/typechain-types/factories/Mailer__factory.js +119 -1
  53. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
  54. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  55. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  56. package/dist/unified-esm/src/evm/index.js +1 -1
  57. package/dist/unified-esm/src/evm/index.js.map +1 -1
  58. package/dist/unified-esm/src/evm/mailer-client.d.ts +936 -180
  59. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -1
  60. package/dist/unified-esm/src/evm/mailer-client.js +453 -251
  61. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -1
  62. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  63. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  64. package/dist/unified-esm/src/solana/index.js +1 -1
  65. package/dist/unified-esm/src/solana/index.js.map +1 -1
  66. package/dist/unified-esm/src/solana/mailer-client.d.ts +86 -20
  67. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -1
  68. package/dist/unified-esm/src/solana/mailer-client.js +291 -59
  69. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -1
  70. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +25 -0
  71. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  72. package/dist/unified-esm/src/unified/onchain-mailer-client.js +147 -4
  73. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  74. package/dist/unified-esm/typechain-types/Mailer.d.ts +81 -11
  75. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
  76. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +93 -1
  77. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  78. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +119 -1
  79. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
  80. package/package.json +1 -1
  81. package/typechain-types/Mailer.ts +137 -9
  82. package/typechain-types/factories/Mailer__factory.ts +119 -1
@@ -1,413 +1,615 @@
1
- import { getAddress } from "viem";
2
- import { Mailer__factory } from "../../typechain-types/factories/Mailer__factory.js";
3
- // Get ABI from typechain-generated factories
1
+ import { getAddress, EstimateGasExecutionError, } from 'viem';
2
+ import { Mailer__factory } from '../../typechain-types/factories/Mailer__factory.js';
4
3
  const MAILER_ABI = Mailer__factory.abi;
5
- // Get bytecode from typechain-generated factories
6
4
  const MAILER_BYTECODE = Mailer__factory.bytecode;
7
5
  /**
8
- * @class MailerClient
9
- * @description High-level TypeScript client for the Mailer contract using viem
10
- * @notice Provides easy-to-use methods for sending messages with USDC fees and revenue sharing
11
- *
12
- * ## Key Features:
13
- * - **Delegation Management**: Delegate mail handling with rejection capability
14
- * - **Priority Messages**: Full fee (0.1 USDC) with 90% revenue share to recipient
15
- * - **Standard Messages**: 10% fee only (0.01 USDC) with no revenue share
16
- * - **Revenue Claims**: 60-day claim period for priority message revenue shares
17
- *
18
- * ## Usage Examples:
19
- * ```typescript
20
- * // Connect to existing contract
21
- * import { createPublicClient, createWalletClient, http } from 'viem';
22
- * import { mainnet } from 'viem/chains';
23
- *
24
- * const publicClient = createPublicClient({
25
- * chain: mainnet,
26
- * transport: http()
27
- * });
28
- *
29
- * const mailer = new MailerClient('CONTRACT_ADDRESS', publicClient);
30
- *
31
- * // Send message with revenue sharing to recipient
32
- * const walletClient = createWalletClient({
33
- * chain: mainnet,
34
- * transport: http()
35
- * });
36
- *
37
- * await mailer.send('0x...', 'Subject', 'Body', true, walletClient, account);
38
- *
39
- * // Claim your revenue share (as recipient)
40
- * await mailer.claimRecipientShare(walletClient, account);
41
- * ```
6
+ * Normalize any Address-like input (string with checksum or lowercase) to checksum format.
7
+ */
8
+ function normalizeAddress(value) {
9
+ return getAddress(value);
10
+ }
11
+ /**
12
+ * High-level client for interacting with the EVM Mailer contract.
13
+ * Exposes every callable contract function with type-safe wrappers.
14
+ * Includes automatic gas estimation with configurable buffer for all transactions.
42
15
  */
43
16
  export class MailerClient {
44
- /**
45
- * @description Creates a new MailerClient instance
46
- * @param contractAddress The deployed Mailer contract address
47
- * @param publicClient Viem public client for reading blockchain state
48
- */
49
17
  constructor(contractAddress, publicClient) {
50
- this.contractAddress = getAddress(contractAddress);
18
+ this.defaultGasMultiplier = 1.2; // 20% buffer by default
19
+ this.contractAddress = normalizeAddress(contractAddress);
51
20
  this.publicClient = publicClient;
52
21
  }
53
22
  /**
54
- * @description Deploy a new Mailer contract and return a client instance
55
- * @param walletClient Viem wallet client with deployment permissions
56
- * @param account Account to deploy from
57
- * @param usdcTokenAddress Address of the USDC token contract
58
- * @param ownerAddress Address that will own the deployed contract
59
- * @returns Promise resolving to a MailerClient instance
23
+ * Helper method to estimate gas for a transaction with optional buffer
24
+ */
25
+ async estimateGasWithBuffer(estimateFn, gasOptions) {
26
+ // If gas limit is explicitly provided, use it
27
+ if (gasOptions?.gasLimit) {
28
+ return gasOptions.gasLimit;
29
+ }
30
+ try {
31
+ // Estimate gas for the transaction
32
+ const estimatedGas = await estimateFn();
33
+ // Apply multiplier for safety buffer
34
+ const multiplier = gasOptions?.gasMultiplier ?? this.defaultGasMultiplier;
35
+ const gasWithBuffer = BigInt(Math.ceil(Number(estimatedGas) * multiplier));
36
+ // Apply max gas limit if specified
37
+ if (gasOptions?.maxGasLimit) {
38
+ return gasWithBuffer > gasOptions.maxGasLimit ? gasOptions.maxGasLimit : gasWithBuffer;
39
+ }
40
+ return gasWithBuffer;
41
+ }
42
+ catch (error) {
43
+ // If estimation fails, throw with helpful message
44
+ if (error instanceof EstimateGasExecutionError) {
45
+ throw new Error(`Gas estimation failed: ${error.message}`);
46
+ }
47
+ throw error;
48
+ }
49
+ }
50
+ /**
51
+ * Helper method to build transaction parameters with gas options
52
+ */
53
+ buildTxParams(gasLimit, gasOptions) {
54
+ const params = { gas: gasLimit };
55
+ if (gasOptions?.maxFeePerGas) {
56
+ params.maxFeePerGas = gasOptions.maxFeePerGas;
57
+ }
58
+ if (gasOptions?.maxPriorityFeePerGas) {
59
+ params.maxPriorityFeePerGas = gasOptions.maxPriorityFeePerGas;
60
+ }
61
+ return params;
62
+ }
63
+ /**
64
+ * Deploy a fresh Mailer contract instance with gas estimation.
60
65
  */
61
- static async deploy(walletClient, publicClient, account, usdcTokenAddress, ownerAddress) {
66
+ static async deploy(walletClient, publicClient, account, usdcTokenAddress, ownerAddress, gasOptions) {
67
+ // For deployment, we need to estimate gas differently
68
+ // Use a reasonable default for deployment gas
69
+ const estimatedGas = BigInt(3000000); // Default deployment gas
70
+ // Apply gas buffer
71
+ const multiplier = gasOptions?.gasMultiplier ?? 1.5; // Higher multiplier for deployment
72
+ const gasLimit = gasOptions?.gasLimit ?? BigInt(Math.ceil(Number(estimatedGas) * multiplier));
73
+ // Deploy with estimated gas
62
74
  const hash = await walletClient.deployContract({
63
75
  abi: MAILER_ABI,
64
76
  bytecode: MAILER_BYTECODE,
65
- args: [getAddress(usdcTokenAddress), getAddress(ownerAddress)],
77
+ args: [normalizeAddress(usdcTokenAddress), normalizeAddress(ownerAddress)],
66
78
  account,
67
79
  chain: walletClient.chain,
80
+ gas: gasLimit,
81
+ ...(gasOptions?.maxFeePerGas && { maxFeePerGas: gasOptions.maxFeePerGas }),
82
+ ...(gasOptions?.maxPriorityFeePerGas && { maxPriorityFeePerGas: gasOptions.maxPriorityFeePerGas }),
68
83
  });
69
84
  const receipt = await publicClient.waitForTransactionReceipt({ hash });
70
85
  if (!receipt.contractAddress) {
71
- throw new Error("Contract deployment failed");
86
+ throw new Error('Contract deployment failed');
72
87
  }
73
- return new MailerClient(receipt.contractAddress, publicClient);
88
+ return {
89
+ client: new MailerClient(receipt.contractAddress, publicClient),
90
+ result: { hash, estimatedGas, gasLimit }
91
+ };
92
+ }
93
+ getAddress() {
94
+ return this.contractAddress;
74
95
  }
75
96
  /**
76
- * @description Send a message with optional revenue sharing
77
- * @notice Two modes:
78
- * - revenueShareToReceiver=true: Sender pays 0.1 USDC, recipient gets 90% claimable
79
- * - revenueShareToReceiver=false: Sender pays 0.01 USDC only
80
- * @param to Recipient address who receives the message and potential revenue share
81
- * @param subject Message subject line
82
- * @param body Message content
83
- * @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
84
- * @param resolveSenderToName If true, resolve sender address to name via off-chain service
85
- * @param walletClient Viem wallet client for transaction
86
- * @param account Account to send from
87
- * @returns Promise resolving to transaction hash
88
- * @example
89
- * ```typescript
90
- * // Send with revenue share to recipient
91
- * const hash = await mailer.send('0x...', 'Subject', 'Priority message', true, false, walletClient, account);
92
- * // Send standard message (no revenue share)
93
- * const hash2 = await mailer.send('0x...', 'Subject', 'Standard message', false, false, walletClient, account);
94
- * await publicClient.waitForTransactionReceipt({ hash });
95
- * ```
97
+ * Core message send with explicit payer control and gas estimation.
96
98
  */
97
- async send(to, subject, body, revenueShareToReceiver, resolveSenderToName = false, walletClient, account) {
98
- return await walletClient.writeContract({
99
+ async send(to, subject, body, payer, revenueShareToReceiver, resolveSenderToName, walletClient, account, gasOptions) {
100
+ // Estimate gas for the transaction
101
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
99
102
  address: this.contractAddress,
100
103
  abi: MAILER_ABI,
101
104
  functionName: 'send',
102
- args: [to, subject, body, revenueShareToReceiver, resolveSenderToName],
105
+ args: [
106
+ normalizeAddress(to),
107
+ subject,
108
+ body,
109
+ normalizeAddress(payer),
110
+ revenueShareToReceiver,
111
+ resolveSenderToName,
112
+ ],
113
+ account,
114
+ }), gasOptions);
115
+ const hash = await walletClient.writeContract({
116
+ address: this.contractAddress,
117
+ abi: MAILER_ABI,
118
+ functionName: 'send',
119
+ args: [
120
+ normalizeAddress(to),
121
+ subject,
122
+ body,
123
+ normalizeAddress(payer),
124
+ revenueShareToReceiver,
125
+ resolveSenderToName,
126
+ ],
103
127
  account,
104
128
  chain: walletClient.chain,
129
+ ...this.buildTxParams(gasLimit, gasOptions),
105
130
  });
131
+ return { hash, estimatedGas: gasLimit, gasLimit };
106
132
  }
107
- /**
108
- * @description Send a message using a pre-prepared mail ID with optional revenue sharing
109
- * @notice Two modes:
110
- * - revenueShareToReceiver=true: Sender pays 0.1 USDC, recipient gets 90% claimable
111
- * - revenueShareToReceiver=false: Sender pays 0.01 USDC only
112
- * @param to Recipient address who receives the message and potential revenue share
113
- * @param mailId Pre-prepared message identifier
114
- * @param revenueShareToReceiver If true, recipient gets 90% revenue share; if false, no revenue share
115
- * @param resolveSenderToName If true, resolve sender address to name via off-chain service
116
- * @param walletClient Viem wallet client for transaction
117
- * @param account Account to send from
118
- * @returns Promise resolving to transaction hash
119
- */
120
- async sendPrepared(to, mailId, revenueShareToReceiver, resolveSenderToName = false, walletClient, account) {
121
- return await walletClient.writeContract({
133
+ async sendPrepared(to, mailId, payer, revenueShareToReceiver, resolveSenderToName, walletClient, account, gasOptions) {
134
+ // Estimate gas for the transaction
135
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
136
+ address: this.contractAddress,
137
+ abi: MAILER_ABI,
138
+ functionName: 'sendPrepared',
139
+ args: [
140
+ normalizeAddress(to),
141
+ mailId,
142
+ normalizeAddress(payer),
143
+ revenueShareToReceiver,
144
+ resolveSenderToName,
145
+ ],
146
+ account,
147
+ }), gasOptions);
148
+ const hash = await walletClient.writeContract({
122
149
  address: this.contractAddress,
123
150
  abi: MAILER_ABI,
124
151
  functionName: 'sendPrepared',
125
- args: [to, mailId, revenueShareToReceiver, resolveSenderToName],
152
+ args: [
153
+ normalizeAddress(to),
154
+ mailId,
155
+ normalizeAddress(payer),
156
+ revenueShareToReceiver,
157
+ resolveSenderToName,
158
+ ],
126
159
  account,
127
160
  chain: walletClient.chain,
161
+ ...this.buildTxParams(gasLimit, gasOptions),
128
162
  });
163
+ return { hash, estimatedGas: gasLimit, gasLimit };
164
+ }
165
+ async sendThroughWebhook(to, webhookId, payer, revenueShareToReceiver, resolveSenderToName, walletClient, account, gasOptions) {
166
+ // Estimate gas for the transaction
167
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
168
+ address: this.contractAddress,
169
+ abi: MAILER_ABI,
170
+ functionName: 'sendThroughWebhook',
171
+ args: [
172
+ normalizeAddress(to),
173
+ webhookId,
174
+ normalizeAddress(payer),
175
+ revenueShareToReceiver,
176
+ resolveSenderToName,
177
+ ],
178
+ account,
179
+ }), gasOptions);
180
+ const hash = await walletClient.writeContract({
181
+ address: this.contractAddress,
182
+ abi: MAILER_ABI,
183
+ functionName: 'sendThroughWebhook',
184
+ args: [
185
+ normalizeAddress(to),
186
+ webhookId,
187
+ normalizeAddress(payer),
188
+ revenueShareToReceiver,
189
+ resolveSenderToName,
190
+ ],
191
+ account,
192
+ chain: walletClient.chain,
193
+ ...this.buildTxParams(gasLimit, gasOptions),
194
+ });
195
+ return { hash, estimatedGas: gasLimit, gasLimit };
196
+ }
197
+ async sendToEmailAddress(toEmail, subject, body, payer, walletClient, account, gasOptions) {
198
+ // Estimate gas for the transaction
199
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
200
+ address: this.contractAddress,
201
+ abi: MAILER_ABI,
202
+ functionName: 'sendToEmailAddress',
203
+ args: [toEmail, subject, body, normalizeAddress(payer)],
204
+ account,
205
+ }), gasOptions);
206
+ const hash = await walletClient.writeContract({
207
+ address: this.contractAddress,
208
+ abi: MAILER_ABI,
209
+ functionName: 'sendToEmailAddress',
210
+ args: [toEmail, subject, body, normalizeAddress(payer)],
211
+ account,
212
+ chain: walletClient.chain,
213
+ ...this.buildTxParams(gasLimit, gasOptions),
214
+ });
215
+ return { hash, estimatedGas: gasLimit, gasLimit };
216
+ }
217
+ async sendPreparedToEmailAddress(toEmail, mailId, payer, walletClient, account, gasOptions) {
218
+ // Estimate gas for the transaction
219
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
220
+ address: this.contractAddress,
221
+ abi: MAILER_ABI,
222
+ functionName: 'sendPreparedToEmailAddress',
223
+ args: [toEmail, mailId, normalizeAddress(payer)],
224
+ account,
225
+ }), gasOptions);
226
+ const hash = await walletClient.writeContract({
227
+ address: this.contractAddress,
228
+ abi: MAILER_ABI,
229
+ functionName: 'sendPreparedToEmailAddress',
230
+ args: [toEmail, mailId, normalizeAddress(payer)],
231
+ account,
232
+ chain: walletClient.chain,
233
+ ...this.buildTxParams(gasLimit, gasOptions),
234
+ });
235
+ return { hash, estimatedGas: gasLimit, gasLimit };
236
+ }
237
+ async getFee() {
238
+ return (await this.publicClient.readContract({
239
+ address: this.contractAddress,
240
+ abi: MAILER_ABI,
241
+ functionName: 'getFee',
242
+ }));
129
243
  }
130
244
  async getSendFee() {
131
- return await this.publicClient.readContract({
245
+ return (await this.publicClient.readContract({
132
246
  address: this.contractAddress,
133
247
  abi: MAILER_ABI,
134
248
  functionName: 'sendFee',
135
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
249
+ }));
250
+ }
251
+ async setFee(newFee, walletClient, account, gasOptions) {
252
+ // Estimate gas for the transaction
253
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
254
+ address: this.contractAddress,
255
+ abi: MAILER_ABI,
256
+ functionName: 'setFee',
257
+ args: [newFee],
258
+ account,
259
+ }), gasOptions);
260
+ const hash = await walletClient.writeContract({
261
+ address: this.contractAddress,
262
+ abi: MAILER_ABI,
263
+ functionName: 'setFee',
264
+ args: [newFee],
265
+ account,
266
+ chain: walletClient.chain,
267
+ ...this.buildTxParams(gasLimit, gasOptions),
136
268
  });
269
+ return { hash, estimatedGas: gasLimit, gasLimit };
137
270
  }
138
271
  async getUsdcToken() {
139
- return await this.publicClient.readContract({
272
+ return (await this.publicClient.readContract({
140
273
  address: this.contractAddress,
141
274
  abi: MAILER_ABI,
142
275
  functionName: 'usdcToken',
143
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
144
- });
276
+ }));
145
277
  }
146
- getAddress() {
147
- return this.contractAddress;
278
+ async getOwner() {
279
+ return (await this.publicClient.readContract({
280
+ address: this.contractAddress,
281
+ abi: MAILER_ABI,
282
+ functionName: 'owner',
283
+ }));
148
284
  }
149
- async claimRecipientShare(walletClient, account) {
150
- return await walletClient.writeContract({
285
+ async claimRecipientShare(walletClient, account, gasOptions) {
286
+ // Estimate gas for the transaction
287
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
288
+ address: this.contractAddress,
289
+ abi: MAILER_ABI,
290
+ functionName: 'claimRecipientShare',
291
+ account,
292
+ }), gasOptions);
293
+ const hash = await walletClient.writeContract({
151
294
  address: this.contractAddress,
152
295
  abi: MAILER_ABI,
153
296
  functionName: 'claimRecipientShare',
154
297
  account,
155
298
  chain: walletClient.chain,
299
+ ...this.buildTxParams(gasLimit, gasOptions),
156
300
  });
301
+ return { hash, estimatedGas: gasLimit, gasLimit };
157
302
  }
158
- async claimOwnerShare(walletClient, account) {
159
- return await walletClient.writeContract({
303
+ async claimOwnerShare(walletClient, account, gasOptions) {
304
+ // Estimate gas for the transaction
305
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
306
+ address: this.contractAddress,
307
+ abi: MAILER_ABI,
308
+ functionName: 'claimOwnerShare',
309
+ account,
310
+ }), gasOptions);
311
+ const hash = await walletClient.writeContract({
160
312
  address: this.contractAddress,
161
313
  abi: MAILER_ABI,
162
314
  functionName: 'claimOwnerShare',
163
315
  account,
164
316
  chain: walletClient.chain,
317
+ ...this.buildTxParams(gasLimit, gasOptions),
165
318
  });
319
+ return { hash, estimatedGas: gasLimit, gasLimit };
166
320
  }
167
- async claimExpiredShares(recipient, walletClient, account) {
168
- return await walletClient.writeContract({
321
+ async claimExpiredShares(recipient, walletClient, account, gasOptions) {
322
+ // Estimate gas for the transaction
323
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
324
+ address: this.contractAddress,
325
+ abi: MAILER_ABI,
326
+ functionName: 'claimExpiredShares',
327
+ args: [normalizeAddress(recipient)],
328
+ account,
329
+ }), gasOptions);
330
+ const hash = await walletClient.writeContract({
169
331
  address: this.contractAddress,
170
332
  abi: MAILER_ABI,
171
333
  functionName: 'claimExpiredShares',
172
- args: [getAddress(recipient)],
334
+ args: [normalizeAddress(recipient)],
173
335
  account,
174
336
  chain: walletClient.chain,
337
+ ...this.buildTxParams(gasLimit, gasOptions),
175
338
  });
339
+ return { hash, estimatedGas: gasLimit, gasLimit };
176
340
  }
177
341
  async getRecipientClaimable(recipient) {
178
- const result = await this.publicClient.readContract({
342
+ const [amount, expiresAt, isExpired] = (await this.publicClient.readContract({
179
343
  address: this.contractAddress,
180
344
  abi: MAILER_ABI,
181
345
  functionName: 'getRecipientClaimable',
182
- args: [getAddress(recipient)],
183
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
184
- });
185
- return {
186
- amount: result[0],
187
- expiresAt: result[1],
188
- isExpired: result[2]
189
- };
346
+ args: [normalizeAddress(recipient)],
347
+ }));
348
+ return { amount, expiresAt, isExpired };
190
349
  }
191
350
  async getOwnerClaimable() {
192
- return await this.publicClient.readContract({
351
+ return (await this.publicClient.readContract({
193
352
  address: this.contractAddress,
194
353
  abi: MAILER_ABI,
195
- functionName: 'getOwnerClaimable'
196
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
197
- });
354
+ functionName: 'getOwnerClaimable',
355
+ }));
198
356
  }
199
- // Delegation functionality
200
- /**
201
- * Delegate mail handling to another address
202
- * @param delegate Address to delegate to (or 0x0 to clear delegation)
203
- * @param walletClient Connected wallet client
204
- * @param account Account to send transaction from
205
- * @returns Transaction hash
206
- */
207
- async delegateTo(delegate, walletClient, account) {
208
- return await walletClient.writeContract({
357
+ async delegateTo(delegate, walletClient, account, gasOptions) {
358
+ // Estimate gas for the transaction
359
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
360
+ address: this.contractAddress,
361
+ abi: MAILER_ABI,
362
+ functionName: 'delegateTo',
363
+ args: [normalizeAddress(delegate)],
364
+ account,
365
+ }), gasOptions);
366
+ const hash = await walletClient.writeContract({
209
367
  address: this.contractAddress,
210
368
  abi: MAILER_ABI,
211
369
  functionName: 'delegateTo',
212
- args: [getAddress(delegate)],
370
+ args: [normalizeAddress(delegate)],
213
371
  account,
214
372
  chain: walletClient.chain,
373
+ ...this.buildTxParams(gasLimit, gasOptions),
215
374
  });
375
+ return { hash, estimatedGas: gasLimit, gasLimit };
216
376
  }
217
- /**
218
- * Reject a delegation made to you by another address
219
- * @param delegatingAddress Address that delegated to you
220
- * @param walletClient Connected wallet client
221
- * @param account Account to send transaction from
222
- * @returns Transaction hash
223
- */
224
- async rejectDelegation(delegatingAddress, walletClient, account) {
225
- return await walletClient.writeContract({
377
+ async rejectDelegation(delegatingAddress, walletClient, account, gasOptions) {
378
+ // Estimate gas for the transaction
379
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
380
+ address: this.contractAddress,
381
+ abi: MAILER_ABI,
382
+ functionName: 'rejectDelegation',
383
+ args: [normalizeAddress(delegatingAddress)],
384
+ account,
385
+ }), gasOptions);
386
+ const hash = await walletClient.writeContract({
226
387
  address: this.contractAddress,
227
388
  abi: MAILER_ABI,
228
389
  functionName: 'rejectDelegation',
229
- args: [getAddress(delegatingAddress)],
390
+ args: [normalizeAddress(delegatingAddress)],
230
391
  account,
231
392
  chain: walletClient.chain,
393
+ ...this.buildTxParams(gasLimit, gasOptions),
232
394
  });
395
+ return { hash, estimatedGas: gasLimit, gasLimit };
233
396
  }
234
- /**
235
- * Get current delegation fee in USDC (6 decimals)
236
- * @returns Delegation fee amount
237
- */
238
397
  async getDelegationFee() {
239
- return await this.publicClient.readContract({
398
+ return (await this.publicClient.readContract({
240
399
  address: this.contractAddress,
241
400
  abi: MAILER_ABI,
242
401
  functionName: 'getDelegationFee',
243
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
244
- });
402
+ }));
245
403
  }
246
- /**
247
- * Update delegation fee (owner only)
248
- * @param newFee New fee amount in USDC (6 decimals)
249
- * @param walletClient Connected wallet client
250
- * @param account Account to send transaction from
251
- * @returns Transaction hash
252
- */
253
- async setDelegationFee(newFee, walletClient, account) {
254
- return await walletClient.writeContract({
404
+ async setDelegationFee(newFee, walletClient, account, gasOptions) {
405
+ // Estimate gas for the transaction
406
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
407
+ address: this.contractAddress,
408
+ abi: MAILER_ABI,
409
+ functionName: 'setDelegationFee',
410
+ args: [newFee],
411
+ account,
412
+ }), gasOptions);
413
+ const hash = await walletClient.writeContract({
255
414
  address: this.contractAddress,
256
415
  abi: MAILER_ABI,
257
416
  functionName: 'setDelegationFee',
258
417
  args: [newFee],
259
418
  account,
260
419
  chain: walletClient.chain,
420
+ ...this.buildTxParams(gasLimit, gasOptions),
261
421
  });
422
+ return { hash, estimatedGas: gasLimit, gasLimit };
262
423
  }
263
- /**
264
- * @description Send a message to an email address (no wallet known)
265
- * @notice Charges only 10% owner fee since recipient wallet is unknown
266
- * @param toEmail Email address of the recipient
267
- * @param subject Message subject line
268
- * @param body Message content
269
- * @param walletClient Viem wallet client for transaction
270
- * @param account Account to send from
271
- * @returns Promise resolving to transaction hash
272
- * @example
273
- * ```typescript
274
- * // Send to email address
275
- * const hash = await mailer.sendToEmailAddress('user@example.com', 'Subject', 'Body', walletClient, account);
276
- * await publicClient.waitForTransactionReceipt({ hash });
277
- * ```
278
- */
279
- async sendToEmailAddress(toEmail, subject, body, walletClient, account) {
280
- return await walletClient.writeContract({
424
+ async setCustomFeePercentage(target, percentage, walletClient, account, gasOptions) {
425
+ // Estimate gas for the transaction
426
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
281
427
  address: this.contractAddress,
282
428
  abi: MAILER_ABI,
283
- functionName: 'sendToEmailAddress',
284
- args: [toEmail, subject, body],
429
+ functionName: 'setCustomFeePercentage',
430
+ args: [normalizeAddress(target), BigInt(percentage)],
431
+ account,
432
+ }), gasOptions);
433
+ const hash = await walletClient.writeContract({
434
+ address: this.contractAddress,
435
+ abi: MAILER_ABI,
436
+ functionName: 'setCustomFeePercentage',
437
+ args: [normalizeAddress(target), BigInt(percentage)],
285
438
  account,
286
439
  chain: walletClient.chain,
440
+ ...this.buildTxParams(gasLimit, gasOptions),
287
441
  });
442
+ return { hash, estimatedGas: gasLimit, gasLimit };
288
443
  }
289
- /**
290
- * @description Send a pre-prepared message to an email address (no wallet known)
291
- * @notice Charges only 10% owner fee since recipient wallet is unknown
292
- * @param toEmail Email address of the recipient
293
- * @param mailId Pre-prepared message identifier
294
- * @param walletClient Viem wallet client for transaction
295
- * @param account Account to send from
296
- * @returns Promise resolving to transaction hash
297
- */
298
- async sendPreparedToEmailAddress(toEmail, mailId, walletClient, account) {
299
- return await walletClient.writeContract({
444
+ async clearCustomFeePercentage(target, walletClient, account, gasOptions) {
445
+ // Estimate gas for the transaction
446
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
300
447
  address: this.contractAddress,
301
448
  abi: MAILER_ABI,
302
- functionName: 'sendPreparedToEmailAddress',
303
- args: [toEmail, mailId],
449
+ functionName: 'clearCustomFeePercentage',
450
+ args: [normalizeAddress(target)],
451
+ account,
452
+ }), gasOptions);
453
+ const hash = await walletClient.writeContract({
454
+ address: this.contractAddress,
455
+ abi: MAILER_ABI,
456
+ functionName: 'clearCustomFeePercentage',
457
+ args: [normalizeAddress(target)],
304
458
  account,
305
459
  chain: walletClient.chain,
460
+ ...this.buildTxParams(gasLimit, gasOptions),
306
461
  });
462
+ return { hash, estimatedGas: gasLimit, gasLimit };
307
463
  }
308
- /**
309
- * Set the send fee (owner only)
310
- * @param newFee New fee amount in USDC (6 decimals)
311
- * @param walletClient Viem wallet client for transaction
312
- * @param account Account to send from (must be owner)
313
- * @returns Promise resolving to transaction hash
314
- */
315
- async setFee(newFee, walletClient, account) {
316
- return await walletClient.writeContract({
464
+ async getCustomFeePercentage(target) {
465
+ const percentage = (await this.publicClient.readContract({
317
466
  address: this.contractAddress,
318
467
  abi: MAILER_ABI,
319
- functionName: 'setFee',
320
- args: [newFee],
468
+ functionName: 'getCustomFeePercentage',
469
+ args: [normalizeAddress(target)],
470
+ }));
471
+ return Number(percentage);
472
+ }
473
+ async getCustomFeeDiscount(target) {
474
+ const discount = (await this.publicClient.readContract({
475
+ address: this.contractAddress,
476
+ abi: MAILER_ABI,
477
+ functionName: 'customFeeDiscount',
478
+ args: [normalizeAddress(target)],
479
+ }));
480
+ return Number(discount);
481
+ }
482
+ async setPermission(contractAddress, walletClient, account, gasOptions) {
483
+ // Estimate gas for the transaction
484
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
485
+ address: this.contractAddress,
486
+ abi: MAILER_ABI,
487
+ functionName: 'setPermission',
488
+ args: [normalizeAddress(contractAddress)],
489
+ account,
490
+ }), gasOptions);
491
+ const hash = await walletClient.writeContract({
492
+ address: this.contractAddress,
493
+ abi: MAILER_ABI,
494
+ functionName: 'setPermission',
495
+ args: [normalizeAddress(contractAddress)],
321
496
  account,
322
497
  chain: walletClient.chain,
498
+ ...this.buildTxParams(gasLimit, gasOptions),
323
499
  });
500
+ return { hash, estimatedGas: gasLimit, gasLimit };
324
501
  }
325
- /**
326
- * Get the current send fee
327
- * @returns Current send fee in USDC (6 decimals)
328
- */
329
- async getFee() {
330
- return await this.publicClient.readContract({
502
+ async removePermission(contractAddress, walletClient, account, gasOptions) {
503
+ // Estimate gas for the transaction
504
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
331
505
  address: this.contractAddress,
332
506
  abi: MAILER_ABI,
333
- functionName: 'getFee',
334
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
507
+ functionName: 'removePermission',
508
+ args: [normalizeAddress(contractAddress)],
509
+ account,
510
+ }), gasOptions);
511
+ const hash = await walletClient.writeContract({
512
+ address: this.contractAddress,
513
+ abi: MAILER_ABI,
514
+ functionName: 'removePermission',
515
+ args: [normalizeAddress(contractAddress)],
516
+ account,
517
+ chain: walletClient.chain,
518
+ ...this.buildTxParams(gasLimit, gasOptions),
335
519
  });
520
+ return { hash, estimatedGas: gasLimit, gasLimit };
336
521
  }
337
- /**
338
- * Pause the contract and distribute all claimable funds (owner only)
339
- * @param walletClient Viem wallet client for transaction
340
- * @param account Account to send from (must be owner)
341
- * @returns Promise resolving to transaction hash
342
- */
343
- async pause(walletClient, account) {
344
- return await walletClient.writeContract({
522
+ async hasPermission(contractAddress, wallet) {
523
+ const permitted = (await this.publicClient.readContract({
524
+ address: this.contractAddress,
525
+ abi: MAILER_ABI,
526
+ functionName: 'permissions',
527
+ args: [normalizeAddress(contractAddress), normalizeAddress(wallet)],
528
+ }));
529
+ return permitted;
530
+ }
531
+ async pause(walletClient, account, gasOptions) {
532
+ // Estimate gas for the transaction
533
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
534
+ address: this.contractAddress,
535
+ abi: MAILER_ABI,
536
+ functionName: 'pause',
537
+ account,
538
+ }), gasOptions);
539
+ const hash = await walletClient.writeContract({
345
540
  address: this.contractAddress,
346
541
  abi: MAILER_ABI,
347
542
  functionName: 'pause',
348
543
  account,
349
544
  chain: walletClient.chain,
545
+ ...this.buildTxParams(gasLimit, gasOptions),
350
546
  });
547
+ return { hash, estimatedGas: gasLimit, gasLimit };
351
548
  }
352
- /**
353
- * Unpause the contract (owner only)
354
- * @param walletClient Viem wallet client for transaction
355
- * @param account Account to send from (must be owner)
356
- * @returns Promise resolving to transaction hash
357
- */
358
- async unpause(walletClient, account) {
359
- return await walletClient.writeContract({
549
+ async unpause(walletClient, account, gasOptions) {
550
+ // Estimate gas for the transaction
551
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
552
+ address: this.contractAddress,
553
+ abi: MAILER_ABI,
554
+ functionName: 'unpause',
555
+ account,
556
+ }), gasOptions);
557
+ const hash = await walletClient.writeContract({
360
558
  address: this.contractAddress,
361
559
  abi: MAILER_ABI,
362
560
  functionName: 'unpause',
363
561
  account,
364
562
  chain: walletClient.chain,
563
+ ...this.buildTxParams(gasLimit, gasOptions),
365
564
  });
565
+ return { hash, estimatedGas: gasLimit, gasLimit };
366
566
  }
367
- /**
368
- * Emergency unpause without fund distribution (owner only)
369
- * @param walletClient Viem wallet client for transaction
370
- * @param account Account to send from (must be owner)
371
- * @returns Promise resolving to transaction hash
372
- */
373
- async emergencyUnpause(walletClient, account) {
374
- return await walletClient.writeContract({
567
+ async emergencyUnpause(walletClient, account, gasOptions) {
568
+ // Estimate gas for the transaction
569
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
570
+ address: this.contractAddress,
571
+ abi: MAILER_ABI,
572
+ functionName: 'emergencyUnpause',
573
+ account,
574
+ }), gasOptions);
575
+ const hash = await walletClient.writeContract({
375
576
  address: this.contractAddress,
376
577
  abi: MAILER_ABI,
377
578
  functionName: 'emergencyUnpause',
378
579
  account,
379
580
  chain: walletClient.chain,
581
+ ...this.buildTxParams(gasLimit, gasOptions),
380
582
  });
583
+ return { hash, estimatedGas: gasLimit, gasLimit };
381
584
  }
382
- /**
383
- * Check if contract is currently paused
384
- * @returns True if contract is paused, false otherwise
385
- */
386
585
  async isPaused() {
387
- return await this.publicClient.readContract({
586
+ return (await this.publicClient.readContract({
388
587
  address: this.contractAddress,
389
588
  abi: MAILER_ABI,
390
589
  functionName: 'isPaused',
391
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
392
- });
590
+ }));
393
591
  }
394
- /**
395
- * Distribute a specific recipient's claimable funds during pause
396
- * Anyone can call this function when contract is paused
397
- * @param recipient Address to distribute funds for
398
- * @param walletClient Viem wallet client for transaction
399
- * @param account Account to send from
400
- * @returns Promise resolving to transaction hash
401
- */
402
- async distributeClaimableFunds(recipient, walletClient, account) {
403
- return await walletClient.writeContract({
592
+ async distributeClaimableFunds(recipient, walletClient, account, gasOptions) {
593
+ // Estimate gas for the transaction
594
+ const gasLimit = await this.estimateGasWithBuffer(() => this.publicClient.estimateContractGas({
595
+ address: this.contractAddress,
596
+ abi: MAILER_ABI,
597
+ functionName: 'distributeClaimableFunds',
598
+ args: [normalizeAddress(recipient)],
599
+ account,
600
+ }), gasOptions);
601
+ const hash = await walletClient.writeContract({
404
602
  address: this.contractAddress,
405
603
  abi: MAILER_ABI,
406
604
  functionName: 'distributeClaimableFunds',
407
- args: [getAddress(recipient)],
605
+ args: [normalizeAddress(recipient)],
408
606
  account,
409
607
  chain: walletClient.chain,
608
+ ...this.buildTxParams(gasLimit, gasOptions),
410
609
  });
610
+ return { hash, estimatedGas: gasLimit, gasLimit };
411
611
  }
412
612
  }
613
+ MailerClient.abi = MAILER_ABI;
614
+ MailerClient.bytecode = MAILER_BYTECODE;
413
615
  //# sourceMappingURL=mailer-client.js.map