@sudobility/contracts 0.14.0 → 1.9.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 (110) hide show
  1. package/README.md +2 -3
  2. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
  3. package/artifacts/contracts/Mailer.sol/Mailer.json +2 -278
  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 +180 -936
  11. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -1
  12. package/dist/evm/src/evm/mailer-client.js +249 -451
  13. package/dist/evm/src/evm/mailer-client.js.map +1 -1
  14. package/dist/evm/typechain-types/Mailer.d.ts +10 -177
  15. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
  16. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +1 -216
  17. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  18. package/dist/evm/typechain-types/factories/Mailer__factory.js +1 -277
  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 +1 -3
  23. package/dist/solana/solana/index.js.map +1 -1
  24. package/dist/solana/solana/mailer-client.d.ts +18 -91
  25. package/dist/solana/solana/mailer-client.d.ts.map +1 -1
  26. package/dist/solana/solana/mailer-client.js +55 -316
  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 +180 -936
  33. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -1
  34. package/dist/unified/src/evm/mailer-client.js +249 -451
  35. package/dist/unified/src/evm/mailer-client.js.map +1 -1
  36. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +1 -1
  37. package/dist/unified/src/react/hooks/useMailerMutations.js +1 -1
  38. package/dist/unified/src/solana/index.d.ts +1 -1
  39. package/dist/unified/src/solana/index.d.ts.map +1 -1
  40. package/dist/unified/src/solana/index.js +1 -3
  41. package/dist/unified/src/solana/index.js.map +1 -1
  42. package/dist/unified/src/solana/mailer-client.d.ts +18 -91
  43. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -1
  44. package/dist/unified/src/solana/mailer-client.js +55 -316
  45. package/dist/unified/src/solana/mailer-client.js.map +1 -1
  46. package/dist/unified/src/unified/index.d.ts +1 -1
  47. package/dist/unified/src/unified/index.d.ts.map +1 -1
  48. package/dist/unified/src/unified/onchain-mailer-client.d.ts +251 -111
  49. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  50. package/dist/unified/src/unified/onchain-mailer-client.js +1375 -744
  51. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  52. package/dist/unified/src/unified/types.d.ts +6 -16
  53. package/dist/unified/src/unified/types.d.ts.map +1 -1
  54. package/dist/unified/src/utils/chain-config.d.ts +2 -4
  55. package/dist/unified/src/utils/chain-config.d.ts.map +1 -1
  56. package/dist/unified/src/utils/chain-config.js +36 -46
  57. package/dist/unified/src/utils/chain-config.js.map +1 -1
  58. package/dist/unified/typechain-types/Mailer.d.ts +10 -177
  59. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
  60. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +1 -216
  61. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  62. package/dist/unified/typechain-types/factories/Mailer__factory.js +1 -277
  63. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
  64. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  65. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  66. package/dist/unified-esm/src/evm/index.js +1 -1
  67. package/dist/unified-esm/src/evm/index.js.map +1 -1
  68. package/dist/unified-esm/src/evm/mailer-client.d.ts +180 -936
  69. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -1
  70. package/dist/unified-esm/src/evm/mailer-client.js +251 -453
  71. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -1
  72. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +1 -1
  73. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +1 -1
  74. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  75. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  76. package/dist/unified-esm/src/solana/index.js +1 -1
  77. package/dist/unified-esm/src/solana/index.js.map +1 -1
  78. package/dist/unified-esm/src/solana/mailer-client.d.ts +18 -91
  79. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -1
  80. package/dist/unified-esm/src/solana/mailer-client.js +56 -317
  81. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -1
  82. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  83. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  84. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +251 -111
  85. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  86. package/dist/unified-esm/src/unified/onchain-mailer-client.js +1379 -748
  87. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  88. package/dist/unified-esm/src/unified/types.d.ts +6 -16
  89. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  90. package/dist/unified-esm/src/utils/chain-config.d.ts +2 -4
  91. package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -1
  92. package/dist/unified-esm/src/utils/chain-config.js +35 -46
  93. package/dist/unified-esm/src/utils/chain-config.js.map +1 -1
  94. package/dist/unified-esm/typechain-types/Mailer.d.ts +10 -177
  95. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
  96. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +1 -216
  97. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  98. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1 -277
  99. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
  100. package/package.json +9 -20
  101. package/programs/mailer/src/lib.rs +171 -1026
  102. package/programs/mailer/tests/integration_tests.rs +65 -586
  103. package/typechain-types/Mailer.ts +8 -319
  104. package/typechain-types/factories/Mailer__factory.ts +1 -277
  105. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +0 -1146
  106. package/artifacts/contracts/Mailer.sol/artifacts.d.ts +0 -21
  107. package/artifacts/contracts/MockUSDC.sol/MockUSDC.d.ts +0 -284
  108. package/artifacts/contracts/MockUSDC.sol/artifacts.d.ts +0 -21
  109. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.d.ts +0 -157
  110. package/artifacts/contracts/interfaces/IERC20.sol/artifacts.d.ts +0 -21
@@ -1,157 +1,226 @@
1
1
  /* eslint-disable @typescript-eslint/ban-ts-comment */
2
2
  // @ts-nocheck - Suppress false TypeScript errors with ESNext modules accessing class properties
3
3
  import { ChainType } from '@sudobility/types';
4
+ import { WalletDetector } from './wallet-detector.js';
4
5
  /**
5
- * OnchainMailerClient v2 - Refactored to use standard wallet libraries
6
+ * OnchainMailerClient - Multi-chain messaging client for Mailer protocol
6
7
  *
7
- * This version removes the UnifiedWallet abstraction and instead accepts
8
- * standard wallet clients from wagmi (EVM) or wallet-adapter (Solana).
8
+ * This class provides a unified interface for interacting with Mailer contracts
9
+ * across different blockchain networks (EVM and Solana). It automatically detects
10
+ * wallet types and routes operations to the appropriate chain implementation.
9
11
  *
10
- * @example EVM Usage with wagmi
12
+ * @example Basic Usage
11
13
  * ```typescript
12
- * import { createWalletClient, createPublicClient, http } from 'viem';
13
- * import { mainnet } from 'viem/chains';
14
+ * // EVM wallet (MetaMask, etc.)
15
+ * const evmWallet = window.ethereum;
16
+ * const evmConfig = {
17
+ * evm: {
18
+ * rpc: 'https://eth-mainnet.alchemyapi.io/v2/your-key',
19
+ * chainId: 1,
20
+ * contracts: {
21
+ * mailer: '0x456...',
22
+ * usdc: '0x789...'
23
+ * }
24
+ * }
25
+ * };
26
+ * const evmClient = new OnchainMailerClient(evmWallet, evmConfig);
14
27
  *
15
- * const walletClient = createWalletClient({
16
- * chain: mainnet,
17
- * transport: http()
18
- * });
19
- * const publicClient = createPublicClient({
20
- * chain: mainnet,
21
- * transport: http()
22
- * });
28
+ * // Solana wallet (Phantom, etc.)
29
+ * const solanaWallet = window.solana;
30
+ * const solanaConfig = {
31
+ * solana: {
32
+ * rpc: 'https://api.mainnet-beta.solana.com',
33
+ * programs: {
34
+ * mailer: '9FLkBDGpZBcR8LMsQ7MwwV6X9P4TDFgN3DeRh5qYyHJF'
35
+ * },
36
+ * usdcMint: 'EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v'
37
+ * }
38
+ * };
39
+ * const solanaClient = new OnchainMailerClient(solanaWallet, solanaConfig);
23
40
  *
24
- * const client = OnchainMailerClient.forEVM(
25
- * walletClient,
26
- * publicClient,
27
- * '0xMailerContractAddress',
28
- * '0xUSDCAddress'
29
- * );
41
+ * // Send messages
42
+ * const result = await client.sendMessage("Hello", "World!", false);
43
+ * console.log('Transaction:', result.transactionHash);
30
44
  * ```
31
45
  *
32
- * @example Solana Usage with wallet-adapter
46
+ * @example Error Handling
33
47
  * ```typescript
34
- * import { useWallet } from '@solana/wallet-adapter-react';
35
- * import { Connection } from '@solana/web3.js';
36
- *
37
- * const wallet = useWallet();
38
- * const connection = new Connection('https://api.mainnet-beta.solana.com');
39
- *
40
- * const client = OnchainMailerClient.forSolana(
41
- * wallet,
42
- * connection,
43
- * 'MailerProgramId',
44
- * 'USDCMintAddress'
45
- * );
48
+ * try {
49
+ * const result = await client.sendMessage("Subject", "Body", true);
50
+ * console.log('Success:', result);
51
+ * } catch (error) {
52
+ * if (error.message.includes('insufficient funds')) {
53
+ * console.log('User needs more USDC');
54
+ * } else if (error.message.includes('user rejected')) {
55
+ * console.log('User cancelled transaction');
56
+ * } else {
57
+ * console.log('Unknown error:', error);
58
+ * }
59
+ * }
46
60
  * ```
61
+ *
62
+ * @author Mailer Protocol Team
63
+ * @version 1.5.2
64
+ * @since 1.0.0
47
65
  */
