@interchain-kit/mock-wallet 0.3.46 → 0.3.48

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.
@@ -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
@@ -1 +1,3 @@
1
1
  export * from './wallet';
2
+ export * from './solana-wallet';
3
+ export * from './ethereum-wallet';
@@ -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
@@ -1 +1,3 @@
1
1
  export * from './wallet';
2
+ export * from './solana-wallet';
3
+ export * from './ethereum-wallet';
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.46",
3
+ "version": "0.3.48",
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.46"
35
+ "@interchain-kit/core": "0.3.48",
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": "15b40f1b694af468aa8a92fedd347a127fefd3ab"
43
+ "gitHead": "763ba776cbfcbff8ef76a512ef5758c7187cb1f4"
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
+ }
@@ -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;