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