@sudobility/contracts 1.12.0 → 1.13.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 (128) hide show
  1. package/dist/evm/src/evm/{mailer-client.d.ts → evm-mailer-client.d.ts} +146 -50
  2. package/dist/evm/src/evm/evm-mailer-client.d.ts.map +1 -0
  3. package/dist/evm/src/evm/evm-mailer-client.js +924 -0
  4. package/dist/evm/src/evm/evm-mailer-client.js.map +1 -0
  5. package/dist/evm/src/evm/index.d.ts +1 -1
  6. package/dist/evm/src/evm/index.d.ts.map +1 -1
  7. package/dist/evm/src/evm/index.js +4 -4
  8. package/dist/evm/src/evm/index.js.map +1 -1
  9. package/dist/solana/solana/index.d.ts +1 -1
  10. package/dist/solana/solana/index.d.ts.map +1 -1
  11. package/dist/solana/solana/index.js +4 -3
  12. package/dist/solana/solana/index.js.map +1 -1
  13. package/dist/solana/solana/solana-mailer-client.d.ts +209 -0
  14. package/dist/solana/solana/solana-mailer-client.d.ts.map +1 -0
  15. package/dist/solana/solana/solana-mailer-client.js +1004 -0
  16. package/dist/solana/solana/solana-mailer-client.js.map +1 -0
  17. package/dist/solana/solana/types.d.ts +3 -2
  18. package/dist/solana/solana/types.d.ts.map +1 -1
  19. package/dist/solana/solana/types.js.map +1 -1
  20. package/dist/{unified-esm/src/evm/mailer-client.d.ts → unified/src/evm/evm-mailer-client.d.ts} +146 -50
  21. package/dist/unified/src/evm/evm-mailer-client.d.ts.map +1 -0
  22. package/dist/unified/src/evm/evm-mailer-client.js +924 -0
  23. package/dist/unified/src/evm/evm-mailer-client.js.map +1 -0
  24. package/dist/unified/src/evm/index.d.ts +1 -1
  25. package/dist/unified/src/evm/index.d.ts.map +1 -1
  26. package/dist/unified/src/evm/index.js +4 -4
  27. package/dist/unified/src/evm/index.js.map +1 -1
  28. package/dist/unified/src/react/context/MailerProvider.d.ts +26 -20
  29. package/dist/unified/src/react/context/MailerProvider.d.ts.map +1 -1
  30. package/dist/unified/src/react/context/MailerProvider.js +26 -26
  31. package/dist/unified/src/react/context/MailerProvider.js.map +1 -1
  32. package/dist/unified/src/react/hooks/useMailerMutations.d.ts +225 -192
  33. package/dist/unified/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  34. package/dist/unified/src/react/hooks/useMailerMutations.js +263 -266
  35. package/dist/unified/src/react/hooks/useMailerMutations.js.map +1 -1
  36. package/dist/unified/src/react/hooks/useMailerQueries.d.ts +117 -63
  37. package/dist/unified/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  38. package/dist/unified/src/react/hooks/useMailerQueries.js +239 -104
  39. package/dist/unified/src/react/hooks/useMailerQueries.js.map +1 -1
  40. package/dist/unified/src/react/index.d.ts +5 -3
  41. package/dist/unified/src/react/index.d.ts.map +1 -1
  42. package/dist/unified/src/react/index.js +41 -26
  43. package/dist/unified/src/react/index.js.map +1 -1
  44. package/dist/unified/src/solana/index.d.ts +1 -1
  45. package/dist/unified/src/solana/index.d.ts.map +1 -1
  46. package/dist/unified/src/solana/index.js +4 -3
  47. package/dist/unified/src/solana/index.js.map +1 -1
  48. package/dist/unified/src/solana/solana-mailer-client.d.ts +209 -0
  49. package/dist/unified/src/solana/solana-mailer-client.d.ts.map +1 -0
  50. package/dist/unified/src/solana/solana-mailer-client.js +1004 -0
  51. package/dist/unified/src/solana/solana-mailer-client.js.map +1 -0
  52. package/dist/unified/src/solana/types.d.ts +3 -2
  53. package/dist/unified/src/solana/types.d.ts.map +1 -1
  54. package/dist/unified/src/solana/types.js.map +1 -1
  55. package/dist/unified/src/unified/index.d.ts +1 -1
  56. package/dist/unified/src/unified/index.d.ts.map +1 -1
  57. package/dist/unified/src/unified/onchain-mailer-client.d.ts +187 -268
  58. package/dist/unified/src/unified/onchain-mailer-client.d.ts.map +1 -1
  59. package/dist/unified/src/unified/onchain-mailer-client.js +539 -1614
  60. package/dist/unified/src/unified/onchain-mailer-client.js.map +1 -1
  61. package/dist/unified/src/unified/types.d.ts +23 -6
  62. package/dist/unified/src/unified/types.d.ts.map +1 -1
  63. package/dist/{unified/src/evm/mailer-client.d.ts → unified-esm/src/evm/evm-mailer-client.d.ts} +146 -50
  64. package/dist/unified-esm/src/evm/evm-mailer-client.d.ts.map +1 -0
  65. package/dist/unified-esm/src/evm/evm-mailer-client.js +920 -0
  66. package/dist/unified-esm/src/evm/evm-mailer-client.js.map +1 -0
  67. package/dist/unified-esm/src/evm/index.d.ts +1 -1
  68. package/dist/unified-esm/src/evm/index.d.ts.map +1 -1
  69. package/dist/unified-esm/src/evm/index.js +2 -2
  70. package/dist/unified-esm/src/evm/index.js.map +1 -1
  71. package/dist/unified-esm/src/react/context/MailerProvider.d.ts +26 -20
  72. package/dist/unified-esm/src/react/context/MailerProvider.d.ts.map +1 -1
  73. package/dist/unified-esm/src/react/context/MailerProvider.js +25 -26
  74. package/dist/unified-esm/src/react/context/MailerProvider.js.map +1 -1
  75. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts +225 -192
  76. package/dist/unified-esm/src/react/hooks/useMailerMutations.d.ts.map +1 -1
  77. package/dist/unified-esm/src/react/hooks/useMailerMutations.js +254 -262
  78. package/dist/unified-esm/src/react/hooks/useMailerMutations.js.map +1 -1
  79. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts +117 -63
  80. package/dist/unified-esm/src/react/hooks/useMailerQueries.d.ts.map +1 -1
  81. package/dist/unified-esm/src/react/hooks/useMailerQueries.js +232 -102
  82. package/dist/unified-esm/src/react/hooks/useMailerQueries.js.map +1 -1
  83. package/dist/unified-esm/src/react/index.d.ts +5 -3
  84. package/dist/unified-esm/src/react/index.d.ts.map +1 -1
  85. package/dist/unified-esm/src/react/index.js +9 -5
  86. package/dist/unified-esm/src/react/index.js.map +1 -1
  87. package/dist/unified-esm/src/solana/index.d.ts +1 -1
  88. package/dist/unified-esm/src/solana/index.d.ts.map +1 -1
  89. package/dist/unified-esm/src/solana/index.js +2 -1
  90. package/dist/unified-esm/src/solana/index.js.map +1 -1
  91. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts +209 -0
  92. package/dist/unified-esm/src/solana/solana-mailer-client.d.ts.map +1 -0
  93. package/dist/unified-esm/src/solana/solana-mailer-client.js +1000 -0
  94. package/dist/unified-esm/src/solana/solana-mailer-client.js.map +1 -0
  95. package/dist/unified-esm/src/solana/types.d.ts +3 -2
  96. package/dist/unified-esm/src/solana/types.d.ts.map +1 -1
  97. package/dist/unified-esm/src/solana/types.js.map +1 -1
  98. package/dist/unified-esm/src/unified/index.d.ts +1 -1
  99. package/dist/unified-esm/src/unified/index.d.ts.map +1 -1
  100. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts +187 -268
  101. package/dist/unified-esm/src/unified/onchain-mailer-client.d.ts.map +1 -1
  102. package/dist/unified-esm/src/unified/onchain-mailer-client.js +539 -1614
  103. package/dist/unified-esm/src/unified/onchain-mailer-client.js.map +1 -1
  104. package/dist/unified-esm/src/unified/types.d.ts +23 -6
  105. package/dist/unified-esm/src/unified/types.d.ts.map +1 -1
  106. package/package.json +5 -4
  107. package/programs/mailer/Cargo.toml +1 -1
  108. package/dist/evm/src/evm/mailer-client.d.ts.map +0 -1
  109. package/dist/evm/src/evm/mailer-client.js +0 -619
  110. package/dist/evm/src/evm/mailer-client.js.map +0 -1
  111. package/dist/solana/solana/mailer-client.d.ts +0 -282
  112. package/dist/solana/solana/mailer-client.d.ts.map +0 -1
  113. package/dist/solana/solana/mailer-client.js +0 -989
  114. package/dist/solana/solana/mailer-client.js.map +0 -1
  115. package/dist/unified/src/evm/mailer-client.d.ts.map +0 -1
  116. package/dist/unified/src/evm/mailer-client.js +0 -619
  117. package/dist/unified/src/evm/mailer-client.js.map +0 -1
  118. package/dist/unified/src/solana/mailer-client.d.ts +0 -282
  119. package/dist/unified/src/solana/mailer-client.d.ts.map +0 -1
  120. package/dist/unified/src/solana/mailer-client.js +0 -989
  121. package/dist/unified/src/solana/mailer-client.js.map +0 -1
  122. package/dist/unified-esm/src/evm/mailer-client.d.ts.map +0 -1
  123. package/dist/unified-esm/src/evm/mailer-client.js +0 -615
  124. package/dist/unified-esm/src/evm/mailer-client.js.map +0 -1
  125. package/dist/unified-esm/src/solana/mailer-client.d.ts +0 -282
  126. package/dist/unified-esm/src/solana/mailer-client.d.ts.map +0 -1
  127. package/dist/unified-esm/src/solana/mailer-client.js +0 -985
  128. package/dist/unified-esm/src/solana/mailer-client.js.map +0 -1
