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