@sudobility/contracts 0.15.1 → 1.10.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 (166) hide show
  1. package/README.md +2 -3
  2. package/artifacts/contracts/Mailer.sol/Mailer.d.ts +2 -185
  3. package/artifacts/contracts/Mailer.sol/Mailer.dbg.json +1 -1
  4. package/artifacts/contracts/Mailer.sol/Mailer.json +2 -185
  5. package/artifacts/contracts/MockUSDC.sol/MockUSDC.dbg.json +1 -1
  6. package/artifacts/contracts/interfaces/IERC20.sol/IERC20.dbg.json +1 -1
  7. package/dist/evm/src/evm/index.d.ts +1 -1
  8. package/dist/evm/src/evm/index.d.ts.map +1 -1
  9. package/dist/evm/src/evm/index.js +4 -4
  10. package/dist/evm/src/evm/index.js.map +1 -1
  11. package/dist/evm/src/evm/mailer-client.d.ts +210 -0
  12. package/dist/evm/src/evm/mailer-client.d.ts.map +1 -0
  13. package/dist/evm/src/evm/mailer-client.js +417 -0
  14. package/dist/evm/src/evm/mailer-client.js.map +1 -0
  15. package/dist/evm/typechain-types/Mailer.d.ts +10 -128
  16. package/dist/evm/typechain-types/Mailer.d.ts.map +1 -1
  17. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts +1 -145
  18. package/dist/evm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  19. package/dist/evm/typechain-types/factories/Mailer__factory.js +1 -184
  20. package/dist/evm/typechain-types/factories/Mailer__factory.js.map +1 -1
  21. package/dist/solana/solana/index.d.ts +1 -1
  22. package/dist/solana/solana/index.d.ts.map +1 -1
  23. package/dist/solana/solana/index.js +1 -4
  24. package/dist/solana/solana/index.js.map +1 -1
  25. package/dist/solana/solana/mailer-client.d.ts +209 -0
  26. package/dist/solana/solana/mailer-client.d.ts.map +1 -0
  27. package/dist/solana/solana/mailer-client.js +728 -0
  28. package/dist/solana/solana/mailer-client.js.map +1 -0
  29. package/dist/solana/solana/types.d.ts +2 -3
  30. package/dist/solana/solana/types.d.ts.map +1 -1
  31. package/dist/solana/solana/types.js.map +1 -1
  32. package/dist/unified/src/evm/index.d.ts +1 -1
  33. package/dist/unified/src/evm/index.d.ts.map +1 -1
  34. package/dist/unified/src/evm/index.js +4 -4
  35. package/dist/unified/src/evm/index.js.map +1 -1
  36. package/dist/unified/src/evm/mailer-client.d.ts +210 -0
  37. package/dist/unified/src/evm/mailer-client.d.ts.map +1 -0
  38. package/dist/unified/src/evm/mailer-client.js +417 -0
  39. package/dist/unified/src/evm/mailer-client.js.map +1 -0
  40. package/dist/unified/src/react/context/MailerProvider.d.ts +20 -26
  41. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
  42. package/dist/unified/src/react/context/MailerProvider.js +26 -26
  43. package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
  44. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +192 -225
  45. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  46. package/dist/unified/src/react/hooks/useMailerMutations.js +266 -263
  47. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
  48. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +63 -117
  49. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  50. package/dist/unified/src/react/hooks/useMailerQueries.js +104 -239
  51. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
  52. package/dist/unified/src/react/index.d.ts +3 -5
  53. package/dist/unified/src/react/index.d.ts.map +1 -1
  54. package/dist/unified/src/react/index.js +26 -41
  55. package/dist/unified/src/react/index.js.map +1 -1
  56. package/dist/unified/src/solana/index.d.ts +1 -1
  57. package/dist/unified/src/solana/index.d.ts.map +1 -1
  58. package/dist/unified/src/solana/index.js +1 -4
  59. package/dist/unified/src/solana/index.js.map +1 -1
  60. package/dist/unified/src/solana/mailer-client.d.ts +209 -0
  61. package/dist/unified/src/solana/mailer-client.d.ts.map +1 -0
  62. package/dist/unified/src/solana/mailer-client.js +728 -0
  63. package/dist/unified/src/solana/mailer-client.js.map +1 -0
  64. package/dist/unified/src/solana/types.d.ts +2 -3
  65. package/dist/unified/src/solana/types.d.ts.map +1 -1
  66. package/dist/unified/src/solana/types.js.map +1 -1
  67. package/dist/unified/src/unified/index.d.ts +1 -1
  68. package/dist/unified/src/unified/index.d.ts.map +1 -1
  69. package/dist/unified/src/unified/onchain-mailer-client.d.ts +247 -192
  70. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  71. package/dist/unified/src/unified/onchain-mailer-client.js +1462 -551
  72. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  73. package/dist/unified/src/unified/types.d.ts +6 -23
  74. package/dist/unified/src/unified/types.d.ts.map +1 -1
  75. package/dist/unified/src/utils/chain-config.d.ts +2 -4
  76. package/dist/unified/src/utils/chain-config.d.ts.map +1 -1
  77. package/dist/unified/src/utils/chain-config.js +36 -46
  78. package/dist/unified/src/utils/chain-config.js.map +1 -1
  79. package/dist/unified/typechain-types/Mailer.d.ts +10 -128
  80. package/dist/unified/typechain-types/Mailer.d.ts.map +1 -1
  81. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts +1 -145
  82. package/dist/unified/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  83. package/dist/unified/typechain-types/factories/Mailer__factory.js +1 -184
  84. package/dist/unified/typechain-types/factories/Mailer__factory.js.map +1 -1
  85. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  86. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  87. package/dist/unified-esm/src/evm/index.js +2 -2
  88. package/dist/unified-esm/src/evm/index.js.map +1 -1
  89. package/dist/unified-esm/src/evm/mailer-client.d.ts +210 -0
  90. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +1 -0
  91. package/dist/unified-esm/src/evm/mailer-client.js +413 -0
  92. package/dist/unified-esm/src/evm/mailer-client.js.map +1 -0
  93. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +20 -26
  94. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  95. package/dist/unified-esm/src/react/context/MailerProvider.js +26 -25
  96. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  97. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +192 -225
  98. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  99. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +262 -254
  100. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  101. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +63 -117
  102. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  103. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +102 -232
  104. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  105. package/dist/unified-esm/src/react/index.d.ts +3 -5
  106. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  107. package/dist/unified-esm/src/react/index.js +5 -9
  108. package/dist/unified-esm/src/react/index.js.map +1 -1
  109. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  110. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  111. package/dist/unified-esm/src/solana/index.js +1 -2
  112. package/dist/unified-esm/src/solana/index.js.map +1 -1
  113. package/dist/unified-esm/src/solana/mailer-client.d.ts +209 -0
  114. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +1 -0
  115. package/dist/unified-esm/src/solana/mailer-client.js +724 -0
  116. package/dist/unified-esm/src/solana/mailer-client.js.map +1 -0
  117. package/dist/unified-esm/src/solana/types.d.ts +2 -3
  118. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  119. package/dist/unified-esm/src/solana/types.js.map +1 -1
  120. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  121. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  122. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +247 -192
  123. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  124. package/dist/unified-esm/src/unified/onchain-mailer-client.js +1462 -551
  125. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  126. package/dist/unified-esm/src/unified/types.d.ts +6 -23
  127. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  128. package/dist/unified-esm/src/utils/chain-config.d.ts +2 -4
  129. package/dist/unified-esm/src/utils/chain-config.d.ts.map +1 -1
  130. package/dist/unified-esm/src/utils/chain-config.js +35 -46
  131. package/dist/unified-esm/src/utils/chain-config.js.map +1 -1
  132. package/dist/unified-esm/typechain-types/Mailer.d.ts +10 -128
  133. package/dist/unified-esm/typechain-types/Mailer.d.ts.map +1 -1
  134. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts +1 -145
  135. package/dist/unified-esm/typechain-types/factories/Mailer__factory.d.ts.map +1 -1
  136. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js +1 -184
  137. package/dist/unified-esm/typechain-types/factories/Mailer__factory.js.map +1 -1
  138. package/package.json +10 -17
  139. package/programs/mailer/src/lib.rs +145 -764
  140. package/programs/mailer/tests/integration_tests.rs +65 -586
  141. package/typechain-types/Mailer.ts +8 -215
  142. package/typechain-types/factories/Mailer__factory.ts +1 -184
  143. package/dist/evm/src/evm/evm-mailer-client.d.ts +0 -1062
  144. package/dist/evm/src/evm/evm-mailer-client.d.ts.map +0 -1
  145. package/dist/evm/src/evm/evm-mailer-client.js +0 -924
  146. package/dist/evm/src/evm/evm-mailer-client.js.map +0 -1
  147. package/dist/solana/solana/solana-mailer-client.d.ts +0 -209
  148. package/dist/solana/solana/solana-mailer-client.d.ts.map +0 -1
  149. package/dist/solana/solana/solana-mailer-client.js +0 -1004
  150. package/dist/solana/solana/solana-mailer-client.js.map +0 -1
  151. package/dist/unified/src/evm/evm-mailer-client.d.ts +0 -1062
  152. package/dist/unified/src/evm/evm-mailer-client.d.ts.map +0 -1
  153. package/dist/unified/src/evm/evm-mailer-client.js +0 -924
  154. package/dist/unified/src/evm/evm-mailer-client.js.map +0 -1
  155. package/dist/unified/src/solana/solana-mailer-client.d.ts +0 -209
  156. package/dist/unified/src/solana/solana-mailer-client.d.ts.map +0 -1
  157. package/dist/unified/src/solana/solana-mailer-client.js +0 -1004
  158. package/dist/unified/src/solana/solana-mailer-client.js.map +0 -1
  159. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts +0 -1062
  160. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +0 -1
  161. package/dist/unified-esm/src/evm/evm-mailer-client.js +0 -920
  162. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +0 -1
  163. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +0 -209
  164. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +0 -1
  165. package/dist/unified-esm/src/solana/solana-mailer-client.js +0 -1000
  166. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +0 -1
