@getpara/graz-connector 0.1.0-alpha.6 → 2.0.0-dev.10
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/__tests__/connector.test.tsx +491 -0
- package/__tests__/connectorModal.test.tsx +148 -0
- package/dist/chunk-M66XENHI.js +25 -0
- package/dist/connector.d.ts +40 -35
- package/dist/connector.js +177 -207
- package/dist/index.d.ts +1 -2
- package/dist/index.js +3 -8
- package/package.json +31 -13
- package/src/connector.ts +186 -287
- package/src/index.ts +1 -2
- package/tsconfig.json +3 -3
- package/vitest.config.js +22 -0
- 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/src/connector.ts
CHANGED
|
@@ -1,77 +1,66 @@
|
|
|
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 } 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;
|
|
28
18
|
}
|
|
29
19
|
|
|
30
|
-
export
|
|
31
|
-
|
|
32
|
-
|
|
20
|
+
export function toArray<T>(v: T | T[]): T[] {
|
|
21
|
+
return Array.isArray(v) ? v : [v];
|
|
22
|
+
}
|
|
33
23
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
24
|
+
class ParaOfflineSigner implements OfflineDirectSigner {
|
|
25
|
+
constructor(
|
|
26
|
+
protected readonly chainId: string,
|
|
27
|
+
protected readonly connector: ParaGrazConnector,
|
|
28
|
+
) {}
|
|
29
|
+
protected get para() {
|
|
30
|
+
return this.connector.getParaWebClient();
|
|
31
|
+
}
|
|
32
|
+
protected get prefix() {
|
|
33
|
+
return this.connector.getBech32Prefix(this.chainId);
|
|
34
|
+
}
|
|
35
|
+
protected async wallet() {
|
|
36
|
+
return this.connector.getFirstWallet();
|
|
37
37
|
}
|
|
38
|
-
|
|
39
38
|
async getAccounts(): Promise<readonly AccountData[]> {
|
|
40
|
-
const key = await getKey(this.
|
|
39
|
+
const key = await this.connector.getKey(this.chainId);
|
|
41
40
|
return [
|
|
42
41
|
{
|
|
43
|
-
address: key.
|
|
42
|
+
address: key.bech32Address,
|
|
44
43
|
algo: key.algo as Algo,
|
|
45
|
-
pubkey: key.
|
|
44
|
+
pubkey: key.pubKey,
|
|
46
45
|
},
|
|
47
46
|
];
|
|
48
47
|
}
|
|
49
|
-
|
|
50
|
-
async signDirect(signerAddress: string, signDoc: KeplrSignDoc): Promise<DirectSignResponse> {
|
|
48
|
+
async signDirect(signerAddress: string, signDoc: SignDoc): Promise<DirectSignResponse> {
|
|
51
49
|
if (this.chainId !== signDoc.chainId) {
|
|
52
|
-
throw new Error(
|
|
50
|
+
throw new Error(`Para connector: signDirect chainId mismatch (expected ${this.chainId}, got ${signDoc.chainId})`);
|
|
53
51
|
}
|
|
54
|
-
|
|
55
52
|
const accounts = await this.getAccounts();
|
|
56
|
-
if (accounts.
|
|
57
|
-
throw new Error(
|
|
53
|
+
if (accounts.every(a => a.address !== signerAddress)) {
|
|
54
|
+
throw new Error(`Para connector: signerAddress ${signerAddress} not found in wallet`);
|
|
58
55
|
}
|
|
59
|
-
|
|
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);
|
|
68
|
-
|
|
56
|
+
const signer = new ParaProtoSigner(this.para, this.prefix, (await this.wallet()).id);
|
|
57
|
+
const result = await signer.signDirect(signerAddress, signDoc);
|
|
69
58
|
return {
|
|
70
59
|
signed: {
|
|
71
60
|
bodyBytes: result.signed.bodyBytes,
|
|
72
61
|
authInfoBytes: result.signed.authInfoBytes,
|
|
73
62
|
chainId: result.signed.chainId,
|
|
74
|
-
accountNumber:
|
|
63
|
+
accountNumber: result.signed.accountNumber,
|
|
75
64
|
},
|
|
76
65
|
signature: result.signature,
|
|
77
66
|
};
|
|
@@ -79,292 +68,202 @@ export class ParaOfflineSigner implements OfflineDirectSigner {
|
|
|
79
68
|
}
|
|
80
69
|
|
|
81
70
|
export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
constructor(
|
|
87
|
-
|
|
88
|
-
|
|
71
|
+
protected paraWebClient: ParaWeb;
|
|
72
|
+
protected enabledChainIds = new Set<string>();
|
|
73
|
+
protected readonly events?: ParaGrazConnectorEvents;
|
|
74
|
+
protected noModal?: boolean;
|
|
75
|
+
constructor(
|
|
76
|
+
protected readonly config: ParaGrazConfig,
|
|
77
|
+
protected readonly chains: ChainInfo[] | null = null,
|
|
78
|
+
) {
|
|
79
|
+
if (!config?.paraWeb) {
|
|
80
|
+
throw new Error('Para connector: missing paraWeb instance in config');
|
|
89
81
|
}
|
|
90
|
-
this.
|
|
91
|
-
this.paraWebClient =
|
|
92
|
-
this.
|
|
82
|
+
this.events = config.events;
|
|
83
|
+
this.paraWebClient = config.paraWeb;
|
|
84
|
+
this.noModal = config.noModal;
|
|
93
85
|
}
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
const startTime = Date.now();
|
|
101
|
-
while (Date.now() - startTime < timeoutMs) {
|
|
102
|
-
if (await this.paraWebClient.isFullyLoggedIn()) {
|
|
103
|
-
return true;
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (this.isModalClosed) {
|
|
107
|
-
throw new Error('user closed modal');
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
86
|
+
protected async ensureChainEnabled(chainId: string): Promise<void> {
|
|
87
|
+
if (!this.enabledChainIds.has(chainId)) {
|
|
88
|
+
throw new Error(`Para connector: chain ${chainId} was not enabled via wallet.enable()`);
|
|
89
|
+
}
|
|
90
|
+
if (!(await this.paraWebClient.isFullyLoggedIn())) {
|
|
91
|
+
throw new Error('Para connector: wallet is not connected – call enable() first');
|
|
111
92
|
}
|
|
112
|
-
|
|
113
|
-
throw new Error('timed out waiting for user to log in');
|
|
114
93
|
}
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
if (
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
94
|
+
protected async waitForLogin(timeoutMs = 60_000): Promise<void> {
|
|
95
|
+
const deadline = Date.now() + timeoutMs;
|
|
96
|
+
let delay = 500;
|
|
97
|
+
const MAX_DELAY = 5_000;
|
|
98
|
+
while (true) {
|
|
99
|
+
if (await this.paraWebClient.isFullyLoggedIn()) return;
|
|
100
|
+
if (Date.now() >= deadline) throw new Error('Para connector: login timeout');
|
|
101
|
+
await new Promise(r => setTimeout(r, delay));
|
|
102
|
+
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
124
103
|
}
|
|
125
|
-
|
|
126
|
-
throw new Error('timed out waiting for accounts to load');
|
|
127
104
|
}
|
|
128
105
|
|
|
129
|
-
async
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
106
|
+
protected async waitForAccounts(timeoutMs = 5_000): Promise<ParaWallet[]> {
|
|
107
|
+
const deadline = Date.now() + timeoutMs;
|
|
108
|
+
let delay = 250;
|
|
109
|
+
const MAX_DELAY = 1_000;
|
|
110
|
+
while (true) {
|
|
111
|
+
const wallets = this.paraWebClient.getWalletsByType('COSMOS');
|
|
112
|
+
if (wallets.length) return wallets;
|
|
113
|
+
if (Date.now() >= deadline) throw new Error('Para connector: no COSMOS wallets found after login');
|
|
114
|
+
await new Promise(r => setTimeout(r, delay));
|
|
115
|
+
delay = Math.min(delay * 1.5, MAX_DELAY);
|
|
135
116
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
117
|
+
}
|
|
118
|
+
protected async hasCosmosWallet(): Promise<boolean> {
|
|
119
|
+
return (await this.paraWebClient.isFullyLoggedIn()) && this.paraWebClient.getWalletsByType('COSMOS').length > 0;
|
|
120
|
+
}
|
|
121
|
+
async enable(chainIdsInput: string | string[]): Promise<void> {
|
|
122
|
+
const chainIds = toArray(chainIdsInput);
|
|
123
|
+
const previousEnabled = new Set(this.enabledChainIds);
|
|
144
124
|
try {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
125
|
+
chainIds.forEach(id => this.enabledChainIds.add(id));
|
|
126
|
+
if (await this.hasCosmosWallet()) {
|
|
127
|
+
this.events?.onEnabled?.(chainIds, this);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
if (!this.noModal) {
|
|
131
|
+
throw new Error('Modal rendering not supported in core library. Use @getpara/graz-integration for modal support.');
|
|
132
|
+
}
|
|
133
|
+
await this.waitForLogin();
|
|
134
|
+
await this.waitForAccounts();
|
|
135
|
+
this.events?.onEnabled?.(chainIds, this);
|
|
136
|
+
} catch (err) {
|
|
137
|
+
this.enabledChainIds = previousEnabled;
|
|
138
|
+
throw err;
|
|
148
139
|
}
|
|
149
140
|
}
|
|
150
141
|
|
|
142
|
+
async disconnect(): Promise<void> {
|
|
143
|
+
await this.paraWebClient.logout();
|
|
144
|
+
this.enabledChainIds.clear();
|
|
145
|
+
}
|
|
146
|
+
async getFirstWallet(): Promise<ParaWallet> {
|
|
147
|
+
const [wallet] = await this.waitForAccounts();
|
|
148
|
+
return wallet;
|
|
149
|
+
}
|
|
150
|
+
getBech32Prefix(chainId: string): string {
|
|
151
|
+
return this.chains?.find(c => c.chainId === chainId)?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
|
|
152
|
+
}
|
|
151
153
|
getParaWebClient(): ParaWeb {
|
|
152
154
|
return this.paraWebClient;
|
|
153
155
|
}
|
|
154
|
-
|
|
155
156
|
getConfig(): ParaGrazConfig {
|
|
156
157
|
return this.config;
|
|
157
158
|
}
|
|
158
|
-
|
|
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];
|
|
159
|
+
protected buildHybridSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
160
|
+
const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
|
|
161
|
+
const directSigner = new ParaOfflineSigner(chainId, this);
|
|
176
162
|
return {
|
|
177
|
-
|
|
178
|
-
|
|
163
|
+
getAccounts: () => directSigner.getAccounts(),
|
|
164
|
+
signAmino: (signer: string, signDoc: StdSignDoc) => aminoSigner.signAmino(signer, signDoc),
|
|
165
|
+
signDirect: (signer: string, signDoc: SignDoc) => directSigner.signDirect(signer, signDoc),
|
|
166
|
+
} as unknown as OfflineAminoSigner & OfflineDirectSigner;
|
|
167
|
+
}
|
|
168
|
+
async getKey(chainId: string) {
|
|
169
|
+
await this.ensureChainEnabled(chainId);
|
|
170
|
+
const wallet = await this.getFirstWallet();
|
|
171
|
+
const signer = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
172
|
+
const [account] = await signer.getAccounts();
|
|
173
|
+
if (!account) throw new Error(`Para connector: wallet ${wallet.id} has no Cosmos accounts`);
|
|
174
|
+
return {
|
|
175
|
+
name: 'Para Wallet',
|
|
179
176
|
algo: account.algo,
|
|
180
|
-
name: account.address,
|
|
181
177
|
pubKey: account.pubkey,
|
|
178
|
+
address: fromBech32(account.address).data,
|
|
179
|
+
bech32Address: account.address,
|
|
182
180
|
isKeystone: false,
|
|
183
181
|
isNanoLedger: false,
|
|
184
182
|
};
|
|
185
183
|
}
|
|
186
|
-
|
|
187
|
-
getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
188
|
-
const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
|
|
189
|
-
const directSigner = new ParaOfflineSigner(chainId, this.paraWebClient);
|
|
190
|
-
|
|
191
|
-
const combinedSigner = {
|
|
192
|
-
getAccounts: () => directSigner.getAccounts(),
|
|
193
|
-
signAmino: (signerAddress: string, signDoc: StdSignDoc) => aminoSigner.signAmino(signerAddress, signDoc),
|
|
194
|
-
signDirect: (signerAddress: string, signDoc: SignDoc) => directSigner.signDirect(signerAddress, signDoc),
|
|
195
|
-
};
|
|
196
|
-
|
|
197
|
-
return combinedSigner as unknown as OfflineAminoSigner & OfflineDirectSigner;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
184
|
getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
185
|
+
void this.ensureChainEnabled(chainId); // fire & forget – returns void
|
|
186
|
+
const wallet = this.paraWebClient.getWalletsByType('COSMOS')[0];
|
|
187
|
+
if (!wallet) {
|
|
188
|
+
throw new Error(`Para connector: no wallets found when requesting Amino signer for ${chainId}`);
|
|
204
189
|
}
|
|
205
|
-
|
|
206
|
-
const bech32Prefix = this.getBech32Prefix(chainId);
|
|
207
|
-
|
|
208
|
-
return new ParaAminoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
|
|
190
|
+
return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
209
191
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
return
|
|
192
|
+
getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
|
|
193
|
+
void this.ensureChainEnabled(chainId);
|
|
194
|
+
return this.buildHybridSigner(chainId);
|
|
213
195
|
}
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
196
|
+
async getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
|
|
197
|
+
void this.ensureChainEnabled(chainId);
|
|
198
|
+
return this.buildHybridSigner(chainId);
|
|
199
|
+
}
|
|
200
|
+
async signAmino(
|
|
201
|
+
chainId: string,
|
|
202
|
+
signer: string,
|
|
203
|
+
signDoc: StdSignDoc,
|
|
204
|
+
_signOptions?: KeplrSignOptions,
|
|
205
|
+
): Promise<AminoSignResponse> {
|
|
206
|
+
await this.ensureChainEnabled(chainId);
|
|
207
|
+
try {
|
|
208
|
+
const wallet = await this.getFirstWallet();
|
|
209
|
+
const signerImpl = new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
210
|
+
return await signerImpl.signAmino(signer, signDoc);
|
|
211
|
+
} catch (err) {
|
|
212
|
+
throw new Error(`Para connector: signAmino failed – ${(err as Error).message}`);
|
|
221
213
|
}
|
|
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
214
|
}
|
|
229
|
-
|
|
230
215
|
async signDirect(
|
|
231
216
|
chainId: string,
|
|
232
217
|
signer: string,
|
|
233
|
-
signDoc:
|
|
234
|
-
|
|
235
|
-
authInfoBytes?: Uint8Array;
|
|
236
|
-
chainId?: string;
|
|
237
|
-
accountNumber?: Long;
|
|
238
|
-
},
|
|
218
|
+
signDoc: GrazSignDoc,
|
|
219
|
+
_signOptions?: KeplrSignOptions,
|
|
239
220
|
): Promise<DirectSignResponse> {
|
|
240
|
-
await this.
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
221
|
+
await this.ensureChainEnabled(chainId);
|
|
222
|
+
try {
|
|
223
|
+
const wallet = await this.getFirstWallet();
|
|
224
|
+
const signerImpl = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
|
|
225
|
+
const convertedSignDoc: SignDoc = {
|
|
226
|
+
bodyBytes: signDoc.bodyBytes ?? new Uint8Array(),
|
|
227
|
+
authInfoBytes: signDoc.authInfoBytes ?? new Uint8Array(),
|
|
228
|
+
chainId: signDoc.chainId,
|
|
229
|
+
accountNumber: typeof signDoc.accountNumber === 'bigint' ? signDoc.accountNumber : BigInt(signDoc.accountNumber),
|
|
230
|
+
};
|
|
231
|
+
const result = await signerImpl.signDirect(signer, convertedSignDoc);
|
|
232
|
+
return {
|
|
233
|
+
signed: {
|
|
234
|
+
bodyBytes: result.signed.bodyBytes,
|
|
235
|
+
authInfoBytes: result.signed.authInfoBytes,
|
|
236
|
+
chainId: result.signed.chainId,
|
|
237
|
+
accountNumber: result.signed.accountNumber,
|
|
238
|
+
},
|
|
239
|
+
signature: result.signature,
|
|
240
|
+
};
|
|
241
|
+
} catch (err) {
|
|
242
|
+
throw new Error(`Para connector: signDirect failed – ${(err as Error).message}`);
|
|
245
243
|
}
|
|
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
244
|
}
|
|
273
|
-
|
|
274
245
|
async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
|
|
275
|
-
await this.
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
let isADR36WithString = false;
|
|
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
|
-
}
|
|
286
|
-
|
|
246
|
+
await this.ensureChainEnabled(chainId);
|
|
247
|
+
const encodedData =
|
|
248
|
+
typeof data === 'string' ? Buffer.from(data, 'utf-8').toString('base64') : Buffer.from(data).toString('base64');
|
|
287
249
|
const signDoc = {
|
|
288
250
|
chain_id: '',
|
|
289
251
|
account_number: '0',
|
|
290
252
|
sequence: '0',
|
|
291
|
-
fee: {
|
|
292
|
-
gas: '0',
|
|
293
|
-
amount: [],
|
|
294
|
-
},
|
|
253
|
+
fee: { gas: '0', amount: [] },
|
|
295
254
|
msgs: [
|
|
296
255
|
{
|
|
297
256
|
type: 'sign/MsgSignData',
|
|
298
|
-
value: {
|
|
299
|
-
signer,
|
|
300
|
-
data: encodedData,
|
|
301
|
-
},
|
|
257
|
+
value: { signer, data: encodedData },
|
|
302
258
|
},
|
|
303
259
|
],
|
|
304
260
|
memo: '',
|
|
305
261
|
};
|
|
306
|
-
|
|
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;
|
|
262
|
+
try {
|
|
263
|
+
const response = await this.signAmino(chainId, signer, signDoc);
|
|
264
|
+
return response.signature;
|
|
265
|
+
} catch (err) {
|
|
266
|
+
throw new Error(`Para connector: signArbitrary failed – ${(err as Error).message}`);
|
|
327
267
|
}
|
|
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
268
|
}
|
|
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
269
|
}
|
package/src/index.ts
CHANGED
package/tsconfig.json
CHANGED
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
"jsx": "react-jsx",
|
|
7
7
|
"module": "ESNext",
|
|
8
8
|
"declaration": true,
|
|
9
|
-
"declarationDir": "dist"
|
|
9
|
+
"declarationDir": "./dist"
|
|
10
10
|
},
|
|
11
|
-
"include": ["
|
|
12
|
-
"exclude": ["node_modules", "dist"]
|
|
11
|
+
"include": ["src/**/*.ts", "src/**/*.tsx"],
|
|
12
|
+
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "__tests__"]
|
|
13
13
|
}
|
package/vitest.config.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { mergeConfig } from 'vite';
|
|
2
|
+
import baseConfig from '../../vitest.config.js';
|
|
3
|
+
|
|
4
|
+
export default mergeConfig(baseConfig, {
|
|
5
|
+
test: {
|
|
6
|
+
environment: 'jsdom',
|
|
7
|
+
coverage: {
|
|
8
|
+
provider: 'v8',
|
|
9
|
+
reporter: ['html', 'text'],
|
|
10
|
+
all: true,
|
|
11
|
+
include: ['src/**/*.{ts,tsx,js,jsx}'],
|
|
12
|
+
thresholds: {
|
|
13
|
+
lines: 98,
|
|
14
|
+
functions: 90,
|
|
15
|
+
branches: 98,
|
|
16
|
+
statements: 98,
|
|
17
|
+
},
|
|
18
|
+
reportOnFailure: true,
|
|
19
|
+
exclude: ['src/index.ts'],
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
});
|
package/dist/chunk-IV3L3JVM.js
DELETED
|
@@ -1,46 +0,0 @@
|
|
|
1
|
-
"use client";
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __defProps = Object.defineProperties;
|
|
4
|
-
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
5
|
-
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
6
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
-
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
8
|
-
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
9
|
-
var __spreadValues = (a, b) => {
|
|
10
|
-
for (var prop in b || (b = {}))
|
|
11
|
-
if (__hasOwnProp.call(b, prop))
|
|
12
|
-
__defNormalProp(a, prop, b[prop]);
|
|
13
|
-
if (__getOwnPropSymbols)
|
|
14
|
-
for (var prop of __getOwnPropSymbols(b)) {
|
|
15
|
-
if (__propIsEnum.call(b, prop))
|
|
16
|
-
__defNormalProp(a, prop, b[prop]);
|
|
17
|
-
}
|
|
18
|
-
return a;
|
|
19
|
-
};
|
|
20
|
-
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
|
-
var __async = (__this, __arguments, generator) => {
|
|
22
|
-
return new Promise((resolve, reject) => {
|
|
23
|
-
var fulfilled = (value) => {
|
|
24
|
-
try {
|
|
25
|
-
step(generator.next(value));
|
|
26
|
-
} catch (e) {
|
|
27
|
-
reject(e);
|
|
28
|
-
}
|
|
29
|
-
};
|
|
30
|
-
var rejected = (value) => {
|
|
31
|
-
try {
|
|
32
|
-
step(generator.throw(value));
|
|
33
|
-
} catch (e) {
|
|
34
|
-
reject(e);
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
|
|
38
|
-
step((generator = generator.apply(__this, __arguments)).next());
|
|
39
|
-
});
|
|
40
|
-
};
|
|
41
|
-
|
|
42
|
-
export {
|
|
43
|
-
__spreadValues,
|
|
44
|
-
__spreadProps,
|
|
45
|
-
__async
|
|
46
|
-
};
|
package/dist/connectorModal.d.ts
DELETED