@@ -1,1806 +1,731 @@
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';
5
4
  /**
6
- * OnchainMailerClient - Multi-chain messaging client for Mailer protocol
5
+ * OnchainMailerClient - Stateless multi-chain messaging client
7
6
  *
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.
7
+ * This version uses stateless EVM and Solana clients underneath.
8
+ * All wallet connections and chain information are passed as parameters to each method.
11
9
  *
12
- * @example Basic Usage
10
+ * @example EVM Usage
13
11
  * ```typescript
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);
12
+ * import { createWalletClient, createPublicClient, http } from 'viem';
13
+ * import { RpcHelpers } from '@sudobility/configs';
14
+ * import { Chain } from '@sudobility/types';
27
15
  *
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);
16
+ * const chainInfo = RpcHelpers.getChainInfo(Chain.ETH_MAINNET);
17
+ * const walletClient = createWalletClient({
18
+ * chain: mainnet,
19
+ * transport: http()
20
+ * });
40
21
  *
41
- * // Send messages
42
- * const result = await client.sendMessage("Hello", "World!", false);
43
- * console.log('Transaction:', result.transactionHash);
22
+ * const client = new OnchainMailerClient();
23
+ * await client.sendMessage(
24
+ * 'Subject',
25
+ * 'Body',
26
+ * { walletClient },
27
+ * chainInfo,
28
+ * { priority: true }
29
+ * );
44
30
  * ```
45
31
  *
46
- * @example Error Handling
32
+ * @example Solana Usage
47
33
  * ```typescript
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
- * }
60
- * ```
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();
61
41
  *
62
- * @author Mailer Protocol Team
63
- * @version 1.5.2
64
- * @since 1.0.0
42
+ * const client = new OnchainMailerClient();
43
+ * await client.sendMessage(
44
+ * 'Subject',
45
+ * 'Body',
46
+ * { wallet },
47
+ * chainInfo,
48
+ * { priority: true }
49
+ * );
50
+ * ```
65
51
  */
66
52
  export class OnchainMailerClient {
67
53
  /**
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
- * ```
54
+ * Create a new stateless OnchainMailerClient
55
+ * No configuration needed in constructor
86
56
  */
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
- }
57
+ constructor() {
58
+ // Stateless - no initialization needed
108
59
  }
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
- }
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();
133
65
  }
66
+ return OnchainMailerClient.evmClient;
134
67
  }
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');
68
+ async getSolanaClient() {
69
+ if (!OnchainMailerClient.solanaClient) {
70
+ const { SolanaMailerClient } = await import('../solana/solana-mailer-client.js');
71
+ OnchainMailerClient.solanaClient = new SolanaMailerClient();
145
72
  }
73
+ return OnchainMailerClient.solanaClient;
146
74
  }
147
75
  /**
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
- *
76
+ * Send a message on the blockchain
153
77
  * @param subject - Message subject (1-200 characters)
154
78
  * @param body - Message body (1-10000 characters)
155
- * @param priority - Whether to use priority sending with revenue share
156
- * - Priority: Full fee paid, 90% claimable by recipient
157
- * - Standard: 10% fee only, no revenue share
158
- * @param resolveSenderToName - If true, resolve sender address to name via off-chain service
159
- *
160
- * @returns Promise resolving to MessageResult with transaction details
161
- *
162
- * @throws {Error} When subject/body validation fails
163
- * @throws {Error} When insufficient USDC balance
164
- * @throws {Error} When user rejects transaction
165
- * @throws {Error} When network connection fails
166
- *
167
- * @example Standard Message
168
- * ```typescript
169
- * const result = await client.sendMessage(
170
- * "Meeting Reminder",
171
- * "Don't forget our 3pm call today!",
172
- * false, // Standard fee (10% of sendFee)
173
- * false // Don't resolve sender to name
174
- * );
175
- * console.log('Sent in tx:', result.transactionHash);
176
- * ```
177
- *
178
- * @example Priority Message with Revenue Share
179
- * ```typescript
180
- * const result = await client.sendMessage(
181
- * "Important Update",
182
- * "Urgent: Please review the attached proposal",
183
- * true, // Priority fee (100% paid, 90% claimable by recipient)
184
- * true // Resolve sender to name
185
- * );
186
- * console.log('Priority message fee:', result.fee);
187
- * ```
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
188
83
  */
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);
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
+ };
193
126
  }
194
127
  else {
195
- return this.sendSolanaMessage(subject, body, priority, resolveSenderToName);
128
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
196
129
  }
197
130
  }
198
131
  /**
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
132
+ * Send a prepared message
203
133
  */
204
- async registerDomain(domain, isExtension = false) {
205
- if (this.chainType === 'evm') {
206
- return this.registerEVMDomain(domain, isExtension);
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
+ };
207
165
  }
208
166
  else {
209
- return this.registerSolanaDomain(domain, isExtension);
167
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
210
168
  }
211
169
  }