48
66
  export class OnchainMailerClient {
49
67
  /**
50
- * Create an OnchainMailerClient for EVM chains using wagmi clients
68
+ * Initialize OnchainMailerClient with wallet and chain configuration
51
69
  *
52
- * @param walletClient - wagmi WalletClient for signing transactions
53
- * @param publicClient - wagmi PublicClient for reading chain data
54
- * @param mailerAddress - Deployed Mailer contract address
55
- * @param usdcAddress - USDC token contract address
56
- * @returns Configured OnchainMailerClient for EVM
57
- */
58
- static forEVM(walletClient, publicClient, mailerAddress, usdcAddress) {
59
- const client = new OnchainMailerClient({}, { evm: undefined, solana: undefined });
60
- client.chainType = ChainType.EVM;
61
- client.evmWalletClient = walletClient;
62
- client.evmPublicClient = publicClient;
63
- client.evmContractAddress = mailerAddress;
64
- client.evmUsdcAddress = usdcAddress;
65
- return client;
66
- }
67
- /**
68
- * Create an OnchainMailerClient for Solana using wallet-adapter
70
+ * @param wallet - Wallet instance (EVM or Solana compatible)
71
+ * @param config - Chain configuration for EVM and/or Solana networks
69
72
  *
70
- * @param wallet - Solana wallet adapter
71
- * @param connection - Solana connection
72
- * @param programId - Deployed Mailer program ID
73
- * @param usdcMint - USDC mint address
74
- * @returns Configured OnchainMailerClient for Solana
75
- */
76
- static forSolana(
77
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
78
- wallet, // Wallet adapter interface
79
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
80
- connection, // Connection
81
- programId, usdcMint) {
82
- const client = new OnchainMailerClient({}, { evm: undefined, solana: undefined });
83
- client.chainType = ChainType.SOLANA;
84
- client.solanaWallet = wallet;
85
- client.solanaConnection = connection;
86
- client.solanaProgramId = programId;
87
- client.solanaUsdcMint = usdcMint;
88
- return client;
89
- }
90
- /**
91
- * Create an OnchainMailerClient from a generic config (backward compatibility)
92
- * This constructor is provided for backward compatibility with React provider
73
+ * @throws {Error} When wallet type cannot be detected
74
+ * @throws {Error} When required configuration is missing
75
+ * @throws {Error} When wallet doesn't implement required methods
76
+ *
77
+ * @example
78
+ * ```typescript
79
+ * // EVM wallet initialization
80
+ * const wallet = window.ethereum;
81
+ * const config = {
82
+ * evm: { rpc: '...', chainId: 1, contracts: {...} }
83
+ * };
84
+ * const client = new OnchainMailerClient(wallet, config);
85
+ * ```
93
86
  */
94
87
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
95
88
  constructor(wallet, config) {
96
- // Simple chain detection based on wallet properties
97
- const hasEthereumProperties = wallet && (wallet.address || wallet.request || wallet.selectedAddress);
98
- const hasSolanaProperties = wallet && wallet.publicKey && typeof wallet.signTransaction === 'function';
99
- if (hasEthereumProperties) {
100
- this.chainType = ChainType.EVM;
101
- if (config.evm) {
102
- // Store config for lazy initialization
103
- this.evmContractAddress = config.evm.contracts.mailer;
104
- this.evmUsdcAddress = config.evm.contracts.usdc;
105
- // Wallet and public clients will be created on first use
106
- // Store raw wallet for backward compatibility
107
- // @ts-ignore
108
- this._rawEvmWallet = wallet;
109
- }
110
- else {
111
- throw new Error('EVM configuration required for EVM wallet');
112
- }
113
- }
114
- else if (hasSolanaProperties) {
115
- this.chainType = ChainType.SOLANA;
116
- if (config.solana) {
117
- this.solanaWallet = wallet;
118
- // Connection will be created on first use
119
- this.solanaProgramId = config.solana.programs.mailer;
120
- this.solanaUsdcMint = config.solana.usdcMint;
121
- }
122
- else {
123
- throw new Error('Solana configuration required for Solana wallet');
89
+ try {
90
+ // Automatically detect whether this is an EVM or Solana wallet
91
+ this.chainType = WalletDetector.detectWalletType(wallet);
92
+ // Normalize wallet interface for internal use
93
+ this.wallet = {
94
+ address: wallet.address || wallet.publicKey?.toString() || '',
95
+ chainType: this.chainType,
96
+ signTransaction: wallet.signTransaction?.bind(wallet),
97
+ publicKey: wallet.publicKey?.toString()
98
+ };
99
+ this.config = config;
100
+ // Ensure we have valid configuration for the detected chain type
101
+ this.validateConfiguration();
102
+ // Ensure wallet implements required methods for its chain type
103
+ this.validateWallet(wallet);
104
+ }
105
+ catch (error) {
106
+ throw new Error(`OnchainMailerClient initialization failed: ${error instanceof Error ? error.message : String(error)}`);
107
+ }
108
+ }
109
+ validateConfiguration() {
110
+ if (this.chainType === 'evm' && !this.config.evm) {
111
+ throw new Error('EVM configuration required for EVM wallet');
112
+ }
113
+ if (this.chainType === 'solana' && !this.config.solana) {
114
+ throw new Error('Solana configuration required for Solana wallet');
115
+ }
116
+ // Validate EVM configuration
117
+ if (this.config.evm) {
118
+ if (!this.config.evm.rpc || !this.config.evm.chainId) {
119
+ throw new Error('EVM configuration missing required fields (rpc, chainId)');
120
+ }
121
+ if (!this.config.evm.contracts || !this.config.evm.contracts.mailer) {
122
+ console.warn('EVM contract addresses not configured - some functionality may fail');
124
123
  }
125
124
  }
126
- else {
127
- throw new Error('Unable to detect wallet type from provided wallet object');
125
+ // Validate Solana configuration
126
+ if (this.config.solana) {
127
+ if (!this.config.solana.rpc || !this.config.solana.usdcMint) {
128
+ throw new Error('Solana configuration missing required fields (rpc, usdcMint)');
129
+ }
130
+ if (!this.config.solana.programs || !this.config.solana.programs.mailer) {
131
+ console.warn('Solana program addresses not configured - some functionality may fail');
132
+ }
133
+ }
134
+ }
135
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
136
+ validateWallet(wallet) {
137
+ if (!wallet.signTransaction && typeof wallet.signTransaction !== 'function') {
138
+ throw new Error('Wallet must have signTransaction method');
139
+ }
140
+ if (this.chainType === 'evm' && !wallet.address) {
141
+ throw new Error('EVM wallet must have address property');
142
+ }
143
+ if (this.chainType === 'solana' && !wallet.publicKey) {
144
+ throw new Error('Solana wallet must have publicKey property');
128
145
  }
129
146
  }
130
147
  /**
131
148
  * Send a message using the appropriate chain implementation
132
- * Note: For backward compatibility, 'to' defaults to sender's own address
149
+ *
150
+ * This method automatically routes to EVM or Solana based on the detected wallet type.
151
+ * Priority messages cost more but include revenue sharing for recipients.
152
+ *
153
+ * @param subject - Message subject (1-200 characters)
154
+ * @param body - Message body (1-10000 characters)
155
+ * @param priority - Whether to use priority sending with revenue share
156
+ * - Priority: Full fee paid, 90% claimable by recipient
157
+ * - Standard: 10% fee only, no revenue share
158
+ * @param resolveSenderToName - If true, resolve sender address to name via off-chain service
159
+ *
160
+ * @returns Promise resolving to MessageResult with transaction details
161
+ *
162
+ * @throws {Error} When subject/body validation fails
163
+ * @throws {Error} When insufficient USDC balance
164
+ * @throws {Error} When user rejects transaction
165
+ * @throws {Error} When network connection fails
166
+ *
167
+ * @example Standard Message
168
+ * ```typescript
169
+ * const result = await client.sendMessage(
170
+ * "Meeting Reminder",
171
+ * "Don't forget our 3pm call today!",
172
+ * false, // Standard fee (10% of sendFee)
173
+ * false // Don't resolve sender to name
174
+ * );
175
+ * console.log('Sent in tx:', result.transactionHash);
176
+ * ```
177
+ *
178
+ * @example Priority Message with Revenue Share
179
+ * ```typescript
180
+ * const result = await client.sendMessage(
181
+ * "Important Update",
182
+ * "Urgent: Please review the attached proposal",
183
+ * true, // Priority fee (100% paid, 90% claimable by recipient)
184
+ * true // Resolve sender to name
185
+ * );
186
+ * console.log('Priority message fee:', result.fee);
187
+ * ```
133
188
  */
134
- async sendMessage(subject, body, priority = false, resolveSenderToName = false, to) {
135
- // For backward compatibility, default to sending to self
136
- const recipient = to || await this.getWalletAddressAsync();
137
- if (this.chainType === ChainType.EVM) {
138
- return this.sendEVMMessage(recipient, subject, body, priority, resolveSenderToName);
189
+ async sendMessage(subject, body, priority = false, resolveSenderToName = false) {
190
+ // Route to appropriate chain implementation based on wallet type
191
+ if (this.chainType === 'evm') {
192
+ return this.sendEVMMessage(subject, body, priority, resolveSenderToName);
139
193
  }
140
194
  else {
141
- return this.sendSolanaMessage(recipient, subject, body, priority, resolveSenderToName);
195
+ return this.sendSolanaMessage(subject, body, priority, resolveSenderToName);
142
196
  }
143
197
  }
144
198
  /**
145
- * Register a domain (not implemented - for backward compatibility)
199
+ * Register a domain using the appropriate chain implementation
200
+ * @param domain - Domain name to register
201
+ * @param isExtension - Whether this is extending an existing domain
202
+ * @returns Domain registration result
146
203
  */
147
- async registerDomain(_domain) {
148
- throw new Error('Domain registration not yet implemented');
204
+ async registerDomain(domain, isExtension = false) {
205
+ if (this.chainType === 'evm') {
206
+ return this.registerEVMDomain(domain, isExtension);
207
+ }
208
+ else {
209
+ return this.registerSolanaDomain(domain, isExtension);
210
+ }
149
211
  }
150
212
  /**
151
- * Delegate to another address
213
+ * Delegate to another address using the appropriate chain implementation
214
+ * @param delegate - Address to delegate to
215
+ * @returns Delegation result
152
216
  */
153
217
  async delegateTo(delegate) {
154
- if (this.chainType === ChainType.EVM) {
218
+ // Validate delegate address format
219
+ const delegateChainType = WalletDetector.detectChainFromAddress(delegate);
220
+ if (delegateChainType !== this.chainType) {
221
+ throw new Error(`Delegate address format doesn't match wallet chain type (${this.chainType})`);
222
+ }
223
+ if (this.chainType === 'evm') {
155
224
  return this.delegateEVM(delegate);
156
225
  }
157
226
  else {
@@ -159,10 +228,11 @@ export class OnchainMailerClient {
159
228
  }
160
229
  }
161
230
  /**
162
- * Claim revenue share
231
+ * Claim revenue share using the appropriate chain implementation
232
+ * @returns Transaction result
163
233
  */
164
234
  async claimRevenue() {
165
- if (this.chainType === ChainType.EVM) {
235
+ if (this.chainType === 'evm') {
166
236
  return this.claimEVMRevenue();
167
237
  }
168
238
  else {
@@ -172,799 +242,1385 @@ export class OnchainMailerClient {
172
242
  // Performance optimization: cache module imports
173
243
  async getEVMModules() {
174
244
  if (!OnchainMailerClient.evmModules) {
175
- const evmModule = await import('../evm/index.js');
176
- OnchainMailerClient.evmModules = {
177
- MailerClient: evmModule.MailerClient
178
- };
245
+ try {
246
+ const [viemModule, evmModule] = await Promise.all([
247
+ import('viem'),
248
+ import('../evm')
249
+ ]);
250
+ OnchainMailerClient.evmModules = {
251
+ viem: viemModule,
252
+ MailerClient: evmModule.MailerClient
253
+ };
254
+ }
255
+ catch (error) {
256
+ throw new Error(`Failed to load EVM modules: ${error instanceof Error ? error.message : String(error)}`);
257
+ }
179
258
  }
180
259
  return OnchainMailerClient.evmModules;
181
260
  }
182
261
  async getSolanaModules() {
183
262
  if (!OnchainMailerClient.solanaModules) {
184
- const [solanaModule, web3Module] = await Promise.all([
185
- import('../solana/index.js'),
186
- import('@solana/web3.js')
187
- ]);
188
- OnchainMailerClient.solanaModules = {
189
- MailerClient: solanaModule.MailerClient,
190
- PublicKey: web3Module.PublicKey,
191
- Connection: web3Module.Connection
192
- };
263
+ try {
264
+ const [solanaModule, web3Module] = await Promise.all([
265
+ import('../solana'),
266
+ import('@solana/web3.js')
267
+ ]);
268
+ OnchainMailerClient.solanaModules = {
269
+ MailerClient: solanaModule.MailerClient,
270
+ PublicKey: web3Module.PublicKey,
271
+ Connection: web3Module.Connection
272
+ };
273
+ }
274
+ catch (error) {
275
+ throw new Error(`Failed to load Solana modules: ${error instanceof Error ? error.message : String(error)}`);
276
+ }
193
277
  }
194
278
  return OnchainMailerClient.solanaModules;
195
279
  }
196
- // EVM implementation methods
197
- async sendEVMMessage(to, subject, body, priority, resolveSenderToName) {
198
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
199
- throw new Error('EVM client not properly initialized');
200
- }
201
- const { MailerClient } = await this.getEVMModules();
202
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
203
- // Validate message
204
- if (!subject || subject.length > 200) {
205
- throw new Error('Subject must be 1-200 characters');
280
+ // Private methods for EVM implementation
281
+ async sendEVMMessage(subject, body, priority, resolveSenderToName = false) {
282
+ try {
283
+ const { viem, MailerClient } = await this.getEVMModules();
284
+ if (!this.config.evm) {
285
+ throw new Error('EVM configuration not provided');
286
+ }
287
+ if (!this.config.evm.contracts.mailer) {
288
+ throw new Error('EVM Mailer contract address not configured');
289
+ }
290
+ // Create clients
291
+ const publicClient = viem.createPublicClient({
292
+ transport: viem.http(this.config.evm.rpc),
293
+ chain: {
294
+ id: this.config.evm.chainId,
295
+ name: 'Custom Chain',
296
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
297
+ rpcUrls: {
298
+ default: { http: [this.config.evm.rpc] }
299
+ }
300
+ }
301
+ });
302
+ const walletClient = viem.createWalletClient({
303
+ transport: viem.http(this.config.evm.rpc),
304
+ chain: {
305
+ id: this.config.evm.chainId,
306
+ name: 'Custom Chain',
307
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
308
+ rpcUrls: {
309
+ default: { http: [this.config.evm.rpc] }
310
+ }
311
+ }
312
+ });
313
+ // Test connection
314
+ try {
315
+ await Promise.race([
316
+ publicClient.getChainId(),
317
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Connection timeout')), 10000))
318
+ ]);
319
+ }
320
+ catch (error) {
321
+ throw new Error(`Failed to connect to EVM network: ${error instanceof Error ? error.message : String(error)}`);
322
+ }
323
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
324
+ // Validate message before sending
325
+ if (!subject || subject.length > 200) {
326
+ throw new Error('Subject must be 1-200 characters');
327
+ }
328
+ if (!body || body.length > 10000) {
329
+ throw new Error('Body must be 1-10000 characters');
330
+ }
331
+ let txHash;
332
+ try {
333
+ txHash = await client.send(this.wallet.address, subject, body, priority, resolveSenderToName, walletClient, this.wallet.address);
334
+ }
335
+ catch (error) {
336
+ const errorMessage = error instanceof Error ? error.message : String(error);
337
+ if (errorMessage.includes('insufficient funds')) {
338
+ throw new Error('Insufficient USDC balance to send message');
339
+ }
340
+ if (errorMessage.includes('user rejected')) {
341
+ throw new Error('Transaction rejected by user');
342
+ }
343
+ throw new Error(`Transaction failed: ${errorMessage}`);
344
+ }
345
+ // Wait for confirmation with timeout
346
+ const receipt = await Promise.race([
347
+ publicClient.waitForTransactionReceipt({ hash: txHash }),
348
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Transaction confirmation timeout')), 60000))
349
+ ]);
350
+ return {
351
+ transactionHash: txHash,
352
+ chainType: ChainType.EVM,
353
+ messageId: undefined, // Could extract from logs if needed
354
+ fee: BigInt(priority ? '100000' : '10000'), // 0.1 or 0.01 USDC in micro-USDC
355
+ gasUsed: receipt.gasUsed,
356
+ isPriority: priority,
357
+ success: true
358
+ };
206
359
  }
207
- if (!body || body.length > 10000) {
208
- throw new Error('Body must be 1-10000 characters');
360
+ catch (error) {
361
+ throw new Error(`EVM message sending failed: ${error instanceof Error ? error.message : String(error)}`);
209
362
  }
210
- const [account] = await this.evmWalletClient.getAddresses();
211
- const payer = account;
212
- const result = await client.send(to, subject, body, payer, priority, resolveSenderToName, this.evmWalletClient, account);
213
- // Convert to MessageResult format
214
- return {
215
- transactionHash: result.hash,
216
- chainType: ChainType.EVM,
217
- fee: BigInt(priority ? '100000' : '10000'),
218
- gasUsed: result.gasUsed,
219
- isPriority: priority,
220
- success: true
221
- };
363
+ }
364
+ async registerEVMDomain(_domain, _isExtension) {
365
+ // Domain registration not implemented in current EVM version (delegation-only)
366
+ throw new Error('Domain registration not yet implemented in EVM version - use delegation instead');
222
367
  }
223
368
  async delegateEVM(delegate) {
224
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
225
- throw new Error('EVM client not properly initialized');
369
+ const { viem } = await this.getEVMModules();
370
+ if (!this.config.evm) {
371
+ throw new Error('EVM configuration not provided');
226
372
  }
227
- const { MailerClient } = await this.getEVMModules();
228
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
229
- const [account] = await this.evmWalletClient.getAddresses();
230
- const result = await client.delegateTo(delegate, this.evmWalletClient, account);
231
- return {
232
- transactionHash: result.hash,
233
- chainType: ChainType.EVM,
234
- delegate,
235
- success: true
236
- };
373
+ // Validate EVM address format
374
+ if (!viem.isAddress(delegate)) {
375
+ throw new Error('Invalid EVM address format for delegate');
376
+ }
377
+ // Note: Domain functionality is now integrated into the Mailer contract
378
+ throw new Error('Domain delegation is now handled through the Mailer contract - use MailerClient instead');
237
379
  }
238
380
  async claimEVMRevenue() {
239
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
240
- throw new Error('EVM client not properly initialized');
241
- }
242
- const { MailerClient } = await this.getEVMModules();
243
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
244
- const [account] = await this.evmWalletClient.getAddresses();
245
- const result = await client.claimRecipientShare(this.evmWalletClient, account);
381
+ const { viem, MailerClient } = await this.getEVMModules();
382
+ if (!this.config.evm) {
383
+ throw new Error('EVM configuration not provided');
384
+ }
385
+ const publicClient = viem.createPublicClient({
386
+ transport: viem.http(this.config.evm.rpc),
387
+ chain: {
388
+ id: this.config.evm.chainId,
389
+ name: 'Custom Chain',
390
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
391
+ rpcUrls: {
392
+ default: { http: [this.config.evm.rpc] }
393
+ }
394
+ }
395
+ });
396
+ const walletClient = viem.createWalletClient({
397
+ transport: viem.http(this.config.evm.rpc),
398
+ chain: {
399
+ id: this.config.evm.chainId,
400
+ name: 'Custom Chain',
401
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
402
+ rpcUrls: {
403
+ default: { http: [this.config.evm.rpc] }
404
+ }
405
+ }
406
+ });
407
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
408
+ const txHash = await client.claimRecipientShare(walletClient, this.wallet.address);
409
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
410
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
246
411
  return {
247
- hash: result.hash,
412
+ hash: txHash,
248
413
  chainType: ChainType.EVM,
249
- blockNumber: result.blockNumber,
250
- timestamp: Date.now()
414
+ blockNumber: receipt.blockNumber,
415
+ timestamp: Number(block.timestamp) * 1000
251
416
  };
252
417
  }
253
- // Solana implementation methods
254
- async sendSolanaMessage(to, subject, body, priority, resolveSenderToName) {
255
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
256
- throw new Error('Solana client not properly initialized');
257
- }
258
- const { MailerClient, PublicKey } = await this.getSolanaModules();
259
- const programId = new PublicKey(this.solanaProgramId);
260
- const usdcMint = new PublicKey(this.solanaUsdcMint);
261
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
262
- const result = await client.send(to, subject, body, priority, resolveSenderToName);
263
- // Get current fees
264
- const fees = await client.getFees();
265
- return {
266
- transactionHash: result.signature,
267
- chainType: ChainType.SOLANA,
268
- fee: priority ? fees.sendFee : fees.sendFee / 10,
269
- isPriority: priority,
270
- success: true
271
- };
418
+ // Private methods for Solana implementation
419
+ async sendSolanaMessage(subject, body, priority, resolveSenderToName = false) {
420
+ try {
421
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
422
+ if (!this.config.solana) {
423
+ throw new Error('Solana configuration not provided');
424
+ }
425
+ if (!this.config.solana.programs.mailer) {
426
+ throw new Error('Solana Mailer program address not configured');
427
+ }
428
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
429
+ // Test connection
430
+ try {
431
+ await Promise.race([
432
+ connection.getSlot(),
433
+ new Promise((_, reject) => setTimeout(() => reject(new Error('Connection timeout')), 10000))
434
+ ]);
435
+ }
436
+ catch (error) {
437
+ throw new Error(`Failed to connect to Solana RPC: ${error instanceof Error ? error.message : String(error)}`);
438
+ }
439
+ // Create wallet adapter for native client
440
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
441
+ const wallet = MailerClient.createWallet(this.wallet);
442
+ const programId = new PublicKey(this.config.solana.programs.mailer);
443
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
444
+ // For now, send to the wallet itself (self-messaging)
445
+ const recipientKey = new PublicKey(this.wallet.address);
446
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
447
+ // Get current fees
448
+ const fees = await client.getFees();
449
+ let txHash;
450
+ txHash = await client.send(recipientKey.toBase58(), subject, body, priority, resolveSenderToName);
451
+ // Get transaction details
452
+ const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
453
+ // Get current slot for transaction info
454
+ const slot = await connection.getSlot();
455
+ return {
456
+ transactionHash: txHash,
457
+ chainType: ChainType.SOLANA,
458
+ fee: priority ? fees.sendFee : fees.sendFee / 10,
459
+ recipient: recipientKey.toBase58(),
460
+ subject,
461
+ body,
462
+ slot,
463
+ timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
464
+ isPriority: priority,
465
+ success: true
466
+ };
467
+ }
468
+ catch (error) {
469
+ throw new Error(`Solana message sending failed: ${error instanceof Error ? error.message : String(error)}`);
470
+ }
471
+ }
472
+ async registerSolanaDomain(_domain, _isExtension) {
473
+ // Domain registration not implemented in current Solana version
474
+ throw new Error('Domain registration not yet implemented in Solana version - use delegation instead');
272
475
  }
273
- async delegateSolana(delegate) {
274
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
275
- throw new Error('Solana client not properly initialized');
476
+ async delegateSolana(_delegate) {
477
+ if (!this.config.solana) {
478
+ throw new Error('Solana configuration not provided');
276
479
  }
277
- const { MailerClient, PublicKey } = await this.getSolanaModules();
278
- const programId = new PublicKey(this.solanaProgramId);
279
- const usdcMint = new PublicKey(this.solanaUsdcMint);
280
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
281
- const result = await client.delegateTo(delegate);
282
- return {
283
- transactionHash: result.signature,
284
- chainType: ChainType.SOLANA,
285
- delegate,
286
- success: true
287
- };
480
+ // Note: Domain functionality is now integrated into the Mailer contract
481
+ throw new Error('Domain delegation is now handled through the Mailer contract - use MailerClient instead');
288
482
  }
289
483
  async claimSolanaRevenue() {
290
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
291
- throw new Error('Solana client not properly initialized');
292
- }
293
- const { MailerClient, PublicKey } = await this.getSolanaModules();
294
- const programId = new PublicKey(this.solanaProgramId);
295
- const usdcMint = new PublicKey(this.solanaUsdcMint);
296
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
297
- const result = await client.claimRecipientShare();
298
- const slot = await this.solanaConnection.getSlot();
484
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
485
+ if (!this.config.solana) {
486
+ throw new Error('Solana configuration not provided');
487
+ }
488
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
489
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
490
+ const wallet = MailerClient.createWallet(this.wallet);
491
+ const programId = new PublicKey(this.config.solana.programs.mailer);
492
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
493
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
494
+ const txHash = await client.claimRecipientShare();
495
+ const slot = await connection.getSlot();
299
496
  return {
300
- hash: result.signature,
497
+ hash: txHash,
301
498
  chainType: ChainType.SOLANA,
302
499
  slot,
303
500
  timestamp: Date.now()
304
501
  };
305
502
  }
306
- // Read methods
503
+ /**
504
+ * Get send fee using the appropriate chain implementation
505
+ * @returns Send fee in USDC micro-units (6 decimals)
506
+ */
307
507
  async getSendFee() {
308
- if (this.chainType === ChainType.EVM) {
508
+ if (this.chainType === 'evm') {
309
509
  return this.getEVMSendFee();
310
510
  }
311
511
  else {
312
512
  return this.getSolanaSendFee();
313
513
  }
314
514
  }
315
- async getEVMSendFee() {
316
- if (!this.evmPublicClient || !this.evmContractAddress) {
317
- throw new Error('EVM client not properly initialized');
318
- }
319
- const { MailerClient } = await this.getEVMModules();
320
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
321
- return client.getSendFee();
322
- }
323
- async getSolanaSendFee() {
324
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
325
- throw new Error('Solana client not properly initialized');
326
- }
327
- const { MailerClient, PublicKey } = await this.getSolanaModules();
328
- const programId = new PublicKey(this.solanaProgramId);
329
- const usdcMint = new PublicKey(this.solanaUsdcMint);
330
- // Create a minimal wallet object for reading
331
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
332
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
333
- const fees = await client.getFees();
334
- return BigInt(fees.sendFee);
335
- }
336
- // Additional read methods
515
+ /**
516
+ * Get claimable amount for an address
517
+ * @param address - Address to check claimable balance for (defaults to connected wallet)
518
+ * @returns Claimable amount in USDC micro-units
519
+ */
337
520
  async getClaimableAmount(address) {
338
- const targetAddress = address || await this.getWalletAddressAsync();
339
- if (this.chainType === ChainType.EVM) {
521
+ const targetAddress = address || this.wallet.address;
522
+ if (this.chainType === 'evm') {
340
523
  return this.getEVMClaimableAmount(targetAddress);
341
524
  }
342
525
  else {
343
526
  return this.getSolanaClaimableAmount(targetAddress);
344
527
  }
345
528
  }
346
- async getEVMClaimableAmount(address) {
347
- if (!this.evmPublicClient || !this.evmContractAddress) {
348
- throw new Error('EVM client not properly initialized');
349
- }
350
- const { MailerClient } = await this.getEVMModules();
351
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
352
- const result = await client.getRecipientClaimable(address);
353
- return result.amount;
354
- }
355
- async getSolanaClaimableAmount(address) {
356
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
357
- throw new Error('Solana client not properly initialized');
358
- }
359
- const { MailerClient, PublicKey } = await this.getSolanaModules();
360
- const programId = new PublicKey(this.solanaProgramId);
361
- const usdcMint = new PublicKey(this.solanaUsdcMint);
362
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
363
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
364
- const recipientKey = new PublicKey(address);
365
- const claimInfo = await client.getRecipientClaimable(recipientKey);
366
- return claimInfo ? BigInt(claimInfo.amount) : 0n;
367
- }
529
+ /**
530
+ * Get owner's claimable fee balance
531
+ * @returns Owner claimable amount in USDC micro-units
532
+ */
368
533
  async getOwnerClaimable() {
369
- if (this.chainType === ChainType.EVM) {
534
+ if (this.chainType === 'evm') {
370
535
  return this.getEVMOwnerClaimable();
371
536
  }
372
537
  else {
373
538
  return this.getSolanaOwnerClaimable();
374
539
  }
375
540
  }
376
- async getEVMOwnerClaimable() {
377
- if (!this.evmPublicClient || !this.evmContractAddress) {
378
- throw new Error('EVM client not properly initialized');
379
- }
380
- const { MailerClient } = await this.getEVMModules();
381
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
382
- return client.getOwnerClaimable();
383
- }
384
- async getSolanaOwnerClaimable() {
385
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
386
- throw new Error('Solana client not properly initialized');
387
- }
388
- const { MailerClient, PublicKey } = await this.getSolanaModules();
389
- const programId = new PublicKey(this.solanaProgramId);
390
- const usdcMint = new PublicKey(this.solanaUsdcMint);
391
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
392
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
393
- const amount = await client.getOwnerClaimable();
394
- return BigInt(amount);
395
- }
541
+ /**
542
+ * Get delegation information for an address
543
+ * @param address - Address to check delegation for (defaults to connected wallet)
544
+ * @returns Delegation address or null if no delegation
545
+ */
396
546
  async getDelegation(address) {
397
- const targetAddress = address || await this.getWalletAddressAsync();
398
- if (this.chainType === ChainType.EVM) {
547
+ const targetAddress = address || this.wallet.address;
548
+ if (this.chainType === 'evm') {
399
549
  return this.getEVMDelegation(targetAddress);
400
550
  }
401
551
  else {
402
552
  return this.getSolanaDelegation(targetAddress);
403
553
  }
404
554
  }
555
+ // EVM read methods
556
+ async getEVMSendFee() {
557
+ const { viem, MailerClient } = await this.getEVMModules();
558
+ if (!this.config.evm?.contracts.mailer) {
559
+ throw new Error('EVM Mailer contract address not configured');
560
+ }
561
+ const publicClient = viem.createPublicClient({
562
+ transport: viem.http(this.config.evm.rpc),
563
+ chain: {
564
+ id: this.config.evm.chainId,
565
+ name: 'Custom Chain',
566
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
567
+ rpcUrls: {
568
+ default: { http: [this.config.evm.rpc] }
569
+ }
570
+ }
571
+ });
572
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
573
+ return client.getSendFee();
574
+ }
575
+ async getEVMClaimableAmount(address) {
576
+ const { viem, MailerClient } = await this.getEVMModules();
577
+ if (!this.config.evm?.contracts.mailer) {
578
+ throw new Error('EVM Mailer contract address not configured');
579
+ }
580
+ const publicClient = viem.createPublicClient({
581
+ transport: viem.http(this.config.evm.rpc),
582
+ chain: {
583
+ id: this.config.evm.chainId,
584
+ name: 'Custom Chain',
585
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
586
+ rpcUrls: {
587
+ default: { http: [this.config.evm.rpc] }
588
+ }
589
+ }
590
+ });
591
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
592
+ const result = await client.getRecipientClaimable(address);
593
+ return result.amount;
594
+ }
595
+ async getEVMOwnerClaimable() {
596
+ const { viem, MailerClient } = await this.getEVMModules();
597
+ if (!this.config.evm?.contracts.mailer) {
598
+ throw new Error('EVM Mailer contract address not configured');
599
+ }
600
+ const publicClient = viem.createPublicClient({
601
+ transport: viem.http(this.config.evm.rpc),
602
+ chain: {
603
+ id: this.config.evm.chainId,
604
+ name: 'Custom Chain',
605
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
606
+ rpcUrls: {
607
+ default: { http: [this.config.evm.rpc] }
608
+ }
609
+ }
610
+ });
611
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
612
+ return client.getOwnerClaimable();
613
+ }
405
614
  async getEVMDelegation(_address) {
406
615
  // Delegation read not implemented in EVM client yet
616
+ // Would need to add getDelegation method to EVM MailerClient
407
617
  throw new Error('getDelegation not yet implemented for EVM');
408
618
  }
619
+ // Solana read methods
620
+ async getSolanaSendFee() {
621
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
622
+ if (!this.config.solana?.programs.mailer) {
623
+ throw new Error('Solana Mailer program address not configured');
624
+ }
625
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
626
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
627
+ const wallet = MailerClient.createWallet(this.wallet);
628
+ const programId = new PublicKey(this.config.solana.programs.mailer);
629
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
630
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
631
+ const fees = await client.getFees();
632
+ return BigInt(fees.sendFee);
633
+ }
634
+ async getSolanaClaimableAmount(address) {
635
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
636
+ if (!this.config.solana?.programs.mailer) {
637
+ throw new Error('Solana Mailer program address not configured');
638
+ }
639
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
640
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
641
+ const wallet = MailerClient.createWallet(this.wallet);
642
+ const programId = new PublicKey(this.config.solana.programs.mailer);
643
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
644
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
645
+ const recipientKey = new PublicKey(address);
646
+ const claimInfo = await client.getRecipientClaimable(recipientKey);
647
+ return claimInfo ? BigInt(claimInfo.amount) : 0n;
648
+ }
649
+ async getSolanaOwnerClaimable() {
650
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
651
+ if (!this.config.solana?.programs.mailer) {
652
+ throw new Error('Solana Mailer program address not configured');
653
+ }
654
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
655
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
656
+ const wallet = MailerClient.createWallet(this.wallet);
657
+ const programId = new PublicKey(this.config.solana.programs.mailer);
658
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
659
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
660
+ const amount = await client.getOwnerClaimable();
661
+ return BigInt(amount);
662
+ }
409
663
  async getSolanaDelegation(address) {
410
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
411
- throw new Error('Solana client not properly initialized');
412
- }
413
- const { MailerClient, PublicKey } = await this.getSolanaModules();
414
- const programId = new PublicKey(this.solanaProgramId);
415
- const usdcMint = new PublicKey(this.solanaUsdcMint);
416
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
417
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
664
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
665
+ if (!this.config.solana?.programs.mailer) {
666
+ throw new Error('Solana Mailer program address not configured');
667
+ }
668
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
669
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
670
+ const wallet = MailerClient.createWallet(this.wallet);
671
+ const programId = new PublicKey(this.config.solana.programs.mailer);
672
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
673
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
418
674
  const delegatorKey = new PublicKey(address);
419
675
  const delegationInfo = await client.getDelegation(delegatorKey);
420
676
  return delegationInfo?.delegate || null;
421
677
  }
422
- async getDelegationFee() {
423
- if (this.chainType === ChainType.EVM) {
424
- return this.getEVMDelegationFee();
678
+ /**
679
+ * Send a prepared message using mail ID (to match cross-chain behavior)
680
+ * @param to - Recipient address
681
+ * @param mailId - Pre-prepared message identifier
682
+ * @param priority - Whether to use priority sending with revenue share
683
+ * @param resolveSenderToName - If true, resolve sender address to name
684
+ * @returns Promise resolving to MessageResult
685
+ */
686
+ async sendPrepared(to, mailId, priority = false, resolveSenderToName = false) {
687
+ if (this.chainType === 'evm') {
688
+ return this.sendPreparedEVM(to, mailId, priority, resolveSenderToName);
425
689
  }
426
690
  else {
427
- return this.getSolanaDelegationFee();
691
+ return this.sendPreparedSolana(to, mailId, priority, resolveSenderToName);
428
692
  }
429
693
  }
430
- async getEVMDelegationFee() {
431
- if (!this.evmPublicClient || !this.evmContractAddress) {
432
- throw new Error('EVM client not properly initialized');
694
+ /**
695
+ * Send message to email address (no wallet known)
696
+ * @param toEmail - Email address of the recipient
697
+ * @param subject - Message subject
698
+ * @param body - Message body
699
+ * @returns Promise resolving to MessageResult
700
+ */
701
+ async sendToEmail(toEmail, subject, body) {
702
+ if (this.chainType === 'evm') {
703
+ return this.sendToEmailEVM(toEmail, subject, body);
433
704
  }
434
- const { MailerClient } = await this.getEVMModules();
435
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
436
- return client.getDelegationFee();
437
- }
438
- async getSolanaDelegationFee() {
439
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
440
- throw new Error('Solana client not properly initialized');
705
+ else {
706
+ return this.sendToEmailSolana(toEmail, subject, body);
441
707
  }
442
- const { MailerClient, PublicKey } = await this.getSolanaModules();
443
- const programId = new PublicKey(this.solanaProgramId);
444
- const usdcMint = new PublicKey(this.solanaUsdcMint);
445
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
446
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
447
- const fees = await client.getFees();
448
- return BigInt(fees.delegationFee);
449
708
  }
450
- async isPaused() {
451
- if (this.chainType === ChainType.EVM) {
452
- return this.isPausedEVM();
709
+ /**
710
+ * Send prepared message to email address (no wallet known)
711
+ * @param toEmail - Email address of the recipient
712
+ * @param mailId - Pre-prepared message identifier
713
+ * @returns Promise resolving to MessageResult
714
+ */
715
+ async sendPreparedToEmail(toEmail, mailId) {
716
+ if (this.chainType === 'evm') {
717
+ return this.sendPreparedToEmailEVM(toEmail, mailId);
453
718
  }
454
719
  else {
455
- return this.isPausedSolana();
720
+ return this.sendPreparedToEmailSolana(toEmail, mailId);
456
721
  }
457
722
  }
458
- async isPausedEVM() {
459
- if (!this.evmPublicClient || !this.evmContractAddress) {
460
- throw new Error('EVM client not properly initialized');
723
+ /**
724
+ * Set the send fee (owner only)
725
+ * @param newFee - New fee amount in USDC micro-units (6 decimals)
726
+ * @returns Promise resolving to transaction details
727
+ */
728
+ async setFee(newFee) {
729
+ if (this.chainType === 'evm') {
730
+ return this.setFeeEVM(newFee);
731
+ }
732
+ else {
733
+ return this.setFeeSolana(newFee);
461
734
  }
462
- const { MailerClient } = await this.getEVMModules();
463
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
464
- return client.isPaused();
465
735
  }
466
- async isPausedSolana() {
467
- if (!this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
468
- throw new Error('Solana client not properly initialized');
469
- }
470
- const { MailerClient, PublicKey } = await this.getSolanaModules();
471
- const programId = new PublicKey(this.solanaProgramId);
472
- const usdcMint = new PublicKey(this.solanaUsdcMint);
473
- const wallet = { publicKey: PublicKey.default, signTransaction: async (tx) => tx };
474
- const client = new MailerClient(this.solanaConnection, wallet, programId, usdcMint);
475
- return client.isPaused();
736
+ /**
737
+ * Get the current send fee
738
+ * @returns Current send fee in USDC micro-units (6 decimals)
739
+ */
740
+ async getFee() {
741
+ return this.getSendFee();
476
742
  }
477
- // Write methods for contract management
478
- async unpause() {
479
- if (this.chainType === ChainType.EVM) {
480
- return this.unpauseEVM();
743
+ /**
744
+ * Set the delegation fee (owner only)
745
+ * @param newFee - New delegation fee in USDC micro-units
746
+ * @returns Promise resolving to transaction details
747
+ */
748
+ async setDelegationFee(newFee) {
749
+ if (this.chainType === 'evm') {
750
+ return this.setDelegationFeeEVM(newFee);
481
751
  }
482
752
  else {
483
- return this.unpauseSolana();
753
+ return this.setDelegationFeeSolana(newFee);
484
754
  }
485
755
  }
486
- async unpauseEVM() {
487
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
488
- throw new Error('EVM client not properly initialized');
756
+ /**
757
+ * Get the current delegation fee
758
+ * @returns Current delegation fee in USDC micro-units
759
+ */
760
+ async getDelegationFee() {
761
+ if (this.chainType === 'evm') {
762
+ return this.getDelegationFeeEVM();
763
+ }
764
+ else {
765
+ return this.getDelegationFeeSolana();
489
766
  }
490
- const { MailerClient } = await this.getEVMModules();
491
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
492
- const [account] = await this.evmWalletClient.getAddresses();
493
- const result = await client.unpause(this.evmWalletClient, account);
494
- return {
495
- hash: result.hash,
496
- chainType: ChainType.EVM,
497
- blockNumber: result.blockNumber,
498
- timestamp: Date.now()
499
- };
500
767
  }
501
- async unpauseSolana() {
502
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
503
- throw new Error('Solana client not properly initialized');
504
- }
505
- const { MailerClient, PublicKey } = await this.getSolanaModules();
506
- const programId = new PublicKey(this.solanaProgramId);
507
- const usdcMint = new PublicKey(this.solanaUsdcMint);
508
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
509
- const result = await client.unpause();
510
- const slot = await this.solanaConnection.getSlot();
511
- return {
512
- hash: result.signature,
513
- chainType: ChainType.SOLANA,
514
- slot,
515
- timestamp: Date.now()
516
- };
768
+ /**
769
+ * Reject a delegation made to you by another address
770
+ * @param delegatorAddress - Address that delegated to you
771
+ * @returns Promise resolving to transaction details
772
+ */
773
+ async rejectDelegation(delegatorAddress) {
774
+ if (this.chainType === 'evm') {
775
+ return this.rejectDelegationEVM(delegatorAddress);
776
+ }
777
+ else {
778
+ return this.rejectDelegationSolana(delegatorAddress);
779
+ }
517
780
  }
518
- async emergencyUnpause() {
519
- if (this.chainType === ChainType.EVM) {
520
- return this.emergencyUnpauseEVM();
781
+ /**
782
+ * Claim owner share of fees (owner only)
783
+ * @returns Promise resolving to transaction details
784
+ */
785
+ async claimOwnerShare() {
786
+ if (this.chainType === 'evm') {
787
+ return this.claimOwnerShareEVM();
521
788
  }
522
789
  else {
523
- return this.emergencyUnpauseSolana();
790
+ return this.claimOwnerShareSolana();
524
791
  }
525
792
  }
526
- async emergencyUnpauseEVM() {
527
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
528
- throw new Error('EVM client not properly initialized');
793
+ /**
794
+ * Claim expired shares (owner only, EVM only)
795
+ * @param recipient - Address to claim expired shares for
796
+ * @returns Promise resolving to transaction details
797
+ */
798
+ async claimExpiredShares(recipient) {
799
+ if (this.chainType === 'evm') {
800
+ return this.claimExpiredSharesEVM(recipient);
801
+ }
802
+ else {
803
+ throw new Error('claimExpiredShares not available on Solana');
529
804
  }
530
- const { MailerClient } = await this.getEVMModules();
531
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
532
- const [account] = await this.evmWalletClient.getAddresses();
533
- const result = await client.emergencyUnpause(this.evmWalletClient, account);
534
- return {
535
- hash: result.hash,
536
- chainType: ChainType.EVM,
537
- blockNumber: result.blockNumber,
538
- timestamp: Date.now()
539
- };
540
805
  }
541
- async emergencyUnpauseSolana() {
542
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
543
- throw new Error('Solana client not properly initialized');
544
- }
545
- const { MailerClient, PublicKey } = await this.getSolanaModules();
546
- const programId = new PublicKey(this.solanaProgramId);
547
- const usdcMint = new PublicKey(this.solanaUsdcMint);
548
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
549
- const result = await client.emergencyUnpause();
550
- const slot = await this.solanaConnection.getSlot();
551
- return {
552
- hash: result.signature,
553
- chainType: ChainType.SOLANA,
554
- slot,
555
- timestamp: Date.now()
556
- };
806
+ /**
807
+ * Pause the contract and distribute funds (owner only)
808
+ * @returns Promise resolving to transaction details
809
+ */
810
+ async pause() {
811
+ if (this.chainType === 'evm') {
812
+ return this.pauseEVM();
813
+ }
814
+ else {
815
+ return this.pauseSolana();
816
+ }
557
817
  }
558
- async distributeClaimableFunds(recipient) {
559
- if (this.chainType === ChainType.EVM) {
560
- return this.distributeClaimableFundsEVM(recipient);
818
+ /**
819
+ * Unpause the contract (owner only)
820
+ * @returns Promise resolving to transaction details
821
+ */
822
+ async unpause() {
823
+ if (this.chainType === 'evm') {
824
+ return this.unpauseEVM();
561
825
  }
562
826
  else {
563
- return this.distributeClaimableFundsSolana(recipient);
827
+ return this.unpauseSolana();
564
828
  }
565
829
  }
566
- async distributeClaimableFundsEVM(recipient) {
567
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
568
- throw new Error('EVM client not properly initialized');
830
+ /**
831
+ * Emergency unpause without fund distribution (owner only)
832
+ * @returns Promise resolving to transaction details
833
+ */
834
+ async emergencyUnpause() {
835
+ if (this.chainType === 'evm') {
836
+ return this.emergencyUnpauseEVM();
837
+ }
838
+ else {
839
+ return this.emergencyUnpauseSolana();
569
840
  }
570
- const { MailerClient } = await this.getEVMModules();
571
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
572
- const [account] = await this.evmWalletClient.getAddresses();
573
- const result = await client.distributeClaimableFunds(recipient, this.evmWalletClient, account);
574
- return {
575
- hash: result.hash,
576
- chainType: ChainType.EVM,
577
- blockNumber: result.blockNumber,
578
- timestamp: Date.now()
579
- };
580
841
  }
581
- async distributeClaimableFundsSolana(recipient) {
582
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
583
- throw new Error('Solana client not properly initialized');
584
- }
585
- const { MailerClient, PublicKey } = await this.getSolanaModules();
586
- const programId = new PublicKey(this.solanaProgramId);
587
- const usdcMint = new PublicKey(this.solanaUsdcMint);
588
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
589
- const result = await client.distributeClaimableFunds(recipient);
590
- const slot = await this.solanaConnection.getSlot();
591
- return {
592
- hash: result.signature,
593
- chainType: ChainType.SOLANA,
594
- slot,
595
- timestamp: Date.now()
596
- };
842
+ /**
843
+ * Check if contract is currently paused
844
+ * @returns True if contract is paused, false otherwise
845
+ */
846
+ async isPaused() {
847
+ if (this.chainType === 'evm') {
848
+ return this.isPausedEVM();
849
+ }
850
+ else {
851
+ return this.isPausedSolana();
852
+ }
597
853
  }
598
- // Additional methods for complete API compatibility
599
- async sendPrepared(to, mailId, priority = false, resolveSenderToName = false) {
600
- if (this.chainType === ChainType.EVM) {
601
- return this.sendPreparedEVM(to, mailId, priority, resolveSenderToName);
854
+ /**
855
+ * Distribute claimable funds to a recipient when contract is paused
856
+ * @param recipient - Address to distribute funds for
857
+ * @returns Promise resolving to transaction details
858
+ */
859
+ async distributeClaimableFunds(recipient) {
860
+ if (this.chainType === 'evm') {
861
+ return this.distributeClaimableFundsEVM(recipient);
602
862
  }
603
863
  else {
604
- return this.sendPreparedSolana(to, mailId, priority, resolveSenderToName);
864
+ return this.distributeClaimableFundsSolana(recipient);
605
865
  }
606
866
  }
867
+ // EVM Implementation Methods
607
868
  async sendPreparedEVM(to, mailId, priority, resolveSenderToName) {
608
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
609
- throw new Error('EVM client not properly initialized');
610
- }
611
- const { MailerClient } = await this.getEVMModules();
612
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
613
- const [account] = await this.evmWalletClient.getAddresses();
614
- const payer = account;
615
- const result = await client.sendPrepared(to, mailId, payer, priority, resolveSenderToName, this.evmWalletClient, account);
869
+ const { viem, MailerClient } = await this.getEVMModules();
870
+ if (!this.config.evm?.contracts.mailer) {
871
+ throw new Error('EVM Mailer contract address not configured');
872
+ }
873
+ const publicClient = viem.createPublicClient({
874
+ transport: viem.http(this.config.evm.rpc),
875
+ chain: {
876
+ id: this.config.evm.chainId,
877
+ name: 'Custom Chain',
878
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
879
+ rpcUrls: {
880
+ default: { http: [this.config.evm.rpc] }
881
+ }
882
+ }
883
+ });
884
+ const walletClient = viem.createWalletClient({
885
+ transport: viem.http(this.config.evm.rpc),
886
+ chain: {
887
+ id: this.config.evm.chainId,
888
+ name: 'Custom Chain',
889
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
890
+ rpcUrls: {
891
+ default: { http: [this.config.evm.rpc] }
892
+ }
893
+ }
894
+ });
895
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
896
+ const txHash = await client.sendPrepared(to, mailId, priority, resolveSenderToName, walletClient, this.wallet.address);
897
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
616
898
  return {
617
- transactionHash: result.hash,
899
+ transactionHash: txHash,
618
900
  chainType: ChainType.EVM,
619
901
  fee: BigInt(priority ? '100000' : '10000'),
620
- gasUsed: result.gasUsed,
902
+ gasUsed: receipt.gasUsed,
621
903
  isPriority: priority,
622
904
  success: true
623
905
  };
624
906
  }
625
- async sendPreparedSolana(to, mailId, priority, resolveSenderToName) {
626
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
627
- throw new Error('Solana client not properly initialized');
628
- }
629
- const { MailerClient, PublicKey } = await this.getSolanaModules();
630
- const programId = new PublicKey(this.solanaProgramId);
631
- const usdcMint = new PublicKey(this.solanaUsdcMint);
632
- const recipientKey = new PublicKey(to);
633
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
634
- const result = await client.sendPrepared(recipientKey, mailId, priority, resolveSenderToName);
635
- const fees = await client.getFees();
907
+ async sendToEmailEVM(toEmail, subject, body) {
908
+ const { viem, MailerClient } = await this.getEVMModules();
909
+ if (!this.config.evm?.contracts.mailer) {
910
+ throw new Error('EVM Mailer contract address not configured');
911
+ }
912
+ const publicClient = viem.createPublicClient({
913
+ transport: viem.http(this.config.evm.rpc),
914
+ chain: {
915
+ id: this.config.evm.chainId,
916
+ name: 'Custom Chain',
917
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
918
+ rpcUrls: {
919
+ default: { http: [this.config.evm.rpc] }
920
+ }
921
+ }
922
+ });
923
+ const walletClient = viem.createWalletClient({
924
+ transport: viem.http(this.config.evm.rpc),
925
+ chain: {
926
+ id: this.config.evm.chainId,
927
+ name: 'Custom Chain',
928
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
929
+ rpcUrls: {
930
+ default: { http: [this.config.evm.rpc] }
931
+ }
932
+ }
933
+ });
934
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
935
+ const txHash = await client.sendToEmailAddress(toEmail, subject, body, walletClient, this.wallet.address);
936
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
636
937
  return {
637
- transactionHash: result.signature,
638
- chainType: ChainType.SOLANA,
639
- fee: priority ? fees.sendFee : fees.sendFee / 10,
640
- isPriority: priority,
938
+ transactionHash: txHash,
939
+ chainType: ChainType.EVM,
940
+ fee: BigInt('10000'), // 10% fee only
941
+ gasUsed: receipt.gasUsed,
942
+ isPriority: false,
641
943
  success: true
642
944
  };
643
945
  }
644
- async sendToEmail(toEmail, subject, body) {
645
- if (this.chainType === ChainType.EVM) {
646
- return this.sendToEmailEVM(toEmail, subject, body);
647
- }
648
- else {
649
- return this.sendToEmailSolana(toEmail, subject, body);
650
- }
651
- }
652
- async sendToEmailEVM(toEmail, subject, body) {
653
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
654
- throw new Error('EVM client not properly initialized');
655
- }
656
- const { MailerClient } = await this.getEVMModules();
657
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
658
- const [account] = await this.evmWalletClient.getAddresses();
659
- const payer = account;
660
- const result = await client.sendToEmailAddress(toEmail, subject, body, payer, this.evmWalletClient, account);
946
+ async sendPreparedToEmailEVM(toEmail, mailId) {
947
+ const { viem, MailerClient } = await this.getEVMModules();
948
+ if (!this.config.evm?.contracts.mailer) {
949
+ throw new Error('EVM Mailer contract address not configured');
950
+ }
951
+ const publicClient = viem.createPublicClient({
952
+ transport: viem.http(this.config.evm.rpc),
953
+ chain: {
954
+ id: this.config.evm.chainId,
955
+ name: 'Custom Chain',
956
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
957
+ rpcUrls: {
958
+ default: { http: [this.config.evm.rpc] }
959
+ }
960
+ }
961
+ });
962
+ const walletClient = viem.createWalletClient({
963
+ transport: viem.http(this.config.evm.rpc),
964
+ chain: {
965
+ id: this.config.evm.chainId,
966
+ name: 'Custom Chain',
967
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
968
+ rpcUrls: {
969
+ default: { http: [this.config.evm.rpc] }
970
+ }
971
+ }
972
+ });
973
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
974
+ const txHash = await client.sendPreparedToEmailAddress(toEmail, mailId, walletClient, this.wallet.address);
975
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
661
976
  return {
662
- transactionHash: result.hash,
977
+ transactionHash: txHash,
663
978
  chainType: ChainType.EVM,
664
979
  fee: BigInt('10000'), // 10% fee only
665
- gasUsed: result.gasUsed,
980
+ gasUsed: receipt.gasUsed,
666
981
  isPriority: false,
667
982
  success: true
668
983
  };
669
984
  }
670
- async sendToEmailSolana(toEmail, subject, body) {
671
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
672
- throw new Error('Solana client not properly initialized');
673
- }
674
- const { MailerClient, PublicKey } = await this.getSolanaModules();
675
- const programId = new PublicKey(this.solanaProgramId);
676
- const usdcMint = new PublicKey(this.solanaUsdcMint);
677
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
678
- const result = await client.sendToEmail(toEmail, subject, body);
679
- const fees = await client.getFees();
985
+ async setFeeEVM(newFee) {
986
+ const { viem, MailerClient } = await this.getEVMModules();
987
+ if (!this.config.evm?.contracts.mailer) {
988
+ throw new Error('EVM Mailer contract address not configured');
989
+ }
990
+ const publicClient = viem.createPublicClient({
991
+ transport: viem.http(this.config.evm.rpc),
992
+ chain: {
993
+ id: this.config.evm.chainId,
994
+ name: 'Custom Chain',
995
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
996
+ rpcUrls: {
997
+ default: { http: [this.config.evm.rpc] }
998
+ }
999
+ }
1000
+ });
1001
+ const walletClient = viem.createWalletClient({
1002
+ transport: viem.http(this.config.evm.rpc),
1003
+ chain: {
1004
+ id: this.config.evm.chainId,
1005
+ name: 'Custom Chain',
1006
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1007
+ rpcUrls: {
1008
+ default: { http: [this.config.evm.rpc] }
1009
+ }
1010
+ }
1011
+ });
1012
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1013
+ const txHash = await client.setFee(newFee, walletClient, this.wallet.address);
1014
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1015
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
680
1016
  return {
681
- transactionHash: result.signature,
682
- chainType: ChainType.SOLANA,
683
- fee: fees.sendFee / 10, // 10% fee only
684
- isPriority: false,
685
- success: true
1017
+ hash: txHash,
1018
+ chainType: ChainType.EVM,
1019
+ blockNumber: receipt.blockNumber,
1020
+ timestamp: Number(block.timestamp) * 1000
686
1021
  };
687
1022
  }
688
- async sendPreparedToEmail(toEmail, mailId) {
689
- if (this.chainType === ChainType.EVM) {
690
- return this.sendPreparedToEmailEVM(toEmail, mailId);
691
- }
692
- else {
693
- return this.sendPreparedToEmailSolana(toEmail, mailId);
694
- }
1023
+ async setDelegationFeeEVM(newFee) {
1024
+ const { viem, MailerClient } = await this.getEVMModules();
1025
+ if (!this.config.evm?.contracts.mailer) {
1026
+ throw new Error('EVM Mailer contract address not configured');
1027
+ }
1028
+ const publicClient = viem.createPublicClient({
1029
+ transport: viem.http(this.config.evm.rpc),
1030
+ chain: {
1031
+ id: this.config.evm.chainId,
1032
+ name: 'Custom Chain',
1033
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1034
+ rpcUrls: {
1035
+ default: { http: [this.config.evm.rpc] }
1036
+ }
1037
+ }
1038
+ });
1039
+ const walletClient = viem.createWalletClient({
1040
+ transport: viem.http(this.config.evm.rpc),
1041
+ chain: {
1042
+ id: this.config.evm.chainId,
1043
+ name: 'Custom Chain',
1044
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1045
+ rpcUrls: {
1046
+ default: { http: [this.config.evm.rpc] }
1047
+ }
1048
+ }
1049
+ });
1050
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1051
+ const txHash = await client.setDelegationFee(newFee, walletClient, this.wallet.address);
1052
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1053
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1054
+ return {
1055
+ hash: txHash,
1056
+ chainType: ChainType.EVM,
1057
+ blockNumber: receipt.blockNumber,
1058
+ timestamp: Number(block.timestamp) * 1000
1059
+ };
695
1060
  }
696
- async sendPreparedToEmailEVM(toEmail, mailId) {
697
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
698
- throw new Error('EVM client not properly initialized');
699
- }
700
- const { MailerClient } = await this.getEVMModules();
701
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
702
- const [account] = await this.evmWalletClient.getAddresses();
703
- const payer = account;
704
- const result = await client.sendPreparedToEmailAddress(toEmail, mailId, payer, this.evmWalletClient, account);
1061
+ async getDelegationFeeEVM() {
1062
+ const { viem, MailerClient } = await this.getEVMModules();
1063
+ if (!this.config.evm?.contracts.mailer) {
1064
+ throw new Error('EVM Mailer contract address not configured');
1065
+ }
1066
+ const publicClient = viem.createPublicClient({
1067
+ transport: viem.http(this.config.evm.rpc),
1068
+ chain: {
1069
+ id: this.config.evm.chainId,
1070
+ name: 'Custom Chain',
1071
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1072
+ rpcUrls: {
1073
+ default: { http: [this.config.evm.rpc] }
1074
+ }
1075
+ }
1076
+ });
1077
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1078
+ return client.getDelegationFee();
1079
+ }
1080
+ async rejectDelegationEVM(delegatorAddress) {
1081
+ const { viem, MailerClient } = await this.getEVMModules();
1082
+ if (!this.config.evm?.contracts.mailer) {
1083
+ throw new Error('EVM Mailer contract address not configured');
1084
+ }
1085
+ const publicClient = viem.createPublicClient({
1086
+ transport: viem.http(this.config.evm.rpc),
1087
+ chain: {
1088
+ id: this.config.evm.chainId,
1089
+ name: 'Custom Chain',
1090
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1091
+ rpcUrls: {
1092
+ default: { http: [this.config.evm.rpc] }
1093
+ }
1094
+ }
1095
+ });
1096
+ const walletClient = viem.createWalletClient({
1097
+ transport: viem.http(this.config.evm.rpc),
1098
+ chain: {
1099
+ id: this.config.evm.chainId,
1100
+ name: 'Custom Chain',
1101
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1102
+ rpcUrls: {
1103
+ default: { http: [this.config.evm.rpc] }
1104
+ }
1105
+ }
1106
+ });
1107
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1108
+ const txHash = await client.rejectDelegation(delegatorAddress, walletClient, this.wallet.address);
1109
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1110
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
705
1111
  return {
706
- transactionHash: result.hash,
1112
+ hash: txHash,
707
1113
  chainType: ChainType.EVM,
708
- fee: BigInt('10000'), // 10% fee only
709
- gasUsed: result.gasUsed,
710
- isPriority: false,
711
- success: true
1114
+ blockNumber: receipt.blockNumber,
1115
+ timestamp: Number(block.timestamp) * 1000
712
1116
  };
713
1117
  }
714
- async sendPreparedToEmailSolana(toEmail, mailId) {
715
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
716
- throw new Error('Solana client not properly initialized');
717
- }
718
- const { MailerClient, PublicKey } = await this.getSolanaModules();
719
- const programId = new PublicKey(this.solanaProgramId);
720
- const usdcMint = new PublicKey(this.solanaUsdcMint);
721
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
722
- const result = await client.sendPreparedToEmail(toEmail, mailId);
723
- const fees = await client.getFees();
1118
+ async claimOwnerShareEVM() {
1119
+ const { viem, MailerClient } = await this.getEVMModules();
1120
+ if (!this.config.evm?.contracts.mailer) {
1121
+ throw new Error('EVM Mailer contract address not configured');
1122
+ }
1123
+ const publicClient = viem.createPublicClient({
1124
+ transport: viem.http(this.config.evm.rpc),
1125
+ chain: {
1126
+ id: this.config.evm.chainId,
1127
+ name: 'Custom Chain',
1128
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1129
+ rpcUrls: {
1130
+ default: { http: [this.config.evm.rpc] }
1131
+ }
1132
+ }
1133
+ });
1134
+ const walletClient = viem.createWalletClient({
1135
+ transport: viem.http(this.config.evm.rpc),
1136
+ chain: {
1137
+ id: this.config.evm.chainId,
1138
+ name: 'Custom Chain',
1139
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1140
+ rpcUrls: {
1141
+ default: { http: [this.config.evm.rpc] }
1142
+ }
1143
+ }
1144
+ });
1145
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1146
+ const txHash = await client.claimOwnerShare(walletClient, this.wallet.address);
1147
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1148
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
724
1149
  return {
725
- transactionHash: result.signature,
726
- chainType: ChainType.SOLANA,
727
- fee: fees.sendFee / 10, // 10% fee only
728
- isPriority: false,
729
- success: true
1150
+ hash: txHash,
1151
+ chainType: ChainType.EVM,
1152
+ blockNumber: receipt.blockNumber,
1153
+ timestamp: Number(block.timestamp) * 1000
730
1154
  };
731
1155
  }
732
- async claimOwnerShare() {
733
- if (this.chainType === ChainType.EVM) {
734
- return this.claimOwnerShareEVM();
735
- }
736
- else {
737
- return this.claimOwnerShareSolana();
738
- }
1156
+ async claimExpiredSharesEVM(recipient) {
1157
+ const { viem, MailerClient } = await this.getEVMModules();
1158
+ if (!this.config.evm?.contracts.mailer) {
1159
+ throw new Error('EVM Mailer contract address not configured');
1160
+ }
1161
+ const publicClient = viem.createPublicClient({
1162
+ transport: viem.http(this.config.evm.rpc),
1163
+ chain: {
1164
+ id: this.config.evm.chainId,
1165
+ name: 'Custom Chain',
1166
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1167
+ rpcUrls: {
1168
+ default: { http: [this.config.evm.rpc] }
1169
+ }
1170
+ }
1171
+ });
1172
+ const walletClient = viem.createWalletClient({
1173
+ transport: viem.http(this.config.evm.rpc),
1174
+ chain: {
1175
+ id: this.config.evm.chainId,
1176
+ name: 'Custom Chain',
1177
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1178
+ rpcUrls: {
1179
+ default: { http: [this.config.evm.rpc] }
1180
+ }
1181
+ }
1182
+ });
1183
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1184
+ const txHash = await client.claimExpiredShares(recipient, walletClient, this.wallet.address);
1185
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1186
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1187
+ return {
1188
+ hash: txHash,
1189
+ chainType: ChainType.EVM,
1190
+ blockNumber: receipt.blockNumber,
1191
+ timestamp: Number(block.timestamp) * 1000
1192
+ };
739
1193
  }
740
- async claimOwnerShareEVM() {
741
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
742
- throw new Error('EVM client not properly initialized');
743
- }
744
- const { MailerClient } = await this.getEVMModules();
745
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
746
- const [account] = await this.evmWalletClient.getAddresses();
747
- const result = await client.claimOwnerShare(this.evmWalletClient, account);
1194
+ async pauseEVM() {
1195
+ const { viem, MailerClient } = await this.getEVMModules();
1196
+ if (!this.config.evm?.contracts.mailer) {
1197
+ throw new Error('EVM Mailer contract address not configured');
1198
+ }
1199
+ const publicClient = viem.createPublicClient({
1200
+ transport: viem.http(this.config.evm.rpc),
1201
+ chain: {
1202
+ id: this.config.evm.chainId,
1203
+ name: 'Custom Chain',
1204
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1205
+ rpcUrls: {
1206
+ default: { http: [this.config.evm.rpc] }
1207
+ }
1208
+ }
1209
+ });
1210
+ const walletClient = viem.createWalletClient({
1211
+ transport: viem.http(this.config.evm.rpc),
1212
+ chain: {
1213
+ id: this.config.evm.chainId,
1214
+ name: 'Custom Chain',
1215
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1216
+ rpcUrls: {
1217
+ default: { http: [this.config.evm.rpc] }
1218
+ }
1219
+ }
1220
+ });
1221
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1222
+ const txHash = await client.pause(walletClient, this.wallet.address);
1223
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1224
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
748
1225
  return {
749
- hash: result.hash,
1226
+ hash: txHash,
750
1227
  chainType: ChainType.EVM,
751
- blockNumber: result.blockNumber,
752
- timestamp: Date.now()
1228
+ blockNumber: receipt.blockNumber,
1229
+ timestamp: Number(block.timestamp) * 1000
753
1230
  };
754
1231
  }
755
- async claimOwnerShareSolana() {
756
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
757
- throw new Error('Solana client not properly initialized');
758
- }
759
- const { MailerClient, PublicKey } = await this.getSolanaModules();
760
- const programId = new PublicKey(this.solanaProgramId);
761
- const usdcMint = new PublicKey(this.solanaUsdcMint);
762
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
763
- const result = await client.claimOwnerShare();
764
- const slot = await this.solanaConnection.getSlot();
1232
+ async unpauseEVM() {
1233
+ const { viem, MailerClient } = await this.getEVMModules();
1234
+ if (!this.config.evm?.contracts.mailer) {
1235
+ throw new Error('EVM Mailer contract address not configured');
1236
+ }
1237
+ const publicClient = viem.createPublicClient({
1238
+ transport: viem.http(this.config.evm.rpc),
1239
+ chain: {
1240
+ id: this.config.evm.chainId,
1241
+ name: 'Custom Chain',
1242
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1243
+ rpcUrls: {
1244
+ default: { http: [this.config.evm.rpc] }
1245
+ }
1246
+ }
1247
+ });
1248
+ const walletClient = viem.createWalletClient({
1249
+ transport: viem.http(this.config.evm.rpc),
1250
+ chain: {
1251
+ id: this.config.evm.chainId,
1252
+ name: 'Custom Chain',
1253
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1254
+ rpcUrls: {
1255
+ default: { http: [this.config.evm.rpc] }
1256
+ }
1257
+ }
1258
+ });
1259
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1260
+ const txHash = await client.unpause(walletClient, this.wallet.address);
1261
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1262
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
765
1263
  return {
766
- hash: result.signature,
767
- chainType: ChainType.SOLANA,
768
- slot,
769
- timestamp: Date.now()
1264
+ hash: txHash,
1265
+ chainType: ChainType.EVM,
1266
+ blockNumber: receipt.blockNumber,
1267
+ timestamp: Number(block.timestamp) * 1000
770
1268
  };
771
1269
  }
772
- async claimExpiredShares(recipient) {
773
- if (this.chainType === ChainType.EVM) {
774
- return this.claimExpiredSharesEVM(recipient);
775
- }
776
- else {
777
- return this.claimExpiredSharesSolana(recipient);
778
- }
1270
+ async emergencyUnpauseEVM() {
1271
+ const { viem, MailerClient } = await this.getEVMModules();
1272
+ if (!this.config.evm?.contracts.mailer) {
1273
+ throw new Error('EVM Mailer contract address not configured');
1274
+ }
1275
+ const publicClient = viem.createPublicClient({
1276
+ transport: viem.http(this.config.evm.rpc),
1277
+ chain: {
1278
+ id: this.config.evm.chainId,
1279
+ name: 'Custom Chain',
1280
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1281
+ rpcUrls: {
1282
+ default: { http: [this.config.evm.rpc] }
1283
+ }
1284
+ }
1285
+ });
1286
+ const walletClient = viem.createWalletClient({
1287
+ transport: viem.http(this.config.evm.rpc),
1288
+ chain: {
1289
+ id: this.config.evm.chainId,
1290
+ name: 'Custom Chain',
1291
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1292
+ rpcUrls: {
1293
+ default: { http: [this.config.evm.rpc] }
1294
+ }
1295
+ }
1296
+ });
1297
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1298
+ const txHash = await client.emergencyUnpause(walletClient, this.wallet.address);
1299
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1300
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1301
+ return {
1302
+ hash: txHash,
1303
+ chainType: ChainType.EVM,
1304
+ blockNumber: receipt.blockNumber,
1305
+ timestamp: Number(block.timestamp) * 1000
1306
+ };
779
1307
  }
780
- async claimExpiredSharesEVM(recipient) {
781
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
782
- throw new Error('EVM client not properly initialized');
783
- }
784
- const { MailerClient } = await this.getEVMModules();
785
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
786
- const [account] = await this.evmWalletClient.getAddresses();
787
- const result = await client.claimExpiredShares(recipient, this.evmWalletClient, account);
1308
+ async isPausedEVM() {
1309
+ const { viem, MailerClient } = await this.getEVMModules();
1310
+ if (!this.config.evm?.contracts.mailer) {
1311
+ throw new Error('EVM Mailer contract address not configured');
1312
+ }
1313
+ const publicClient = viem.createPublicClient({
1314
+ transport: viem.http(this.config.evm.rpc),
1315
+ chain: {
1316
+ id: this.config.evm.chainId,
1317
+ name: 'Custom Chain',
1318
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1319
+ rpcUrls: {
1320
+ default: { http: [this.config.evm.rpc] }
1321
+ }
1322
+ }
1323
+ });
1324
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1325
+ return client.isPaused();
1326
+ }
1327
+ async distributeClaimableFundsEVM(recipient) {
1328
+ const { viem, MailerClient } = await this.getEVMModules();
1329
+ if (!this.config.evm?.contracts.mailer) {
1330
+ throw new Error('EVM Mailer contract address not configured');
1331
+ }
1332
+ const publicClient = viem.createPublicClient({
1333
+ transport: viem.http(this.config.evm.rpc),
1334
+ chain: {
1335
+ id: this.config.evm.chainId,
1336
+ name: 'Custom Chain',
1337
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1338
+ rpcUrls: {
1339
+ default: { http: [this.config.evm.rpc] }
1340
+ }
1341
+ }
1342
+ });
1343
+ const walletClient = viem.createWalletClient({
1344
+ transport: viem.http(this.config.evm.rpc),
1345
+ chain: {
1346
+ id: this.config.evm.chainId,
1347
+ name: 'Custom Chain',
1348
+ nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1349
+ rpcUrls: {
1350
+ default: { http: [this.config.evm.rpc] }
1351
+ }
1352
+ }
1353
+ });
1354
+ const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1355
+ const txHash = await client.distributeClaimableFunds(recipient, walletClient, this.wallet.address);
1356
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1357
+ const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
788
1358
  return {
789
- hash: result.hash,
1359
+ hash: txHash,
790
1360
  chainType: ChainType.EVM,
791
- blockNumber: result.blockNumber,
792
- timestamp: Date.now()
1361
+ blockNumber: receipt.blockNumber,
1362
+ timestamp: Number(block.timestamp) * 1000
793
1363
  };
794
1364
  }
795
- async claimExpiredSharesSolana(recipient) {
796
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
797
- throw new Error('Solana client not properly initialized');
798
- }
799
- const { MailerClient, PublicKey } = await this.getSolanaModules();
800
- const programId = new PublicKey(this.solanaProgramId);
801
- const usdcMint = new PublicKey(this.solanaUsdcMint);
802
- const recipientKey = new PublicKey(recipient);
803
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
804
- const result = await client.claimExpiredShares(recipientKey);
805
- const slot = await this.solanaConnection.getSlot();
1365
+ // Solana Implementation Methods
1366
+ async sendPreparedSolana(to, mailId, priority, resolveSenderToName) {
1367
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1368
+ if (!this.config.solana?.programs.mailer) {
1369
+ throw new Error('Solana Mailer program address not configured');
1370
+ }
1371
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1372
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1373
+ const wallet = MailerClient.createWallet(this.wallet);
1374
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1375
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1376
+ const recipientKey = new PublicKey(to);
1377
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1378
+ const txHash = await client.sendPrepared(recipientKey, mailId, priority, resolveSenderToName);
1379
+ const fees = await client.getFees();
1380
+ const slot = await connection.getSlot();
1381
+ const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
806
1382
  return {
807
- hash: result.signature,
1383
+ transactionHash: txHash,
808
1384
  chainType: ChainType.SOLANA,
1385
+ fee: priority ? fees.sendFee : fees.sendFee / 10,
809
1386
  slot,
810
- timestamp: Date.now()
1387
+ timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1388
+ isPriority: priority,
1389
+ success: true
811
1390
  };
812
1391
  }
813
- async rejectDelegation(delegatorAddress) {
814
- if (this.chainType === ChainType.EVM) {
815
- return this.rejectDelegationEVM(delegatorAddress);
816
- }
817
- else {
818
- return this.rejectDelegationSolana(delegatorAddress);
819
- }
1392
+ async sendToEmailSolana(toEmail, subject, body) {
1393
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1394
+ if (!this.config.solana?.programs.mailer) {
1395
+ throw new Error('Solana Mailer program address not configured');
1396
+ }
1397
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1398
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1399
+ const wallet = MailerClient.createWallet(this.wallet);
1400
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1401
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1402
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1403
+ const txHash = await client.sendToEmail(toEmail, subject, body);
1404
+ const fees = await client.getFees();
1405
+ const slot = await connection.getSlot();
1406
+ const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
1407
+ return {
1408
+ transactionHash: txHash,
1409
+ chainType: ChainType.SOLANA,
1410
+ fee: fees.sendFee / 10, // 10% fee only
1411
+ slot,
1412
+ timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1413
+ isPriority: false,
1414
+ success: true
1415
+ };
820
1416
  }
821
- async rejectDelegationEVM(delegatorAddress) {
822
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
823
- throw new Error('EVM client not properly initialized');
824
- }
825
- const { MailerClient } = await this.getEVMModules();
826
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
827
- const [account] = await this.evmWalletClient.getAddresses();
828
- const result = await client.rejectDelegation(delegatorAddress, this.evmWalletClient, account);
1417
+ async sendPreparedToEmailSolana(toEmail, mailId) {
1418
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1419
+ if (!this.config.solana?.programs.mailer) {
1420
+ throw new Error('Solana Mailer program address not configured');
1421
+ }
1422
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1423
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1424
+ const wallet = MailerClient.createWallet(this.wallet);
1425
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1426
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1427
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1428
+ const txHash = await client.sendPreparedToEmail(toEmail, mailId);
1429
+ const fees = await client.getFees();
1430
+ const slot = await connection.getSlot();
1431
+ const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
829
1432
  return {
830
- hash: result.hash,
831
- chainType: ChainType.EVM,
832
- blockNumber: result.blockNumber,
1433
+ transactionHash: txHash,
1434
+ chainType: ChainType.SOLANA,
1435
+ fee: fees.sendFee / 10, // 10% fee only
1436
+ slot,
1437
+ timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1438
+ isPriority: false,
1439
+ success: true
1440
+ };
1441
+ }
1442
+ async setFeeSolana(newFee) {
1443
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1444
+ if (!this.config.solana?.programs.mailer) {
1445
+ throw new Error('Solana Mailer program address not configured');
1446
+ }
1447
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1448
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1449
+ const wallet = MailerClient.createWallet(this.wallet);
1450
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1451
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1452
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1453
+ const txHash = await client.setFee(newFee);
1454
+ const slot = await connection.getSlot();
1455
+ return {
1456
+ hash: txHash,
1457
+ chainType: ChainType.SOLANA,
1458
+ slot,
833
1459
  timestamp: Date.now()
834
1460
  };
835
1461
  }
836
- async rejectDelegationSolana(delegatorAddress) {
837
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
838
- throw new Error('Solana client not properly initialized');
839
- }
840
- const { MailerClient, PublicKey } = await this.getSolanaModules();
841
- const programId = new PublicKey(this.solanaProgramId);
842
- const usdcMint = new PublicKey(this.solanaUsdcMint);
843
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
844
- const result = await client.rejectDelegation(delegatorAddress);
845
- const slot = await this.solanaConnection.getSlot();
1462
+ async setDelegationFeeSolana(newFee) {
1463
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1464
+ if (!this.config.solana?.programs.mailer) {
1465
+ throw new Error('Solana Mailer program address not configured');
1466
+ }
1467
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1468
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1469
+ const wallet = MailerClient.createWallet(this.wallet);
1470
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1471
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1472
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1473
+ const txHash = await client.setDelegationFee(newFee);
1474
+ const slot = await connection.getSlot();
846
1475
  return {
847
- hash: result.signature,
1476
+ hash: txHash,
848
1477
  chainType: ChainType.SOLANA,
849
1478
  slot,
850
1479
  timestamp: Date.now()
851
1480
  };
852
1481
  }
853
- async setFee(newFee) {
854
- if (this.chainType === ChainType.EVM) {
855
- return this.setFeeEVM(newFee);
856
- }
857
- else {
858
- return this.setFeeSolana(newFee);
859
- }
1482
+ async getDelegationFeeSolana() {
1483
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1484
+ if (!this.config.solana?.programs.mailer) {
1485
+ throw new Error('Solana Mailer program address not configured');
1486
+ }
1487
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1488
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1489
+ const wallet = MailerClient.createWallet(this.wallet);
1490
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1491
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1492
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1493
+ const fees = await client.getFees();
1494
+ return BigInt(fees.delegationFee);
860
1495
  }
861
- async setFeeEVM(newFee) {
862
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
863
- throw new Error('EVM client not properly initialized');
864
- }
865
- const { MailerClient } = await this.getEVMModules();
866
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
867
- const [account] = await this.evmWalletClient.getAddresses();
868
- const result = await client.setFee(newFee, this.evmWalletClient, account);
1496
+ async rejectDelegationSolana(delegatorAddress) {
1497
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1498
+ if (!this.config.solana?.programs.mailer) {
1499
+ throw new Error('Solana Mailer program address not configured');
1500
+ }
1501
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1502
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1503
+ const wallet = MailerClient.createWallet(this.wallet);
1504
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1505
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1506
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1507
+ const txHash = await client.rejectDelegation(delegatorAddress);
1508
+ const slot = await connection.getSlot();
869
1509
  return {
870
- hash: result.hash,
871
- chainType: ChainType.EVM,
872
- blockNumber: result.blockNumber,
1510
+ hash: txHash,
1511
+ chainType: ChainType.SOLANA,
1512
+ slot,
873
1513
  timestamp: Date.now()
874
1514
  };
875
1515
  }
876
- async setFeeSolana(newFee) {
877
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
878
- throw new Error('Solana client not properly initialized');
879
- }
880
- const { MailerClient, PublicKey } = await this.getSolanaModules();
881
- const programId = new PublicKey(this.solanaProgramId);
882
- const usdcMint = new PublicKey(this.solanaUsdcMint);
883
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
884
- const result = await client.setFee(newFee);
885
- const slot = await this.solanaConnection.getSlot();
1516
+ async claimOwnerShareSolana() {
1517
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1518
+ if (!this.config.solana?.programs.mailer) {
1519
+ throw new Error('Solana Mailer program address not configured');
1520
+ }
1521
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1522
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1523
+ const wallet = MailerClient.createWallet(this.wallet);
1524
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1525
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1526
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1527
+ const txHash = await client.claimOwnerShare();
1528
+ const slot = await connection.getSlot();
886
1529
  return {
887
- hash: result.signature,
1530
+ hash: txHash,
888
1531
  chainType: ChainType.SOLANA,
889
1532
  slot,
890
1533
  timestamp: Date.now()
891
1534
  };
892
1535
  }
893
- async setDelegationFee(newFee) {
894
- if (this.chainType === ChainType.EVM) {
895
- return this.setDelegationFeeEVM(newFee);
896
- }
897
- else {
898
- return this.setDelegationFeeSolana(newFee);
899
- }
900
- }
901
- async setDelegationFeeEVM(newFee) {
902
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
903
- throw new Error('EVM client not properly initialized');
904
- }
905
- const { MailerClient } = await this.getEVMModules();
906
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
907
- const [account] = await this.evmWalletClient.getAddresses();
908
- const result = await client.setDelegationFee(newFee, this.evmWalletClient, account);
1536
+ async pauseSolana() {
1537
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1538
+ if (!this.config.solana?.programs.mailer) {
1539
+ throw new Error('Solana Mailer program address not configured');
1540
+ }
1541
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1542
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1543
+ const wallet = MailerClient.createWallet(this.wallet);
1544
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1545
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1546
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1547
+ const txHash = await client.pause();
1548
+ const slot = await connection.getSlot();
909
1549
  return {
910
- hash: result.hash,
911
- chainType: ChainType.EVM,
912
- blockNumber: result.blockNumber,
1550
+ hash: txHash,
1551
+ chainType: ChainType.SOLANA,
1552
+ slot,
913
1553
  timestamp: Date.now()
914
1554
  };
915
1555
  }
916
- async setDelegationFeeSolana(newFee) {
917
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
918
- throw new Error('Solana client not properly initialized');
919
- }
920
- const { MailerClient, PublicKey } = await this.getSolanaModules();
921
- const programId = new PublicKey(this.solanaProgramId);
922
- const usdcMint = new PublicKey(this.solanaUsdcMint);
923
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
924
- const result = await client.setDelegationFee(newFee);
925
- const slot = await this.solanaConnection.getSlot();
1556
+ async unpauseSolana() {
1557
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1558
+ if (!this.config.solana?.programs.mailer) {
1559
+ throw new Error('Solana Mailer program address not configured');
1560
+ }
1561
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1562
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1563
+ const wallet = MailerClient.createWallet(this.wallet);
1564
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1565
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1566
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1567
+ const txHash = await client.unpause();
1568
+ const slot = await connection.getSlot();
926
1569
  return {
927
- hash: result.signature,
1570
+ hash: txHash,
928
1571
  chainType: ChainType.SOLANA,
929
1572
  slot,
930
1573
  timestamp: Date.now()
931
1574
  };
932
1575
  }
933
- async pause() {
934
- if (this.chainType === ChainType.EVM) {
935
- return this.pauseEVM();
936
- }
937
- else {
938
- return this.pauseSolana();
939
- }
940
- }
941
- async pauseEVM() {
942
- if (!this.evmWalletClient || !this.evmPublicClient || !this.evmContractAddress) {
943
- throw new Error('EVM client not properly initialized');
944
- }
945
- const { MailerClient } = await this.getEVMModules();
946
- const client = new MailerClient(this.evmContractAddress, this.evmPublicClient);
947
- const [account] = await this.evmWalletClient.getAddresses();
948
- const result = await client.pause(this.evmWalletClient, account);
1576
+ async emergencyUnpauseSolana() {
1577
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1578
+ if (!this.config.solana?.programs.mailer) {
1579
+ throw new Error('Solana Mailer program address not configured');
1580
+ }
1581
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1582
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1583
+ const wallet = MailerClient.createWallet(this.wallet);
1584
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1585
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1586
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1587
+ const txHash = await client.emergencyUnpause();
1588
+ const slot = await connection.getSlot();
949
1589
  return {
950
- hash: result.hash,
951
- chainType: ChainType.EVM,
952
- blockNumber: result.blockNumber,
1590
+ hash: txHash,
1591
+ chainType: ChainType.SOLANA,
1592
+ slot,
953
1593
  timestamp: Date.now()
954
1594
  };
955
1595
  }
956
- async pauseSolana() {
957
- if (!this.solanaWallet || !this.solanaConnection || !this.solanaProgramId || !this.solanaUsdcMint) {
958
- throw new Error('Solana client not properly initialized');
959
- }
960
- const { MailerClient, PublicKey } = await this.getSolanaModules();
961
- const programId = new PublicKey(this.solanaProgramId);
962
- const usdcMint = new PublicKey(this.solanaUsdcMint);
963
- const client = new MailerClient(this.solanaConnection, this.solanaWallet, programId, usdcMint);
964
- const result = await client.pause();
965
- const slot = await this.solanaConnection.getSlot();
1596
+ async isPausedSolana() {
1597
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1598
+ if (!this.config.solana?.programs.mailer) {
1599
+ throw new Error('Solana Mailer program address not configured');
1600
+ }
1601
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1602
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1603
+ const wallet = MailerClient.createWallet(this.wallet);
1604
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1605
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1606
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1607
+ return client.isPaused();
1608
+ }
1609
+ async distributeClaimableFundsSolana(recipient) {
1610
+ const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1611
+ if (!this.config.solana?.programs.mailer) {
1612
+ throw new Error('Solana Mailer program address not configured');
1613
+ }
1614
+ const connection = new Connection(this.config.solana.rpc, 'confirmed');
1615
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1616
+ const wallet = MailerClient.createWallet(this.wallet);
1617
+ const programId = new PublicKey(this.config.solana.programs.mailer);
1618
+ const usdcMint = new PublicKey(this.config.solana.usdcMint);
1619
+ const client = new MailerClient(connection, wallet, programId, usdcMint);
1620
+ const txHash = await client.distributeClaimableFunds(recipient);
1621
+ const slot = await connection.getSlot();
966
1622
  return {
967
- hash: result.signature,
1623
+ hash: txHash,
968
1624
  chainType: ChainType.SOLANA,
969
1625
  slot,
970
1626
  timestamp: Date.now()
@@ -975,35 +1631,10 @@ export class OnchainMailerClient {
975
1631
  return this.chainType;
976
1632
  }
977
1633
  getWalletAddress() {
978
- if (this.chainType === ChainType.EVM) {
979
- // Try to get address from raw wallet for backward compatibility
980
- // @ts-ignore
981
- if (this._rawEvmWallet) {
982
- // @ts-ignore
983
- return this._rawEvmWallet.address || this._rawEvmWallet.selectedAddress || '';
984
- }
985
- return ''; // Caller should use getWalletAddressAsync() for accurate address
986
- }
987
- else if (this.chainType === ChainType.SOLANA && this.solanaWallet) {
988
- return this.solanaWallet.publicKey?.toString() || '';
989
- }
990
- return '';
991
- }
992
- /**
993
- * Get wallet address asynchronously
994
- */
995
- async getWalletAddressAsync() {
996
- if (this.chainType === ChainType.EVM && this.evmWalletClient) {
997
- const [address] = await this.evmWalletClient.getAddresses();
998
- return address;
999
- }
1000
- else if (this.chainType === ChainType.SOLANA && this.solanaWallet) {
1001
- return this.solanaWallet.publicKey?.toString() || '';
1002
- }
1003
- throw new Error('Wallet not initialized');
1634
+ return this.wallet.address;
1004
1635
  }
1005
1636
  }
1006
- // Cache for dynamic imports
1637
+ // Performance optimization: cache imported modules
1007
1638
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1008
1639
  OnchainMailerClient.evmModules = null;
1009
1640
  // eslint-disable-next-line @typescript-eslint/no-explicit-any