@interchain-kit/mock-wallet 0.3.44 → 0.3.47
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/esm/ethereum-wallet.js +116 -0
- package/esm/index.js +2 -0
- package/esm/solana-wallet.js +243 -0
- package/ethereum-wallet.d.ts +49 -0
- package/ethereum-wallet.js +120 -0
- package/index.d.ts +2 -0
- package/index.js +2 -0
- package/package.json +9 -3
- package/solana-wallet.d.ts +32 -0
- package/solana-wallet.js +280 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { EthereumWallet } from "@interchain-kit/core";
|
|
2
|
+
import { ethers } from 'ethers';
|
|
3
|
+
export class MockEthereumWallet extends EthereumWallet {
|
|
4
|
+
accounts = [];
|
|
5
|
+
currentAccountIndex = 0;
|
|
6
|
+
currentChainId = '1'; // Default to Ethereum mainnet
|
|
7
|
+
mnemonic;
|
|
8
|
+
derivationPaths;
|
|
9
|
+
walletMap = {};
|
|
10
|
+
constructor(options, mnemonic) {
|
|
11
|
+
super(options);
|
|
12
|
+
// 设置默认值
|
|
13
|
+
this.mnemonic = mnemonic;
|
|
14
|
+
this.derivationPaths = [
|
|
15
|
+
`44'/60'/0'/0/0`, // 第一个钱包
|
|
16
|
+
`44'/60'/0'/0/1` // 第二个钱包
|
|
17
|
+
];
|
|
18
|
+
}
|
|
19
|
+
async init() {
|
|
20
|
+
const chains = Array.from(this.chainMap.values());
|
|
21
|
+
console.log(chains);
|
|
22
|
+
this.currentChainId = chains[0].chainId;
|
|
23
|
+
for (const chain of chains) {
|
|
24
|
+
const hdNode = ethers.HDNodeWallet.fromPhrase(this.mnemonic);
|
|
25
|
+
const wallet0 = hdNode.derivePath("44'/60'/0'/0/0");
|
|
26
|
+
const wallet1 = hdNode.derivePath("44'/60'/0'/0/1");
|
|
27
|
+
const rpc = chain.apis?.rpc[0].address || '';
|
|
28
|
+
const provider = new ethers.JsonRpcProvider(rpc);
|
|
29
|
+
this.walletMap[chain.chainId] = {
|
|
30
|
+
'0': {
|
|
31
|
+
wallet: wallet0,
|
|
32
|
+
provider,
|
|
33
|
+
signer: new ethers.Wallet(wallet0.privateKey, provider)
|
|
34
|
+
},
|
|
35
|
+
'1': {
|
|
36
|
+
wallet: wallet1,
|
|
37
|
+
provider,
|
|
38
|
+
signer: new ethers.Wallet(wallet1.privateKey, provider)
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return Promise.resolve();
|
|
43
|
+
}
|
|
44
|
+
async connect(chainId) {
|
|
45
|
+
await this.switchChain(chainId);
|
|
46
|
+
return Promise.resolve();
|
|
47
|
+
}
|
|
48
|
+
async disconnect() {
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
}
|
|
51
|
+
async switchChain(chainId) {
|
|
52
|
+
this.currentChainId = chainId;
|
|
53
|
+
}
|
|
54
|
+
async switchAccount() {
|
|
55
|
+
this.currentAccountIndex = this.currentAccountIndex === 0 ? 1 : 0;
|
|
56
|
+
this.events.emit('accountChanged', () => { });
|
|
57
|
+
}
|
|
58
|
+
async getAccount() {
|
|
59
|
+
const account = this.walletMap[this.currentChainId][this.currentAccountIndex].wallet;
|
|
60
|
+
return {
|
|
61
|
+
address: account.address,
|
|
62
|
+
pubkey: new Uint8Array(), // Ethereum doesn't use pubkey in the same way
|
|
63
|
+
algo: 'eth_secp256k1',
|
|
64
|
+
isNanoLedger: false,
|
|
65
|
+
isSmartContract: false,
|
|
66
|
+
username: `Account ${this.currentAccountIndex + 1}`
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
async getAccounts() {
|
|
70
|
+
return this.accounts;
|
|
71
|
+
}
|
|
72
|
+
async getCurrentAccount() {
|
|
73
|
+
return this.accounts[this.currentAccountIndex];
|
|
74
|
+
}
|
|
75
|
+
async getBalance() {
|
|
76
|
+
const { provider, wallet } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
77
|
+
const balance = await provider.getBalance(wallet.address);
|
|
78
|
+
return ethers.formatEther(balance);
|
|
79
|
+
}
|
|
80
|
+
async sendTransaction(transaction) {
|
|
81
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
82
|
+
const tx = await signer.sendTransaction({
|
|
83
|
+
from: transaction.from,
|
|
84
|
+
to: transaction.to,
|
|
85
|
+
value: transaction.value,
|
|
86
|
+
// data: transaction.data || '0x',
|
|
87
|
+
// gasLimit: transaction.gasLimit ? BigInt(transaction.gasLimit) : undefined,
|
|
88
|
+
// gasPrice: transaction.gasPrice ? ethers.parseUnits(transaction.gasPrice, 'gwei') : undefined
|
|
89
|
+
});
|
|
90
|
+
console.log(`Transaction sent: ${tx.hash}`);
|
|
91
|
+
return tx.hash;
|
|
92
|
+
}
|
|
93
|
+
async signMessage(message) {
|
|
94
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
95
|
+
const signature = await signer.signMessage(message);
|
|
96
|
+
console.log(`Message signed: ${signature}`);
|
|
97
|
+
return signature;
|
|
98
|
+
}
|
|
99
|
+
async signTypedData(domain, types, value) {
|
|
100
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
101
|
+
const signature = await signer.signTypedData(domain, types, value);
|
|
102
|
+
console.log(`Typed data signed: ${signature}`);
|
|
103
|
+
return signature;
|
|
104
|
+
}
|
|
105
|
+
async getProvider() {
|
|
106
|
+
return this.provider;
|
|
107
|
+
}
|
|
108
|
+
getWalletInfo() {
|
|
109
|
+
return {
|
|
110
|
+
mnemonic: this.mnemonic,
|
|
111
|
+
derivationPaths: [...this.derivationPaths],
|
|
112
|
+
accountCount: this.accounts.length,
|
|
113
|
+
currentAccountIndex: this.currentAccountIndex
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
}
|
package/esm/index.js
CHANGED
|
@@ -0,0 +1,243 @@
|
|
|
1
|
+
import { SolanaWallet } from '@interchain-kit/core';
|
|
2
|
+
import { Connection, Keypair, LAMPORTS_PER_SOL, Transaction } from '@solana/web3.js';
|
|
3
|
+
import * as bip39 from 'bip39';
|
|
4
|
+
import { derivePath } from 'ed25519-hd-key';
|
|
5
|
+
import * as nacl from 'tweetnacl';
|
|
6
|
+
export class MockSolanaWallet extends SolanaWallet {
|
|
7
|
+
connection;
|
|
8
|
+
isConnected;
|
|
9
|
+
derivationPath1 = "m/44'/501'/0'/0'";
|
|
10
|
+
derivationPath2 = "m/44'/501'/1'/0'";
|
|
11
|
+
currentKeypairIndex = '1';
|
|
12
|
+
keypairMap = {
|
|
13
|
+
1: {},
|
|
14
|
+
2: {},
|
|
15
|
+
};
|
|
16
|
+
constructor(network = 'devnet', info, mnemonic) {
|
|
17
|
+
super(info);
|
|
18
|
+
// 如果提供了助记词,从助记词派生密钥对
|
|
19
|
+
if (mnemonic) {
|
|
20
|
+
if (!bip39.validateMnemonic(mnemonic)) {
|
|
21
|
+
throw new Error('Invalid mnemonic phrase');
|
|
22
|
+
}
|
|
23
|
+
const seed = bip39.mnemonicToSeedSync(mnemonic);
|
|
24
|
+
const derivedSeed1 = derivePath(this.derivationPath1, seed.toString('hex')).key;
|
|
25
|
+
this.keypairMap['1'] = Keypair.fromSeed(derivedSeed1);
|
|
26
|
+
const derivedSeed2 = derivePath(this.derivationPath2, seed.toString('hex')).key;
|
|
27
|
+
this.keypairMap['2'] = Keypair.fromSeed(derivedSeed2);
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
// 否则随机生成密钥对
|
|
31
|
+
this.keypairMap['1'] = Keypair.generate();
|
|
32
|
+
this.keypairMap['2'] = Keypair.generate();
|
|
33
|
+
}
|
|
34
|
+
this.connection = new Connection(`https://api.${network}.solana.com`, 'confirmed');
|
|
35
|
+
this.isConnected = false;
|
|
36
|
+
}
|
|
37
|
+
async init() {
|
|
38
|
+
//@ts-ignore
|
|
39
|
+
window[this.info.windowKey] = {};
|
|
40
|
+
//@ts-ignore
|
|
41
|
+
window[this.info.solanaKey] = {};
|
|
42
|
+
await super.init();
|
|
43
|
+
}
|
|
44
|
+
bindingEvent() {
|
|
45
|
+
window.addEventListener(this.info.keystoreChange, () => {
|
|
46
|
+
this.events.emit('accountChanged', () => { });
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
getCurrentKeypair() {
|
|
50
|
+
const keypair = this.keypairMap[this.currentKeypairIndex];
|
|
51
|
+
if (!keypair) {
|
|
52
|
+
throw new Error(`No keypair found for account index: ${this.currentKeypairIndex}`);
|
|
53
|
+
}
|
|
54
|
+
return keypair;
|
|
55
|
+
}
|
|
56
|
+
changeWalletAccount() {
|
|
57
|
+
this.currentKeypairIndex = this.currentKeypairIndex === '1' ? '2' : '1';
|
|
58
|
+
//@ts-ignore
|
|
59
|
+
window.dispatchEvent(new CustomEvent(this.info.keystoreChange));
|
|
60
|
+
console.log('trigger in mock solana wallet');
|
|
61
|
+
}
|
|
62
|
+
// 模拟 Phantom 的 connect 方法
|
|
63
|
+
async connect(chainId) {
|
|
64
|
+
this.isConnected = true;
|
|
65
|
+
return Promise.resolve();
|
|
66
|
+
}
|
|
67
|
+
// 模拟 Phantom 的 disconnect 方法
|
|
68
|
+
async disconnect(chainId) {
|
|
69
|
+
this.isConnected = false;
|
|
70
|
+
return Promise.resolve();
|
|
71
|
+
}
|
|
72
|
+
async getAccount(chainId) {
|
|
73
|
+
const keypair = this.getCurrentKeypair();
|
|
74
|
+
return {
|
|
75
|
+
address: keypair.publicKey.toBase58(),
|
|
76
|
+
algo: 'secp256k1',
|
|
77
|
+
pubkey: keypair.publicKey.toBytes()
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
// 模拟 Sign In With Solana (SIWS)
|
|
81
|
+
async signIn(data) {
|
|
82
|
+
if (!this.isConnected) {
|
|
83
|
+
throw new Error('Wallet not connected.');
|
|
84
|
+
}
|
|
85
|
+
const keypair = this.getCurrentKeypair();
|
|
86
|
+
const { domain = 'my-dapp.com', statement = 'Login to My dApp', uri = 'https://my-dapp.com/login', version = '1', chainId = 'solana:devnet', nonce = Math.random().toString(36).substring(2, 10), issuedAt = new Date().toISOString(), expirationTime = new Date(Date.now() + 1000 * 60 * 60).toISOString(), } = data;
|
|
87
|
+
const message = `${domain} wants you to sign in with your Solana account:
|
|
88
|
+
${keypair.publicKey.toBase58()}
|
|
89
|
+
|
|
90
|
+
Statement: ${statement}
|
|
91
|
+
URI: ${uri}
|
|
92
|
+
Version: ${version}
|
|
93
|
+
Chain ID: ${chainId}
|
|
94
|
+
Nonce: ${nonce}
|
|
95
|
+
Issued At: ${issuedAt}
|
|
96
|
+
Expiration Time: ${expirationTime}`;
|
|
97
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
98
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
|
|
99
|
+
return {
|
|
100
|
+
address: keypair.publicKey.toBase58(),
|
|
101
|
+
signature: signature,
|
|
102
|
+
signedMessage: messageBytes,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
// 模拟 signMessage
|
|
106
|
+
async signMessage(message, encoding = 'utf8') {
|
|
107
|
+
if (!this.isConnected) {
|
|
108
|
+
throw new Error('Wallet not connected.');
|
|
109
|
+
}
|
|
110
|
+
const keypair = this.getCurrentKeypair();
|
|
111
|
+
const signature = nacl.sign.detached(message, keypair.secretKey);
|
|
112
|
+
return {
|
|
113
|
+
signature: signature,
|
|
114
|
+
publicKey: keypair.publicKey,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
// 模拟 signTransaction
|
|
118
|
+
async signTransaction(transaction) {
|
|
119
|
+
if (!this.isConnected) {
|
|
120
|
+
throw new Error('Wallet not connected.');
|
|
121
|
+
}
|
|
122
|
+
if (!(transaction instanceof Transaction)) {
|
|
123
|
+
throw new Error('Invalid transaction');
|
|
124
|
+
}
|
|
125
|
+
const keypair = this.getCurrentKeypair();
|
|
126
|
+
transaction.partialSign(keypair);
|
|
127
|
+
return transaction;
|
|
128
|
+
}
|
|
129
|
+
// 模拟 signAllTransactions
|
|
130
|
+
async signAllTransactions(transactions) {
|
|
131
|
+
if (!this.isConnected) {
|
|
132
|
+
throw new Error('Wallet not connected.');
|
|
133
|
+
}
|
|
134
|
+
if (!Array.isArray(transactions)) {
|
|
135
|
+
throw new Error('Invalid transactions array');
|
|
136
|
+
}
|
|
137
|
+
return transactions.map((tx) => {
|
|
138
|
+
if (!(tx instanceof Transaction))
|
|
139
|
+
throw new Error('Invalid transaction');
|
|
140
|
+
const keypair = this.getCurrentKeypair();
|
|
141
|
+
tx.partialSign(keypair);
|
|
142
|
+
return tx;
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
// 模拟 signAndSendTransaction
|
|
146
|
+
async signAndSendTransaction(transaction) {
|
|
147
|
+
if (!this.isConnected) {
|
|
148
|
+
throw new Error('Wallet not connected.');
|
|
149
|
+
}
|
|
150
|
+
if (!(transaction instanceof Transaction)) {
|
|
151
|
+
throw new Error('Invalid transaction');
|
|
152
|
+
}
|
|
153
|
+
const keypair = this.getCurrentKeypair();
|
|
154
|
+
transaction.partialSign(keypair);
|
|
155
|
+
const signature = await this.connection.sendTransaction(transaction, [keypair]);
|
|
156
|
+
await this.connection.confirmTransaction(signature);
|
|
157
|
+
return signature;
|
|
158
|
+
}
|
|
159
|
+
// 模拟 signAndSendAllTransactions
|
|
160
|
+
async signAndSendAllTransactions(transactions) {
|
|
161
|
+
if (!this.isConnected) {
|
|
162
|
+
throw new Error('Wallet not connected.');
|
|
163
|
+
}
|
|
164
|
+
if (!Array.isArray(transactions)) {
|
|
165
|
+
throw new Error('Invalid transactions array');
|
|
166
|
+
}
|
|
167
|
+
const signatures = [];
|
|
168
|
+
for (const tx of transactions) {
|
|
169
|
+
if (!(tx instanceof Transaction))
|
|
170
|
+
throw new Error('Invalid transaction');
|
|
171
|
+
const keypair = this.getCurrentKeypair();
|
|
172
|
+
tx.partialSign(keypair);
|
|
173
|
+
const signature = await this.connection.sendTransaction(tx, [keypair]);
|
|
174
|
+
await this.connection.confirmTransaction(signature);
|
|
175
|
+
signatures.push(signature);
|
|
176
|
+
}
|
|
177
|
+
return signatures;
|
|
178
|
+
}
|
|
179
|
+
// 获取余额
|
|
180
|
+
async getBalance() {
|
|
181
|
+
try {
|
|
182
|
+
const keypair = this.getCurrentKeypair();
|
|
183
|
+
const balance = await this.connection.getBalance(keypair.publicKey);
|
|
184
|
+
return balance;
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
console.error('Error getting balance:', error);
|
|
188
|
+
return 0;
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
// 请求空投(仅限 devnet/testnet)
|
|
192
|
+
async requestAirdrop(lamports = LAMPORTS_PER_SOL) {
|
|
193
|
+
const keypair = this.getCurrentKeypair();
|
|
194
|
+
const signature = await this.connection.requestAirdrop(keypair.publicKey, lamports);
|
|
195
|
+
await this.connection.confirmTransaction(signature);
|
|
196
|
+
return signature;
|
|
197
|
+
}
|
|
198
|
+
// 添加 request 方法以符合接口要求
|
|
199
|
+
async request(method, params) {
|
|
200
|
+
const keypair = this.getCurrentKeypair();
|
|
201
|
+
switch (method) {
|
|
202
|
+
case 'connect':
|
|
203
|
+
this.isConnected = true;
|
|
204
|
+
return { publicKey: keypair.publicKey };
|
|
205
|
+
case 'disconnect':
|
|
206
|
+
this.isConnected = false;
|
|
207
|
+
return {};
|
|
208
|
+
case 'getAccountInfo':
|
|
209
|
+
return {
|
|
210
|
+
address: keypair.publicKey.toBase58(),
|
|
211
|
+
publicKey: keypair.publicKey
|
|
212
|
+
};
|
|
213
|
+
case 'signMessage':
|
|
214
|
+
if (params?.message) {
|
|
215
|
+
const messageBytes = typeof params.message === 'string' ? new TextEncoder().encode(params.message) : params.message;
|
|
216
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
|
|
217
|
+
return {
|
|
218
|
+
signature: signature,
|
|
219
|
+
publicKey: keypair.publicKey
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
throw new Error('Message parameter required');
|
|
223
|
+
case 'signTransaction':
|
|
224
|
+
if (params?.transaction) {
|
|
225
|
+
const tx = params.transaction;
|
|
226
|
+
tx.partialSign(keypair);
|
|
227
|
+
return tx;
|
|
228
|
+
}
|
|
229
|
+
throw new Error('Transaction parameter required');
|
|
230
|
+
case 'signAndSendTransaction':
|
|
231
|
+
if (params?.transaction) {
|
|
232
|
+
const tx = params.transaction;
|
|
233
|
+
tx.partialSign(keypair);
|
|
234
|
+
const signature = await this.connection.sendTransaction(tx, [keypair]);
|
|
235
|
+
await this.connection.confirmTransaction(signature);
|
|
236
|
+
return { signature };
|
|
237
|
+
}
|
|
238
|
+
throw new Error('Transaction parameter required');
|
|
239
|
+
default:
|
|
240
|
+
return Promise.resolve({ method, params });
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Wallet, WalletAccount, EthereumWallet } from "@interchain-kit/core";
|
|
2
|
+
import { HDNodeWallet, Eip1193Provider } from 'ethers';
|
|
3
|
+
export interface MockEthereumNetwork {
|
|
4
|
+
chainId: number;
|
|
5
|
+
name: string;
|
|
6
|
+
rpcUrl: string;
|
|
7
|
+
blockExplorer?: string;
|
|
8
|
+
currencySymbol: string;
|
|
9
|
+
currencyDecimals: number;
|
|
10
|
+
}
|
|
11
|
+
export interface MockEthereumWalletOptions extends Wallet {
|
|
12
|
+
mnemonic?: string;
|
|
13
|
+
derivationPaths?: string[];
|
|
14
|
+
}
|
|
15
|
+
export declare class MockEthereumWallet extends EthereumWallet {
|
|
16
|
+
private accounts;
|
|
17
|
+
private currentAccountIndex;
|
|
18
|
+
private currentChainId;
|
|
19
|
+
private mnemonic;
|
|
20
|
+
private derivationPaths;
|
|
21
|
+
private walletMap;
|
|
22
|
+
constructor(options: Wallet, mnemonic: string);
|
|
23
|
+
init(): Promise<void>;
|
|
24
|
+
connect(chainId: string): Promise<void>;
|
|
25
|
+
disconnect(): Promise<void>;
|
|
26
|
+
switchChain(chainId: string): Promise<void>;
|
|
27
|
+
switchAccount(): Promise<void>;
|
|
28
|
+
getAccount(): Promise<WalletAccount>;
|
|
29
|
+
getAccounts(): Promise<HDNodeWallet[]>;
|
|
30
|
+
getCurrentAccount(): Promise<HDNodeWallet>;
|
|
31
|
+
getBalance(): Promise<string>;
|
|
32
|
+
sendTransaction(transaction: {
|
|
33
|
+
from: string;
|
|
34
|
+
to: string;
|
|
35
|
+
value: string;
|
|
36
|
+
data?: string;
|
|
37
|
+
gasLimit?: string;
|
|
38
|
+
gasPrice?: string;
|
|
39
|
+
}): Promise<string>;
|
|
40
|
+
signMessage(message: string): Promise<string>;
|
|
41
|
+
signTypedData(domain: any, types: any, value: any): Promise<string>;
|
|
42
|
+
getProvider(): Promise<Eip1193Provider | null>;
|
|
43
|
+
getWalletInfo(): {
|
|
44
|
+
mnemonic: string;
|
|
45
|
+
derivationPaths: string[];
|
|
46
|
+
accountCount: number;
|
|
47
|
+
currentAccountIndex: number;
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MockEthereumWallet = void 0;
|
|
4
|
+
const core_1 = require("@interchain-kit/core");
|
|
5
|
+
const ethers_1 = require("ethers");
|
|
6
|
+
class MockEthereumWallet extends core_1.EthereumWallet {
|
|
7
|
+
accounts = [];
|
|
8
|
+
currentAccountIndex = 0;
|
|
9
|
+
currentChainId = '1'; // Default to Ethereum mainnet
|
|
10
|
+
mnemonic;
|
|
11
|
+
derivationPaths;
|
|
12
|
+
walletMap = {};
|
|
13
|
+
constructor(options, mnemonic) {
|
|
14
|
+
super(options);
|
|
15
|
+
// 设置默认值
|
|
16
|
+
this.mnemonic = mnemonic;
|
|
17
|
+
this.derivationPaths = [
|
|
18
|
+
`44'/60'/0'/0/0`, // 第一个钱包
|
|
19
|
+
`44'/60'/0'/0/1` // 第二个钱包
|
|
20
|
+
];
|
|
21
|
+
}
|
|
22
|
+
async init() {
|
|
23
|
+
const chains = Array.from(this.chainMap.values());
|
|
24
|
+
console.log(chains);
|
|
25
|
+
this.currentChainId = chains[0].chainId;
|
|
26
|
+
for (const chain of chains) {
|
|
27
|
+
const hdNode = ethers_1.ethers.HDNodeWallet.fromPhrase(this.mnemonic);
|
|
28
|
+
const wallet0 = hdNode.derivePath("44'/60'/0'/0/0");
|
|
29
|
+
const wallet1 = hdNode.derivePath("44'/60'/0'/0/1");
|
|
30
|
+
const rpc = chain.apis?.rpc[0].address || '';
|
|
31
|
+
const provider = new ethers_1.ethers.JsonRpcProvider(rpc);
|
|
32
|
+
this.walletMap[chain.chainId] = {
|
|
33
|
+
'0': {
|
|
34
|
+
wallet: wallet0,
|
|
35
|
+
provider,
|
|
36
|
+
signer: new ethers_1.ethers.Wallet(wallet0.privateKey, provider)
|
|
37
|
+
},
|
|
38
|
+
'1': {
|
|
39
|
+
wallet: wallet1,
|
|
40
|
+
provider,
|
|
41
|
+
signer: new ethers_1.ethers.Wallet(wallet1.privateKey, provider)
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
return Promise.resolve();
|
|
46
|
+
}
|
|
47
|
+
async connect(chainId) {
|
|
48
|
+
await this.switchChain(chainId);
|
|
49
|
+
return Promise.resolve();
|
|
50
|
+
}
|
|
51
|
+
async disconnect() {
|
|
52
|
+
return Promise.resolve();
|
|
53
|
+
}
|
|
54
|
+
async switchChain(chainId) {
|
|
55
|
+
this.currentChainId = chainId;
|
|
56
|
+
}
|
|
57
|
+
async switchAccount() {
|
|
58
|
+
this.currentAccountIndex = this.currentAccountIndex === 0 ? 1 : 0;
|
|
59
|
+
this.events.emit('accountChanged', () => { });
|
|
60
|
+
}
|
|
61
|
+
async getAccount() {
|
|
62
|
+
const account = this.walletMap[this.currentChainId][this.currentAccountIndex].wallet;
|
|
63
|
+
return {
|
|
64
|
+
address: account.address,
|
|
65
|
+
pubkey: new Uint8Array(), // Ethereum doesn't use pubkey in the same way
|
|
66
|
+
algo: 'eth_secp256k1',
|
|
67
|
+
isNanoLedger: false,
|
|
68
|
+
isSmartContract: false,
|
|
69
|
+
username: `Account ${this.currentAccountIndex + 1}`
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
async getAccounts() {
|
|
73
|
+
return this.accounts;
|
|
74
|
+
}
|
|
75
|
+
async getCurrentAccount() {
|
|
76
|
+
return this.accounts[this.currentAccountIndex];
|
|
77
|
+
}
|
|
78
|
+
async getBalance() {
|
|
79
|
+
const { provider, wallet } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
80
|
+
const balance = await provider.getBalance(wallet.address);
|
|
81
|
+
return ethers_1.ethers.formatEther(balance);
|
|
82
|
+
}
|
|
83
|
+
async sendTransaction(transaction) {
|
|
84
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
85
|
+
const tx = await signer.sendTransaction({
|
|
86
|
+
from: transaction.from,
|
|
87
|
+
to: transaction.to,
|
|
88
|
+
value: transaction.value,
|
|
89
|
+
// data: transaction.data || '0x',
|
|
90
|
+
// gasLimit: transaction.gasLimit ? BigInt(transaction.gasLimit) : undefined,
|
|
91
|
+
// gasPrice: transaction.gasPrice ? ethers.parseUnits(transaction.gasPrice, 'gwei') : undefined
|
|
92
|
+
});
|
|
93
|
+
console.log(`Transaction sent: ${tx.hash}`);
|
|
94
|
+
return tx.hash;
|
|
95
|
+
}
|
|
96
|
+
async signMessage(message) {
|
|
97
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
98
|
+
const signature = await signer.signMessage(message);
|
|
99
|
+
console.log(`Message signed: ${signature}`);
|
|
100
|
+
return signature;
|
|
101
|
+
}
|
|
102
|
+
async signTypedData(domain, types, value) {
|
|
103
|
+
const { signer } = this.walletMap[this.currentChainId][this.currentAccountIndex];
|
|
104
|
+
const signature = await signer.signTypedData(domain, types, value);
|
|
105
|
+
console.log(`Typed data signed: ${signature}`);
|
|
106
|
+
return signature;
|
|
107
|
+
}
|
|
108
|
+
async getProvider() {
|
|
109
|
+
return this.provider;
|
|
110
|
+
}
|
|
111
|
+
getWalletInfo() {
|
|
112
|
+
return {
|
|
113
|
+
mnemonic: this.mnemonic,
|
|
114
|
+
derivationPaths: [...this.derivationPaths],
|
|
115
|
+
accountCount: this.accounts.length,
|
|
116
|
+
currentAccountIndex: this.currentAccountIndex
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
exports.MockEthereumWallet = MockEthereumWallet;
|
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -15,3 +15,5 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
15
15
|
};
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./wallet"), exports);
|
|
18
|
+
__exportStar(require("./solana-wallet"), exports);
|
|
19
|
+
__exportStar(require("./ethereum-wallet"), exports);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interchain-kit/mock-wallet",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.47",
|
|
4
4
|
"author": "Cosmology <developers@hyperweb.io>",
|
|
5
5
|
"description": "interchain-kit wallet connector",
|
|
6
6
|
"main": "index.js",
|
|
@@ -32,7 +32,13 @@
|
|
|
32
32
|
},
|
|
33
33
|
"keywords": [],
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@interchain-kit/core": "0.3.
|
|
35
|
+
"@interchain-kit/core": "0.3.47",
|
|
36
|
+
"@solana/web3.js": "^1.98.4",
|
|
37
|
+
"bip39": "^3.1.0",
|
|
38
|
+
"bs58": "^6.0.0",
|
|
39
|
+
"ed25519-hd-key": "^1.3.0",
|
|
40
|
+
"ethers": "^6.15.0",
|
|
41
|
+
"tweetnacl": "^1.0.3"
|
|
36
42
|
},
|
|
37
|
-
"gitHead": "
|
|
43
|
+
"gitHead": "4583b572672abd85a0918f39f534a5bf9312c261"
|
|
38
44
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { SolanaWallet, Wallet, WalletAccount } from '@interchain-kit/core';
|
|
2
|
+
import { SolanaSignInData } from '@interchain-kit/core/types/solana';
|
|
3
|
+
import { Keypair, Transaction } from '@solana/web3.js';
|
|
4
|
+
export declare class MockSolanaWallet extends SolanaWallet {
|
|
5
|
+
private connection;
|
|
6
|
+
isConnected: boolean;
|
|
7
|
+
derivationPath1: string;
|
|
8
|
+
derivationPath2: string;
|
|
9
|
+
currentKeypairIndex: '1' | '2';
|
|
10
|
+
keypairMap: Record<'1' | '2', Keypair>;
|
|
11
|
+
constructor(network: 'mainnet-beta' | 'devnet' | 'testnet', info: Wallet, mnemonic?: string);
|
|
12
|
+
init(): Promise<void>;
|
|
13
|
+
bindingEvent(): void;
|
|
14
|
+
getCurrentKeypair(): Keypair;
|
|
15
|
+
changeWalletAccount(): void;
|
|
16
|
+
connect(chainId: string): Promise<void>;
|
|
17
|
+
disconnect(chainId: string): Promise<void>;
|
|
18
|
+
getAccount(chainId: string): Promise<WalletAccount>;
|
|
19
|
+
signIn(data: SolanaSignInData): Promise<{
|
|
20
|
+
address: string;
|
|
21
|
+
signature: Uint8Array;
|
|
22
|
+
signedMessage: Uint8Array;
|
|
23
|
+
}>;
|
|
24
|
+
signMessage(message: Uint8Array, encoding?: 'utf8' | 'hex'): Promise<any>;
|
|
25
|
+
signTransaction(transaction: Transaction): Promise<Transaction>;
|
|
26
|
+
signAllTransactions(transactions: Transaction[]): Promise<Transaction[]>;
|
|
27
|
+
signAndSendTransaction(transaction: Transaction): Promise<string>;
|
|
28
|
+
signAndSendAllTransactions(transactions: Transaction[]): Promise<string[]>;
|
|
29
|
+
getBalance(): Promise<number>;
|
|
30
|
+
requestAirdrop(lamports?: number): Promise<string>;
|
|
31
|
+
request(method: string, params: any): Promise<any>;
|
|
32
|
+
}
|
package/solana-wallet.js
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.MockSolanaWallet = void 0;
|
|
37
|
+
const core_1 = require("@interchain-kit/core");
|
|
38
|
+
const web3_js_1 = require("@solana/web3.js");
|
|
39
|
+
const bip39 = __importStar(require("bip39"));
|
|
40
|
+
const ed25519_hd_key_1 = require("ed25519-hd-key");
|
|
41
|
+
const nacl = __importStar(require("tweetnacl"));
|
|
42
|
+
class MockSolanaWallet extends core_1.SolanaWallet {
|
|
43
|
+
connection;
|
|
44
|
+
isConnected;
|
|
45
|
+
derivationPath1 = "m/44'/501'/0'/0'";
|
|
46
|
+
derivationPath2 = "m/44'/501'/1'/0'";
|
|
47
|
+
currentKeypairIndex = '1';
|
|
48
|
+
keypairMap = {
|
|
49
|
+
1: {},
|
|
50
|
+
2: {},
|
|
51
|
+
};
|
|
52
|
+
constructor(network = 'devnet', info, mnemonic) {
|
|
53
|
+
super(info);
|
|
54
|
+
// 如果提供了助记词,从助记词派生密钥对
|
|
55
|
+
if (mnemonic) {
|
|
56
|
+
if (!bip39.validateMnemonic(mnemonic)) {
|
|
57
|
+
throw new Error('Invalid mnemonic phrase');
|
|
58
|
+
}
|
|
59
|
+
const seed = bip39.mnemonicToSeedSync(mnemonic);
|
|
60
|
+
const derivedSeed1 = (0, ed25519_hd_key_1.derivePath)(this.derivationPath1, seed.toString('hex')).key;
|
|
61
|
+
this.keypairMap['1'] = web3_js_1.Keypair.fromSeed(derivedSeed1);
|
|
62
|
+
const derivedSeed2 = (0, ed25519_hd_key_1.derivePath)(this.derivationPath2, seed.toString('hex')).key;
|
|
63
|
+
this.keypairMap['2'] = web3_js_1.Keypair.fromSeed(derivedSeed2);
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// 否则随机生成密钥对
|
|
67
|
+
this.keypairMap['1'] = web3_js_1.Keypair.generate();
|
|
68
|
+
this.keypairMap['2'] = web3_js_1.Keypair.generate();
|
|
69
|
+
}
|
|
70
|
+
this.connection = new web3_js_1.Connection(`https://api.${network}.solana.com`, 'confirmed');
|
|
71
|
+
this.isConnected = false;
|
|
72
|
+
}
|
|
73
|
+
async init() {
|
|
74
|
+
//@ts-ignore
|
|
75
|
+
window[this.info.windowKey] = {};
|
|
76
|
+
//@ts-ignore
|
|
77
|
+
window[this.info.solanaKey] = {};
|
|
78
|
+
await super.init();
|
|
79
|
+
}
|
|
80
|
+
bindingEvent() {
|
|
81
|
+
window.addEventListener(this.info.keystoreChange, () => {
|
|
82
|
+
this.events.emit('accountChanged', () => { });
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
getCurrentKeypair() {
|
|
86
|
+
const keypair = this.keypairMap[this.currentKeypairIndex];
|
|
87
|
+
if (!keypair) {
|
|
88
|
+
throw new Error(`No keypair found for account index: ${this.currentKeypairIndex}`);
|
|
89
|
+
}
|
|
90
|
+
return keypair;
|
|
91
|
+
}
|
|
92
|
+
changeWalletAccount() {
|
|
93
|
+
this.currentKeypairIndex = this.currentKeypairIndex === '1' ? '2' : '1';
|
|
94
|
+
//@ts-ignore
|
|
95
|
+
window.dispatchEvent(new CustomEvent(this.info.keystoreChange));
|
|
96
|
+
console.log('trigger in mock solana wallet');
|
|
97
|
+
}
|
|
98
|
+
// 模拟 Phantom 的 connect 方法
|
|
99
|
+
async connect(chainId) {
|
|
100
|
+
this.isConnected = true;
|
|
101
|
+
return Promise.resolve();
|
|
102
|
+
}
|
|
103
|
+
// 模拟 Phantom 的 disconnect 方法
|
|
104
|
+
async disconnect(chainId) {
|
|
105
|
+
this.isConnected = false;
|
|
106
|
+
return Promise.resolve();
|
|
107
|
+
}
|
|
108
|
+
async getAccount(chainId) {
|
|
109
|
+
const keypair = this.getCurrentKeypair();
|
|
110
|
+
return {
|
|
111
|
+
address: keypair.publicKey.toBase58(),
|
|
112
|
+
algo: 'secp256k1',
|
|
113
|
+
pubkey: keypair.publicKey.toBytes()
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// 模拟 Sign In With Solana (SIWS)
|
|
117
|
+
async signIn(data) {
|
|
118
|
+
if (!this.isConnected) {
|
|
119
|
+
throw new Error('Wallet not connected.');
|
|
120
|
+
}
|
|
121
|
+
const keypair = this.getCurrentKeypair();
|
|
122
|
+
const { domain = 'my-dapp.com', statement = 'Login to My dApp', uri = 'https://my-dapp.com/login', version = '1', chainId = 'solana:devnet', nonce = Math.random().toString(36).substring(2, 10), issuedAt = new Date().toISOString(), expirationTime = new Date(Date.now() + 1000 * 60 * 60).toISOString(), } = data;
|
|
123
|
+
const message = `${domain} wants you to sign in with your Solana account:
|
|
124
|
+
${keypair.publicKey.toBase58()}
|
|
125
|
+
|
|
126
|
+
Statement: ${statement}
|
|
127
|
+
URI: ${uri}
|
|
128
|
+
Version: ${version}
|
|
129
|
+
Chain ID: ${chainId}
|
|
130
|
+
Nonce: ${nonce}
|
|
131
|
+
Issued At: ${issuedAt}
|
|
132
|
+
Expiration Time: ${expirationTime}`;
|
|
133
|
+
const messageBytes = new TextEncoder().encode(message);
|
|
134
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
|
|
135
|
+
return {
|
|
136
|
+
address: keypair.publicKey.toBase58(),
|
|
137
|
+
signature: signature,
|
|
138
|
+
signedMessage: messageBytes,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
// 模拟 signMessage
|
|
142
|
+
async signMessage(message, encoding = 'utf8') {
|
|
143
|
+
if (!this.isConnected) {
|
|
144
|
+
throw new Error('Wallet not connected.');
|
|
145
|
+
}
|
|
146
|
+
const keypair = this.getCurrentKeypair();
|
|
147
|
+
const signature = nacl.sign.detached(message, keypair.secretKey);
|
|
148
|
+
return {
|
|
149
|
+
signature: signature,
|
|
150
|
+
publicKey: keypair.publicKey,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
// 模拟 signTransaction
|
|
154
|
+
async signTransaction(transaction) {
|
|
155
|
+
if (!this.isConnected) {
|
|
156
|
+
throw new Error('Wallet not connected.');
|
|
157
|
+
}
|
|
158
|
+
if (!(transaction instanceof web3_js_1.Transaction)) {
|
|
159
|
+
throw new Error('Invalid transaction');
|
|
160
|
+
}
|
|
161
|
+
const keypair = this.getCurrentKeypair();
|
|
162
|
+
transaction.partialSign(keypair);
|
|
163
|
+
return transaction;
|
|
164
|
+
}
|
|
165
|
+
// 模拟 signAllTransactions
|
|
166
|
+
async signAllTransactions(transactions) {
|
|
167
|
+
if (!this.isConnected) {
|
|
168
|
+
throw new Error('Wallet not connected.');
|
|
169
|
+
}
|
|
170
|
+
if (!Array.isArray(transactions)) {
|
|
171
|
+
throw new Error('Invalid transactions array');
|
|
172
|
+
}
|
|
173
|
+
return transactions.map((tx) => {
|
|
174
|
+
if (!(tx instanceof web3_js_1.Transaction))
|
|
175
|
+
throw new Error('Invalid transaction');
|
|
176
|
+
const keypair = this.getCurrentKeypair();
|
|
177
|
+
tx.partialSign(keypair);
|
|
178
|
+
return tx;
|
|
179
|
+
});
|
|
180
|
+
}
|
|
181
|
+
// 模拟 signAndSendTransaction
|
|
182
|
+
async signAndSendTransaction(transaction) {
|
|
183
|
+
if (!this.isConnected) {
|
|
184
|
+
throw new Error('Wallet not connected.');
|
|
185
|
+
}
|
|
186
|
+
if (!(transaction instanceof web3_js_1.Transaction)) {
|
|
187
|
+
throw new Error('Invalid transaction');
|
|
188
|
+
}
|
|
189
|
+
const keypair = this.getCurrentKeypair();
|
|
190
|
+
transaction.partialSign(keypair);
|
|
191
|
+
const signature = await this.connection.sendTransaction(transaction, [keypair]);
|
|
192
|
+
await this.connection.confirmTransaction(signature);
|
|
193
|
+
return signature;
|
|
194
|
+
}
|
|
195
|
+
// 模拟 signAndSendAllTransactions
|
|
196
|
+
async signAndSendAllTransactions(transactions) {
|
|
197
|
+
if (!this.isConnected) {
|
|
198
|
+
throw new Error('Wallet not connected.');
|
|
199
|
+
}
|
|
200
|
+
if (!Array.isArray(transactions)) {
|
|
201
|
+
throw new Error('Invalid transactions array');
|
|
202
|
+
}
|
|
203
|
+
const signatures = [];
|
|
204
|
+
for (const tx of transactions) {
|
|
205
|
+
if (!(tx instanceof web3_js_1.Transaction))
|
|
206
|
+
throw new Error('Invalid transaction');
|
|
207
|
+
const keypair = this.getCurrentKeypair();
|
|
208
|
+
tx.partialSign(keypair);
|
|
209
|
+
const signature = await this.connection.sendTransaction(tx, [keypair]);
|
|
210
|
+
await this.connection.confirmTransaction(signature);
|
|
211
|
+
signatures.push(signature);
|
|
212
|
+
}
|
|
213
|
+
return signatures;
|
|
214
|
+
}
|
|
215
|
+
// 获取余额
|
|
216
|
+
async getBalance() {
|
|
217
|
+
try {
|
|
218
|
+
const keypair = this.getCurrentKeypair();
|
|
219
|
+
const balance = await this.connection.getBalance(keypair.publicKey);
|
|
220
|
+
return balance;
|
|
221
|
+
}
|
|
222
|
+
catch (error) {
|
|
223
|
+
console.error('Error getting balance:', error);
|
|
224
|
+
return 0;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// 请求空投(仅限 devnet/testnet)
|
|
228
|
+
async requestAirdrop(lamports = web3_js_1.LAMPORTS_PER_SOL) {
|
|
229
|
+
const keypair = this.getCurrentKeypair();
|
|
230
|
+
const signature = await this.connection.requestAirdrop(keypair.publicKey, lamports);
|
|
231
|
+
await this.connection.confirmTransaction(signature);
|
|
232
|
+
return signature;
|
|
233
|
+
}
|
|
234
|
+
// 添加 request 方法以符合接口要求
|
|
235
|
+
async request(method, params) {
|
|
236
|
+
const keypair = this.getCurrentKeypair();
|
|
237
|
+
switch (method) {
|
|
238
|
+
case 'connect':
|
|
239
|
+
this.isConnected = true;
|
|
240
|
+
return { publicKey: keypair.publicKey };
|
|
241
|
+
case 'disconnect':
|
|
242
|
+
this.isConnected = false;
|
|
243
|
+
return {};
|
|
244
|
+
case 'getAccountInfo':
|
|
245
|
+
return {
|
|
246
|
+
address: keypair.publicKey.toBase58(),
|
|
247
|
+
publicKey: keypair.publicKey
|
|
248
|
+
};
|
|
249
|
+
case 'signMessage':
|
|
250
|
+
if (params?.message) {
|
|
251
|
+
const messageBytes = typeof params.message === 'string' ? new TextEncoder().encode(params.message) : params.message;
|
|
252
|
+
const signature = nacl.sign.detached(messageBytes, keypair.secretKey);
|
|
253
|
+
return {
|
|
254
|
+
signature: signature,
|
|
255
|
+
publicKey: keypair.publicKey
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
throw new Error('Message parameter required');
|
|
259
|
+
case 'signTransaction':
|
|
260
|
+
if (params?.transaction) {
|
|
261
|
+
const tx = params.transaction;
|
|
262
|
+
tx.partialSign(keypair);
|
|
263
|
+
return tx;
|
|
264
|
+
}
|
|
265
|
+
throw new Error('Transaction parameter required');
|
|
266
|
+
case 'signAndSendTransaction':
|
|
267
|
+
if (params?.transaction) {
|
|
268
|
+
const tx = params.transaction;
|
|
269
|
+
tx.partialSign(keypair);
|
|
270
|
+
const signature = await this.connection.sendTransaction(tx, [keypair]);
|
|
271
|
+
await this.connection.confirmTransaction(signature);
|
|
272
|
+
return { signature };
|
|
273
|
+
}
|
|
274
|
+
throw new Error('Transaction parameter required');
|
|
275
|
+
default:
|
|
276
|
+
return Promise.resolve({ method, params });
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
exports.MockSolanaWallet = MockSolanaWallet;
|