@interchain-kit/store 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/LICENSE +21 -0
- package/README.md +70 -0
- package/esm/index.js +3 -0
- package/esm/proxied-wallets/cosmos-wallet.js +51 -0
- package/esm/proxied-wallets/create-proxied-wallet.js +30 -0
- package/esm/proxied-wallets/ethereum-wallet.js +24 -0
- package/esm/proxied-wallets/index.js +5 -0
- package/esm/proxied-wallets/multi-chain-wallet.js +27 -0
- package/esm/store/index.js +125 -0
- package/esm/types/index.js +1 -0
- package/esm/types/store.js +1 -0
- package/esm/utils/aop.js +172 -0
- package/esm/utils/index.js +1 -0
- package/esm/utils/local-storage.js +9 -0
- package/esm/wallet-manager/chain-wallet-store.js +111 -0
- package/esm/wallet-manager/index.js +3 -0
- package/esm/wallet-manager/wallet-manager-store.js +230 -0
- package/esm/wallet-manager/wallet-store.js +99 -0
- package/index.d.ts +3 -0
- package/index.js +19 -0
- package/package.json +35 -0
- package/proxied-wallets/cosmos-wallet.d.ts +3 -0
- package/proxied-wallets/cosmos-wallet.js +55 -0
- package/proxied-wallets/create-proxied-wallet.d.ts +2 -0
- package/proxied-wallets/create-proxied-wallet.js +34 -0
- package/proxied-wallets/ethereum-wallet.d.ts +3 -0
- package/proxied-wallets/ethereum-wallet.js +28 -0
- package/proxied-wallets/index.d.ts +4 -0
- package/proxied-wallets/index.js +21 -0
- package/proxied-wallets/multi-chain-wallet.d.ts +3 -0
- package/proxied-wallets/multi-chain-wallet.js +31 -0
- package/store/index.d.ts +21 -0
- package/store/index.js +129 -0
- package/types/index.d.ts +1 -0
- package/types/index.js +17 -0
- package/types/store.d.ts +17 -0
- package/types/store.js +2 -0
- package/utils/aop.d.ts +58 -0
- package/utils/aop.js +178 -0
- package/utils/index.d.ts +1 -0
- package/utils/index.js +17 -0
- package/utils/local-storage.d.ts +5 -0
- package/utils/local-storage.js +13 -0
- package/wallet-manager/chain-wallet-store.d.ts +22 -0
- package/wallet-manager/chain-wallet-store.js +115 -0
- package/wallet-manager/index.d.ts +3 -0
- package/wallet-manager/index.js +19 -0
- package/wallet-manager/wallet-manager-store.d.ts +58 -0
- package/wallet-manager/wallet-manager-store.js +234 -0
- package/wallet-manager/wallet-store.d.ts +21 -0
- package/wallet-manager/wallet-store.js +103 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createMultiChainWallet = void 0;
|
|
4
|
+
const core_1 = require("@interchain-kit/core");
|
|
5
|
+
const aop_1 = require("../utils/aop");
|
|
6
|
+
const createMultiChainWallet = (target, store) => {
|
|
7
|
+
return (0, aop_1.createAOPProxy)({
|
|
8
|
+
target,
|
|
9
|
+
advice: {
|
|
10
|
+
connect: {
|
|
11
|
+
async around(methodName, target, originalMethod, chainId) {
|
|
12
|
+
const chain = target.getChainById(chainId);
|
|
13
|
+
store.updateChainWalletState(target.info.name, chain.chainName, { walletState: core_1.WalletState.Connecting });
|
|
14
|
+
await originalMethod(chainId);
|
|
15
|
+
const account = await target.getAccount(chainId);
|
|
16
|
+
store.updateChainWalletState(target.info.name, chain.chainName, {
|
|
17
|
+
walletState: core_1.WalletState.Connected,
|
|
18
|
+
account
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
disconnect: {
|
|
23
|
+
after(methodName, target, result, chainId) {
|
|
24
|
+
const chain = target.getChainById(chainId);
|
|
25
|
+
store.updateChainWalletState(target.info.name, chain.chainName, { walletState: core_1.WalletState.Disconnected });
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
exports.createMultiChainWallet = createMultiChainWallet;
|
package/store/index.d.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ChainWalletState, InterchainStoreType } from '../types';
|
|
2
|
+
export declare class InterchainStore {
|
|
3
|
+
private state;
|
|
4
|
+
private listeners;
|
|
5
|
+
private chainWalletIndexMap;
|
|
6
|
+
constructor();
|
|
7
|
+
getState(): InterchainStoreType;
|
|
8
|
+
subscribe(listener: (state: InterchainStoreType) => void): () => void;
|
|
9
|
+
emit(): void;
|
|
10
|
+
setState(newState: Partial<InterchainStoreType>): void;
|
|
11
|
+
updateState(partialState: Partial<InterchainStoreType>): void;
|
|
12
|
+
setCurrentChainName(chainName: string): void;
|
|
13
|
+
setCurrentWalletName(walletName: string): void;
|
|
14
|
+
updateChainWalletState(walletName: string, chainName: string, state: Partial<ChainWalletState>): void;
|
|
15
|
+
addChainWalletState(walletName: string, chainName: string, state: Partial<ChainWalletState>): void;
|
|
16
|
+
removeChainWalletState(walletName: string, chainName: string): void;
|
|
17
|
+
getChainWalletState(walletName: string, chainName: string): ChainWalletState | undefined;
|
|
18
|
+
buildIndexMap(): void;
|
|
19
|
+
updateWalletState(walletName: string, state: Partial<ChainWalletState>): void;
|
|
20
|
+
isChainWalletStateExisted(walletName: string, chainName: string): number;
|
|
21
|
+
}
|
package/store/index.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.InterchainStore = void 0;
|
|
4
|
+
const core_1 = require("@interchain-kit/core");
|
|
5
|
+
class InterchainStore {
|
|
6
|
+
state;
|
|
7
|
+
listeners = new Set();
|
|
8
|
+
// 快速查找索引的 Map: walletName-chainName -> index
|
|
9
|
+
chainWalletIndexMap = new Map();
|
|
10
|
+
constructor() {
|
|
11
|
+
this.state = {
|
|
12
|
+
currentWalletName: '',
|
|
13
|
+
currentChainName: '',
|
|
14
|
+
chainWalletStates: [],
|
|
15
|
+
isReady: false,
|
|
16
|
+
modalIsOpen: false,
|
|
17
|
+
walletConnectQRCodeUri: '',
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// Get current state
|
|
21
|
+
getState() {
|
|
22
|
+
return this.state;
|
|
23
|
+
}
|
|
24
|
+
// Subscribe to state changes
|
|
25
|
+
subscribe(listener) {
|
|
26
|
+
this.listeners.add(listener);
|
|
27
|
+
// Return unsubscribe function
|
|
28
|
+
return () => {
|
|
29
|
+
this.listeners.delete(listener);
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
// Emit state changes to all listeners
|
|
33
|
+
emit() {
|
|
34
|
+
this.listeners.forEach(listener => {
|
|
35
|
+
try {
|
|
36
|
+
listener(this.state);
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Error in store listener:', error);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Update state and emit changes
|
|
44
|
+
setState(newState) {
|
|
45
|
+
this.state = { ...this.state, ...newState };
|
|
46
|
+
this.emit();
|
|
47
|
+
}
|
|
48
|
+
// Update partial state and emit changes
|
|
49
|
+
updateState(partialState) {
|
|
50
|
+
this.state = { ...this.state, ...partialState };
|
|
51
|
+
this.emit();
|
|
52
|
+
}
|
|
53
|
+
setCurrentChainName(chainName) {
|
|
54
|
+
this.setState({ ...this.state, currentChainName: chainName });
|
|
55
|
+
}
|
|
56
|
+
setCurrentWalletName(walletName) {
|
|
57
|
+
this.setState({ ...this.state, currentWalletName: walletName });
|
|
58
|
+
}
|
|
59
|
+
updateChainWalletState(walletName, chainName, state) {
|
|
60
|
+
const key = `${walletName}-${chainName}`;
|
|
61
|
+
const index = this.chainWalletIndexMap.get(key);
|
|
62
|
+
if (index !== undefined) {
|
|
63
|
+
// 直接通过索引更新,避免遍历
|
|
64
|
+
const newChainWalletStates = [...this.state.chainWalletStates];
|
|
65
|
+
newChainWalletStates[index] = { ...newChainWalletStates[index], ...state };
|
|
66
|
+
this.setState({ ...this.state, chainWalletStates: newChainWalletStates });
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
this.addChainWalletState(walletName, chainName, state);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
// 添加新的 chain wallet state
|
|
73
|
+
addChainWalletState(walletName, chainName, state) {
|
|
74
|
+
const newChainWalletState = [...this.state.chainWalletStates];
|
|
75
|
+
const newIndex = newChainWalletState.length;
|
|
76
|
+
newChainWalletState.push({
|
|
77
|
+
chainName,
|
|
78
|
+
walletName,
|
|
79
|
+
walletState: core_1.WalletState.Disconnected,
|
|
80
|
+
rpcEndpoint: '', errorMessage: '', account: undefined, ...state
|
|
81
|
+
});
|
|
82
|
+
// 更新索引映射
|
|
83
|
+
const key = `${walletName}-${chainName}`;
|
|
84
|
+
this.chainWalletIndexMap.set(key, newIndex);
|
|
85
|
+
this.setState({ ...this.state, chainWalletStates: newChainWalletState });
|
|
86
|
+
}
|
|
87
|
+
// 移除 chain wallet state
|
|
88
|
+
removeChainWalletState(walletName, chainName) {
|
|
89
|
+
const key = `${walletName}-${chainName}`;
|
|
90
|
+
const index = this.chainWalletIndexMap.get(key);
|
|
91
|
+
if (index !== undefined) {
|
|
92
|
+
const newChainWalletState = this.state.chainWalletStates.filter((_, i) => i !== index);
|
|
93
|
+
// 重新构建索引映射
|
|
94
|
+
this.chainWalletIndexMap.clear();
|
|
95
|
+
newChainWalletState.forEach((item, i) => {
|
|
96
|
+
const itemKey = `${item.walletName}-${item.chainName}`;
|
|
97
|
+
this.chainWalletIndexMap.set(itemKey, i);
|
|
98
|
+
});
|
|
99
|
+
this.setState({ ...this.state, chainWalletStates: newChainWalletState });
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
// 获取指定 chain 的 wallet state
|
|
103
|
+
getChainWalletState(walletName, chainName) {
|
|
104
|
+
const key = `${walletName}-${chainName}`;
|
|
105
|
+
const index = this.chainWalletIndexMap.get(key);
|
|
106
|
+
return index !== undefined ? this.state.chainWalletStates[index] : undefined;
|
|
107
|
+
}
|
|
108
|
+
// 恢复索引映射(用于从localStorage恢复数据后重建索引)
|
|
109
|
+
buildIndexMap() {
|
|
110
|
+
this.chainWalletIndexMap.clear();
|
|
111
|
+
this.state.chainWalletStates.forEach((item, index) => {
|
|
112
|
+
const key = `${item.walletName}-${item.chainName}`;
|
|
113
|
+
this.chainWalletIndexMap.set(key, index);
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
updateWalletState(walletName, state) {
|
|
117
|
+
const newChainWalletStates = this.state.chainWalletStates.map(cws => {
|
|
118
|
+
if (cws.walletName === walletName) {
|
|
119
|
+
return { ...cws, ...state };
|
|
120
|
+
}
|
|
121
|
+
return cws;
|
|
122
|
+
});
|
|
123
|
+
this.setState({ chainWalletStates: newChainWalletStates });
|
|
124
|
+
}
|
|
125
|
+
isChainWalletStateExisted(walletName, chainName) {
|
|
126
|
+
return this.chainWalletIndexMap.get(`${walletName}-${chainName}`);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
exports.InterchainStore = InterchainStore;
|
package/types/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './store';
|
package/types/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./store"), exports);
|
package/types/store.d.ts
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { WalletAccount, WalletState } from '@interchain-kit/core';
|
|
2
|
+
export type ChainWalletState = {
|
|
3
|
+
chainName: string;
|
|
4
|
+
walletName: string;
|
|
5
|
+
walletState: WalletState;
|
|
6
|
+
rpcEndpoint: string;
|
|
7
|
+
errorMessage: string;
|
|
8
|
+
account: WalletAccount | undefined;
|
|
9
|
+
};
|
|
10
|
+
export type InterchainStoreType = {
|
|
11
|
+
currentWalletName: string;
|
|
12
|
+
currentChainName: string;
|
|
13
|
+
chainWalletStates: ChainWalletState[];
|
|
14
|
+
isReady: boolean;
|
|
15
|
+
modalIsOpen: boolean;
|
|
16
|
+
walletConnectQRCodeUri: string;
|
|
17
|
+
};
|
package/types/store.js
ADDED
package/utils/aop.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AOP (Aspect-Oriented Programming) implementation similar to Java AOP
|
|
3
|
+
* Using Object.create, Object.getOwnPropertyNames, and Object.getPrototypeOf
|
|
4
|
+
*/
|
|
5
|
+
export type MethodName<T> = keyof T & string;
|
|
6
|
+
export type MethodArgs<T, K extends MethodName<T>> = T[K] extends (...args: infer A) => any ? A : never;
|
|
7
|
+
export type MethodReturn<T, K extends MethodName<T>> = T[K] extends (...args: any[]) => infer R ? R : never;
|
|
8
|
+
export interface MethodAdvice<T, K extends MethodName<T>> {
|
|
9
|
+
before?: (methodName: K, target: T, ...args: MethodArgs<T, K>) => void;
|
|
10
|
+
after?: (methodName: K, target: T, result: MethodReturn<T, K>, ...args: MethodArgs<T, K>) => void;
|
|
11
|
+
afterReturn?: (methodName: K, target: T, result: MethodReturn<T, K>, ...args: MethodArgs<T, K>) => void;
|
|
12
|
+
around?: (methodName: K, target: T, originalMethod: T[K], ...args: MethodArgs<T, K>) => MethodReturn<T, K>;
|
|
13
|
+
onError?: (methodName: K, target: T, error: Error, ...args: MethodArgs<T, K>) => void;
|
|
14
|
+
}
|
|
15
|
+
export interface AOPConfig<T = any> {
|
|
16
|
+
target: T;
|
|
17
|
+
advice: {
|
|
18
|
+
[K in MethodName<T>]?: MethodAdvice<T, K>;
|
|
19
|
+
};
|
|
20
|
+
defaultAdvice?: MethodAdvice<T, MethodName<T>>;
|
|
21
|
+
}
|
|
22
|
+
export type AOPProxyType<T> = {
|
|
23
|
+
[K in keyof T]: T[K] extends (...args: any[]) => any ? T[K] : T[K];
|
|
24
|
+
};
|
|
25
|
+
export declare class AOPProxy<T = any> {
|
|
26
|
+
private target;
|
|
27
|
+
private advice;
|
|
28
|
+
private defaultAdvice?;
|
|
29
|
+
constructor(config: AOPConfig<T>);
|
|
30
|
+
/**
|
|
31
|
+
* Get advice for a specific method
|
|
32
|
+
*/
|
|
33
|
+
private getMethodAdvice;
|
|
34
|
+
/**
|
|
35
|
+
* Collect all property names from the instance and its prototype chain
|
|
36
|
+
* (excluding Object.prototype). This allows intercepting prototype methods
|
|
37
|
+
* in addition to own instance methods.
|
|
38
|
+
*/
|
|
39
|
+
private getAllMemberNames;
|
|
40
|
+
/**
|
|
41
|
+
* Create a proxy object with AOP capabilities
|
|
42
|
+
*/
|
|
43
|
+
createProxy(): AOPProxyType<T>;
|
|
44
|
+
/**
|
|
45
|
+
* Intercept a specific method with AOP advice
|
|
46
|
+
*/
|
|
47
|
+
private interceptMethod;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Utility function to create AOP proxy with type safety
|
|
51
|
+
*/
|
|
52
|
+
export declare function createAOPProxy<T>(config: AOPConfig<T>): AOPProxyType<T>;
|
|
53
|
+
/**
|
|
54
|
+
* Utility function to apply advice to an existing object
|
|
55
|
+
*/
|
|
56
|
+
export declare function applyAdvice<T>(target: T, advice: {
|
|
57
|
+
[K in MethodName<T>]?: MethodAdvice<T, K>;
|
|
58
|
+
}, defaultAdvice?: MethodAdvice<T, MethodName<T>>): AOPProxyType<T>;
|
package/utils/aop.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* AOP (Aspect-Oriented Programming) implementation similar to Java AOP
|
|
4
|
+
* Using Object.create, Object.getOwnPropertyNames, and Object.getPrototypeOf
|
|
5
|
+
*/
|
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
+
exports.AOPProxy = void 0;
|
|
8
|
+
exports.createAOPProxy = createAOPProxy;
|
|
9
|
+
exports.applyAdvice = applyAdvice;
|
|
10
|
+
class AOPProxy {
|
|
11
|
+
target;
|
|
12
|
+
advice;
|
|
13
|
+
defaultAdvice;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.target = config.target;
|
|
16
|
+
this.advice = config.advice;
|
|
17
|
+
this.defaultAdvice = config.defaultAdvice;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Get advice for a specific method
|
|
21
|
+
*/
|
|
22
|
+
getMethodAdvice(methodName) {
|
|
23
|
+
return this.advice[methodName] || this.defaultAdvice;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Collect all property names from the instance and its prototype chain
|
|
27
|
+
* (excluding Object.prototype). This allows intercepting prototype methods
|
|
28
|
+
* in addition to own instance methods.
|
|
29
|
+
*/
|
|
30
|
+
getAllMemberNames() {
|
|
31
|
+
const names = new Set();
|
|
32
|
+
// Own properties (instance fields and own methods)
|
|
33
|
+
Object.getOwnPropertyNames(this.target).forEach((name) => {
|
|
34
|
+
names.add(name);
|
|
35
|
+
});
|
|
36
|
+
// Prototype chain methods
|
|
37
|
+
let proto = Object.getPrototypeOf(this.target);
|
|
38
|
+
while (proto && proto !== Object.prototype) {
|
|
39
|
+
Object.getOwnPropertyNames(proto).forEach((name) => {
|
|
40
|
+
if (name !== 'constructor') {
|
|
41
|
+
names.add(name);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
proto = Object.getPrototypeOf(proto);
|
|
45
|
+
}
|
|
46
|
+
return Array.from(names);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Create a proxy object with AOP capabilities
|
|
50
|
+
*/
|
|
51
|
+
createProxy() {
|
|
52
|
+
const proxy = Object.create(Object.getPrototypeOf(this.target));
|
|
53
|
+
// Gather members from the instance and its prototype chain
|
|
54
|
+
const memberNames = this.getAllMemberNames();
|
|
55
|
+
memberNames.forEach((name) => {
|
|
56
|
+
const value = this.target[name];
|
|
57
|
+
const isFunction = typeof value === 'function';
|
|
58
|
+
if (isFunction) {
|
|
59
|
+
const methodAdvice = this.getMethodAdvice(name);
|
|
60
|
+
if (methodAdvice) {
|
|
61
|
+
// 只拦截有 advice 的方法,其他方法保持原型链结构
|
|
62
|
+
this.interceptMethod(proxy, name, methodAdvice);
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
// 对于没有 advice 的方法,创建一个委托到原始实例的包装器
|
|
66
|
+
Object.defineProperty(proxy, name, {
|
|
67
|
+
value: (...args) => {
|
|
68
|
+
return value.apply(this.target, args);
|
|
69
|
+
},
|
|
70
|
+
writable: true,
|
|
71
|
+
enumerable: true,
|
|
72
|
+
configurable: true
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
// 对于非函数属性,创建 getter/setter 来委托到原始实例
|
|
78
|
+
Object.defineProperty(proxy, name, {
|
|
79
|
+
get: () => this.target[name],
|
|
80
|
+
set: (newValue) => {
|
|
81
|
+
this.target[name] = newValue;
|
|
82
|
+
},
|
|
83
|
+
enumerable: true,
|
|
84
|
+
configurable: true
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
});
|
|
88
|
+
return proxy;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Intercept a specific method with AOP advice
|
|
92
|
+
*/
|
|
93
|
+
interceptMethod(proxy, methodName, methodAdvice) {
|
|
94
|
+
const originalMethod = this.target[methodName];
|
|
95
|
+
Object.defineProperty(proxy, methodName, {
|
|
96
|
+
value: (...args) => {
|
|
97
|
+
try {
|
|
98
|
+
// Before advice - 传递 proxy 作为 target 参数
|
|
99
|
+
if (methodAdvice.before) {
|
|
100
|
+
methodAdvice.before(methodName, proxy, ...args);
|
|
101
|
+
}
|
|
102
|
+
let result;
|
|
103
|
+
// Around advice - 传递绑定了原始目标上下文的原始方法
|
|
104
|
+
if (methodAdvice.around) {
|
|
105
|
+
// 创建一个包装函数,确保 originalMethod 使用 target 作为 this 上下文
|
|
106
|
+
// 使用 bind 来确保 this 上下文正确绑定
|
|
107
|
+
const wrappedOriginalMethod = originalMethod.bind(this.target);
|
|
108
|
+
result = methodAdvice.around(methodName, proxy, wrappedOriginalMethod, ...args);
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
// Execute original method with target as this context to ensure state consistency
|
|
113
|
+
result = originalMethod.apply(this.target, args);
|
|
114
|
+
}
|
|
115
|
+
// 检查结果是否是 Promise
|
|
116
|
+
if (result && typeof result.then === 'function') {
|
|
117
|
+
// 异步方法 - 使用 Promise 链处理
|
|
118
|
+
return result
|
|
119
|
+
.then((resolvedResult) => {
|
|
120
|
+
// After advice - 传递 proxy 作为 target 参数
|
|
121
|
+
if (methodAdvice.after) {
|
|
122
|
+
methodAdvice.after(methodName, proxy, resolvedResult, ...args);
|
|
123
|
+
}
|
|
124
|
+
// AfterReturn advice - 在方法返回之前执行
|
|
125
|
+
if (methodAdvice.afterReturn) {
|
|
126
|
+
methodAdvice.afterReturn(methodName, proxy, resolvedResult, ...args);
|
|
127
|
+
}
|
|
128
|
+
return resolvedResult;
|
|
129
|
+
})
|
|
130
|
+
.catch((error) => {
|
|
131
|
+
// Error advice - 传递 proxy 作为 target 参数
|
|
132
|
+
if (methodAdvice.onError) {
|
|
133
|
+
methodAdvice.onError(methodName, proxy, error, ...args);
|
|
134
|
+
}
|
|
135
|
+
throw error;
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
// 同步方法
|
|
140
|
+
// After advice - 传递 proxy 作为 target 参数
|
|
141
|
+
if (methodAdvice.after) {
|
|
142
|
+
methodAdvice.after(methodName, proxy, result, ...args);
|
|
143
|
+
}
|
|
144
|
+
// AfterReturn advice - 在方法返回之前执行
|
|
145
|
+
if (methodAdvice.afterReturn) {
|
|
146
|
+
methodAdvice.afterReturn(methodName, proxy, result, ...args);
|
|
147
|
+
}
|
|
148
|
+
return result;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
// Error advice - 传递 proxy 作为 target 参数
|
|
153
|
+
if (methodAdvice.onError) {
|
|
154
|
+
methodAdvice.onError(methodName, proxy, error, ...args);
|
|
155
|
+
}
|
|
156
|
+
throw error;
|
|
157
|
+
}
|
|
158
|
+
},
|
|
159
|
+
writable: true,
|
|
160
|
+
enumerable: true,
|
|
161
|
+
configurable: true
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
exports.AOPProxy = AOPProxy;
|
|
166
|
+
/**
|
|
167
|
+
* Utility function to create AOP proxy with type safety
|
|
168
|
+
*/
|
|
169
|
+
function createAOPProxy(config) {
|
|
170
|
+
const aopProxy = new AOPProxy(config);
|
|
171
|
+
return aopProxy.createProxy();
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Utility function to apply advice to an existing object
|
|
175
|
+
*/
|
|
176
|
+
function applyAdvice(target, advice, defaultAdvice) {
|
|
177
|
+
return createAOPProxy({ target, advice, defaultAdvice });
|
|
178
|
+
}
|
package/utils/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './aop';
|
package/utils/index.js
ADDED
|
@@ -0,0 +1,17 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./aop"), exports);
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LocalStorage = void 0;
|
|
4
|
+
const INTERCHAIN_KIT_STORAGE_KEY = 'interchain-kit-store';
|
|
5
|
+
class LocalStorage {
|
|
6
|
+
save(value) {
|
|
7
|
+
localStorage.setItem(INTERCHAIN_KIT_STORAGE_KEY, JSON.stringify(value));
|
|
8
|
+
}
|
|
9
|
+
load() {
|
|
10
|
+
return JSON.parse(localStorage.getItem(INTERCHAIN_KIT_STORAGE_KEY) || '{}');
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
exports.LocalStorage = LocalStorage;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { Chain } from '@chain-registry/types';
|
|
2
|
+
import { BaseWallet, OfflineAminoSigner, OfflineDirectSigner, SignType, WalletAccount, WalletManager, WalletState } from '@interchain-kit/core';
|
|
3
|
+
import { InterchainStore } from '../store';
|
|
4
|
+
export declare class ChainWalletStore extends BaseWallet {
|
|
5
|
+
networkWalletMap: Map<Chain['chainType'], BaseWallet>;
|
|
6
|
+
wallet: BaseWallet;
|
|
7
|
+
chain: Chain;
|
|
8
|
+
store: InterchainStore;
|
|
9
|
+
walletManager: WalletManager;
|
|
10
|
+
constructor(wallet: BaseWallet, chain: Chain, store: InterchainStore, walletManager: WalletManager);
|
|
11
|
+
get walletState(): WalletState;
|
|
12
|
+
get errorMessage(): string;
|
|
13
|
+
init(): Promise<void>;
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
disconnect(): Promise<void>;
|
|
16
|
+
refreshAccount(): Promise<void>;
|
|
17
|
+
getAccount(): Promise<WalletAccount>;
|
|
18
|
+
addSuggestChain(): Promise<void>;
|
|
19
|
+
getProvider(): Promise<any>;
|
|
20
|
+
getOfflineSigner(preferSignType?: SignType): Promise<OfflineAminoSigner | OfflineDirectSigner>;
|
|
21
|
+
getWalletOfType<T>(WalletClass: new (...args: any[]) => T): T;
|
|
22
|
+
}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ChainWalletStore = void 0;
|
|
4
|
+
const core_1 = require("@interchain-kit/core");
|
|
5
|
+
class ChainWalletStore extends core_1.BaseWallet {
|
|
6
|
+
networkWalletMap;
|
|
7
|
+
wallet;
|
|
8
|
+
chain;
|
|
9
|
+
store;
|
|
10
|
+
walletManager;
|
|
11
|
+
constructor(wallet, chain, store, walletManager) {
|
|
12
|
+
super(wallet.info);
|
|
13
|
+
this.wallet = wallet;
|
|
14
|
+
this.chain = chain;
|
|
15
|
+
this.store = store;
|
|
16
|
+
this.walletManager = walletManager;
|
|
17
|
+
}
|
|
18
|
+
get walletState() {
|
|
19
|
+
return this.store.getChainWalletState(this.chain.chainName, this.wallet.info.name)?.walletState || core_1.WalletState.NotExist;
|
|
20
|
+
}
|
|
21
|
+
get errorMessage() {
|
|
22
|
+
return this.store.getChainWalletState(this.chain.chainName, this.wallet.info.name)?.errorMessage || '';
|
|
23
|
+
}
|
|
24
|
+
async init() {
|
|
25
|
+
this.wallet.events.on('accountChanged', () => {
|
|
26
|
+
this.refreshAccount();
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
async connect() {
|
|
30
|
+
const chainWalletState = this.store.getChainWalletState(this.wallet.info.name, this.chain.chainName);
|
|
31
|
+
if (chainWalletState && chainWalletState.walletState === core_1.WalletState.NotExist) {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
}
|
|
34
|
+
if ((0, core_1.isInstanceOf)(this.wallet, core_1.WCWallet)) {
|
|
35
|
+
this.wallet.setOnPairingUriCreatedCallback((uri) => {
|
|
36
|
+
console.log('Callback called with uri:', uri);
|
|
37
|
+
this.store.setState({ walletConnectQRCodeUri: uri });
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Connecting });
|
|
42
|
+
await this.wallet.connect(this.chain.chainId);
|
|
43
|
+
const account = await this.getAccount();
|
|
44
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Connected, account });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Disconnected, errorMessage: error.message });
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
async disconnect() {
|
|
51
|
+
if ((0, core_1.isInstanceOf)(this.wallet, core_1.WCWallet)) {
|
|
52
|
+
this.wallet.events.on('disconnect', () => {
|
|
53
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Disconnected, account: undefined });
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await this.wallet.disconnect(this.chain.chainId);
|
|
58
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Disconnected, account: undefined, errorMessage: '' });
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
console.error(error);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async refreshAccount() {
|
|
65
|
+
try {
|
|
66
|
+
const account = await this.wallet.getAccount(this.chain.chainId);
|
|
67
|
+
console.log(this.wallet);
|
|
68
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { account });
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { walletState: core_1.WalletState.Disconnected, account: undefined, errorMessage: error.message });
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async getAccount() {
|
|
75
|
+
const existed = this.store.getChainWalletState(this.wallet.info.name, this.chain.chainName)?.account;
|
|
76
|
+
if (existed) {
|
|
77
|
+
return existed;
|
|
78
|
+
}
|
|
79
|
+
const account = await this.wallet.getAccount(this.chain.chainId);
|
|
80
|
+
this.store.updateChainWalletState(this.wallet.info.name, this.chain.chainName, { account });
|
|
81
|
+
return account;
|
|
82
|
+
}
|
|
83
|
+
addSuggestChain() {
|
|
84
|
+
return this.wallet.addSuggestChain(this.chain.chainId);
|
|
85
|
+
}
|
|
86
|
+
getProvider() {
|
|
87
|
+
return this.wallet.getProvider(this.chain.chainId);
|
|
88
|
+
}
|
|
89
|
+
async getOfflineSigner(preferSignType) {
|
|
90
|
+
const cosmosWallet = (0, core_1.getWalletByType)(this.wallet, core_1.CosmosWallet);
|
|
91
|
+
const preferredSignTypeFromSettings = this.walletManager.getPreferSignType(this.chain.chainName);
|
|
92
|
+
const account = await this.getAccount();
|
|
93
|
+
const aminoOfflineSigner = {
|
|
94
|
+
getAccounts: async () => [account],
|
|
95
|
+
signAmino: async (signer, signDoc) => {
|
|
96
|
+
return cosmosWallet.signAmino(this.chain.chainId, signer, signDoc, {});
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
const directOfflineSigner = {
|
|
100
|
+
getAccounts: async () => [account],
|
|
101
|
+
signDirect: async (signer, signDoc) => {
|
|
102
|
+
return cosmosWallet.signDirect(this.chain.chainId, signer, signDoc, {});
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
const signType = preferSignType || preferredSignTypeFromSettings;
|
|
106
|
+
if (account.isNanoLedger || signType === 'amino') {
|
|
107
|
+
return aminoOfflineSigner;
|
|
108
|
+
}
|
|
109
|
+
return directOfflineSigner;
|
|
110
|
+
}
|
|
111
|
+
getWalletOfType(WalletClass) {
|
|
112
|
+
return (0, core_1.getWalletByType)(this.wallet, WalletClass);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
exports.ChainWalletStore = ChainWalletStore;
|
|
@@ -0,0 +1,19 @@
|
|
|
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 __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./wallet-manager-store"), exports);
|
|
18
|
+
__exportStar(require("./wallet-store"), exports);
|
|
19
|
+
__exportStar(require("./chain-wallet-store"), exports);
|