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