@getpara/graz-connector 2.0.0-dev.10 → 2.0.0-dev.12
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connector.js +83 -46
- package/package.json +10 -17
- package/src/connector.ts +133 -47
package/dist/connector.js
CHANGED
|
@@ -38,23 +38,27 @@ class ParaOfflineSigner {
|
|
|
38
38
|
signDirect(signerAddress, signDoc) {
|
|
39
39
|
return __async(this, null, function* () {
|
|
40
40
|
if (this.chainId !== signDoc.chainId) {
|
|
41
|
-
throw new Error(`
|
|
41
|
+
throw new Error(`Chain ID mismatch: expected ${this.chainId}, got ${signDoc.chainId}`);
|
|
42
42
|
}
|
|
43
43
|
const accounts = yield this.getAccounts();
|
|
44
44
|
if (accounts.every((a) => a.address !== signerAddress)) {
|
|
45
|
-
throw new Error(`
|
|
45
|
+
throw new Error(`Signer address ${signerAddress} not found in wallet`);
|
|
46
46
|
}
|
|
47
47
|
const signer = new ParaProtoSigner(this.para, this.prefix, (yield this.wallet()).id);
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
48
|
+
try {
|
|
49
|
+
const result = yield signer.signDirect(signerAddress, signDoc);
|
|
50
|
+
return {
|
|
51
|
+
signed: {
|
|
52
|
+
bodyBytes: result.signed.bodyBytes,
|
|
53
|
+
authInfoBytes: result.signed.authInfoBytes,
|
|
54
|
+
chainId: result.signed.chainId,
|
|
55
|
+
accountNumber: result.signed.accountNumber
|
|
56
|
+
},
|
|
57
|
+
signature: result.signature
|
|
58
|
+
};
|
|
59
|
+
} catch (err) {
|
|
60
|
+
throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
61
|
+
}
|
|
58
62
|
});
|
|
59
63
|
}
|
|
60
64
|
}
|
|
@@ -64,7 +68,7 @@ class ParaGrazConnector {
|
|
|
64
68
|
this.chains = chains;
|
|
65
69
|
this.enabledChainIds = /* @__PURE__ */ new Set();
|
|
66
70
|
if (!(config == null ? void 0 : config.paraWeb)) {
|
|
67
|
-
throw new Error("
|
|
71
|
+
throw new Error("ParaWeb instance required in config");
|
|
68
72
|
}
|
|
69
73
|
this.events = config.events;
|
|
70
74
|
this.paraWebClient = config.paraWeb;
|
|
@@ -73,10 +77,10 @@ class ParaGrazConnector {
|
|
|
73
77
|
ensureChainEnabled(chainId) {
|
|
74
78
|
return __async(this, null, function* () {
|
|
75
79
|
if (!this.enabledChainIds.has(chainId)) {
|
|
76
|
-
throw new Error(`
|
|
80
|
+
throw new Error(`Chain ${chainId} not enabled. Call enable() first`);
|
|
77
81
|
}
|
|
78
82
|
if (!(yield this.paraWebClient.isFullyLoggedIn())) {
|
|
79
|
-
throw new Error("Para
|
|
83
|
+
throw new Error("Para wallet not authenticated");
|
|
80
84
|
}
|
|
81
85
|
});
|
|
82
86
|
}
|
|
@@ -86,8 +90,12 @@ class ParaGrazConnector {
|
|
|
86
90
|
let delay = 500;
|
|
87
91
|
const MAX_DELAY = 5e3;
|
|
88
92
|
while (true) {
|
|
89
|
-
if (yield this.paraWebClient.isFullyLoggedIn())
|
|
90
|
-
|
|
93
|
+
if (yield this.paraWebClient.isFullyLoggedIn()) {
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
if (Date.now() >= deadline) {
|
|
97
|
+
throw new Error(`Login timeout after ${timeoutMs / 1e3}s`);
|
|
98
|
+
}
|
|
91
99
|
yield new Promise((r) => setTimeout(r, delay));
|
|
92
100
|
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
93
101
|
}
|
|
@@ -100,8 +108,12 @@ class ParaGrazConnector {
|
|
|
100
108
|
const MAX_DELAY = 1e3;
|
|
101
109
|
while (true) {
|
|
102
110
|
const wallets = this.paraWebClient.getWalletsByType("COSMOS");
|
|
103
|
-
if (wallets.length)
|
|
104
|
-
|
|
111
|
+
if (wallets.length) {
|
|
112
|
+
return wallets;
|
|
113
|
+
}
|
|
114
|
+
if (Date.now() >= deadline) {
|
|
115
|
+
throw new Error("No Cosmos wallets found");
|
|
116
|
+
}
|
|
105
117
|
yield new Promise((r) => setTimeout(r, delay));
|
|
106
118
|
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
107
119
|
}
|
|
@@ -109,7 +121,9 @@ class ParaGrazConnector {
|
|
|
109
121
|
}
|
|
110
122
|
hasCosmosWallet() {
|
|
111
123
|
return __async(this, null, function* () {
|
|
112
|
-
|
|
124
|
+
const isLoggedIn = yield this.paraWebClient.isFullyLoggedIn();
|
|
125
|
+
const wallets = this.paraWebClient.getWalletsByType("COSMOS");
|
|
126
|
+
return isLoggedIn && wallets.length > 0;
|
|
113
127
|
});
|
|
114
128
|
}
|
|
115
129
|
enable(chainIdsInput) {
|
|
@@ -124,32 +138,45 @@ class ParaGrazConnector {
|
|
|
124
138
|
return;
|
|
125
139
|
}
|
|
126
140
|
if (!this.noModal) {
|
|
127
|
-
throw new Error("Modal
|
|
141
|
+
throw new Error("Modal not supported. Use @getpara/graz-integration or set noModal: true");
|
|
128
142
|
}
|
|
129
143
|
yield this.waitForLogin();
|
|
130
144
|
yield this.waitForAccounts();
|
|
131
145
|
(_d = (_c = this.events) == null ? void 0 : _c.onEnabled) == null ? void 0 : _d.call(_c, chainIds, this);
|
|
132
146
|
} catch (err) {
|
|
133
147
|
this.enabledChainIds = previousEnabled;
|
|
134
|
-
|
|
148
|
+
if (err instanceof Error) {
|
|
149
|
+
throw err;
|
|
150
|
+
}
|
|
151
|
+
throw new Error("Failed to enable Para wallet");
|
|
135
152
|
}
|
|
136
153
|
});
|
|
137
154
|
}
|
|
138
155
|
disconnect() {
|
|
139
156
|
return __async(this, null, function* () {
|
|
140
|
-
|
|
141
|
-
|
|
157
|
+
try {
|
|
158
|
+
yield this.paraWebClient.logout();
|
|
159
|
+
} catch (err) {
|
|
160
|
+
throw new Error("Disconnect failed");
|
|
161
|
+
} finally {
|
|
162
|
+
this.enabledChainIds.clear();
|
|
163
|
+
}
|
|
142
164
|
});
|
|
143
165
|
}
|
|
144
166
|
getFirstWallet() {
|
|
145
167
|
return __async(this, null, function* () {
|
|
146
|
-
|
|
147
|
-
|
|
168
|
+
try {
|
|
169
|
+
const [wallet] = yield this.waitForAccounts();
|
|
170
|
+
return wallet;
|
|
171
|
+
} catch (err) {
|
|
172
|
+
throw new Error("No Para wallet available");
|
|
173
|
+
}
|
|
148
174
|
});
|
|
149
175
|
}
|
|
150
176
|
getBech32Prefix(chainId) {
|
|
151
177
|
var _a, _b, _c;
|
|
152
|
-
|
|
178
|
+
const prefix = ((_c = (_b = (_a = this.chains) == null ? void 0 : _a.find((c) => c.chainId === chainId)) == null ? void 0 : _b.bech32Config) == null ? void 0 : _c.bech32PrefixAccAddr) || "cosmos";
|
|
179
|
+
return prefix;
|
|
153
180
|
}
|
|
154
181
|
getParaWebClient() {
|
|
155
182
|
return this.paraWebClient;
|
|
@@ -168,27 +195,36 @@ class ParaGrazConnector {
|
|
|
168
195
|
}
|
|
169
196
|
getKey(chainId) {
|
|
170
197
|
return __async(this, null, function* () {
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
198
|
+
try {
|
|
199
|
+
yield this.ensureChainEnabled(chainId);
|
|
200
|
+
const wallet = yield this.getFirstWallet();
|
|
201
|
+
const signer = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
202
|
+
const [account] = yield signer.getAccounts();
|
|
203
|
+
if (!account) {
|
|
204
|
+
throw new Error(`No Cosmos accounts for chain ${chainId}`);
|
|
205
|
+
}
|
|
206
|
+
return {
|
|
207
|
+
name: "Para Wallet",
|
|
208
|
+
algo: account.algo,
|
|
209
|
+
pubKey: account.pubkey,
|
|
210
|
+
address: fromBech32(account.address).data,
|
|
211
|
+
bech32Address: account.address,
|
|
212
|
+
isKeystone: false,
|
|
213
|
+
isNanoLedger: false
|
|
214
|
+
};
|
|
215
|
+
} catch (err) {
|
|
216
|
+
if (err instanceof Error) {
|
|
217
|
+
throw err;
|
|
218
|
+
}
|
|
219
|
+
throw new Error(`Failed to get key for chain ${chainId}`);
|
|
220
|
+
}
|
|
185
221
|
});
|
|
186
222
|
}
|
|
187
223
|
getOfflineSignerOnlyAmino(chainId) {
|
|
188
224
|
void this.ensureChainEnabled(chainId);
|
|
189
225
|
const wallet = this.paraWebClient.getWalletsByType("COSMOS")[0];
|
|
190
226
|
if (!wallet) {
|
|
191
|
-
throw new Error(
|
|
227
|
+
throw new Error("No Cosmos wallet for Amino signing");
|
|
192
228
|
}
|
|
193
229
|
return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
194
230
|
}
|
|
@@ -208,9 +244,10 @@ class ParaGrazConnector {
|
|
|
208
244
|
try {
|
|
209
245
|
const wallet = yield this.getFirstWallet();
|
|
210
246
|
const signerImpl = new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
211
|
-
|
|
247
|
+
const response = yield signerImpl.signAmino(signer, signDoc);
|
|
248
|
+
return response;
|
|
212
249
|
} catch (err) {
|
|
213
|
-
throw new Error(`
|
|
250
|
+
throw new Error(`Amino signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
214
251
|
}
|
|
215
252
|
});
|
|
216
253
|
}
|
|
@@ -238,7 +275,7 @@ class ParaGrazConnector {
|
|
|
238
275
|
signature: result.signature
|
|
239
276
|
};
|
|
240
277
|
} catch (err) {
|
|
241
|
-
throw new Error(`
|
|
278
|
+
throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
242
279
|
}
|
|
243
280
|
});
|
|
244
281
|
}
|
|
@@ -263,7 +300,7 @@ class ParaGrazConnector {
|
|
|
263
300
|
const response = yield this.signAmino(chainId, signer, signDoc);
|
|
264
301
|
return response.signature;
|
|
265
302
|
} catch (err) {
|
|
266
|
-
throw new Error(`
|
|
303
|
+
throw new Error(`Arbitrary signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
|
|
267
304
|
}
|
|
268
305
|
});
|
|
269
306
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpara/graz-connector",
|
|
3
|
-
"version": "2.0.0-dev.
|
|
3
|
+
"version": "2.0.0-dev.12",
|
|
4
4
|
"sideEffects": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,33 +11,26 @@
|
|
|
11
11
|
"typegen": "tsc --emitDeclarationOnly"
|
|
12
12
|
},
|
|
13
13
|
"dependencies": {
|
|
14
|
-
"@getpara/cosmjs-v0-integration": "2.0.0-alpha.
|
|
15
|
-
"@getpara/web-sdk": "2.0.0-alpha.
|
|
14
|
+
"@getpara/cosmjs-v0-integration": "~2.0.0-alpha.44",
|
|
15
|
+
"@getpara/web-sdk": "~2.0.0-alpha.44"
|
|
16
16
|
},
|
|
17
17
|
"devDependencies": {
|
|
18
18
|
"@cosmjs/amino": "^0.32.4",
|
|
19
|
-
"@cosmjs/cosmwasm-stargate": "^0.32.4",
|
|
20
19
|
"@cosmjs/encoding": "^0.32.4",
|
|
21
|
-
"@cosmjs/launchpad": "0.27.1",
|
|
22
20
|
"@cosmjs/proto-signing": "^0.32.4",
|
|
23
|
-
"@
|
|
24
|
-
"@cosmjs/tendermint-rpc": "^0.32.4",
|
|
25
|
-
"@keplr-wallet/types": "0.12.156",
|
|
21
|
+
"@keplr-wallet/types": "^0.12.156",
|
|
26
22
|
"cosmjs-types": "^0.9.0",
|
|
27
23
|
"graz": "^0.3.3",
|
|
28
|
-
"long": "5.3.2",
|
|
29
24
|
"typescript": "5.1.6"
|
|
30
25
|
},
|
|
31
26
|
"peerDependencies": {
|
|
32
|
-
"@cosmjs/amino": "
|
|
33
|
-
"@cosmjs/
|
|
34
|
-
"@cosmjs/
|
|
35
|
-
"@cosmjs/
|
|
36
|
-
"@cosmjs/
|
|
37
|
-
"@cosmjs/stargate": "*",
|
|
38
|
-
"@cosmjs/tendermint-rpc": "*",
|
|
27
|
+
"@cosmjs/amino": ">=0.32.4",
|
|
28
|
+
"@cosmjs/encoding": ">=0.32.4",
|
|
29
|
+
"@cosmjs/proto-signing": ">=0.32.4",
|
|
30
|
+
"@cosmjs/stargate": ">=0.32.4",
|
|
31
|
+
"@cosmjs/tendermint-rpc": ">=0.32.4",
|
|
39
32
|
"@keplr-wallet/types": ">=0.12.156",
|
|
40
|
-
"cosmjs-types": ">=0.
|
|
33
|
+
"cosmjs-types": ">=0.9.0",
|
|
41
34
|
"graz": ">=0.3.3"
|
|
42
35
|
}
|
|
43
36
|
}
|
package/src/connector.ts
CHANGED
|
@@ -26,15 +26,19 @@ class ParaOfflineSigner implements OfflineDirectSigner {
|
|
|
26
26
|
protected readonly chainId: string,
|
|
27
27
|
protected readonly connector: ParaGrazConnector,
|
|
28
28
|
) {}
|
|
29
|
+
|
|
29
30
|
protected get para() {
|
|
30
31
|
return this.connector.getParaWebClient();
|
|
31
32
|
}
|
|
33
|
+
|
|
32
34
|
protected get prefix() {
|
|
33
35
|
return this.connector.getBech32Prefix(this.chainId);
|
|
34
36
|
}
|
|
37
|
+
|
|
35
38
|
protected async wallet() {
|
|
36
39
|
return this.connector.getFirstWallet();
|
|
37
40
|
}
|
|
41
|
+
|
|
38
42
|
async getAccounts(): Promise<readonly AccountData[]> {
|
|
39
43
|
const key = await this.connector.getKey(this.chainId);
|
|
40
44
|
return [
|
|
@@ -45,25 +49,33 @@ class ParaOfflineSigner implements OfflineDirectSigner {
|
|
|
45
49
|
},
|
|
46
50
|
];
|
|
47
51
|
}
|
|
52
|
+
|
|
48
53
|
async signDirect(signerAddress: string, signDoc: SignDoc): Promise<DirectSignResponse> {
|
|
49
54
|
if (this.chainId !== signDoc.chainId) {
|
|
50
|
-
throw new Error(`
|
|
55
|
+
throw new Error(`Chain ID mismatch: expected ${this.chainId}, got ${signDoc.chainId}`);
|
|
51
56
|
}
|
|
57
|
+
|
|
52
58
|
const accounts = await this.getAccounts();
|
|
53
59
|
if (accounts.every(a => a.address !== signerAddress)) {
|
|
54
|
-
throw new Error(`
|
|
60
|
+
throw new Error(`Signer address ${signerAddress} not found in wallet`);
|
|
55
61
|
}
|
|
62
|
+
|
|
56
63
|
const signer = new ParaProtoSigner(this.para, this.prefix, (await this.wallet()).id);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const result = await signer.signDirect(signerAddress, signDoc);
|
|
67
|
+
return {
|
|
68
|
+
signed: {
|
|
69
|
+
bodyBytes: result.signed.bodyBytes,
|
|
70
|
+
authInfoBytes: result.signed.authInfoBytes,
|
|
71
|
+
chainId: result.signed.chainId,
|
|
72
|
+
accountNumber: result.signed.accountNumber,
|
|
73
|
+
},
|
|
74
|
+
signature: result.signature,
|
|
75
|
+
};
|
|
76
|
+
} catch (err) {
|
|
77
|
+
throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
78
|
+
}
|
|
67
79
|
}
|
|
68
80
|
}
|
|
69
81
|
|
|
@@ -72,32 +84,43 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
72
84
|
protected enabledChainIds = new Set<string>();
|
|
73
85
|
protected readonly events?: ParaGrazConnectorEvents;
|
|
74
86
|
protected noModal?: boolean;
|
|
87
|
+
|
|
75
88
|
constructor(
|
|
76
89
|
protected readonly config: ParaGrazConfig,
|
|
77
90
|
protected readonly chains: ChainInfo[] | null = null,
|
|
78
91
|
) {
|
|
79
92
|
if (!config?.paraWeb) {
|
|
80
|
-
throw new Error('
|
|
93
|
+
throw new Error('ParaWeb instance required in config');
|
|
81
94
|
}
|
|
82
95
|
this.events = config.events;
|
|
83
96
|
this.paraWebClient = config.paraWeb;
|
|
84
97
|
this.noModal = config.noModal;
|
|
85
98
|
}
|
|
99
|
+
|
|
86
100
|
protected async ensureChainEnabled(chainId: string): Promise<void> {
|
|
87
101
|
if (!this.enabledChainIds.has(chainId)) {
|
|
88
|
-
throw new Error(`
|
|
102
|
+
throw new Error(`Chain ${chainId} not enabled. Call enable() first`);
|
|
89
103
|
}
|
|
104
|
+
|
|
90
105
|
if (!(await this.paraWebClient.isFullyLoggedIn())) {
|
|
91
|
-
throw new Error('Para
|
|
106
|
+
throw new Error('Para wallet not authenticated');
|
|
92
107
|
}
|
|
93
108
|
}
|
|
109
|
+
|
|
94
110
|
protected async waitForLogin(timeoutMs = 60_000): Promise<void> {
|
|
95
111
|
const deadline = Date.now() + timeoutMs;
|
|
96
112
|
let delay = 500;
|
|
97
113
|
const MAX_DELAY = 5_000;
|
|
114
|
+
|
|
98
115
|
while (true) {
|
|
99
|
-
if (await this.paraWebClient.isFullyLoggedIn())
|
|
100
|
-
|
|
116
|
+
if (await this.paraWebClient.isFullyLoggedIn()) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
if (Date.now() >= deadline) {
|
|
121
|
+
throw new Error(`Login timeout after ${timeoutMs / 1000}s`);
|
|
122
|
+
}
|
|
123
|
+
|
|
101
124
|
await new Promise(r => setTimeout(r, delay));
|
|
102
125
|
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
103
126
|
}
|
|
@@ -107,55 +130,90 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
107
130
|
const deadline = Date.now() + timeoutMs;
|
|
108
131
|
let delay = 250;
|
|
109
132
|
const MAX_DELAY = 1_000;
|
|
133
|
+
|
|
110
134
|
while (true) {
|
|
111
135
|
const wallets = this.paraWebClient.getWalletsByType('COSMOS');
|
|
112
|
-
if (wallets.length)
|
|
113
|
-
|
|
136
|
+
if (wallets.length) {
|
|
137
|
+
return wallets;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (Date.now() >= deadline) {
|
|
141
|
+
throw new Error('No Cosmos wallets found');
|
|
142
|
+
}
|
|
143
|
+
|
|
114
144
|
await new Promise(r => setTimeout(r, delay));
|
|
115
145
|
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
116
146
|
}
|
|
117
147
|
}
|
|
148
|
+
|
|
118
149
|
protected async hasCosmosWallet(): Promise<boolean> {
|
|
119
|
-
|
|
150
|
+
const isLoggedIn = await this.paraWebClient.isFullyLoggedIn();
|
|
151
|
+
const wallets = this.paraWebClient.getWalletsByType('COSMOS');
|
|
152
|
+
return isLoggedIn && wallets.length > 0;
|
|
120
153
|
}
|
|
154
|
+
|
|
121
155
|
async enable(chainIdsInput: string | string[]): Promise<void> {
|
|
122
156
|
const chainIds = toArray(chainIdsInput);
|
|
123
157
|
const previousEnabled = new Set(this.enabledChainIds);
|
|
158
|
+
|
|
124
159
|
try {
|
|
125
160
|
chainIds.forEach(id => this.enabledChainIds.add(id));
|
|
161
|
+
|
|
126
162
|
if (await this.hasCosmosWallet()) {
|
|
127
163
|
this.events?.onEnabled?.(chainIds, this);
|
|
128
164
|
return;
|
|
129
165
|
}
|
|
166
|
+
|
|
130
167
|
if (!this.noModal) {
|
|
131
|
-
throw new Error('Modal
|
|
168
|
+
throw new Error('Modal not supported. Use @getpara/graz-integration or set noModal: true');
|
|
132
169
|
}
|
|
170
|
+
|
|
133
171
|
await this.waitForLogin();
|
|
134
172
|
await this.waitForAccounts();
|
|
135
173
|
this.events?.onEnabled?.(chainIds, this);
|
|
136
174
|
} catch (err) {
|
|
137
175
|
this.enabledChainIds = previousEnabled;
|
|
138
|
-
|
|
176
|
+
|
|
177
|
+
if (err instanceof Error) {
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
throw new Error('Failed to enable Para wallet');
|
|
139
182
|
}
|
|
140
183
|
}
|
|
141
184
|
|
|
142
185
|
async disconnect(): Promise<void> {
|
|
143
|
-
|
|
144
|
-
|
|
186
|
+
try {
|
|
187
|
+
await this.paraWebClient.logout();
|
|
188
|
+
} catch (err) {
|
|
189
|
+
throw new Error('Disconnect failed');
|
|
190
|
+
} finally {
|
|
191
|
+
this.enabledChainIds.clear();
|
|
192
|
+
}
|
|
145
193
|
}
|
|
194
|
+
|
|
146
195
|
async getFirstWallet(): Promise<ParaWallet> {
|
|
147
|
-
|
|
148
|
-
|
|
196
|
+
try {
|
|
197
|
+
const [wallet] = await this.waitForAccounts();
|
|
198
|
+
return wallet;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
throw new Error('No Para wallet available');
|
|
201
|
+
}
|
|
149
202
|
}
|
|
203
|
+
|
|
150
204
|
getBech32Prefix(chainId: string): string {
|
|
151
|
-
|
|
205
|
+
const prefix = this.chains?.find(c => c.chainId === chainId)?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
|
|
206
|
+
return prefix;
|
|
152
207
|
}
|
|
208
|
+
|
|
153
209
|
getParaWebClient(): ParaWeb {
|
|
154
210
|
return this.paraWebClient;
|
|
155
211
|
}
|
|
212
|
+
|
|
156
213
|
getConfig(): ParaGrazConfig {
|
|
157
214
|
return this.config;
|
|
158
215
|
}
|
|
216
|
+
|
|
159
217
|
protected buildHybridSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
160
218
|
const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
|
|
161
219
|
const directSigner = new ParaOfflineSigner(chainId, this);
|
|
@@ -165,38 +223,57 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
165
223
|
signDirect: (signer: string, signDoc: SignDoc) => directSigner.signDirect(signer, signDoc),
|
|
166
224
|
} as unknown as OfflineAminoSigner & OfflineDirectSigner;
|
|
167
225
|
}
|
|
226
|
+
|
|
168
227
|
async getKey(chainId: string) {
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
228
|
+
try {
|
|
229
|
+
await this.ensureChainEnabled(chainId);
|
|
230
|
+
const wallet = await this.getFirstWallet();
|
|
231
|
+
const signer = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
232
|
+
const [account] = await signer.getAccounts();
|
|
233
|
+
|
|
234
|
+
if (!account) {
|
|
235
|
+
throw new Error(`No Cosmos accounts for chain ${chainId}`);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
name: 'Para Wallet',
|
|
240
|
+
algo: account.algo,
|
|
241
|
+
pubKey: account.pubkey,
|
|
242
|
+
address: fromBech32(account.address).data,
|
|
243
|
+
bech32Address: account.address,
|
|
244
|
+
isKeystone: false,
|
|
245
|
+
isNanoLedger: false,
|
|
246
|
+
};
|
|
247
|
+
} catch (err) {
|
|
248
|
+
if (err instanceof Error) {
|
|
249
|
+
throw err;
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
throw new Error(`Failed to get key for chain ${chainId}`);
|
|
253
|
+
}
|
|
183
254
|
}
|
|
255
|
+
|
|
184
256
|
getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
|
|
185
|
-
void this.ensureChainEnabled(chainId);
|
|
257
|
+
void this.ensureChainEnabled(chainId);
|
|
186
258
|
const wallet = this.paraWebClient.getWalletsByType('COSMOS')[0];
|
|
259
|
+
|
|
187
260
|
if (!wallet) {
|
|
188
|
-
throw new Error(
|
|
261
|
+
throw new Error('No Cosmos wallet for Amino signing');
|
|
189
262
|
}
|
|
263
|
+
|
|
190
264
|
return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
191
265
|
}
|
|
266
|
+
|
|
192
267
|
getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
193
268
|
void this.ensureChainEnabled(chainId);
|
|
194
269
|
return this.buildHybridSigner(chainId);
|
|
195
270
|
}
|
|
271
|
+
|
|
196
272
|
async getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
|
|
197
273
|
void this.ensureChainEnabled(chainId);
|
|
198
274
|
return this.buildHybridSigner(chainId);
|
|
199
275
|
}
|
|
276
|
+
|
|
200
277
|
async signAmino(
|
|
201
278
|
chainId: string,
|
|
202
279
|
signer: string,
|
|
@@ -204,14 +281,17 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
204
281
|
_signOptions?: KeplrSignOptions,
|
|
205
282
|
): Promise<AminoSignResponse> {
|
|
206
283
|
await this.ensureChainEnabled(chainId);
|
|
284
|
+
|
|
207
285
|
try {
|
|
208
286
|
const wallet = await this.getFirstWallet();
|
|
209
287
|
const signerImpl = new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
210
|
-
|
|
288
|
+
const response = await signerImpl.signAmino(signer, signDoc);
|
|
289
|
+
return response;
|
|
211
290
|
} catch (err) {
|
|
212
|
-
throw new Error(`
|
|
291
|
+
throw new Error(`Amino signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
213
292
|
}
|
|
214
293
|
}
|
|
294
|
+
|
|
215
295
|
async signDirect(
|
|
216
296
|
chainId: string,
|
|
217
297
|
signer: string,
|
|
@@ -219,6 +299,7 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
219
299
|
_signOptions?: KeplrSignOptions,
|
|
220
300
|
): Promise<DirectSignResponse> {
|
|
221
301
|
await this.ensureChainEnabled(chainId);
|
|
302
|
+
|
|
222
303
|
try {
|
|
223
304
|
const wallet = await this.getFirstWallet();
|
|
224
305
|
const signerImpl = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
@@ -228,6 +309,7 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
228
309
|
chainId: signDoc.chainId,
|
|
229
310
|
accountNumber: typeof signDoc.accountNumber === 'bigint' ? signDoc.accountNumber : BigInt(signDoc.accountNumber),
|
|
230
311
|
};
|
|
312
|
+
|
|
231
313
|
const result = await signerImpl.signDirect(signer, convertedSignDoc);
|
|
232
314
|
return {
|
|
233
315
|
signed: {
|
|
@@ -239,13 +321,16 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
239
321
|
signature: result.signature,
|
|
240
322
|
};
|
|
241
323
|
} catch (err) {
|
|
242
|
-
throw new Error(`
|
|
324
|
+
throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
243
325
|
}
|
|
244
326
|
}
|
|
327
|
+
|
|
245
328
|
async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
|
|
246
329
|
await this.ensureChainEnabled(chainId);
|
|
330
|
+
|
|
247
331
|
const encodedData =
|
|
248
332
|
typeof data === 'string' ? Buffer.from(data, 'utf-8').toString('base64') : Buffer.from(data).toString('base64');
|
|
333
|
+
|
|
249
334
|
const signDoc = {
|
|
250
335
|
chain_id: '',
|
|
251
336
|
account_number: '0',
|
|
@@ -259,11 +344,12 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
259
344
|
],
|
|
260
345
|
memo: '',
|
|
261
346
|
};
|
|
347
|
+
|
|
262
348
|
try {
|
|
263
349
|
const response = await this.signAmino(chainId, signer, signDoc);
|
|
264
350
|
return response.signature;
|
|
265
351
|
} catch (err) {
|
|
266
|
-
throw new Error(`
|
|
352
|
+
throw new Error(`Arbitrary signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
267
353
|
}
|
|
268
354
|
}
|
|
269
355
|
}
|