@@ -1,731 +1,1642 @@
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 - Stateless multi-chain messaging client
6
+ * OnchainMailerClient - Multi-chain messaging client for Mailer protocol
6
7
  *
7
- * This version uses stateless EVM and Solana clients underneath.
8
- * All wallet connections and chain information are passed as parameters to each method.
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
12
+ * @example Basic Usage
11
13
  * ```typescript
12
- * import { createWalletClient, createPublicClient, http } from 'viem';
13
- * import { RpcHelpers } from '@sudobility/configs';
14
- * import { Chain } from '@sudobility/types';
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);
15
27
  *
16
- * const chainInfo = RpcHelpers.getChainInfo(Chain.ETH_MAINNET);
17
- * const walletClient = createWalletClient({
18
- * chain: mainnet,
19
- * transport: http()
20
- * });
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);
21
40
  *
22
- * const client = new OnchainMailerClient();
23
- * await client.sendMessage(
24
- * 'Subject',
25
- * 'Body',
26
- * { walletClient },
27
- * chainInfo,
28
- * { priority: true }
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
46
+ * @example Error Handling
33
47
  * ```typescript
34
- * import { useWallet } from '@solana/wallet-adapter-react';
35
- * import { Connection } from '@solana/web3.js';
36
- * import { RpcHelpers } from '@sudobility/configs';
37
- * import { Chain } from '@sudobility/types';
38
- *
39
- * const chainInfo = RpcHelpers.getChainInfo(Chain.SOLANA_MAINNET);
40
- * const wallet = useWallet();
41
- *
42
- * const client = new OnchainMailerClient();
43
- * await client.sendMessage(
44
- * 'Subject',
45
- * 'Body',
46
- * { wallet },
47
- * chainInfo,
48
- * { priority: true }
49
- * );
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
+ * }
50
60
  * ```
61
+ *
62
+ * @author Mailer Protocol Team
63
+ * @version 1.5.2
64
+ * @since 1.0.0
51
65
  */
52
66
  export class OnchainMailerClient {
53
67
  /**
54
- * Create a new stateless OnchainMailerClient
55
- * No configuration needed in constructor
68
+ * Initialize OnchainMailerClient with wallet and chain configuration
69
+ *
70
+ * @param wallet - Wallet instance (EVM or Solana compatible)
71
+ * @param config - Chain configuration for EVM and/or Solana networks
72
+ *
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
+ * ```
56
86
  */
57
- constructor() {
58
- // Stateless - no initialization needed
87
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
88
+ constructor(wallet, config) {
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
+ }
59
108
  }
60
- // Performance optimization: cache client imports
61
- async getEVMClient() {
62
- if (!OnchainMailerClient.evmClient) {
63
- const { EVMMailerClient } = await import('../evm/evm-mailer-client.js');
64
- OnchainMailerClient.evmClient = new EVMMailerClient();
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');
123
+ }
124
+ }
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
+ }
65
133
  }
66
- return OnchainMailerClient.evmClient;
67
134
  }
68
- async getSolanaClient() {
69
- if (!OnchainMailerClient.solanaClient) {
70
- const { SolanaMailerClient } = await import('../solana/solana-mailer-client.js');
71
- OnchainMailerClient.solanaClient = new SolanaMailerClient();
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');
72
145
  }
73
- return OnchainMailerClient.solanaClient;
74
146
  }