212
170
  /**
213
- * Delegate to another address using the appropriate chain implementation
214
- * @param delegate - Address to delegate to
215
- * @returns Delegation result
171
+ * Send through webhook
216
172
  */
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})`);
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
+ };
222
189
  }
223
- if (this.chainType === 'evm') {
224
- return this.delegateEVM(delegate);
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
+ };
225
202
  }
226
203
  else {
227
- return this.delegateSolana(delegate);
204
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
228
205
  }
229
206
  }
230
207
  /**
231
- * Claim revenue share using the appropriate chain implementation
208
+ * Delegate to another address
209
+ * @param delegate - Address to delegate to
210
+ * @param wallet - Wallet connection
211
+ * @param chainInfo - Chain information
232
212
  * @returns Transaction result
233
213
  */
234
- async claimRevenue() {
235
- if (this.chainType === 'evm') {
236
- return this.claimEVMRevenue();
237
- }
238
- else {
239
- return this.claimSolanaRevenue();
240
- }
241
- }
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
- const payer = this.wallet.address;
334
- txHash = await client.send(this.wallet.address, subject, body, payer, priority, resolveSenderToName, walletClient, this.wallet.address);
335
- }
336
- catch (error) {
337
- const errorMessage = error instanceof Error ? error.message : String(error);
338
- if (errorMessage.includes('insufficient funds')) {
339
- throw new Error('Insufficient USDC balance to send message');
340
- }
341
- if (errorMessage.includes('user rejected')) {
342
- throw new Error('Transaction rejected by user');
343
- }
344
- throw new Error(`Transaction failed: ${errorMessage}`);
345
- }
346
- // Wait for confirmation with timeout
347
- const receipt = await Promise.race([
348
- publicClient.waitForTransactionReceipt({ hash: txHash }),
349
- new Promise((_, reject) => setTimeout(() => reject(new Error('Transaction confirmation timeout')), 60000))
350
- ]);
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);
351
218
  return {
352
- transactionHash: txHash,
219
+ transactionHash: result.hash,
353
220
  chainType: ChainType.EVM,
354
- messageId: undefined, // Could extract from logs if needed
355
- fee: BigInt(priority ? '100000' : '10000'), // 0.1 or 0.01 USDC in micro-USDC
356
- gasUsed: receipt.gasUsed,
357
- isPriority: priority,
221
+ delegate,
358
222
  success: true
359
223
  };
360
224
  }
361
- catch (error) {
362
- throw new Error(`EVM message sending failed: ${error instanceof Error ? error.message : String(error)}`);
363
- }
364
- }
365
- async registerEVMDomain(_domain, _isExtension) {
366
- // Domain registration not implemented in current EVM version (delegation-only)
367
- throw new Error('Domain registration not yet implemented in EVM version - use delegation instead');
368
- }
369
- async delegateEVM(delegate) {
370
- const { viem } = await this.getEVMModules();
371
- if (!this.config.evm) {
372
- throw new Error('EVM configuration not provided');
373
- }
374
- // Validate EVM address format
375
- if (!viem.isAddress(delegate)) {
376
- throw new Error('Invalid EVM address format for delegate');
377
- }
378
- // Note: Domain functionality is now integrated into the Mailer contract
379
- throw new Error('Domain delegation is now handled through the Mailer contract - use MailerClient instead');
380
- }
381
- async claimEVMRevenue() {
382
- const { viem, MailerClient } = await this.getEVMModules();
383
- if (!this.config.evm) {
384
- throw new Error('EVM configuration not provided');
385
- }
386
- const publicClient = viem.createPublicClient({
387
- transport: viem.http(this.config.evm.rpc),
388
- chain: {
389
- id: this.config.evm.chainId,
390
- name: 'Custom Chain',
391
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
392
- rpcUrls: {
393
- default: { http: [this.config.evm.rpc] }
394
- }
395
- }
396
- });
397
- const walletClient = viem.createWalletClient({
398
- transport: viem.http(this.config.evm.rpc),
399
- chain: {
400
- id: this.config.evm.chainId,
401
- name: 'Custom Chain',
402
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
403
- rpcUrls: {
404
- default: { http: [this.config.evm.rpc] }
405
- }
406
- }
407
- });
408
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
409
- const txHash = await client.claimRecipientShare(walletClient, this.wallet.address);
410
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
411
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
412
- return {
413
- hash: txHash,
414
- chainType: ChainType.EVM,
415
- blockNumber: receipt.blockNumber,
416
- timestamp: Number(block.timestamp) * 1000
417
- };
418
- }
419
- // Private methods for Solana implementation
420
- async sendSolanaMessage(subject, body, priority, resolveSenderToName = false) {
421
- try {
422
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
423
- if (!this.config.solana) {
424
- throw new Error('Solana configuration not provided');
425
- }
426
- if (!this.config.solana.programs.mailer) {
427
- throw new Error('Solana Mailer program address not configured');
428
- }
429
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
430
- // Test connection
431
- try {
432
- await Promise.race([
433
- connection.getSlot(),
434
- new Promise((_, reject) => setTimeout(() => reject(new Error('Connection timeout')), 10000))
435
- ]);
436
- }
437
- catch (error) {
438
- throw new Error(`Failed to connect to Solana RPC: ${error instanceof Error ? error.message : String(error)}`);
439
- }
440
- // Create wallet adapter for native client
441
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
442
- const wallet = MailerClient.createWallet(this.wallet);
443
- const programId = new PublicKey(this.config.solana.programs.mailer);
444
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
445
- // For now, send to the wallet itself (self-messaging)
446
- const recipientKey = new PublicKey(this.wallet.address);
447
- const client = new MailerClient(connection, wallet, programId, usdcMint);
448
- // Get current fees
449
- const fees = await client.getFees();
450
- let txHash;
451
- txHash = await client.send(recipientKey.toBase58(), subject, body, priority, resolveSenderToName);
452
- // Get transaction details
453
- const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
454
- // Get current slot for transaction info
455
- const slot = await connection.getSlot();
225
+ else if (chainInfo.chainType === ChainType.SOLANA) {
226
+ const solanaClient = await this.getSolanaClient();
227
+ const result = await solanaClient.delegateTo(delegate, connectedWallet, chainInfo, options?.computeOptions);
456
228
  return {
457
- transactionHash: txHash,
229
+ transactionHash: result.transactionHash,
458
230
  chainType: ChainType.SOLANA,
459
- fee: priority ? fees.sendFee : fees.sendFee / 10,
460
- recipient: recipientKey.toBase58(),
461
- subject,
462
- body,
463
- slot,
464
- timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
465
- isPriority: priority,
231
+ delegate,
466
232
  success: true
467
233
  };
468
234
  }
469
- catch (error) {
470
- throw new Error(`Solana message sending failed: ${error instanceof Error ? error.message : String(error)}`);
471
- }
472
- }
473
- async registerSolanaDomain(_domain, _isExtension) {
474
- // Domain registration not implemented in current Solana version
475
- throw new Error('Domain registration not yet implemented in Solana version - use delegation instead');
476
- }
477
- async delegateSolana(_delegate) {
478
- if (!this.config.solana) {
479
- throw new Error('Solana configuration not provided');
235
+ else {
236
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
480
237
  }
481
- // Note: Domain functionality is now integrated into the Mailer contract
482
- throw new Error('Domain delegation is now handled through the Mailer contract - use MailerClient instead');
483
- }
484
- async claimSolanaRevenue() {
485
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
486
- if (!this.config.solana) {
487
- throw new Error('Solana configuration not provided');
488
- }
489
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
490
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
491
- const wallet = MailerClient.createWallet(this.wallet);
492
- const programId = new PublicKey(this.config.solana.programs.mailer);
493
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
494
- const client = new MailerClient(connection, wallet, programId, usdcMint);
495
- const txHash = await client.claimRecipientShare();
496
- const slot = await connection.getSlot();
497
- return {
498
- hash: txHash,
499
- chainType: ChainType.SOLANA,
500
- slot,
501
- timestamp: Date.now()
502
- };
503
238
  }
504
239
  /**
505
- * Get send fee using the appropriate chain implementation
506
- * @returns Send fee in USDC micro-units (6 decimals)
240
+ * Reject delegation
507
241
  */
508
- async getSendFee() {
509
- if (this.chainType === 'evm') {
510
- return this.getEVMSendFee();
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);
254
+ return {
255
+ hash: result.transactionHash,
256
+ chainType: ChainType.SOLANA
257
+ };
511
258
  }
512
259
  else {
513
- return this.getSolanaSendFee();
260
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
514
261
  }
515
262
  }
516
263
  /**
517
- * Get claimable amount for an address
518
- * @param address - Address to check claimable balance for (defaults to connected wallet)
519
- * @returns Claimable amount in USDC micro-units
264
+ * Claim revenue share
265
+ * @param wallet - Wallet connection
266
+ * @param chainInfo - Chain information
267
+ * @returns Transaction result
520
268
  */
521
- async getClaimableAmount(address) {
522
- const targetAddress = address || this.wallet.address;
523
- if (this.chainType === 'evm') {
524
- return this.getEVMClaimableAmount(targetAddress);
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
+ };
525
285
  }
526
286
  else {
527
- return this.getSolanaClaimableAmount(targetAddress);
287
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
528
288
  }
529
289
  }
530
290
  /**
531
- * Get owner's claimable fee balance
532
- * @returns Owner claimable amount in USDC micro-units
291
+ * Claim owner share (owner only)
533
292
  */
534
- async getOwnerClaimable() {
535
- if (this.chainType === 'evm') {
536
- return this.getEVMOwnerClaimable();
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);
297
+ return {
298
+ hash: result.hash,
299
+ chainType: ChainType.EVM
300
+ };
301
+ }
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
+ };
537
309
  }
538
310
  else {
539
- return this.getSolanaOwnerClaimable();
311
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
540
312
  }
541
313
  }
542
314
  /**
543
- * Get delegation information for an address
544
- * @param address - Address to check delegation for (defaults to connected wallet)
545
- * @returns Delegation address or null if no delegation
315
+ * Claim expired shares (owner only)
546
316
  */
547
- async getDelegation(address) {
548
- const targetAddress = address || this.wallet.address;
549
- if (this.chainType === 'evm') {
550
- return this.getEVMDelegation(targetAddress);
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
+ };
551
333
  }
552
334
  else {
553
- return this.getSolanaDelegation(targetAddress);
335
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
554
336
  }
555
337
  }
556
- // EVM read methods
557
- async getEVMSendFee() {
558
- const { viem, MailerClient } = await this.getEVMModules();
559
- if (!this.config.evm?.contracts.mailer) {
560
- throw new Error('EVM Mailer contract address not configured');
561
- }
562
- const publicClient = viem.createPublicClient({
563
- transport: viem.http(this.config.evm.rpc),
564
- chain: {
565
- id: this.config.evm.chainId,
566
- name: 'Custom Chain',
567
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
568
- rpcUrls: {
569
- default: { http: [this.config.evm.rpc] }
570
- }
571
- }
572
- });
573
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
574
- return client.getSendFee();
575
- }
576
- async getEVMClaimableAmount(address) {
577
- const { viem, MailerClient } = await this.getEVMModules();
578
- if (!this.config.evm?.contracts.mailer) {
579
- throw new Error('EVM Mailer contract address not configured');
580
- }
581
- const publicClient = viem.createPublicClient({
582
- transport: viem.http(this.config.evm.rpc),
583
- chain: {
584
- id: this.config.evm.chainId,
585
- name: 'Custom Chain',
586
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
587
- rpcUrls: {
588
- default: { http: [this.config.evm.rpc] }
589
- }
590
- }
591
- });
592
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
593
- const result = await client.getRecipientClaimable(address);
594
- return result.amount;
595
- }
596
- async getEVMOwnerClaimable() {
597
- const { viem, MailerClient } = await this.getEVMModules();
598
- if (!this.config.evm?.contracts.mailer) {
599
- throw new Error('EVM Mailer contract address not configured');
600
- }
601
- const publicClient = viem.createPublicClient({
602
- transport: viem.http(this.config.evm.rpc),
603
- chain: {
604
- id: this.config.evm.chainId,
605
- name: 'Custom Chain',
606
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
607
- rpcUrls: {
608
- default: { http: [this.config.evm.rpc] }
609
- }
610
- }
611
- });
612
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
613
- return client.getOwnerClaimable();
614
- }
615
- async getEVMDelegation(_address) {
616
- // Delegation read not implemented in EVM client yet
617
- // Would need to add getDelegation method to EVM MailerClient
618
- throw new Error('getDelegation not yet implemented for EVM');
619
- }
620
- // Solana read methods
621
- async getSolanaSendFee() {
622
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
623
- if (!this.config.solana?.programs.mailer) {
624
- throw new Error('Solana Mailer program address not configured');
625
- }
626
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
627
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
628
- const wallet = MailerClient.createWallet(this.wallet);
629
- const programId = new PublicKey(this.config.solana.programs.mailer);
630
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
631
- const client = new MailerClient(connection, wallet, programId, usdcMint);
632
- const fees = await client.getFees();
633
- return BigInt(fees.sendFee);
634
- }
635
- async getSolanaClaimableAmount(address) {
636
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
637
- if (!this.config.solana?.programs.mailer) {
638
- throw new Error('Solana Mailer program address not configured');
639
- }
640
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
641
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
642
- const wallet = MailerClient.createWallet(this.wallet);
643
- const programId = new PublicKey(this.config.solana.programs.mailer);
644
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
645
- const client = new MailerClient(connection, wallet, programId, usdcMint);
646
- const recipientKey = new PublicKey(address);
647
- const claimInfo = await client.getRecipientClaimable(recipientKey);
648
- return claimInfo ? BigInt(claimInfo.amount) : 0n;
649
- }
650
- async getSolanaOwnerClaimable() {
651
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
652
- if (!this.config.solana?.programs.mailer) {
653
- throw new Error('Solana Mailer program address not configured');
654
- }
655
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
656
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
657
- const wallet = MailerClient.createWallet(this.wallet);
658
- const programId = new PublicKey(this.config.solana.programs.mailer);
659
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
660
- const client = new MailerClient(connection, wallet, programId, usdcMint);
661
- const amount = await client.getOwnerClaimable();
662
- return BigInt(amount);
663
- }
664
- async getSolanaDelegation(address) {
665
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
666
- if (!this.config.solana?.programs.mailer) {
667
- throw new Error('Solana Mailer program address not configured');
668
- }
669
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
670
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
671
- const wallet = MailerClient.createWallet(this.wallet);
672
- const programId = new PublicKey(this.config.solana.programs.mailer);
673
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
674
- const client = new MailerClient(connection, wallet, programId, usdcMint);
675
- const delegatorKey = new PublicKey(address);
676
- const delegationInfo = await client.getDelegation(delegatorKey);
677
- return delegationInfo?.delegate || null;
678
- }
679
338
  /**
680
- * Send a prepared message using mail ID (to match cross-chain behavior)
681
- * @param to - Recipient address
682
- * @param mailId - Pre-prepared message identifier
683
- * @param priority - Whether to use priority sending with revenue share
684
- * @param resolveSenderToName - If true, resolve sender address to name
685
- * @returns Promise resolving to MessageResult
339
+ * Set fees (owner only)
686
340
  */
687
- async sendPrepared(to, mailId, priority = false, resolveSenderToName = false) {
688
- if (this.chainType === 'evm') {
689
- return this.sendPreparedEVM(to, mailId, priority, resolveSenderToName);
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
+ };
690
359
  }
691
360
  else {
692
- return this.sendPreparedSolana(to, mailId, priority, resolveSenderToName);
361
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
693
362
  }
694
363
  }
695
364
  /**
696
- * Send message to email address (no wallet known)
697
- * @param toEmail - Email address of the recipient
698
- * @param subject - Message subject
699
- * @param body - Message body
700
- * @returns Promise resolving to MessageResult
365
+ * Set custom fee percentage
701
366
  */
702
- async sendToEmail(toEmail, subject, body) {
703
- if (this.chainType === 'evm') {
704
- return this.sendToEmailEVM(toEmail, subject, body);
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
+ };
705
383
  }
706
384
  else {
707
- return this.sendToEmailSolana(toEmail, subject, body);
385
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
708
386
  }
709
387
  }
710
388
  /**
711
- * Send prepared message to email address (no wallet known)
712
- * @param toEmail - Email address of the recipient
713
- * @param mailId - Pre-prepared message identifier
714
- * @returns Promise resolving to MessageResult
389
+ * Clear custom fee percentage
715
390
  */
716
- async sendPreparedToEmail(toEmail, mailId) {
717
- if (this.chainType === 'evm') {
718
- return this.sendPreparedToEmailEVM(toEmail, mailId);
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
+ };
719
407
  }
720
408
  else {
721
- return this.sendPreparedToEmailSolana(toEmail, mailId);
409
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
722
410
  }
723
411
  }
724
412
  /**
725
- * Set the send fee (owner only)
726
- * @param newFee - New fee amount in USDC micro-units (6 decimals)
727
- * @returns Promise resolving to transaction details
413
+ * Pause the contract/program (owner only)
728
414
  */
729
- async setFee(newFee) {
730
- if (this.chainType === 'evm') {
731
- return this.setFeeEVM(newFee);
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
+ };
732
431
  }
733
432
  else {
734
- return this.setFeeSolana(newFee);
433
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
735
434
  }
736
435
  }
737
436
  /**
738
- * Get the current send fee
739
- * @returns Current send fee in USDC micro-units (6 decimals)
437
+ * Unpause the contract/program (owner only)
740
438
  */
741
- async getFee() {
742
- return this.getSendFee();
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
+ };
455
+ }
456
+ else {
457
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
458
+ }
743
459
  }
744
460
  /**
745
- * Set the delegation fee (owner only)
746
- * @param newFee - New delegation fee in USDC micro-units
747
- * @returns Promise resolving to transaction details
461
+ * Emergency unpause (owner only)
748
462
  */
749
- async setDelegationFee(newFee) {
750
- if (this.chainType === 'evm') {
751
- return this.setDelegationFeeEVM(newFee);
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
+ };
752
479
  }
753
480
  else {
754
- return this.setDelegationFeeSolana(newFee);
481
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
755
482
  }
756
483
  }
757
484
  /**
758
- * Get the current delegation fee
759
- * @returns Current delegation fee in USDC micro-units
485
+ * Distribute claimable funds when paused
486
+ * Note: EVM supports single recipient, Solana supports multiple
760
487
  */
761
- async getDelegationFee() {
762
- if (this.chainType === 'evm') {
763
- return this.getDelegationFeeEVM();
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
+ };
764
508
  }
765
509
  else {
766
- return this.getDelegationFeeSolana();
510
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
767
511
  }
768
512
  }
769
513
  /**
770
- * Reject a delegation made to you by another address
771
- * @param delegatorAddress - Address that delegated to you
772
- * @returns Promise resolving to transaction details
514
+ * Set permission for a contract to use caller's USDC for sending messages
515
+ * Note: Only supported on EVM chains
773
516
  */
774
- async rejectDelegation(delegatorAddress) {
775
- if (this.chainType === 'evm') {
776
- return this.rejectDelegationEVM(delegatorAddress);
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');
777
528
  }
778
529
  else {
779
- return this.rejectDelegationSolana(delegatorAddress);
530
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
780
531
  }
781
532
  }
782
533
  /**
783
- * Claim owner share of fees (owner only)
784
- * @returns Promise resolving to transaction details
534
+ * Remove permission from a contract
535
+ * Note: Only supported on EVM chains
785
536
  */
786
- async claimOwnerShare() {
787
- if (this.chainType === 'evm') {
788
- return this.claimOwnerShareEVM();
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');
789
548
  }
790
549
  else {
791
- return this.claimOwnerShareSolana();
550
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
792
551
  }
793
552
  }
794
553
  /**
795
- * Claim expired shares (owner only)
796
- * @param recipient - Address to claim expired shares for
797
- * @returns Promise resolving to transaction details
554
+ * Check if permission exists for a contract/wallet pair
555
+ * Note: Only supported on EVM chains
798
556
  */
799
- async claimExpiredShares(recipient) {
800
- if (this.chainType === 'evm') {
801
- return this.claimExpiredSharesEVM(recipient);
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;
802
565
  }
803
566
  else {
804
- return this.claimExpiredSharesSolana(recipient);
567
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
805
568
  }
806
569
  }
570
+ // ============= Read Methods =============
807
571
  /**
808
- * Pause the contract and distribute funds (owner only)
809
- * @returns Promise resolving to transaction details
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
810
577
  */
811
- async pause() {
812
- if (this.chainType === 'evm') {
813
- return this.pauseEVM();
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);
814
586
  }
815
587
  else {
816
- return this.pauseSolana();
588
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
817
589
  }
818
590
  }
819
591
  /**
820
- * Unpause the contract (owner only)
821
- * @returns Promise resolving to transaction details
592
+ * Get delegation fee
822
593
  */
823
- async unpause() {
824
- if (this.chainType === 'evm') {
825
- return this.unpauseEVM();
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);
826
602
  }
827
603
  else {
828
- return this.unpauseSolana();
604
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
829
605
  }
830
606
  }
831
607
  /**
832
- * Emergency unpause without fund distribution (owner only)
833
- * @returns Promise resolving to transaction details
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
834
614
  */
835
- async emergencyUnpause() {
836
- if (this.chainType === 'evm') {
837
- return this.emergencyUnpauseEVM();
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;
838
625
  }
839
626
  else {
840
- return this.emergencyUnpauseSolana();
627
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
841
628
  }
842
629
  }
843
630
  /**
844
- * Check if contract is currently paused
845
- * @returns True if contract is paused, false otherwise
631
+ * Get recipient claimable info
846
632
  */
847
- async isPaused() {
848
- if (this.chainType === 'evm') {
849
- return this.isPausedEVM();
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
+ };
850
648
  }
851
649
  else {
852
- return this.isPausedSolana();
650
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
853
651
  }
854
652
  }
855
653
  /**
856
- * Distribute claimable funds to a recipient when contract is paused
857
- * @param recipient - Address to distribute funds for
858
- * @returns Promise resolving to transaction details
654
+ * Get owner claimable amount
859
655
  */
860
- async distributeClaimableFunds(recipient) {
861
- if (this.chainType === 'evm') {
862
- return this.distributeClaimableFundsEVM(recipient);
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);
863
665
  }
864
666
  else {
865
- return this.distributeClaimableFundsSolana(recipient);
667
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
866
668
  }
867
669
  }
868
- // EVM Implementation Methods
869
- async sendPreparedEVM(to, mailId, priority, resolveSenderToName) {
870
- const { viem, MailerClient } = await this.getEVMModules();
871
- if (!this.config.evm?.contracts.mailer) {
872
- throw new Error('EVM Mailer contract address not configured');
873
- }
874
- const publicClient = viem.createPublicClient({
875
- transport: viem.http(this.config.evm.rpc),
876
- chain: {
877
- id: this.config.evm.chainId,
878
- name: 'Custom Chain',
879
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
880
- rpcUrls: {
881
- default: { http: [this.config.evm.rpc] }
882
- }
883
- }
884
- });
885
- const walletClient = viem.createWalletClient({
886
- transport: viem.http(this.config.evm.rpc),
887
- chain: {
888
- id: this.config.evm.chainId,
889
- name: 'Custom Chain',
890
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
891
- rpcUrls: {
892
- default: { http: [this.config.evm.rpc] }
893
- }
894
- }
895
- });
896
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
897
- const payer = this.wallet.address;
898
- const txHash = await client.sendPrepared(to, mailId, payer, priority, resolveSenderToName, walletClient, this.wallet.address);
899
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
900
- return {
901
- transactionHash: txHash,
902
- chainType: ChainType.EVM,
903
- fee: BigInt(priority ? '100000' : '10000'),
904
- gasUsed: receipt.gasUsed,
905
- isPriority: priority,
906
- success: true
907
- };
908
- }
909
- async sendToEmailEVM(toEmail, subject, body) {
910
- const { viem, MailerClient } = await this.getEVMModules();
911
- if (!this.config.evm?.contracts.mailer) {
912
- throw new Error('EVM Mailer contract address not configured');
913
- }
914
- const publicClient = viem.createPublicClient({
915
- transport: viem.http(this.config.evm.rpc),
916
- chain: {
917
- id: this.config.evm.chainId,
918
- name: 'Custom Chain',
919
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
920
- rpcUrls: {
921
- default: { http: [this.config.evm.rpc] }
922
- }
923
- }
924
- });
925
- const walletClient = viem.createWalletClient({
926
- transport: viem.http(this.config.evm.rpc),
927
- chain: {
928
- id: this.config.evm.chainId,
929
- name: 'Custom Chain',
930
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
931
- rpcUrls: {
932
- default: { http: [this.config.evm.rpc] }
933
- }
934
- }
935
- });
936
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
937
- const payer = this.wallet.address;
938
- const txHash = await client.sendToEmailAddress(toEmail, subject, body, payer, walletClient, this.wallet.address);
939
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
940
- return {
941
- transactionHash: txHash,
942
- chainType: ChainType.EVM,
943
- fee: BigInt('10000'), // 10% fee only
944
- gasUsed: receipt.gasUsed,
945
- isPriority: false,
946
- success: true
947
- };
948
- }
949
- async sendPreparedToEmailEVM(toEmail, mailId) {
950
- const { viem, MailerClient } = await this.getEVMModules();
951
- if (!this.config.evm?.contracts.mailer) {
952
- throw new Error('EVM Mailer contract address not configured');
953
- }
954
- const publicClient = viem.createPublicClient({
955
- transport: viem.http(this.config.evm.rpc),
956
- chain: {
957
- id: this.config.evm.chainId,
958
- name: 'Custom Chain',
959
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
960
- rpcUrls: {
961
- default: { http: [this.config.evm.rpc] }
962
- }
963
- }
964
- });
965
- const walletClient = viem.createWalletClient({
966
- transport: viem.http(this.config.evm.rpc),
967
- chain: {
968
- id: this.config.evm.chainId,
969
- name: 'Custom Chain',
970
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
971
- rpcUrls: {
972
- default: { http: [this.config.evm.rpc] }
973
- }
974
- }
975
- });
976
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
977
- const payer = this.wallet.address;
978
- const txHash = await client.sendPreparedToEmailAddress(toEmail, mailId, payer, walletClient, this.wallet.address);
979
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
980
- return {
981
- transactionHash: txHash,
982
- chainType: ChainType.EVM,
983
- fee: BigInt('10000'), // 10% fee only
984
- gasUsed: receipt.gasUsed,
985
- isPriority: false,
986
- success: true
987
- };
988
- }
989
- async setFeeEVM(newFee) {
990
- const { viem, MailerClient } = await this.getEVMModules();
991
- if (!this.config.evm?.contracts.mailer) {
992
- throw new Error('EVM Mailer contract address not configured');
993
- }
994
- const publicClient = viem.createPublicClient({
995
- transport: viem.http(this.config.evm.rpc),
996
- chain: {
997
- id: this.config.evm.chainId,
998
- name: 'Custom Chain',
999
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1000
- rpcUrls: {
1001
- default: { http: [this.config.evm.rpc] }
1002
- }
1003
- }
1004
- });
1005
- const walletClient = viem.createWalletClient({
1006
- transport: viem.http(this.config.evm.rpc),
1007
- chain: {
1008
- id: this.config.evm.chainId,
1009
- name: 'Custom Chain',
1010
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1011
- rpcUrls: {
1012
- default: { http: [this.config.evm.rpc] }
1013
- }
1014
- }
1015
- });
1016
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1017
- const txHash = await client.setFee(newFee, walletClient, this.wallet.address);
1018
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1019
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1020
- return {
1021
- hash: txHash,
1022
- chainType: ChainType.EVM,
1023
- blockNumber: receipt.blockNumber,
1024
- timestamp: Number(block.timestamp) * 1000
1025
- };
1026
- }
1027
- async setDelegationFeeEVM(newFee) {
1028
- const { viem, MailerClient } = await this.getEVMModules();
1029
- if (!this.config.evm?.contracts.mailer) {
1030
- throw new Error('EVM Mailer contract address not configured');
1031
- }
1032
- const publicClient = viem.createPublicClient({
1033
- transport: viem.http(this.config.evm.rpc),
1034
- chain: {
1035
- id: this.config.evm.chainId,
1036
- name: 'Custom Chain',
1037
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1038
- rpcUrls: {
1039
- default: { http: [this.config.evm.rpc] }
1040
- }
1041
- }
1042
- });
1043
- const walletClient = viem.createWalletClient({
1044
- transport: viem.http(this.config.evm.rpc),
1045
- chain: {
1046
- id: this.config.evm.chainId,
1047
- name: 'Custom Chain',
1048
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1049
- rpcUrls: {
1050
- default: { http: [this.config.evm.rpc] }
1051
- }
1052
- }
1053
- });
1054
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1055
- const txHash = await client.setDelegationFee(newFee, walletClient, this.wallet.address);
1056
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1057
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1058
- return {
1059
- hash: txHash,
1060
- chainType: ChainType.EVM,
1061
- blockNumber: receipt.blockNumber,
1062
- timestamp: Number(block.timestamp) * 1000
1063
- };
1064
- }
1065
- async getDelegationFeeEVM() {
1066
- const { viem, MailerClient } = await this.getEVMModules();
1067
- if (!this.config.evm?.contracts.mailer) {
1068
- throw new Error('EVM Mailer contract address not configured');
1069
- }
1070
- const publicClient = viem.createPublicClient({
1071
- transport: viem.http(this.config.evm.rpc),
1072
- chain: {
1073
- id: this.config.evm.chainId,
1074
- name: 'Custom Chain',
1075
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1076
- rpcUrls: {
1077
- default: { http: [this.config.evm.rpc] }
1078
- }
1079
- }
1080
- });
1081
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1082
- return client.getDelegationFee();
1083
- }
1084
- async rejectDelegationEVM(delegatorAddress) {
1085
- const { viem, MailerClient } = await this.getEVMModules();
1086
- if (!this.config.evm?.contracts.mailer) {
1087
- throw new Error('EVM Mailer contract address not configured');
1088
- }
1089
- const publicClient = viem.createPublicClient({
1090
- transport: viem.http(this.config.evm.rpc),
1091
- chain: {
1092
- id: this.config.evm.chainId,
1093
- name: 'Custom Chain',
1094
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1095
- rpcUrls: {
1096
- default: { http: [this.config.evm.rpc] }
1097
- }
1098
- }
1099
- });
1100
- const walletClient = viem.createWalletClient({
1101
- transport: viem.http(this.config.evm.rpc),
1102
- chain: {
1103
- id: this.config.evm.chainId,
1104
- name: 'Custom Chain',
1105
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1106
- rpcUrls: {
1107
- default: { http: [this.config.evm.rpc] }
1108
- }
1109
- }
1110
- });
1111
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1112
- const txHash = await client.rejectDelegation(delegatorAddress, walletClient, this.wallet.address);
1113
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1114
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1115
- return {
1116
- hash: txHash,
1117
- chainType: ChainType.EVM,
1118
- blockNumber: receipt.blockNumber,
1119
- timestamp: Number(block.timestamp) * 1000
1120
- };
1121
- }
1122
- async claimOwnerShareEVM() {
1123
- const { viem, MailerClient } = await this.getEVMModules();
1124
- if (!this.config.evm?.contracts.mailer) {
1125
- throw new Error('EVM Mailer contract address not configured');
1126
- }
1127
- const publicClient = viem.createPublicClient({
1128
- transport: viem.http(this.config.evm.rpc),
1129
- chain: {
1130
- id: this.config.evm.chainId,
1131
- name: 'Custom Chain',
1132
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1133
- rpcUrls: {
1134
- default: { http: [this.config.evm.rpc] }
1135
- }
1136
- }
1137
- });
1138
- const walletClient = viem.createWalletClient({
1139
- transport: viem.http(this.config.evm.rpc),
1140
- chain: {
1141
- id: this.config.evm.chainId,
1142
- name: 'Custom Chain',
1143
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1144
- rpcUrls: {
1145
- default: { http: [this.config.evm.rpc] }
1146
- }
1147
- }
1148
- });
1149
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1150
- const txHash = await client.claimOwnerShare(walletClient, this.wallet.address);
1151
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1152
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1153
- return {
1154
- hash: txHash,
1155
- chainType: ChainType.EVM,
1156
- blockNumber: receipt.blockNumber,
1157
- timestamp: Number(block.timestamp) * 1000
1158
- };
1159
- }
1160
- async claimExpiredSharesEVM(recipient) {
1161
- const { viem, MailerClient } = await this.getEVMModules();
1162
- if (!this.config.evm?.contracts.mailer) {
1163
- throw new Error('EVM Mailer contract address not configured');
1164
- }
1165
- const publicClient = viem.createPublicClient({
1166
- transport: viem.http(this.config.evm.rpc),
1167
- chain: {
1168
- id: this.config.evm.chainId,
1169
- name: 'Custom Chain',
1170
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1171
- rpcUrls: {
1172
- default: { http: [this.config.evm.rpc] }
1173
- }
1174
- }
1175
- });
1176
- const walletClient = viem.createWalletClient({
1177
- transport: viem.http(this.config.evm.rpc),
1178
- chain: {
1179
- id: this.config.evm.chainId,
1180
- name: 'Custom Chain',
1181
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1182
- rpcUrls: {
1183
- default: { http: [this.config.evm.rpc] }
1184
- }
1185
- }
1186
- });
1187
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1188
- const txHash = await client.claimExpiredShares(recipient, walletClient, this.wallet.address);
1189
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1190
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1191
- return {
1192
- hash: txHash,
1193
- chainType: ChainType.EVM,
1194
- blockNumber: receipt.blockNumber,
1195
- timestamp: Number(block.timestamp) * 1000
1196
- };
1197
- }
1198
- async pauseEVM() {
1199
- const { viem, MailerClient } = await this.getEVMModules();
1200
- if (!this.config.evm?.contracts.mailer) {
1201
- throw new Error('EVM Mailer contract address not configured');
1202
- }
1203
- const publicClient = viem.createPublicClient({
1204
- transport: viem.http(this.config.evm.rpc),
1205
- chain: {
1206
- id: this.config.evm.chainId,
1207
- name: 'Custom Chain',
1208
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1209
- rpcUrls: {
1210
- default: { http: [this.config.evm.rpc] }
1211
- }
1212
- }
1213
- });
1214
- const walletClient = viem.createWalletClient({
1215
- transport: viem.http(this.config.evm.rpc),
1216
- chain: {
1217
- id: this.config.evm.chainId,
1218
- name: 'Custom Chain',
1219
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1220
- rpcUrls: {
1221
- default: { http: [this.config.evm.rpc] }
1222
- }
1223
- }
1224
- });
1225
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1226
- const txHash = await client.pause(walletClient, this.wallet.address);
1227
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1228
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1229
- return {
1230
- hash: txHash,
1231
- chainType: ChainType.EVM,
1232
- blockNumber: receipt.blockNumber,
1233
- timestamp: Number(block.timestamp) * 1000
1234
- };
1235
- }
1236
- async unpauseEVM() {
1237
- const { viem, MailerClient } = await this.getEVMModules();
1238
- if (!this.config.evm?.contracts.mailer) {
1239
- throw new Error('EVM Mailer contract address not configured');
1240
- }
1241
- const publicClient = viem.createPublicClient({
1242
- transport: viem.http(this.config.evm.rpc),
1243
- chain: {
1244
- id: this.config.evm.chainId,
1245
- name: 'Custom Chain',
1246
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1247
- rpcUrls: {
1248
- default: { http: [this.config.evm.rpc] }
1249
- }
1250
- }
1251
- });
1252
- const walletClient = viem.createWalletClient({
1253
- transport: viem.http(this.config.evm.rpc),
1254
- chain: {
1255
- id: this.config.evm.chainId,
1256
- name: 'Custom Chain',
1257
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1258
- rpcUrls: {
1259
- default: { http: [this.config.evm.rpc] }
1260
- }
1261
- }
1262
- });
1263
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1264
- const txHash = await client.unpause(walletClient, this.wallet.address);
1265
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1266
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1267
- return {
1268
- hash: txHash,
1269
- chainType: ChainType.EVM,
1270
- blockNumber: receipt.blockNumber,
1271
- timestamp: Number(block.timestamp) * 1000
1272
- };
1273
- }
1274
- async emergencyUnpauseEVM() {
1275
- const { viem, MailerClient } = await this.getEVMModules();
1276
- if (!this.config.evm?.contracts.mailer) {
1277
- throw new Error('EVM Mailer contract address not configured');
1278
- }
1279
- const publicClient = viem.createPublicClient({
1280
- transport: viem.http(this.config.evm.rpc),
1281
- chain: {
1282
- id: this.config.evm.chainId,
1283
- name: 'Custom Chain',
1284
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1285
- rpcUrls: {
1286
- default: { http: [this.config.evm.rpc] }
1287
- }
1288
- }
1289
- });
1290
- const walletClient = viem.createWalletClient({
1291
- transport: viem.http(this.config.evm.rpc),
1292
- chain: {
1293
- id: this.config.evm.chainId,
1294
- name: 'Custom Chain',
1295
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1296
- rpcUrls: {
1297
- default: { http: [this.config.evm.rpc] }
1298
- }
1299
- }
1300
- });
1301
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1302
- const txHash = await client.emergencyUnpause(walletClient, this.wallet.address);
1303
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1304
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1305
- return {
1306
- hash: txHash,
1307
- chainType: ChainType.EVM,
1308
- blockNumber: receipt.blockNumber,
1309
- timestamp: Number(block.timestamp) * 1000
1310
- };
1311
- }
1312
- async isPausedEVM() {
1313
- const { viem, MailerClient } = await this.getEVMModules();
1314
- if (!this.config.evm?.contracts.mailer) {
1315
- throw new Error('EVM Mailer contract address not configured');
1316
- }
1317
- const publicClient = viem.createPublicClient({
1318
- transport: viem.http(this.config.evm.rpc),
1319
- chain: {
1320
- id: this.config.evm.chainId,
1321
- name: 'Custom Chain',
1322
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1323
- rpcUrls: {
1324
- default: { http: [this.config.evm.rpc] }
1325
- }
1326
- }
1327
- });
1328
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1329
- return client.isPaused();
1330
- }
1331
- async distributeClaimableFundsEVM(recipient) {
1332
- const { viem, MailerClient } = await this.getEVMModules();
1333
- if (!this.config.evm?.contracts.mailer) {
1334
- throw new Error('EVM Mailer contract address not configured');
1335
- }
1336
- const publicClient = viem.createPublicClient({
1337
- transport: viem.http(this.config.evm.rpc),
1338
- chain: {
1339
- id: this.config.evm.chainId,
1340
- name: 'Custom Chain',
1341
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1342
- rpcUrls: {
1343
- default: { http: [this.config.evm.rpc] }
1344
- }
1345
- }
1346
- });
1347
- const walletClient = viem.createWalletClient({
1348
- transport: viem.http(this.config.evm.rpc),
1349
- chain: {
1350
- id: this.config.evm.chainId,
1351
- name: 'Custom Chain',
1352
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1353
- rpcUrls: {
1354
- default: { http: [this.config.evm.rpc] }
1355
- }
1356
- }
1357
- });
1358
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1359
- const txHash = await client.distributeClaimableFunds(recipient, walletClient, this.wallet.address);
1360
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1361
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1362
- return {
1363
- hash: txHash,
1364
- chainType: ChainType.EVM,
1365
- blockNumber: receipt.blockNumber,
1366
- timestamp: Number(block.timestamp) * 1000
1367
- };
1368
- }
1369
- // Solana Implementation Methods
1370
- async sendPreparedSolana(to, mailId, priority, resolveSenderToName) {
1371
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1372
- if (!this.config.solana?.programs.mailer) {
1373
- throw new Error('Solana Mailer program address not configured');
1374
- }
1375
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1376
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1377
- const wallet = MailerClient.createWallet(this.wallet);
1378
- const programId = new PublicKey(this.config.solana.programs.mailer);
1379
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1380
- const recipientKey = new PublicKey(to);
1381
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1382
- const txHash = await client.sendPrepared(recipientKey, mailId, priority, resolveSenderToName);
1383
- const fees = await client.getFees();
1384
- const slot = await connection.getSlot();
1385
- const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
1386
- return {
1387
- transactionHash: txHash,
1388
- chainType: ChainType.SOLANA,
1389
- fee: priority ? fees.sendFee : fees.sendFee / 10,
1390
- slot,
1391
- timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1392
- isPriority: priority,
1393
- success: true
1394
- };
1395
- }
1396
- async sendToEmailSolana(toEmail, subject, body) {
1397
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1398
- if (!this.config.solana?.programs.mailer) {
1399
- throw new Error('Solana Mailer program address not configured');
1400
- }
1401
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1402
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1403
- const wallet = MailerClient.createWallet(this.wallet);
1404
- const programId = new PublicKey(this.config.solana.programs.mailer);
1405
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1406
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1407
- const txHash = await client.sendToEmail(toEmail, subject, body);
1408
- const fees = await client.getFees();
1409
- const slot = await connection.getSlot();
1410
- const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
1411
- return {
1412
- transactionHash: txHash,
1413
- chainType: ChainType.SOLANA,
1414
- fee: fees.sendFee / 10, // 10% fee only
1415
- slot,
1416
- timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1417
- isPriority: false,
1418
- success: true
1419
- };
1420
- }
1421
- async sendPreparedToEmailSolana(toEmail, mailId) {
1422
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1423
- if (!this.config.solana?.programs.mailer) {
1424
- throw new Error('Solana Mailer program address not configured');
1425
- }
1426
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1427
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1428
- const wallet = MailerClient.createWallet(this.wallet);
1429
- const programId = new PublicKey(this.config.solana.programs.mailer);
1430
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1431
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1432
- const txHash = await client.sendPreparedToEmail(toEmail, mailId);
1433
- const fees = await client.getFees();
1434
- const slot = await connection.getSlot();
1435
- const tx = await connection.getTransaction(txHash, { commitment: 'confirmed', maxSupportedTransactionVersion: 0 });
1436
- return {
1437
- transactionHash: txHash,
1438
- chainType: ChainType.SOLANA,
1439
- fee: fees.sendFee / 10, // 10% fee only
1440
- slot,
1441
- timestamp: tx?.blockTime ? tx.blockTime * 1000 : Date.now(),
1442
- isPriority: false,
1443
- success: true
1444
- };
1445
- }
1446
- async setFeeSolana(newFee) {
1447
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1448
- if (!this.config.solana?.programs.mailer) {
1449
- throw new Error('Solana Mailer program address not configured');
1450
- }
1451
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1452
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1453
- const wallet = MailerClient.createWallet(this.wallet);
1454
- const programId = new PublicKey(this.config.solana.programs.mailer);
1455
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1456
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1457
- const txHash = await client.setFee(newFee);
1458
- const slot = await connection.getSlot();
1459
- return {
1460
- hash: txHash,
1461
- chainType: ChainType.SOLANA,
1462
- slot,
1463
- timestamp: Date.now()
1464
- };
1465
- }
1466
- async setDelegationFeeSolana(newFee) {
1467
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1468
- if (!this.config.solana?.programs.mailer) {
1469
- throw new Error('Solana Mailer program address not configured');
1470
- }
1471
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1472
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1473
- const wallet = MailerClient.createWallet(this.wallet);
1474
- const programId = new PublicKey(this.config.solana.programs.mailer);
1475
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1476
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1477
- const txHash = await client.setDelegationFee(newFee);
1478
- const slot = await connection.getSlot();
1479
- return {
1480
- hash: txHash,
1481
- chainType: ChainType.SOLANA,
1482
- slot,
1483
- timestamp: Date.now()
1484
- };
1485
- }
1486
- async getDelegationFeeSolana() {
1487
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1488
- if (!this.config.solana?.programs.mailer) {
1489
- throw new Error('Solana Mailer program address not configured');
1490
- }
1491
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1492
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1493
- const wallet = MailerClient.createWallet(this.wallet);
1494
- const programId = new PublicKey(this.config.solana.programs.mailer);
1495
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1496
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1497
- const fees = await client.getFees();
1498
- return BigInt(fees.delegationFee);
1499
- }
1500
- async rejectDelegationSolana(delegatorAddress) {
1501
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1502
- if (!this.config.solana?.programs.mailer) {
1503
- throw new Error('Solana Mailer program address not configured');
1504
- }
1505
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1506
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1507
- const wallet = MailerClient.createWallet(this.wallet);
1508
- const programId = new PublicKey(this.config.solana.programs.mailer);
1509
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1510
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1511
- const txHash = await client.rejectDelegation(delegatorAddress);
1512
- const slot = await connection.getSlot();
1513
- return {
1514
- hash: txHash,
1515
- chainType: ChainType.SOLANA,
1516
- slot,
1517
- timestamp: Date.now()
1518
- };
1519
- }
1520
- async claimOwnerShareSolana() {
1521
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1522
- if (!this.config.solana?.programs.mailer) {
1523
- throw new Error('Solana Mailer program address not configured');
1524
- }
1525
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1526
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1527
- const wallet = MailerClient.createWallet(this.wallet);
1528
- const programId = new PublicKey(this.config.solana.programs.mailer);
1529
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1530
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1531
- const txHash = await client.claimOwnerShare();
1532
- const slot = await connection.getSlot();
1533
- return {
1534
- hash: txHash,
1535
- chainType: ChainType.SOLANA,
1536
- slot,
1537
- timestamp: Date.now()
1538
- };
1539
- }
1540
- async claimExpiredSharesSolana(recipient) {
1541
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1542
- if (!this.config.solana?.programs.mailer) {
1543
- throw new Error('Solana Mailer program address not configured');
1544
- }
1545
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1546
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1547
- const wallet = MailerClient.createWallet(this.wallet);
1548
- const programId = new PublicKey(this.config.solana.programs.mailer);
1549
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1550
- const recipientKey = new PublicKey(recipient);
1551
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1552
- const txHash = await client.claimExpiredShares(recipientKey);
1553
- const slot = await connection.getSlot();
1554
- return {
1555
- hash: txHash,
1556
- chainType: ChainType.SOLANA,
1557
- slot,
1558
- timestamp: Date.now()
1559
- };
1560
- }
1561
- async pauseSolana() {
1562
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1563
- if (!this.config.solana?.programs.mailer) {
1564
- throw new Error('Solana Mailer program address not configured');
1565
- }
1566
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1567
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1568
- const wallet = MailerClient.createWallet(this.wallet);
1569
- const programId = new PublicKey(this.config.solana.programs.mailer);
1570
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1571
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1572
- const txHash = await client.pause();
1573
- const slot = await connection.getSlot();
1574
- return {
1575
- hash: txHash,
1576
- chainType: ChainType.SOLANA,
1577
- slot,
1578
- timestamp: Date.now()
1579
- };
1580
- }
1581
- async unpauseSolana() {
1582
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1583
- if (!this.config.solana?.programs.mailer) {
1584
- throw new Error('Solana Mailer program address not configured');
1585
- }
1586
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1587
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1588
- const wallet = MailerClient.createWallet(this.wallet);
1589
- const programId = new PublicKey(this.config.solana.programs.mailer);
1590
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1591
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1592
- const txHash = await client.unpause();
1593
- const slot = await connection.getSlot();
1594
- return {
1595
- hash: txHash,
1596
- chainType: ChainType.SOLANA,
1597
- slot,
1598
- timestamp: Date.now()
1599
- };
1600
- }
1601
- async emergencyUnpauseSolana() {
1602
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1603
- if (!this.config.solana?.programs.mailer) {
1604
- throw new Error('Solana Mailer program address not configured');
1605
- }
1606
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1607
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1608
- const wallet = MailerClient.createWallet(this.wallet);
1609
- const programId = new PublicKey(this.config.solana.programs.mailer);
1610
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1611
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1612
- const txHash = await client.emergencyUnpause();
1613
- const slot = await connection.getSlot();
1614
- return {
1615
- hash: txHash,
1616
- chainType: ChainType.SOLANA,
1617
- slot,
1618
- timestamp: Date.now()
1619
- };
1620
- }
1621
- async isPausedSolana() {
1622
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1623
- if (!this.config.solana?.programs.mailer) {
1624
- throw new Error('Solana Mailer program address not configured');
1625
- }
1626
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1627
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1628
- const wallet = MailerClient.createWallet(this.wallet);
1629
- const programId = new PublicKey(this.config.solana.programs.mailer);
1630
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1631
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1632
- return client.isPaused();
1633
- }
1634
- async distributeClaimableFundsSolana(recipient) {
1635
- const { MailerClient, PublicKey, Connection } = await this.getSolanaModules();
1636
- if (!this.config.solana?.programs.mailer) {
1637
- throw new Error('Solana Mailer program address not configured');
1638
- }
1639
- const connection = new Connection(this.config.solana.rpc, 'confirmed');
1640
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
1641
- const wallet = MailerClient.createWallet(this.wallet);
1642
- const programId = new PublicKey(this.config.solana.programs.mailer);
1643
- const usdcMint = new PublicKey(this.config.solana.usdcMint);
1644
- const client = new MailerClient(connection, wallet, programId, usdcMint);
1645
- const txHash = await client.distributeClaimableFunds(recipient);
1646
- const slot = await connection.getSlot();
1647
- return {
1648
- hash: txHash,
1649
- chainType: ChainType.SOLANA,
1650
- slot,
1651
- timestamp: Date.now()
1652
- };
1653
- }
1654
670
  /**
1655
- * Set permission for a contract to use your wallet as payer (EVM only)
1656
- * @param contractAddress - Contract address to grant permission to
1657
- * @returns Promise resolving to transaction details
1658
- * @throws {Error} When called on Solana (not supported)
671
+ * Get custom fee percentage
1659
672
  */
1660
- async setPermission(contractAddress) {
1661
- if (this.chainType === 'evm') {
1662
- return this.setPermissionEVM(contractAddress);
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);
1663
681
  }
1664
682
  else {
1665
- throw new Error('Permission management is only available on EVM chains');
683
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
1666
684
  }
1667
685
  }
1668
686
  /**
1669
- * Remove permission for a contract to use your wallet as payer (EVM only)
1670
- * @param contractAddress - Contract address to revoke permission from
1671
- * @returns Promise resolving to transaction details
1672
- * @throws {Error} When called on Solana (not supported)
687
+ * Check if contract/program is paused
1673
688
  */
1674
- async removePermission(contractAddress) {
1675
- if (this.chainType === 'evm') {
1676
- return this.removePermissionEVM(contractAddress);
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);
1677
697
  }
1678
698
  else {
1679
- throw new Error('Permission management is only available on EVM chains');
699
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
1680
700
  }
1681
701
  }
1682
702
  /**
1683
- * Check if a contract has permission to use a wallet as payer (EVM only)
1684
- * @param contractAddress - Contract address to check
1685
- * @param wallet - Wallet address to check permission for (defaults to connected wallet)
1686
- * @returns Promise resolving to true if permission exists, false otherwise
1687
- * @throws {Error} When called on Solana (not supported)
703
+ * Get contract/program owner
1688
704
  */
1689
- async hasPermission(contractAddress, wallet) {
1690
- if (this.chainType === 'evm') {
1691
- return this.hasPermissionEVM(contractAddress, wallet || this.wallet.address);
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();
1692
714
  }
1693
715
  else {
1694
- throw new Error('Permission management is only available on EVM chains');
716
+ throw new Error(`Unsupported chain type: ${chainInfo.chainType}`);
1695
717
  }
1696
718
  }
1697
- // EVM Permission Management Implementation
1698
- async setPermissionEVM(contractAddress) {
1699
- const { viem, MailerClient } = await this.getEVMModules();
1700
- if (!this.config.evm?.contracts.mailer) {
1701
- throw new Error('EVM Mailer contract address not configured');
1702
- }
1703
- const publicClient = viem.createPublicClient({
1704
- transport: viem.http(this.config.evm.rpc),
1705
- chain: {
1706
- id: this.config.evm.chainId,
1707
- name: 'Custom Chain',
1708
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1709
- rpcUrls: {
1710
- default: { http: [this.config.evm.rpc] }
1711
- }
1712
- }
1713
- });
1714
- const walletClient = viem.createWalletClient({
1715
- transport: viem.http(this.config.evm.rpc),
1716
- chain: {
1717
- id: this.config.evm.chainId,
1718
- name: 'Custom Chain',
1719
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1720
- rpcUrls: {
1721
- default: { http: [this.config.evm.rpc] }
1722
- }
1723
- }
1724
- });
1725
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1726
- const txHash = await client.setPermission(contractAddress, walletClient, this.wallet.address);
1727
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1728
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1729
- return {
1730
- hash: txHash,
1731
- chainType: ChainType.EVM,
1732
- blockNumber: receipt.blockNumber,
1733
- timestamp: Number(block.timestamp) * 1000
1734
- };
1735
- }
1736
- async removePermissionEVM(contractAddress) {
1737
- const { viem, MailerClient } = await this.getEVMModules();
1738
- if (!this.config.evm?.contracts.mailer) {
1739
- throw new Error('EVM Mailer contract address not configured');
1740
- }
1741
- const publicClient = viem.createPublicClient({
1742
- transport: viem.http(this.config.evm.rpc),
1743
- chain: {
1744
- id: this.config.evm.chainId,
1745
- name: 'Custom Chain',
1746
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1747
- rpcUrls: {
1748
- default: { http: [this.config.evm.rpc] }
1749
- }
1750
- }
1751
- });
1752
- const walletClient = viem.createWalletClient({
1753
- transport: viem.http(this.config.evm.rpc),
1754
- chain: {
1755
- id: this.config.evm.chainId,
1756
- name: 'Custom Chain',
1757
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1758
- rpcUrls: {
1759
- default: { http: [this.config.evm.rpc] }
1760
- }
1761
- }
1762
- });
1763
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1764
- const txHash = await client.removePermission(contractAddress, walletClient, this.wallet.address);
1765
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
1766
- const block = await publicClient.getBlock({ blockNumber: receipt.blockNumber });
1767
- return {
1768
- hash: txHash,
1769
- chainType: ChainType.EVM,
1770
- blockNumber: receipt.blockNumber,
1771
- timestamp: Number(block.timestamp) * 1000
1772
- };
1773
- }
1774
- async hasPermissionEVM(contractAddress, wallet) {
1775
- const { viem, MailerClient } = await this.getEVMModules();
1776
- if (!this.config.evm?.contracts.mailer) {
1777
- throw new Error('EVM Mailer contract address not configured');
1778
- }
1779
- const publicClient = viem.createPublicClient({
1780
- transport: viem.http(this.config.evm.rpc),
1781
- chain: {
1782
- id: this.config.evm.chainId,
1783
- name: 'Custom Chain',
1784
- nativeCurrency: { name: 'ETH', symbol: 'ETH', decimals: 18 },
1785
- rpcUrls: {
1786
- default: { http: [this.config.evm.rpc] }
1787
- }
1788
- }
1789
- });
1790
- const client = new MailerClient(this.config.evm.contracts.mailer, publicClient);
1791
- return client.hasPermission(contractAddress, wallet);
1792
- }
1793
- // Utility methods
1794
- getChainType() {
1795
- return this.chainType;
1796
- }
1797
- getWalletAddress() {
1798
- return this.wallet.address;
719
+ /**
720
+ * Register a domain (not implemented - for backward compatibility)
721
+ */
722
+ async registerDomain(_domain) {
723
+ throw new Error('Domain registration not yet implemented');
1799
724
  }
1800
725
  }
1801
- // Performance optimization: cache imported modules
726
+ // Cache for dynamic imports
1802
727
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1803
- OnchainMailerClient.evmModules = null;
728
+ OnchainMailerClient.evmClient = null;
1804
729
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1805
- OnchainMailerClient.solanaModules = null;
730
+ OnchainMailerClient.solanaClient = null;
1806
731
  //# sourceMappingURL=onchain-mailer-client.js.map