@getpara/graz-connector 0.1.0-alpha.6 → 2.0.0-alpha.50
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/chunk-M66XENHI.js +25 -0
- package/dist/connector.d.ts +32 -35
- package/dist/connector.js +221 -214
- package/dist/index.d.ts +1 -2
- package/dist/index.js +3 -8
- package/package.json +27 -15
- package/src/connector.ts +247 -262
- package/src/index.ts +1 -2
- package/tsconfig.json +3 -3
- package/dist/chunk-IV3L3JVM.js +0 -46
- package/dist/connectorModal.d.ts +0 -2
- package/dist/connectorModal.js +0 -36
- package/src/connectorModal.tsx +0 -32
package/package.json
CHANGED
|
@@ -1,25 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getpara/graz-connector",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "2.0.0-alpha.50",
|
|
4
|
+
"sideEffects": false,
|
|
4
5
|
"type": "module",
|
|
5
6
|
"main": "dist/index.js",
|
|
6
7
|
"types": "dist/index.d.ts",
|
|
7
|
-
"sideEffects": false,
|
|
8
|
-
"dependencies": {
|
|
9
|
-
"@getpara/react-sdk": "1.11.0",
|
|
10
|
-
"@getpara/cosmjs-v0-integration": "1.11.0"
|
|
11
|
-
},
|
|
12
8
|
"scripts": {
|
|
13
|
-
"
|
|
14
|
-
"
|
|
9
|
+
"typegen": "tsc --emitDeclarationOnly",
|
|
10
|
+
"build": "rm -rf dist && yarn typegen && node ./scripts/build.mjs"
|
|
11
|
+
},
|
|
12
|
+
"dependencies": {
|
|
13
|
+
"@getpara/cosmjs-v0-integration": "2.0.0-alpha.50",
|
|
14
|
+
"@getpara/web-sdk": "2.0.0-alpha.50"
|
|
15
15
|
},
|
|
16
16
|
"devDependencies": {
|
|
17
|
-
"@cosmjs/amino": "^0.32.
|
|
18
|
-
"@cosmjs/encoding": "^0.32.
|
|
19
|
-
"@cosmjs/proto-signing": "^0.32.
|
|
20
|
-
"cosmjs
|
|
21
|
-
"
|
|
22
|
-
"
|
|
23
|
-
"
|
|
17
|
+
"@cosmjs/amino": "^0.32.4",
|
|
18
|
+
"@cosmjs/encoding": "^0.32.4",
|
|
19
|
+
"@cosmjs/proto-signing": "^0.32.4",
|
|
20
|
+
"@cosmjs/stargate": "^0.32.4",
|
|
21
|
+
"@cosmjs/tendermint-rpc": "^0.32.4",
|
|
22
|
+
"@keplr-wallet/types": "^0.12.156",
|
|
23
|
+
"cosmjs-types": "^0.9.0",
|
|
24
|
+
"graz": "^0.3.3",
|
|
25
|
+
"typescript": "5.1.6"
|
|
26
|
+
},
|
|
27
|
+
"peerDependencies": {
|
|
28
|
+
"@cosmjs/amino": ">=0.32.4",
|
|
29
|
+
"@cosmjs/encoding": ">=0.32.4",
|
|
30
|
+
"@cosmjs/proto-signing": ">=0.32.4",
|
|
31
|
+
"@cosmjs/stargate": ">=0.32.4",
|
|
32
|
+
"@cosmjs/tendermint-rpc": ">=0.32.4",
|
|
33
|
+
"@keplr-wallet/types": ">=0.12.156",
|
|
34
|
+
"cosmjs-types": ">=0.8.0",
|
|
35
|
+
"graz": ">=0.3.3"
|
|
24
36
|
}
|
|
25
37
|
}
|
package/src/connector.ts
CHANGED
|
@@ -1,153 +1,211 @@
|
|
|
1
|
-
import ParaWeb from '@getpara/react-sdk';
|
|
2
|
-
import type { Environment, ParaModalProps } from '@getpara/react-sdk';
|
|
3
|
-
import type { Wallet, Key as GrazKey } from 'graz';
|
|
4
|
-
import { getChainInfo } from 'graz';
|
|
5
|
-
import type {
|
|
6
|
-
OfflineAminoSigner,
|
|
7
|
-
OfflineDirectSigner,
|
|
8
|
-
AminoSignResponse,
|
|
9
|
-
StdSignDoc,
|
|
10
|
-
StdSignature,
|
|
11
|
-
DirectSignResponse,
|
|
12
|
-
AccountData,
|
|
13
|
-
Algo,
|
|
14
|
-
SignDoc as KeplrSignDoc,
|
|
15
|
-
SignDoc,
|
|
16
|
-
} from '@keplr-wallet/types';
|
|
17
|
-
import { ParaAminoSigner, ParaProtoSigner } from '@getpara/cosmjs-v0-integration';
|
|
18
1
|
import { fromBech32 } from '@cosmjs/encoding';
|
|
19
|
-
import {
|
|
20
|
-
import
|
|
2
|
+
import { SignDoc } from 'cosmjs-types/cosmos/tx/v1beta1/tx.js';
|
|
3
|
+
import { Wallet, SignDoc as GrazSignDoc, Key } from 'graz';
|
|
4
|
+
import { ParaAminoSigner, ParaProtoSigner } from '@getpara/cosmjs-v0-integration';
|
|
5
|
+
import { ParaWeb, Wallet as ParaWallet } from '@getpara/web-sdk';
|
|
6
|
+
import { Algo, DirectSignResponse, OfflineDirectSigner } from '@cosmjs/proto-signing';
|
|
7
|
+
import { AccountData, AminoSignResponse, OfflineAminoSigner, StdSignature, StdSignDoc } from '@cosmjs/amino';
|
|
8
|
+
import { ChainInfo, KeplrSignOptions } from '@keplr-wallet/types';
|
|
21
9
|
|
|
22
|
-
|
|
10
|
+
export type ParaGrazConnectorEvents = {
|
|
11
|
+
onEnabled?: (chainIds: string[], connector: ParaGrazConnector) => void;
|
|
12
|
+
};
|
|
23
13
|
|
|
24
14
|
export interface ParaGrazConfig {
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
15
|
+
paraWeb: ParaWeb;
|
|
16
|
+
events?: ParaGrazConnectorEvents;
|
|
17
|
+
noModal?: boolean;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export function toArray<T>(v: T | T[]): T[] {
|
|
21
|
+
return Array.isArray(v) ? v : [v];
|
|
28
22
|
}
|
|
29
23
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
class ParaOfflineSigner implements OfflineDirectSigner {
|
|
25
|
+
constructor(
|
|
26
|
+
protected readonly chainId: string,
|
|
27
|
+
protected readonly connector: ParaGrazConnector,
|
|
28
|
+
) {}
|
|
29
|
+
|
|
30
|
+
protected get para() {
|
|
31
|
+
return this.connector.getParaWebClient();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
protected get prefix() {
|
|
35
|
+
return this.connector.getBech32Prefix(this.chainId);
|
|
36
|
+
}
|
|
33
37
|
|
|
34
|
-
|
|
35
|
-
this.
|
|
36
|
-
this.paraWebClient = paraWebClient;
|
|
38
|
+
protected async wallet() {
|
|
39
|
+
return this.connector.getFirstWallet();
|
|
37
40
|
}
|
|
38
41
|
|
|
39
42
|
async getAccounts(): Promise<readonly AccountData[]> {
|
|
40
|
-
const key = await getKey(this.
|
|
43
|
+
const key = await this.connector.getKey(this.chainId);
|
|
41
44
|
return [
|
|
42
45
|
{
|
|
43
|
-
address: key.
|
|
46
|
+
address: key.bech32Address,
|
|
44
47
|
algo: key.algo as Algo,
|
|
45
|
-
pubkey: key.
|
|
48
|
+
pubkey: key.pubKey,
|
|
46
49
|
},
|
|
47
50
|
];
|
|
48
51
|
}
|
|
49
52
|
|
|
50
|
-
async signDirect(signerAddress: string, signDoc:
|
|
53
|
+
async signDirect(signerAddress: string, signDoc: SignDoc): Promise<DirectSignResponse> {
|
|
51
54
|
if (this.chainId !== signDoc.chainId) {
|
|
52
|
-
throw new Error(
|
|
55
|
+
throw new Error(`Chain ID mismatch: expected ${this.chainId}, got ${signDoc.chainId}`);
|
|
53
56
|
}
|
|
54
57
|
|
|
55
58
|
const accounts = await this.getAccounts();
|
|
56
|
-
if (accounts.
|
|
57
|
-
throw new Error(
|
|
59
|
+
if (accounts.every(a => a.address !== signerAddress)) {
|
|
60
|
+
throw new Error(`Signer address ${signerAddress} not found in wallet`);
|
|
58
61
|
}
|
|
59
62
|
|
|
60
|
-
const
|
|
61
|
-
bodyBytes: signDoc.bodyBytes,
|
|
62
|
-
authInfoBytes: signDoc.authInfoBytes,
|
|
63
|
-
chainId: signDoc.chainId,
|
|
64
|
-
accountNumber: typeof signDoc.accountNumber === 'string' ? signDoc.accountNumber : signDoc.accountNumber.toString(),
|
|
65
|
-
};
|
|
66
|
-
|
|
67
|
-
const result = await requestSignature(this.paraWebClient, this.chainId, signerAddress, convertedSignDoc);
|
|
63
|
+
const signer = new ParaProtoSigner(this.para, this.prefix, (await this.wallet()).id);
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
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
|
+
}
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
81
|
|
|
81
82
|
export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
83
|
+
protected paraWebClient: ParaWeb;
|
|
84
|
+
protected enabledChainIds = new Set<string>();
|
|
85
|
+
protected readonly events?: ParaGrazConnectorEvents;
|
|
86
|
+
protected noModal?: boolean;
|
|
87
|
+
|
|
88
|
+
constructor(
|
|
89
|
+
protected readonly config: ParaGrazConfig,
|
|
90
|
+
protected readonly chains: ChainInfo[] | null = null,
|
|
91
|
+
) {
|
|
92
|
+
if (!config?.paraWeb) {
|
|
93
|
+
throw new Error('ParaWeb instance required in config');
|
|
94
|
+
}
|
|
95
|
+
this.events = config.events;
|
|
96
|
+
this.paraWebClient = config.paraWeb;
|
|
97
|
+
this.noModal = config.noModal;
|
|
98
|
+
}
|
|
85
99
|
|
|
86
|
-
|
|
87
|
-
if (!
|
|
88
|
-
throw new Error(
|
|
100
|
+
protected async ensureChainEnabled(chainId: string): Promise<void> {
|
|
101
|
+
if (!this.enabledChainIds.has(chainId)) {
|
|
102
|
+
throw new Error(`Chain ${chainId} not enabled. Call enable() first`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
if (!(await this.paraWebClient.isFullyLoggedIn())) {
|
|
106
|
+
throw new Error('Para wallet not authenticated');
|
|
89
107
|
}
|
|
90
|
-
this.config = config;
|
|
91
|
-
this.paraWebClient = new ParaWeb(config.env, config.apiKey);
|
|
92
|
-
this.isModalClosed = true;
|
|
93
108
|
}
|
|
94
109
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
110
|
+
protected async waitForLogin(timeoutMs = 60_000): Promise<void> {
|
|
111
|
+
const deadline = Date.now() + timeoutMs;
|
|
112
|
+
let delay = 500;
|
|
113
|
+
const MAX_DELAY = 5_000;
|
|
98
114
|
|
|
99
|
-
|
|
100
|
-
const startTime = Date.now();
|
|
101
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
115
|
+
while (true) {
|
|
102
116
|
if (await this.paraWebClient.isFullyLoggedIn()) {
|
|
103
|
-
return
|
|
117
|
+
return;
|
|
104
118
|
}
|
|
105
119
|
|
|
106
|
-
if (
|
|
107
|
-
throw new Error(
|
|
120
|
+
if (Date.now() >= deadline) {
|
|
121
|
+
throw new Error(`Login timeout after ${timeoutMs / 1000}s`);
|
|
108
122
|
}
|
|
109
123
|
|
|
110
|
-
await new Promise(
|
|
124
|
+
await new Promise(r => setTimeout(r, delay));
|
|
125
|
+
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
111
126
|
}
|
|
112
|
-
|
|
113
|
-
throw new Error('timed out waiting for user to log in');
|
|
114
127
|
}
|
|
115
128
|
|
|
116
|
-
|
|
117
|
-
const
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
129
|
+
protected async waitForAccounts(timeoutMs = 5_000): Promise<ParaWallet[]> {
|
|
130
|
+
const deadline = Date.now() + timeoutMs;
|
|
131
|
+
let delay = 250;
|
|
132
|
+
const MAX_DELAY = 1_000;
|
|
133
|
+
|
|
134
|
+
while (true) {
|
|
135
|
+
const wallets = this.paraWebClient.getWalletsByType('COSMOS');
|
|
136
|
+
if (wallets.length) {
|
|
137
|
+
return wallets;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (Date.now() >= deadline) {
|
|
141
|
+
throw new Error('No Cosmos wallets found');
|
|
122
142
|
}
|
|
123
|
-
|
|
143
|
+
|
|
144
|
+
await new Promise(r => setTimeout(r, delay));
|
|
145
|
+
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
124
146
|
}
|
|
147
|
+
}
|
|
125
148
|
|
|
126
|
-
|
|
149
|
+
protected async hasCosmosWallet(): Promise<boolean> {
|
|
150
|
+
const isLoggedIn = await this.paraWebClient.isFullyLoggedIn();
|
|
151
|
+
const wallets = this.paraWebClient.getWalletsByType('COSMOS');
|
|
152
|
+
return isLoggedIn && wallets.length > 0;
|
|
127
153
|
}
|
|
128
154
|
|
|
129
|
-
async enable(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
155
|
+
async enable(chainIdsInput: string | string[]): Promise<void> {
|
|
156
|
+
const chainIds = toArray(chainIdsInput);
|
|
157
|
+
const previousEnabled = new Set(this.enabledChainIds);
|
|
158
|
+
|
|
159
|
+
try {
|
|
160
|
+
chainIds.forEach(id => this.enabledChainIds.add(id));
|
|
161
|
+
|
|
162
|
+
if (await this.hasCosmosWallet()) {
|
|
163
|
+
this.events?.onEnabled?.(chainIds, this);
|
|
133
164
|
return;
|
|
134
165
|
}
|
|
135
|
-
}
|
|
136
166
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
167
|
+
if (!this.noModal) {
|
|
168
|
+
throw new Error('Modal not supported. Use @getpara/graz-integration or set noModal: true');
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
await this.waitForLogin();
|
|
172
|
+
await this.waitForAccounts();
|
|
173
|
+
this.events?.onEnabled?.(chainIds, this);
|
|
174
|
+
} catch (err) {
|
|
175
|
+
this.enabledChainIds = previousEnabled;
|
|
176
|
+
|
|
177
|
+
if (err instanceof Error) {
|
|
178
|
+
throw err;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
throw new Error('Failed to enable Para wallet');
|
|
182
|
+
}
|
|
183
|
+
}
|
|
141
184
|
|
|
142
|
-
|
|
185
|
+
async disconnect(): Promise<void> {
|
|
186
|
+
try {
|
|
187
|
+
await this.paraWebClient.logout();
|
|
188
|
+
} catch (err) {
|
|
189
|
+
throw new Error('Disconnect failed');
|
|
190
|
+
} finally {
|
|
191
|
+
this.enabledChainIds.clear();
|
|
192
|
+
}
|
|
193
|
+
}
|
|
143
194
|
|
|
195
|
+
async getFirstWallet(): Promise<ParaWallet> {
|
|
144
196
|
try {
|
|
145
|
-
await this.waitForAccounts(
|
|
146
|
-
|
|
147
|
-
|
|
197
|
+
const [wallet] = await this.waitForAccounts();
|
|
198
|
+
return wallet;
|
|
199
|
+
} catch (err) {
|
|
200
|
+
throw new Error('No Para wallet available');
|
|
148
201
|
}
|
|
149
202
|
}
|
|
150
203
|
|
|
204
|
+
getBech32Prefix(chainId: string): string {
|
|
205
|
+
const prefix = this.chains?.find(c => c.chainId === chainId)?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
|
|
206
|
+
return prefix;
|
|
207
|
+
}
|
|
208
|
+
|
|
151
209
|
getParaWebClient(): ParaWeb {
|
|
152
210
|
return this.paraWebClient;
|
|
153
211
|
}
|
|
@@ -156,215 +214,142 @@ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain
|
|
|
156
214
|
return this.config;
|
|
157
215
|
}
|
|
158
216
|
|
|
159
|
-
|
|
160
|
-
const
|
|
161
|
-
|
|
162
|
-
if (wallets.length === 0) {
|
|
163
|
-
throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// Get the bech32 prefix from chain info
|
|
167
|
-
const bech32Prefix = this.getBech32Prefix(chainId);
|
|
168
|
-
|
|
169
|
-
const walletSigner = new ParaProtoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
|
|
170
|
-
const accountData = await walletSigner.getAccounts();
|
|
171
|
-
if (accountData.length === 0) {
|
|
172
|
-
throw new Error(`Para Connector: No accounts found for wallet ${wallets[0].id}`);
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const account = accountData[0];
|
|
217
|
+
protected buildHybridSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
218
|
+
const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
|
|
219
|
+
const directSigner = new ParaOfflineSigner(chainId, this);
|
|
176
220
|
return {
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
pubKey: account.pubkey,
|
|
182
|
-
isKeystone: false,
|
|
183
|
-
isNanoLedger: false,
|
|
184
|
-
};
|
|
221
|
+
getAccounts: () => directSigner.getAccounts(),
|
|
222
|
+
signAmino: (signer: string, signDoc: StdSignDoc) => aminoSigner.signAmino(signer, signDoc),
|
|
223
|
+
signDirect: (signer: string, signDoc: SignDoc) => directSigner.signDirect(signer, signDoc),
|
|
224
|
+
} as unknown as OfflineAminoSigner & OfflineDirectSigner;
|
|
185
225
|
}
|
|
186
226
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
227
|
+
async getKey(chainId: string): Promise<Key> {
|
|
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();
|
|
190
233
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
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
|
+
}
|
|
196
251
|
|
|
197
|
-
|
|
252
|
+
throw new Error(`Failed to get key for chain ${chainId}`);
|
|
253
|
+
}
|
|
198
254
|
}
|
|
199
255
|
|
|
200
256
|
getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
257
|
+
void this.ensureChainEnabled(chainId);
|
|
258
|
+
const wallet = this.paraWebClient.getWalletsByType('COSMOS')[0];
|
|
259
|
+
|
|
260
|
+
if (!wallet) {
|
|
261
|
+
throw new Error('No Cosmos wallet for Amino signing');
|
|
204
262
|
}
|
|
205
263
|
|
|
206
|
-
|
|
264
|
+
return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
265
|
+
}
|
|
207
266
|
|
|
208
|
-
|
|
267
|
+
getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
268
|
+
void this.ensureChainEnabled(chainId);
|
|
269
|
+
return this.buildHybridSigner(chainId);
|
|
209
270
|
}
|
|
210
271
|
|
|
211
|
-
getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
|
|
212
|
-
|
|
272
|
+
async getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
|
|
273
|
+
void this.ensureChainEnabled(chainId);
|
|
274
|
+
return this.buildHybridSigner(chainId);
|
|
213
275
|
}
|
|
214
276
|
|
|
215
|
-
async signAmino(
|
|
216
|
-
|
|
277
|
+
async signAmino(
|
|
278
|
+
chainId: string,
|
|
279
|
+
signer: string,
|
|
280
|
+
signDoc: StdSignDoc,
|
|
281
|
+
_signOptions?: KeplrSignOptions,
|
|
282
|
+
): Promise<AminoSignResponse> {
|
|
283
|
+
await this.ensureChainEnabled(chainId);
|
|
217
284
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
285
|
+
try {
|
|
286
|
+
const wallet = await this.getFirstWallet();
|
|
287
|
+
const signerImpl = new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
288
|
+
const response = await signerImpl.signAmino(signer, signDoc);
|
|
289
|
+
return response;
|
|
290
|
+
} catch (err) {
|
|
291
|
+
throw new Error(`Amino signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
221
292
|
}
|
|
222
|
-
|
|
223
|
-
const bech32Prefix = this.getBech32Prefix(chainId);
|
|
224
|
-
|
|
225
|
-
const walletSigner = new ParaAminoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
|
|
226
|
-
|
|
227
|
-
return walletSigner.signAmino(signer, signDoc);
|
|
228
293
|
}
|
|
229
294
|
|
|
230
295
|
async signDirect(
|
|
231
296
|
chainId: string,
|
|
232
297
|
signer: string,
|
|
233
|
-
signDoc:
|
|
234
|
-
|
|
235
|
-
authInfoBytes?: Uint8Array;
|
|
236
|
-
chainId?: string;
|
|
237
|
-
accountNumber?: Long;
|
|
238
|
-
},
|
|
298
|
+
signDoc: GrazSignDoc,
|
|
299
|
+
_signOptions?: KeplrSignOptions,
|
|
239
300
|
): Promise<DirectSignResponse> {
|
|
240
|
-
await this.
|
|
301
|
+
await this.ensureChainEnabled(chainId);
|
|
241
302
|
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
303
|
+
try {
|
|
304
|
+
const wallet = await this.getFirstWallet();
|
|
305
|
+
const signerImpl = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
306
|
+
const convertedSignDoc: SignDoc = {
|
|
307
|
+
bodyBytes: signDoc.bodyBytes ?? new Uint8Array(),
|
|
308
|
+
authInfoBytes: signDoc.authInfoBytes ?? new Uint8Array(),
|
|
309
|
+
chainId: signDoc.chainId,
|
|
310
|
+
accountNumber: typeof signDoc.accountNumber === 'bigint' ? signDoc.accountNumber : BigInt(signDoc.accountNumber),
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
const result = await signerImpl.signDirect(signer, convertedSignDoc);
|
|
314
|
+
return {
|
|
315
|
+
signed: {
|
|
316
|
+
bodyBytes: result.signed.bodyBytes,
|
|
317
|
+
authInfoBytes: result.signed.authInfoBytes,
|
|
318
|
+
chainId: result.signed.chainId,
|
|
319
|
+
accountNumber: result.signed.accountNumber,
|
|
320
|
+
},
|
|
321
|
+
signature: result.signature,
|
|
322
|
+
};
|
|
323
|
+
} catch (err) {
|
|
324
|
+
throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
245
325
|
}
|
|
246
|
-
|
|
247
|
-
const convertedSignDoc = {
|
|
248
|
-
bodyBytes: signDoc.bodyBytes || new Uint8Array(),
|
|
249
|
-
authInfoBytes: signDoc.authInfoBytes || new Uint8Array(),
|
|
250
|
-
chainId: signDoc.chainId || chainId,
|
|
251
|
-
accountNumber: signDoc.accountNumber ? signDoc.accountNumber.toString() : '0',
|
|
252
|
-
};
|
|
253
|
-
|
|
254
|
-
const bech32Prefix = this.getBech32Prefix(chainId);
|
|
255
|
-
|
|
256
|
-
const walletSigner = new ParaProtoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
|
|
257
|
-
|
|
258
|
-
const result = await walletSigner.signDirect(signer, {
|
|
259
|
-
...convertedSignDoc,
|
|
260
|
-
accountNumber: BigInt(convertedSignDoc.accountNumber),
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
return {
|
|
264
|
-
signed: {
|
|
265
|
-
bodyBytes: result.signed.bodyBytes,
|
|
266
|
-
authInfoBytes: result.signed.authInfoBytes,
|
|
267
|
-
chainId: result.signed.chainId,
|
|
268
|
-
accountNumber: Long.fromString(result.signed.accountNumber.toString()),
|
|
269
|
-
},
|
|
270
|
-
signature: result.signature,
|
|
271
|
-
};
|
|
272
326
|
}
|
|
273
327
|
|
|
274
328
|
async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
|
|
275
|
-
await this.
|
|
329
|
+
await this.ensureChainEnabled(chainId);
|
|
276
330
|
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
if (typeof data === 'string') {
|
|
281
|
-
encodedData = Buffer.from(data).toString('base64');
|
|
282
|
-
isADR36WithString = true;
|
|
283
|
-
} else {
|
|
284
|
-
encodedData = Buffer.from(data).toString('base64');
|
|
285
|
-
}
|
|
331
|
+
const encodedData =
|
|
332
|
+
typeof data === 'string' ? Buffer.from(data, 'utf-8').toString('base64') : Buffer.from(data).toString('base64');
|
|
286
333
|
|
|
287
334
|
const signDoc = {
|
|
288
335
|
chain_id: '',
|
|
289
336
|
account_number: '0',
|
|
290
337
|
sequence: '0',
|
|
291
|
-
fee: {
|
|
292
|
-
gas: '0',
|
|
293
|
-
amount: [],
|
|
294
|
-
},
|
|
338
|
+
fee: { gas: '0', amount: [] },
|
|
295
339
|
msgs: [
|
|
296
340
|
{
|
|
297
341
|
type: 'sign/MsgSignData',
|
|
298
|
-
value: {
|
|
299
|
-
signer,
|
|
300
|
-
data: encodedData,
|
|
301
|
-
},
|
|
342
|
+
value: { signer, data: encodedData },
|
|
302
343
|
},
|
|
303
344
|
],
|
|
304
345
|
memo: '',
|
|
305
346
|
};
|
|
306
347
|
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
async disconnect(): Promise<void> {
|
|
313
|
-
await this.paraWebClient.logout();
|
|
314
|
-
}
|
|
315
|
-
|
|
316
|
-
private async ensureConnected(): Promise<void> {
|
|
317
|
-
const isConnected = await this.paraWebClient.isFullyLoggedIn();
|
|
318
|
-
if (!isConnected) {
|
|
319
|
-
throw new Error('Wallet is not connected, please connect first');
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
private getBech32Prefix(chainId: string): string {
|
|
324
|
-
const chainInfo = getChainInfo({ chainId });
|
|
325
|
-
if (chainInfo?.bech32Config?.bech32PrefixAccAddr) {
|
|
326
|
-
return chainInfo.bech32Config.bech32PrefixAccAddr;
|
|
348
|
+
try {
|
|
349
|
+
const response = await this.signAmino(chainId, signer, signDoc);
|
|
350
|
+
return response.signature;
|
|
351
|
+
} catch (err) {
|
|
352
|
+
throw new Error(`Arbitrary signing failed: ${err instanceof Error ? err.message : 'Unknown error'}`);
|
|
327
353
|
}
|
|
328
|
-
|
|
329
|
-
return 'cosmos';
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
|
|
333
|
-
async function getKey(paraWebClient: ParaWeb, chainId: string) {
|
|
334
|
-
const wallets = Object.values(paraWebClient.getWalletsByType('COSMOS'));
|
|
335
|
-
|
|
336
|
-
if (wallets.length < 1) {
|
|
337
|
-
throw Error('No wallets available');
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
const chainInfo = getChainInfo({ chainId });
|
|
341
|
-
const bech32Prefix = chainInfo?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
|
|
342
|
-
|
|
343
|
-
const walletSigner = new ParaProtoSigner(paraWebClient, bech32Prefix, wallets[0].id);
|
|
344
|
-
|
|
345
|
-
const accountData = (await walletSigner.getAccounts())[0];
|
|
346
|
-
if (!accountData) {
|
|
347
|
-
throw new Error('No account data found');
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
return accountData;
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
async function requestSignature(paraWebClient: ParaWeb, chainId: string, signerAddress: string, signDoc: any) {
|
|
354
|
-
const isConnected = await paraWebClient.isFullyLoggedIn();
|
|
355
|
-
if (!isConnected) {
|
|
356
|
-
throw new Error('Wallet is not connected, please connect first');
|
|
357
|
-
}
|
|
358
|
-
|
|
359
|
-
const wallets = Object.values(paraWebClient.getWalletsByType('COSMOS'));
|
|
360
|
-
if (wallets.length === 0) {
|
|
361
|
-
throw new Error('No wallets available');
|
|
362
354
|
}
|
|
363
|
-
|
|
364
|
-
const chainInfo = getChainInfo({ chainId });
|
|
365
|
-
const bech32Prefix = chainInfo?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
|
|
366
|
-
|
|
367
|
-
const walletSigner = new ParaProtoSigner(paraWebClient, bech32Prefix, wallets[0].id);
|
|
368
|
-
|
|
369
|
-
return walletSigner.signDirect(signerAddress, signDoc);
|
|
370
355
|
}
|
package/src/index.ts
CHANGED