75
147
  /**
76
- * Send a message on the blockchain
148
+ * Send a message using the appropriate chain implementation
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
+ *
77
153
  * @param subject - Message subject (1-200 characters)
78
154
  * @param body - Message body (1-10000 characters)
79
- * @param wallet - Wallet connection (EVM or Solana)
80
- * @param chainInfo - Chain information including RPC endpoints and contract addresses
81
- * @param options - Optional parameters
82
- * @returns Transaction result
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
+ * ```
83
188
  */
84
- async sendMessage(connectedWallet, chainInfo, subject, body, options) {
85
- // Validate message
86
- if (!subject || subject.length > 200) {
87
- throw new Error('Subject must be 1-200 characters');
88
- }
89
- if (!body || body.length > 10000) {
90
- throw new Error('Body must be 1-10000 characters');
91
- }
92
- // Route to appropriate implementation based on chain type
93
- if (chainInfo.chainType === ChainType.EVM) {
94
- const evmClient = await this.getEVMClient();
95
- const evmWallet = connectedWallet;
96
- const [account] = await evmWallet.walletClient.getAddresses();
97
- const to = options?.to || account;
98
- const priority = options?.priority ?? false;
99
- const resolveSenderToName = options?.resolveSenderToName ?? false;
100
- const result = await evmClient.send(evmWallet, chainInfo, to, subject, body, account, // payer
101
- priority, // revenueShareToReceiver
102
- resolveSenderToName, options?.gasOptions);
103
- return {
104
- transactionHash: result.hash,
105
- chainType: ChainType.EVM,
106
- fee: BigInt(priority ? '100000' : '10000'),
107
- gasUsed: result.gasUsed,
108
- isPriority: priority,
109
- success: true
110
- };
111
- }
112
- else if (chainInfo.chainType === ChainType.SOLANA) {
113
- const solanaClient = await this.getSolanaClient();
114
- const solanaWallet = connectedWallet;
115
- const to = options?.to || solanaWallet.wallet.publicKey.toBase58();
116
- const priority = options?.priority ?? false;
117
- const result = await solanaClient.send(solanaWallet, chainInfo, to, subject, body, priority, // revenueShareToReceiver
118
- options?.computeOptions);
119
- return {
120
- transactionHash: result.transactionHash,
121
- chainType: ChainType.SOLANA,
122
- fee: BigInt(priority ? '100000' : '10000'),
123
- isPriority: priority,
124
- success: true
125
- };
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);
126
193
  }
127
194
  else {
128
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
195
+ return this.sendSolanaMessage(subject, body, priority, resolveSenderToName);
129
196
  }
130
197
  }
131
198
  /**
132
- * Send a prepared message
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
133
203
  */
134
- async sendPrepared(connectedWallet, chainInfo, to, mailId, options) {
135
- if (chainInfo.chainType === ChainType.EVM) {
136
- const evmClient = await this.getEVMClient();
137
- const evmWallet = connectedWallet;
138
- const [account] = await evmWallet.walletClient.getAddresses();
139
- const priority = options?.priority ?? false;
140
- const resolveSenderToName = options?.resolveSenderToName ?? false;
141
- const result = await evmClient.sendPrepared(evmWallet, chainInfo, to, mailId, account, // payer
142
- priority, // revenueShareToReceiver
143
- resolveSenderToName, options?.gasOptions);
144
- return {
145
- transactionHash: result.hash,
146
- chainType: ChainType.EVM,
147
- fee: BigInt(priority ? '100000' : '10000'),
148
- gasUsed: result.gasUsed,
149
- isPriority: priority,
150
- success: true
151
- };
152
- }
153
- else if (chainInfo.chainType === ChainType.SOLANA) {
154
- const solanaClient = await this.getSolanaClient();
155
- const solanaWallet = connectedWallet;
156
- const priority = options?.priority ?? false;
157
- const result = await solanaClient.sendPrepared(solanaWallet, chainInfo, to, mailId, priority, options?.computeOptions);
158
- return {
159
- transactionHash: result.transactionHash,
160
- chainType: ChainType.SOLANA,
161
- fee: BigInt(priority ? '100000' : '10000'),
162
- isPriority: priority,
163
- success: true
164
- };
204
+ async registerDomain(domain, isExtension = false) {
205
+ if (this.chainType === 'evm') {
206
+ return this.registerEVMDomain(domain, isExtension);
165
207
  }
166
208
  else {
167
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
209
+ return this.registerSolanaDomain(domain, isExtension);
168
210
  }
169
211
  }
170
212
  /**
171
- * Send through webhook
213
+ * Delegate to another address using the appropriate chain implementation
214
+ * @param delegate - Address to delegate to
215
+ * @returns Delegation result
172
216
  */
173
- async sendThroughWebhook(connectedWallet, chainInfo, to, webhookId, options) {
174
- if (chainInfo.chainType === ChainType.EVM) {
175
- const evmClient = await this.getEVMClient();
176
- const evmWallet = connectedWallet;
177
- const [account] = await evmWallet.walletClient.getAddresses();
178
- const priority = options?.priority ?? false;
179
- const result = await evmClient.sendThroughWebhook(to, subject, body, webhookId, account, // payer
180
- priority, evmWallet, chainInfo, options?.gasOptions);
181
- return {
182
- transactionHash: result.hash,
183
- chainType: ChainType.EVM,
184
- fee: BigInt(priority ? '100000' : '10000'),
185
- gasUsed: result.gasUsed,
186
- isPriority: priority,
187
- success: true
188
- };
217
+ async delegateTo(delegate) {
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})`);
189
222
  }
190
- else if (chainInfo.chainType === ChainType.SOLANA) {
191
- const solanaClient = await this.getSolanaClient();
192
- const solanaWallet = connectedWallet;
193
- const priority = options?.priority ?? false;
194
- const result = await solanaClient.sendThroughWebhook(solanaWallet, chainInfo, to, webhookId, priority, options?.computeOptions);
195
- return {
196
- transactionHash: result.transactionHash,
197
- chainType: ChainType.SOLANA,
198
- fee: BigInt(priority ? '100000' : '10000'),
199
- isPriority: priority,
200
- success: true
201
- };
223
+ if (this.chainType === 'evm') {
224
+ return this.delegateEVM(delegate);
202
225
  }
203
226
  else {
204
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
227
+ return this.delegateSolana(delegate);
205
228
  }
206
229
  }
207
230
  /**
208
- * Delegate to another address
209
- * @param delegate - Address to delegate to
210
- * @param wallet - Wallet connection
211
- * @param chainInfo - Chain information
231
+ * Claim revenue share using the appropriate chain implementation
212
232
  * @returns Transaction result
213
233
  */
214
- async delegateTo(connectedWallet, chainInfo, delegate, options) {
215
- if (chainInfo.chainType === ChainType.EVM) {
216
- const evmClient = await this.getEVMClient();
217
- const result = await evmClient.delegateTo(delegate, connectedWallet, chainInfo, options?.gasOptions);
218
- return {
219
- transactionHash: result.hash,
220
- chainType: ChainType.EVM,
221
- delegate,
222
- success: true
223
- };
224
- }
225
- else if (chainInfo.chainType === ChainType.SOLANA) {
226
- const solanaClient = await this.getSolanaClient();
227
- const result = await solanaClient.delegateTo(delegate, connectedWallet, chainInfo, options?.computeOptions);
228
- return {
229
- transactionHash: result.transactionHash,
230
- chainType: ChainType.SOLANA,
231
- delegate,
232
- success: true
233
- };
234
+ async claimRevenue() {
235
+ if (this.chainType === 'evm') {
236
+ return this.claimEVMRevenue();
234
237
  }
235
238
  else {
236
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
239
+ return this.claimSolanaRevenue();
237
240
  }
238
241
  }
239
- /**
240
- * Reject delegation
241
- */
242
- async rejectDelegation(connectedWallet, chainInfo, delegatingAddress, options) {
243
- if (chainInfo.chainType === ChainType.EVM) {
244
- const evmClient = await this.getEVMClient();
245
- const result = await evmClient.rejectDelegation(connectedWallet, chainInfo, delegatingAddress, options?.gasOptions);
246
- return {
247
- hash: result.hash,
248
- chainType: ChainType.EVM
249
- };
250
- }
251
- else if (chainInfo.chainType === ChainType.SOLANA) {
252
- const solanaClient = await this.getSolanaClient();
253
- const result = await solanaClient.rejectDelegation(connectedWallet, chainInfo, delegatingAddress, options?.computeOptions);
242
+ // Performance optimization: cache module imports
243
+ async getEVMModules() {
244
+ if (!OnchainMailerClient.evmModules) {
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
+ }
258
+ }
259
+ return OnchainMailerClient.evmModules;
260
+ }
261
+ async getSolanaModules() {
262
+ if (!OnchainMailerClient.solanaModules) {
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
+ }
277
+ }
278
+ return OnchainMailerClient.solanaModules;
279
+ }
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
+ ]);
254
350
  return {
255
- hash: result.transactionHash,
256
- chainType: ChainType.SOLANA
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
257
358
  };
258
359
  }
259
- else {
260
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
360
+ catch (error) {
361
+ throw new Error(`EVM message sending failed: ${error instanceof Error ? error.message : String(error)}`);
261
362
  }
262
363
  }
263
- /**
264
- * Claim revenue share
265
- * @param wallet - Wallet connection
266
- * @param chainInfo - Chain information
267
- * @returns Transaction result
268
- */
269
- async claimRevenue(connectedWallet, chainInfo, options) {
270
- if (chainInfo.chainType === ChainType.EVM) {
271
- const evmClient = await this.getEVMClient();
272
- const result = await evmClient.claimRecipientShare(connectedWallet, chainInfo, options?.gasOptions);
273
- return {
274
- hash: result.hash,
275
- chainType: ChainType.EVM
276
- };
277
- }
278
- else if (chainInfo.chainType === ChainType.SOLANA) {
279
- const solanaClient = await this.getSolanaClient();
280
- const result = await solanaClient.claimRecipientShare(connectedWallet, chainInfo, options?.computeOptions);
281
- return {
282
- hash: result.transactionHash,
283
- chainType: ChainType.SOLANA
284
- };
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');
367
+ }
368
+ async delegateEVM(delegate) {
369
+ const { viem } = await this.getEVMModules();
370
+ if (!this.config.evm) {
371
+ throw new Error('EVM configuration not provided');
285
372
  }
286
- else {
287
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
373
+ // Validate EVM address format
374
+ if (!viem.isAddress(delegate)) {
375
+ throw new Error('Invalid EVM address format for delegate');
288
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');
289
379
  }
290
- /**
291
- * Claim owner share (owner only)
292
- */
293
- async claimOwnerShare(connectedWallet, chainInfo, options) {
294
- if (chainInfo.chainType === ChainType.EVM) {
295
- const evmClient = await this.getEVMClient();
296
- const result = await evmClient.claimOwnerShare(connectedWallet, chainInfo, options?.gasOptions);
380
+ async claimEVMRevenue() {
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 });
411
+ return {
412
+ hash: txHash,
413
+ chainType: ChainType.EVM,
414
+ blockNumber: receipt.blockNumber,
415
+ timestamp: Number(block.timestamp) * 1000
416
+ };
417
+ }
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();
297
455
  return {
298
- hash: result.hash,
299
- chainType: ChainType.EVM
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
300
466
  };
301
467
  }
302
- else if (chainInfo.chainType === ChainType.SOLANA) {
303
- const solanaClient = await this.getSolanaClient();
304
- const result = await solanaClient.claimOwnerShare(connectedWallet, chainInfo, options?.computeOptions);
305
- return {
306
- hash: result.transactionHash,
307
- chainType: ChainType.SOLANA
308
- };
468
+ catch (error) {
469
+ throw new Error(`Solana message sending failed: ${error instanceof Error ? error.message : String(error)}`);
309
470
  }
310
- else {
311
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
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');
475
+ }
476
+ async delegateSolana(_delegate) {
477
+ if (!this.config.solana) {
478
+ throw new Error('Solana configuration not provided');
312
479
  }
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');
482
+ }
483
+ async claimSolanaRevenue() {
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();
496
+ return {
497
+ hash: txHash,
498
+ chainType: ChainType.SOLANA,
499
+ slot,
500
+ timestamp: Date.now()
501
+ };
313
502
  }
314
503
  /**
315
- * Claim expired shares (owner only)
504
+ * Get send fee using the appropriate chain implementation
505
+ * @returns Send fee in USDC micro-units (6 decimals)
316
506
  */
317
- async claimExpiredShares(connectedWallet, chainInfo, recipient, options) {
318
- if (chainInfo.chainType === ChainType.EVM) {
319
- const evmClient = await this.getEVMClient();
320
- const result = await evmClient.claimExpiredShares(recipient, connectedWallet, chainInfo, options?.gasOptions);
321
- return {
322
- hash: result.hash,
323
- chainType: ChainType.EVM
324
- };
325
- }
326
- else if (chainInfo.chainType === ChainType.SOLANA) {
327
- const solanaClient = await this.getSolanaClient();
328
- const result = await solanaClient.claimExpiredShares(recipient, connectedWallet, chainInfo, options?.computeOptions);
329
- return {
330
- hash: result.transactionHash,
331
- chainType: ChainType.SOLANA
332
- };
507
+ async getSendFee() {
508
+ if (this.chainType === 'evm') {
509
+ return this.getEVMSendFee();
333
510
  }
334
511
  else {
335
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
512
+ return this.getSolanaSendFee();
336
513
  }
337
514
  }
338
515
  /**
339
- * Set fees (owner only)
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
340
519
  */
341
- async setFees(connectedWallet, chainInfo, sendFee, delegationFee, options) {
342
- if (chainInfo.chainType === ChainType.EVM) {
343
- const evmClient = await this.getEVMClient();
344
- // EVM client uses separate methods
345
- await evmClient.setFee(connectedWallet, chainInfo, sendFee, options?.gasOptions);
346
- const result2 = await evmClient.setDelegationFee(connectedWallet, chainInfo, delegationFee, options?.gasOptions);
347
- return {
348
- hash: result2.hash, // Return last transaction
349
- chainType: ChainType.EVM
350
- };
351
- }
352
- else if (chainInfo.chainType === ChainType.SOLANA) {
353
- const solanaClient = await this.getSolanaClient();
354
- const result = await solanaClient.setFees(connectedWallet, chainInfo, sendFee, delegationFee, options?.computeOptions);
355
- return {
356
- hash: result.transactionHash,
357
- chainType: ChainType.SOLANA
358
- };
520
+ async getClaimableAmount(address) {
521
+ const targetAddress = address || this.wallet.address;
522
+ if (this.chainType === 'evm') {
523
+ return this.getEVMClaimableAmount(targetAddress);
359
524
  }
360
525
  else {
361
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
526
+ return this.getSolanaClaimableAmount(targetAddress);
362
527
  }
363
528
  }
364
529
  /**
365
- * Set custom fee percentage
530
+ * Get owner's claimable fee balance
531
+ * @returns Owner claimable amount in USDC micro-units
366
532
  */
367
- async setCustomFeePercentage(connectedWallet, chainInfo, target, percentage, options) {
368
- if (chainInfo.chainType === ChainType.EVM) {
369
- const evmClient = await this.getEVMClient();
370
- const result = await evmClient.setCustomFeePercentage(connectedWallet, chainInfo, target, percentage, options?.gasOptions);
371
- return {
372
- hash: result.hash,
373
- chainType: ChainType.EVM
374
- };
375
- }
376
- else if (chainInfo.chainType === ChainType.SOLANA) {
377
- const solanaClient = await this.getSolanaClient();
378
- const result = await solanaClient.setCustomFeePercentage(connectedWallet, chainInfo, target, percentage, options?.computeOptions);
379
- return {
380
- hash: result.transactionHash,
381
- chainType: ChainType.SOLANA
382
- };
533
+ async getOwnerClaimable() {
534
+ if (this.chainType === 'evm') {
535
+ return this.getEVMOwnerClaimable();
383
536
  }
384
537
  else {
385
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
538
+ return this.getSolanaOwnerClaimable();
386
539
  }
387
540
  }
388
541
  /**
389
- * Clear custom fee percentage
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
390
545
  */
391
- async clearCustomFeePercentage(connectedWallet, chainInfo, target, options) {
392
- if (chainInfo.chainType === ChainType.EVM) {
393
- const evmClient = await this.getEVMClient();
394
- const result = await evmClient.clearCustomFeePercentage(connectedWallet, chainInfo, target, options?.gasOptions);
395
- return {
396
- hash: result.hash,
397
- chainType: ChainType.EVM
398
- };
399
- }
400
- else if (chainInfo.chainType === ChainType.SOLANA) {
401
- const solanaClient = await this.getSolanaClient();
402
- const result = await solanaClient.clearCustomFeePercentage(connectedWallet, chainInfo, target, options?.computeOptions);
403
- return {
404
- hash: result.transactionHash,
405
- chainType: ChainType.SOLANA
406
- };
546
+ async getDelegation(address) {
547
+ const targetAddress = address || this.wallet.address;
548
+ if (this.chainType === 'evm') {
549
+ return this.getEVMDelegation(targetAddress);
407
550
  }
408
551
  else {
409
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
552
+ return this.getSolanaDelegation(targetAddress);
410
553
  }
411
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
+ }
614
+ async getEVMDelegation(_address) {
615
+ // Delegation read not implemented in EVM client yet
616
+ // Would need to add getDelegation method to EVM MailerClient
617
+ throw new Error('getDelegation not yet implemented for EVM');
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
+ }
663
+ async getSolanaDelegation(address) {
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);
674
+ const delegatorKey = new PublicKey(address);
675
+ const delegationInfo = await client.getDelegation(delegatorKey);
676
+ return delegationInfo?.delegate || null;
677
+ }
412
678
  /**
413
- * Pause the contract/program (owner only)
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
414
685
  */
415
- async pause(connectedWallet, chainInfo, options) {
416
- if (chainInfo.chainType === ChainType.EVM) {
417
- const evmClient = await this.getEVMClient();
418
- const result = await evmClient.pause(connectedWallet, chainInfo, options?.gasOptions);
419
- return {
420
- hash: result.hash,
421
- chainType: ChainType.EVM
422
- };
423
- }
424
- else if (chainInfo.chainType === ChainType.SOLANA) {
425
- const solanaClient = await this.getSolanaClient();
426
- const result = await solanaClient.pause(connectedWallet, chainInfo, options?.computeOptions);
427
- return {
428
- hash: result.transactionHash,
429
- chainType: ChainType.SOLANA
430
- };
686
+ async sendPrepared(to, mailId, priority = false, resolveSenderToName = false) {
687
+ if (this.chainType === 'evm') {
688
+ return this.sendPreparedEVM(to, mailId, priority, resolveSenderToName);
431
689
  }
432
690
  else {
433
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
691
+ return this.sendPreparedSolana(to, mailId, priority, resolveSenderToName);
434
692
  }
435
693
  }
436
694
  /**
437
- * Unpause the contract/program (owner only)
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
438
700
  */
439
- async unpause(connectedWallet, chainInfo, options) {
440
- if (chainInfo.chainType === ChainType.EVM) {
441
- const evmClient = await this.getEVMClient();
442
- const result = await evmClient.unpause(connectedWallet, chainInfo, options?.gasOptions);
443
- return {
444
- hash: result.hash,
445
- chainType: ChainType.EVM
446
- };
447
- }
448
- else if (chainInfo.chainType === ChainType.SOLANA) {
449
- const solanaClient = await this.getSolanaClient();
450
- const result = await solanaClient.unpause(connectedWallet, chainInfo, options?.computeOptions);
451
- return {
452
- hash: result.transactionHash,
453
- chainType: ChainType.SOLANA
454
- };
701
+ async sendToEmail(toEmail, subject, body) {
702
+ if (this.chainType === 'evm') {
703
+ return this.sendToEmailEVM(toEmail, subject, body);
455
704
  }
456
705
  else {
457
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
706
+ return this.sendToEmailSolana(toEmail, subject, body);
458
707
  }
459
708
  }
460
709
  /**
461
- * Emergency unpause (owner only)
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
462
714
  */
463
- async emergencyUnpause(connectedWallet, chainInfo, options) {
464
- if (chainInfo.chainType === ChainType.EVM) {
465
- const evmClient = await this.getEVMClient();
466
- const result = await evmClient.emergencyUnpause(connectedWallet, chainInfo, options?.gasOptions);
467
- return {
468
- hash: result.hash,
469
- chainType: ChainType.EVM
470
- };
471
- }
472
- else if (chainInfo.chainType === ChainType.SOLANA) {
473
- const solanaClient = await this.getSolanaClient();
474
- const result = await solanaClient.emergencyUnpause(connectedWallet, chainInfo, options?.computeOptions);
475
- return {
476
- hash: result.transactionHash,
477
- chainType: ChainType.SOLANA
478
- };
715
+ async sendPreparedToEmail(toEmail, mailId) {
716
+ if (this.chainType === 'evm') {
717
+ return this.sendPreparedToEmailEVM(toEmail, mailId);
479
718
  }
480
719
  else {
481
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
720
+ return this.sendPreparedToEmailSolana(toEmail, mailId);
482
721
  }
483
722
  }
484
723
  /**
485
- * Distribute claimable funds when paused
486
- * Note: EVM supports single recipient, Solana supports multiple
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
487
727
  */
488
- async distributeClaimableFunds(connectedWallet, chainInfo, recipient, options) {
489
- if (chainInfo.chainType === ChainType.EVM) {
490
- const evmClient = await this.getEVMClient();
491
- // EVM only supports single recipient
492
- const singleRecipient = Array.isArray(recipient) ? recipient[0] : recipient;
493
- const result = await evmClient.distributeClaimableFunds(connectedWallet, chainInfo, singleRecipient, options?.gasOptions);
494
- return {
495
- hash: result.hash,
496
- chainType: ChainType.EVM
497
- };
498
- }
499
- else if (chainInfo.chainType === ChainType.SOLANA) {
500
- const solanaClient = await this.getSolanaClient();
501
- // Solana supports multiple recipients
502
- const recipients = Array.isArray(recipient) ? recipient : [recipient];
503
- const result = await solanaClient.distributeClaimableFunds(connectedWallet, chainInfo, recipients, options?.computeOptions);
504
- return {
505
- hash: result.transactionHash,
506
- chainType: ChainType.SOLANA
507
- };
728
+ async setFee(newFee) {
729
+ if (this.chainType === 'evm') {
730
+ return this.setFeeEVM(newFee);
508
731
  }
509
732
  else {
510
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
733
+ return this.setFeeSolana(newFee);
511
734
  }
512
735
  }
513
736
  /**
514
- * Set permission for a contract to use caller's USDC for sending messages
515
- * Note: Only supported on EVM chains
737
+ * Get the current send fee
738
+ * @returns Current send fee in USDC micro-units (6 decimals)
516
739
  */
517
- async setPermission(connectedWallet, chainInfo, contractAddress, options) {
518
- if (chainInfo.chainType === ChainType.EVM) {
519
- const evmClient = await this.getEVMClient();
520
- const result = await evmClient.setPermission(connectedWallet, chainInfo, contractAddress, options?.gasOptions);
521
- return {
522
- hash: result.hash,
523
- chainType: ChainType.EVM
524
- };
525
- }
526
- else if (chainInfo.chainType === ChainType.SOLANA) {
527
- throw new Error('Permission system is not supported on Solana');
528
- }
529
- else {
530
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
531
- }
740
+ async getFee() {
741
+ return this.getSendFee();
532
742
  }
533
743
  /**
534
- * Remove permission from a contract
535
- * Note: Only supported on EVM chains
744
+ * Set the delegation fee (owner only)
745
+ * @param newFee - New delegation fee in USDC micro-units
746
+ * @returns Promise resolving to transaction details
536
747
  */
537
- async removePermission(connectedWallet, chainInfo, contractAddress, options) {
538
- if (chainInfo.chainType === ChainType.EVM) {
539
- const evmClient = await this.getEVMClient();
540
- const result = await evmClient.removePermission(connectedWallet, chainInfo, contractAddress, options?.gasOptions);
541
- return {
542
- hash: result.hash,
543
- chainType: ChainType.EVM
544
- };
545
- }
546
- else if (chainInfo.chainType === ChainType.SOLANA) {
547
- throw new Error('Permission system is not supported on Solana');
748
+ async setDelegationFee(newFee) {
749
+ if (this.chainType === 'evm') {
750
+ return this.setDelegationFeeEVM(newFee);
548
751
  }
549
752
  else {
550
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
753
+ return this.setDelegationFeeSolana(newFee);
551
754
  }
552
755
  }
553
756
  /**
554
- * Check if permission exists for a contract/wallet pair
555
- * Note: Only supported on EVM chains
757
+ * Get the current delegation fee
758
+ * @returns Current delegation fee in USDC micro-units
556
759
  */
557
- async hasPermission(chainInfo, contractAddress, walletAddress, publicClient) {
558
- if (chainInfo.chainType === ChainType.EVM) {
559
- const evmClient = await this.getEVMClient();
560
- return await evmClient.hasPermission(chainInfo, contractAddress, walletAddress, publicClient);
561
- }
562
- else if (chainInfo.chainType === ChainType.SOLANA) {
563
- // Solana doesn't have permission system, always return false
564
- return false;
760
+ async getDelegationFee() {
761
+ if (this.chainType === 'evm') {
762
+ return this.getDelegationFeeEVM();
565
763
  }
566
764
  else {
567
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
765
+ return this.getDelegationFeeSolana();
568
766
  }
569
767
  }
570
- // ============= Read Methods =============
571
768
  /**
572
- * Get the send fee for messages
573
- * @param chainInfo - Chain information with RPC endpoint
574
- * @param publicClient - Optional public client for EVM (will create if not provided)
575
- * @param connection - Optional connection for Solana (will create if not provided)
576
- * @returns Fee amount in USDC micro-units
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
577
772
  */
578
- async getSendFee(chainInfo, publicClient, connection) {
579
- if (chainInfo.chainType === ChainType.EVM) {
580
- const evmClient = await this.getEVMClient();
581
- return await evmClient.getSendFee(chainInfo, publicClient);
582
- }
583
- else if (chainInfo.chainType === ChainType.SOLANA) {
584
- const solanaClient = await this.getSolanaClient();
585
- return await solanaClient.getSendFee(chainInfo, connection);
773
+ async rejectDelegation(delegatorAddress) {
774
+ if (this.chainType === 'evm') {
775
+ return this.rejectDelegationEVM(delegatorAddress);
586
776
  }
587
777
  else {
588
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
778
+ return this.rejectDelegationSolana(delegatorAddress);
589
779
  }
590
780
  }
591
781
  /**
592
- * Get delegation fee
782
+ * Claim owner share of fees (owner only)
783
+ * @returns Promise resolving to transaction details
593
784
  */
594
- async getDelegationFee(chainInfo, publicClient, connection) {
595
- if (chainInfo.chainType === ChainType.EVM) {
596
- const evmClient = await this.getEVMClient();
597
- return await evmClient.getDelegationFee(chainInfo, publicClient);
598
- }
599
- else if (chainInfo.chainType === ChainType.SOLANA) {
600
- const solanaClient = await this.getSolanaClient();
601
- return await solanaClient.getDelegationFee(chainInfo, connection);
785
+ async claimOwnerShare() {
786
+ if (this.chainType === 'evm') {
787
+ return this.claimOwnerShareEVM();
602
788
  }
603
789
  else {
604
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
790
+ return this.claimOwnerShareSolana();
605
791
  }
606
792
  }
607
793
  /**
608
- * Get delegation for an address
609
- * @param address - Address to check
610
- * @param chainInfo - Chain information with RPC endpoint
611
- * @param publicClient - Optional public client for EVM
612
- * @param connection - Optional connection for Solana
613
- * @returns Delegated address or null
794
+ * Claim expired shares (owner only, EVM only)
795
+ * @param recipient - Address to claim expired shares for
796
+ * @returns Promise resolving to transaction details
614
797
  */
615
- async getDelegation(address, chainInfo, publicClient, connection) {
616
- if (chainInfo.chainType === ChainType.EVM) {
617
- const evmClient = await this.getEVMClient();
618
- const delegation = await evmClient.getDelegation(address, chainInfo, publicClient);
619
- return delegation === '0x0000000000000000000000000000000000000000' ? null : delegation;
620
- }
621
- else if (chainInfo.chainType === ChainType.SOLANA) {
622
- const solanaClient = await this.getSolanaClient();
623
- const delegation = await solanaClient.getDelegation(address, chainInfo, connection);
624
- return delegation ? delegation.toBase58() : null;
798
+ async claimExpiredShares(recipient) {
799
+ if (this.chainType === 'evm') {
800
+ return this.claimExpiredSharesEVM(recipient);
625
801
  }
626
802
  else {
627
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
803
+ throw new Error('claimExpiredShares not available on Solana');
628
804
  }
629
805
  }
630
806
  /**
631
- * Get recipient claimable info
807
+ * Pause the contract and distribute funds (owner only)
808
+ * @returns Promise resolving to transaction details
632
809
  */
633
- async getRecipientClaimable(recipient, chainInfo, publicClient, connection) {
634
- if (chainInfo.chainType === ChainType.EVM) {
635
- const evmClient = await this.getEVMClient();
636
- return await evmClient.getRecipientClaimable(recipient, chainInfo, publicClient);
637
- }
638
- else if (chainInfo.chainType === ChainType.SOLANA) {
639
- const solanaClient = await this.getSolanaClient();
640
- const info = await solanaClient.getRecipientClaimable(recipient, chainInfo, connection);
641
- if (!info)
642
- return null;
643
- return {
644
- amount: BigInt(info.amount),
645
- expiresAt: BigInt(info.expiresAt),
646
- isExpired: info.isExpired
647
- };
810
+ async pause() {
811
+ if (this.chainType === 'evm') {
812
+ return this.pauseEVM();
648
813
  }
649
814
  else {
650
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
815
+ return this.pauseSolana();
651
816
  }
652
817
  }
653
818
  /**
654
- * Get owner claimable amount
819
+ * Unpause the contract (owner only)
820
+ * @returns Promise resolving to transaction details
655
821
  */
656
- async getOwnerClaimable(chainInfo, publicClient, connection) {
657
- if (chainInfo.chainType === ChainType.EVM) {
658
- const evmClient = await this.getEVMClient();
659
- return await evmClient.getOwnerClaimable(chainInfo, publicClient);
660
- }
661
- else if (chainInfo.chainType === ChainType.SOLANA) {
662
- const solanaClient = await this.getSolanaClient();
663
- const amount = await solanaClient.getOwnerClaimable(chainInfo, connection);
664
- return BigInt(amount);
822
+ async unpause() {
823
+ if (this.chainType === 'evm') {
824
+ return this.unpauseEVM();
665
825
  }
666
826
  else {
667
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
827
+ return this.unpauseSolana();
668
828
  }
669
829
  }
670
830
  /**
671
- * Get custom fee percentage
831
+ * Emergency unpause without fund distribution (owner only)
832
+ * @returns Promise resolving to transaction details
672
833
  */
673
- async getCustomFeePercentage(target, chainInfo, publicClient, connection) {
674
- if (chainInfo.chainType === ChainType.EVM) {
675
- const evmClient = await this.getEVMClient();
676
- return await evmClient.getCustomFeePercentage(target, chainInfo, publicClient);
677
- }
678
- else if (chainInfo.chainType === ChainType.SOLANA) {
679
- const solanaClient = await this.getSolanaClient();
680
- return await solanaClient.getCustomFeePercentage(target, chainInfo, connection);
834
+ async emergencyUnpause() {
835
+ if (this.chainType === 'evm') {
836
+ return this.emergencyUnpauseEVM();
681
837
  }
682
838
  else {
683
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
839
+ return this.emergencyUnpauseSolana();
684
840
  }
685
841
  }
686
842
  /**
687
- * Check if contract/program is paused
843
+ * Check if contract is currently paused
844
+ * @returns True if contract is paused, false otherwise
688
845
  */
689
- async isPaused(chainInfo, publicClient, connection) {
690
- if (chainInfo.chainType === ChainType.EVM) {
691
- const evmClient = await this.getEVMClient();
692
- return await evmClient.isPaused(chainInfo, publicClient);
693
- }
694
- else if (chainInfo.chainType === ChainType.SOLANA) {
695
- const solanaClient = await this.getSolanaClient();
696
- return await solanaClient.isPaused(chainInfo, connection);
846
+ async isPaused() {
847
+ if (this.chainType === 'evm') {
848
+ return this.isPausedEVM();
697
849
  }
698
850
  else {
699
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
851
+ return this.isPausedSolana();
700
852
  }
701
853
  }
702
854
  /**
703
- * Get contract/program owner
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
704
858
  */
705
- async getOwner(chainInfo, publicClient, connection) {
706
- if (chainInfo.chainType === ChainType.EVM) {
707
- const evmClient = await this.getEVMClient();
708
- return await evmClient.getOwner(chainInfo, publicClient);
709
- }
710
- else if (chainInfo.chainType === ChainType.SOLANA) {
711
- const solanaClient = await this.getSolanaClient();
712
- const owner = await solanaClient.getOwner(chainInfo, connection);
713
- return owner.toBase58();
859
+ async distributeClaimableFunds(recipient) {
860
+ if (this.chainType === 'evm') {
861
+ return this.distributeClaimableFundsEVM(recipient);
714
862
  }
715
863
  else {
716
- throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
864
+ return this.distributeClaimableFundsSolana(recipient);
717
865
  }
718
866
  }
719
- /**
720
- * Register a domain (not implemented - for backward compatibility)
721
- */
722
- async registerDomain(_domain) {
723
- throw new Error('Domain registration not yet implemented');
867
+ // EVM Implementation Methods
868
+ async sendPreparedEVM(to, mailId, priority, resolveSenderToName) {
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 });
898
+ return {
899
+ transactionHash: txHash,
900
+ chainType: ChainType.EVM,
901
+ fee: BigInt(priority ? '100000' : '10000'),
902
+ gasUsed: receipt.gasUsed,
903
+ isPriority: priority,
904
+ success: true
905
+ };
906
+ }
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 });
937
+ return {
938
+ transactionHash: txHash,
939
+ chainType: ChainType.EVM,
940
+ fee: BigInt('10000'), // 10% fee only
941
+ gasUsed: receipt.gasUsed,
942
+ isPriority: false,
943
+ success: true
944
+ };
945
+ }
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 });
976
+ return {
977
+ transactionHash: txHash,
978
+ chainType: ChainType.EVM,
979
+ fee: BigInt('10000'), // 10% fee only
980
+ gasUsed: receipt.gasUsed,
981
+ isPriority: false,
982
+ success: true
983
+ };
984
+ }
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 });
1016
+ return {
1017
+ hash: txHash,
1018
+ chainType: ChainType.EVM,
1019
+ blockNumber: receipt.blockNumber,
1020
+ timestamp: Number(block.timestamp) * 1000
1021
+ };
1022
+ }
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
+ };
1060
+ }
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 });
1111
+ return {
1112
+ hash: txHash,
1113
+ chainType: ChainType.EVM,
1114
+ blockNumber: receipt.blockNumber,
1115
+ timestamp: Number(block.timestamp) * 1000
1116
+ };
1117
+ }
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 });
1149
+ return {
1150
+ hash: txHash,
1151
+ chainType: ChainType.EVM,
1152
+ blockNumber: receipt.blockNumber,
1153
+ timestamp: Number(block.timestamp) * 1000
1154
+ };
1155
+ }
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
+ };
1193
+ }
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 });
1225
+ return {
1226
+ hash: txHash,
1227
+ chainType: ChainType.EVM,
1228
+ blockNumber: receipt.blockNumber,
1229
+ timestamp: Number(block.timestamp) * 1000
1230
+ };
1231
+ }
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 });
1263
+ return {
1264
+ hash: txHash,
1265
+ chainType: ChainType.EVM,
1266
+ blockNumber: receipt.blockNumber,
1267
+ timestamp: Number(block.timestamp) * 1000
1268
+ };
1269
+ }
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
+ };
1307
+ }
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 });
1358
+ return {
1359
+ hash: txHash,
1360
+ chainType: ChainType.EVM,
1361
+ blockNumber: receipt.blockNumber,
1362
+ timestamp: Number(block.timestamp) * 1000
1363
+ };
1364
+ }
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 });
1382
+ return {
1383
+ transactionHash: txHash,
1384
+ chainType: ChainType.SOLANA,
1385
+ fee: priority ? fees.sendFee : fees.sendFee / 10,
1386
+ slot,
1387
+ timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1388
+ isPriority: priority,
1389
+ success: true
1390
+ };
1391
+ }
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
+ };
1416
+ }
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 });
1432
+ return {
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,
1459
+ timestamp: Date.now()
1460
+ };
1461
+ }
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();
1475
+ return {
1476
+ hash: txHash,
1477
+ chainType: ChainType.SOLANA,
1478
+ slot,
1479
+ timestamp: Date.now()
1480
+ };
1481
+ }
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);
1495
+ }
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();
1509
+ return {
1510
+ hash: txHash,
1511
+ chainType: ChainType.SOLANA,
1512
+ slot,
1513
+ timestamp: Date.now()
1514
+ };
1515
+ }
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();
1529
+ return {
1530
+ hash: txHash,
1531
+ chainType: ChainType.SOLANA,
1532
+ slot,
1533
+ timestamp: Date.now()
1534
+ };
1535
+ }
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();
1549
+ return {
1550
+ hash: txHash,
1551
+ chainType: ChainType.SOLANA,
1552
+ slot,
1553
+ timestamp: Date.now()
1554
+ };
1555
+ }
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();
1569
+ return {
1570
+ hash: txHash,
1571
+ chainType: ChainType.SOLANA,
1572
+ slot,
1573
+ timestamp: Date.now()
1574
+ };
1575
+ }
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();
1589
+ return {
1590
+ hash: txHash,
1591
+ chainType: ChainType.SOLANA,
1592
+ slot,
1593
+ timestamp: Date.now()
1594
+ };
1595
+ }
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();
1622
+ return {
1623
+ hash: txHash,
1624
+ chainType: ChainType.SOLANA,
1625
+ slot,
1626
+ timestamp: Date.now()
1627
+ };
1628
+ }
1629
+ // Utility methods
1630
+ getChainType() {
1631
+ return this.chainType;
1632
+ }
1633
+ getWalletAddress() {
1634
+ return this.wallet.address;
724
1635
  }
725
1636
  }
726
- // Cache for dynamic imports
1637
+ // Performance optimization: cache imported modules
727
1638
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
728
- OnchainMailerClient.evmClient = null;
1639
+ OnchainMailerClient.evmModules = null;
729
1640
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
730
- OnchainMailerClient.solanaClient = null;
1641
+ OnchainMailerClient.solanaModules = null;
731
1642
  //# sourceMappingURL=onchain-mailer-client.js.map