@getpara/graz-connector 0.1.0-alpha.5 → 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.
@@ -0,0 +1,25 @@
1
+ "use client";
2
+ var __async = (__this, __arguments, generator) => {
3
+ return new Promise((resolve, reject) => {
4
+ var fulfilled = (value) => {
5
+ try {
6
+ step(generator.next(value));
7
+ } catch (e) {
8
+ reject(e);
9
+ }
10
+ };
11
+ var rejected = (value) => {
12
+ try {
13
+ step(generator.throw(value));
14
+ } catch (e) {
15
+ reject(e);
16
+ }
17
+ };
18
+ var step = (x) => x.done ? resolve(x.value) : Promise.resolve(x.value).then(fulfilled, rejected);
19
+ step((generator = generator.apply(__this, __arguments)).next());
20
+ });
21
+ };
22
+
23
+ export {
24
+ __async
25
+ };
@@ -0,0 +1,41 @@
1
+ import { Wallet, SignDoc as GrazSignDoc, Key } from 'graz';
2
+ import { ParaWeb, Wallet as ParaWallet } from '@getpara/web-sdk';
3
+ import { DirectSignResponse, OfflineDirectSigner } from '@cosmjs/proto-signing';
4
+ import { AminoSignResponse, OfflineAminoSigner, StdSignature, StdSignDoc } from '@cosmjs/amino';
5
+ import { ChainInfo, KeplrSignOptions } from '@keplr-wallet/types';
6
+ export type ParaGrazConnectorEvents = {
7
+ onEnabled?: (chainIds: string[], connector: ParaGrazConnector) => void;
8
+ };
9
+ export interface ParaGrazConfig {
10
+ paraWeb: ParaWeb;
11
+ events?: ParaGrazConnectorEvents;
12
+ noModal?: boolean;
13
+ }
14
+ export declare function toArray<T>(v: T | T[]): T[];
15
+ export declare class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
16
+ protected readonly config: ParaGrazConfig;
17
+ protected readonly chains: ChainInfo[] | null;
18
+ protected paraWebClient: ParaWeb;
19
+ protected enabledChainIds: Set<string>;
20
+ protected readonly events?: ParaGrazConnectorEvents;
21
+ protected noModal?: boolean;
22
+ constructor(config: ParaGrazConfig, chains?: ChainInfo[] | null);
23
+ protected ensureChainEnabled(chainId: string): Promise<void>;
24
+ protected waitForLogin(timeoutMs?: number): Promise<void>;
25
+ protected waitForAccounts(timeoutMs?: number): Promise<ParaWallet[]>;
26
+ protected hasCosmosWallet(): Promise<boolean>;
27
+ enable(chainIdsInput: string | string[]): Promise<void>;
28
+ disconnect(): Promise<void>;
29
+ getFirstWallet(): Promise<ParaWallet>;
30
+ getBech32Prefix(chainId: string): string;
31
+ getParaWebClient(): ParaWeb;
32
+ getConfig(): ParaGrazConfig;
33
+ protected buildHybridSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner;
34
+ getKey(chainId: string): Promise<Key>;
35
+ getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner;
36
+ getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner;
37
+ getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner>;
38
+ signAmino(chainId: string, signer: string, signDoc: StdSignDoc, _signOptions?: KeplrSignOptions): Promise<AminoSignResponse>;
39
+ signDirect(chainId: string, signer: string, signDoc: GrazSignDoc, _signOptions?: KeplrSignOptions): Promise<DirectSignResponse>;
40
+ signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature>;
41
+ }
@@ -0,0 +1,311 @@
1
+ "use client";
2
+ import {
3
+ __async
4
+ } from "./chunk-M66XENHI.js";
5
+ import { fromBech32 } from "@cosmjs/encoding";
6
+ import { ParaAminoSigner, ParaProtoSigner } from "@getpara/cosmjs-v0-integration";
7
+ function toArray(v) {
8
+ return Array.isArray(v) ? v : [v];
9
+ }
10
+ class ParaOfflineSigner {
11
+ constructor(chainId, connector) {
12
+ this.chainId = chainId;
13
+ this.connector = connector;
14
+ }
15
+ get para() {
16
+ return this.connector.getParaWebClient();
17
+ }
18
+ get prefix() {
19
+ return this.connector.getBech32Prefix(this.chainId);
20
+ }
21
+ wallet() {
22
+ return __async(this, null, function* () {
23
+ return this.connector.getFirstWallet();
24
+ });
25
+ }
26
+ getAccounts() {
27
+ return __async(this, null, function* () {
28
+ const key = yield this.connector.getKey(this.chainId);
29
+ return [
30
+ {
31
+ address: key.bech32Address,
32
+ algo: key.algo,
33
+ pubkey: key.pubKey
34
+ }
35
+ ];
36
+ });
37
+ }
38
+ signDirect(signerAddress, signDoc) {
39
+ return __async(this, null, function* () {
40
+ if (this.chainId !== signDoc.chainId) {
41
+ throw new Error(`Chain ID mismatch: expected ${this.chainId}, got ${signDoc.chainId}`);
42
+ }
43
+ const accounts = yield this.getAccounts();
44
+ if (accounts.every((a) => a.address !== signerAddress)) {
45
+ throw new Error(`Signer address ${signerAddress} not found in wallet`);
46
+ }
47
+ const signer = new ParaProtoSigner(this.para, this.prefix, (yield this.wallet()).id);
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
+ }
62
+ });
63
+ }
64
+ }
65
+ class ParaGrazConnector {
66
+ constructor(config, chains = null) {
67
+ this.config = config;
68
+ this.chains = chains;
69
+ this.enabledChainIds = /* @__PURE__ */ new Set();
70
+ if (!(config == null ? void 0 : config.paraWeb)) {
71
+ throw new Error("ParaWeb instance required in config");
72
+ }
73
+ this.events = config.events;
74
+ this.paraWebClient = config.paraWeb;
75
+ this.noModal = config.noModal;
76
+ }
77
+ ensureChainEnabled(chainId) {
78
+ return __async(this, null, function* () {
79
+ if (!this.enabledChainIds.has(chainId)) {
80
+ throw new Error(`Chain ${chainId} not enabled. Call enable() first`);
81
+ }
82
+ if (!(yield this.paraWebClient.isFullyLoggedIn())) {
83
+ throw new Error("Para wallet not authenticated");
84
+ }
85
+ });
86
+ }
87
+ waitForLogin(timeoutMs = 6e4) {
88
+ return __async(this, null, function* () {
89
+ const deadline = Date.now() + timeoutMs;
90
+ let delay = 500;
91
+ const MAX_DELAY = 5e3;
92
+ while (true) {
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
+ }
99
+ yield new Promise((r) => setTimeout(r, delay));
100
+ delay = Math.min(delay * 1.5, MAX_DELAY);
101
+ }
102
+ });
103
+ }
104
+ waitForAccounts(timeoutMs = 5e3) {
105
+ return __async(this, null, function* () {
106
+ const deadline = Date.now() + timeoutMs;
107
+ let delay = 250;
108
+ const MAX_DELAY = 1e3;
109
+ while (true) {
110
+ const wallets = this.paraWebClient.getWalletsByType("COSMOS");
111
+ if (wallets.length) {
112
+ return wallets;
113
+ }
114
+ if (Date.now() >= deadline) {
115
+ throw new Error("No Cosmos wallets found");
116
+ }
117
+ yield new Promise((r) => setTimeout(r, delay));
118
+ delay = Math.min(delay * 1.5, MAX_DELAY);
119
+ }
120
+ });
121
+ }
122
+ hasCosmosWallet() {
123
+ return __async(this, null, function* () {
124
+ const isLoggedIn = yield this.paraWebClient.isFullyLoggedIn();
125
+ const wallets = this.paraWebClient.getWalletsByType("COSMOS");
126
+ return isLoggedIn && wallets.length > 0;
127
+ });
128
+ }
129
+ enable(chainIdsInput) {
130
+ return __async(this, null, function* () {
131
+ var _a, _b, _c, _d;
132
+ const chainIds = toArray(chainIdsInput);
133
+ const previousEnabled = new Set(this.enabledChainIds);
134
+ try {
135
+ chainIds.forEach((id) => this.enabledChainIds.add(id));
136
+ if (yield this.hasCosmosWallet()) {
137
+ (_b = (_a = this.events) == null ? void 0 : _a.onEnabled) == null ? void 0 : _b.call(_a, chainIds, this);
138
+ return;
139
+ }
140
+ if (!this.noModal) {
141
+ throw new Error("Modal not supported. Use @getpara/graz-integration or set noModal: true");
142
+ }
143
+ yield this.waitForLogin();
144
+ yield this.waitForAccounts();
145
+ (_d = (_c = this.events) == null ? void 0 : _c.onEnabled) == null ? void 0 : _d.call(_c, chainIds, this);
146
+ } catch (err) {
147
+ this.enabledChainIds = previousEnabled;
148
+ if (err instanceof Error) {
149
+ throw err;
150
+ }
151
+ throw new Error("Failed to enable Para wallet");
152
+ }
153
+ });
154
+ }
155
+ disconnect() {
156
+ return __async(this, null, function* () {
157
+ try {
158
+ yield this.paraWebClient.logout();
159
+ } catch (err) {
160
+ throw new Error("Disconnect failed");
161
+ } finally {
162
+ this.enabledChainIds.clear();
163
+ }
164
+ });
165
+ }
166
+ getFirstWallet() {
167
+ return __async(this, null, function* () {
168
+ try {
169
+ const [wallet] = yield this.waitForAccounts();
170
+ return wallet;
171
+ } catch (err) {
172
+ throw new Error("No Para wallet available");
173
+ }
174
+ });
175
+ }
176
+ getBech32Prefix(chainId) {
177
+ var _a, _b, _c;
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;
180
+ }
181
+ getParaWebClient() {
182
+ return this.paraWebClient;
183
+ }
184
+ getConfig() {
185
+ return this.config;
186
+ }
187
+ buildHybridSigner(chainId) {
188
+ const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
189
+ const directSigner = new ParaOfflineSigner(chainId, this);
190
+ return {
191
+ getAccounts: () => directSigner.getAccounts(),
192
+ signAmino: (signer, signDoc) => aminoSigner.signAmino(signer, signDoc),
193
+ signDirect: (signer, signDoc) => directSigner.signDirect(signer, signDoc)
194
+ };
195
+ }
196
+ getKey(chainId) {
197
+ return __async(this, null, function* () {
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
+ }
221
+ });
222
+ }
223
+ getOfflineSignerOnlyAmino(chainId) {
224
+ void this.ensureChainEnabled(chainId);
225
+ const wallet = this.paraWebClient.getWalletsByType("COSMOS")[0];
226
+ if (!wallet) {
227
+ throw new Error("No Cosmos wallet for Amino signing");
228
+ }
229
+ return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
230
+ }
231
+ getOfflineSigner(chainId) {
232
+ void this.ensureChainEnabled(chainId);
233
+ return this.buildHybridSigner(chainId);
234
+ }
235
+ getOfflineSignerAuto(chainId) {
236
+ return __async(this, null, function* () {
237
+ void this.ensureChainEnabled(chainId);
238
+ return this.buildHybridSigner(chainId);
239
+ });
240
+ }
241
+ signAmino(chainId, signer, signDoc, _signOptions) {
242
+ return __async(this, null, function* () {
243
+ yield this.ensureChainEnabled(chainId);
244
+ try {
245
+ const wallet = yield this.getFirstWallet();
246
+ const signerImpl = new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
247
+ const response = yield signerImpl.signAmino(signer, signDoc);
248
+ return response;
249
+ } catch (err) {
250
+ throw new Error(`Amino signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
251
+ }
252
+ });
253
+ }
254
+ signDirect(chainId, signer, signDoc, _signOptions) {
255
+ return __async(this, null, function* () {
256
+ var _a, _b;
257
+ yield this.ensureChainEnabled(chainId);
258
+ try {
259
+ const wallet = yield this.getFirstWallet();
260
+ const signerImpl = new ParaProtoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
261
+ const convertedSignDoc = {
262
+ bodyBytes: (_a = signDoc.bodyBytes) != null ? _a : new Uint8Array(),
263
+ authInfoBytes: (_b = signDoc.authInfoBytes) != null ? _b : new Uint8Array(),
264
+ chainId: signDoc.chainId,
265
+ accountNumber: typeof signDoc.accountNumber === "bigint" ? signDoc.accountNumber : BigInt(signDoc.accountNumber)
266
+ };
267
+ const result = yield signerImpl.signDirect(signer, convertedSignDoc);
268
+ return {
269
+ signed: {
270
+ bodyBytes: result.signed.bodyBytes,
271
+ authInfoBytes: result.signed.authInfoBytes,
272
+ chainId: result.signed.chainId,
273
+ accountNumber: result.signed.accountNumber
274
+ },
275
+ signature: result.signature
276
+ };
277
+ } catch (err) {
278
+ throw new Error(`Direct signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
279
+ }
280
+ });
281
+ }
282
+ signArbitrary(chainId, signer, data) {
283
+ return __async(this, null, function* () {
284
+ yield this.ensureChainEnabled(chainId);
285
+ const encodedData = typeof data === "string" ? Buffer.from(data, "utf-8").toString("base64") : Buffer.from(data).toString("base64");
286
+ const signDoc = {
287
+ chain_id: "",
288
+ account_number: "0",
289
+ sequence: "0",
290
+ fee: { gas: "0", amount: [] },
291
+ msgs: [
292
+ {
293
+ type: "sign/MsgSignData",
294
+ value: { signer, data: encodedData }
295
+ }
296
+ ],
297
+ memo: ""
298
+ };
299
+ try {
300
+ const response = yield this.signAmino(chainId, signer, signDoc);
301
+ return response.signature;
302
+ } catch (err) {
303
+ throw new Error(`Arbitrary signing failed: ${err instanceof Error ? err.message : "Unknown error"}`);
304
+ }
305
+ });
306
+ }
307
+ }
308
+ export {
309
+ ParaGrazConnector,
310
+ toArray
311
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { WalletType, AuthLayout, AuthMethod, OAuthMethod, Environment } from '@getpara/react-sdk';
2
- export { ParaGrazInternalProvider } from './ParaGrazProvider.js';
3
- export type { ParaGrazConfig, ParaGrazModalProps } from './ParaGrazProvider.js';
1
+ export { toArray, ParaGrazConnector } from './connector.js';
2
+ export type { ParaGrazConfig } from './connector.js';
package/dist/index.js CHANGED
@@ -1,12 +1,7 @@
1
1
  "use client";
2
- import "./chunk-IV3L3JVM.js";
3
- import { WalletType, AuthLayout, AuthMethod, OAuthMethod, Environment } from "@getpara/react-sdk";
4
- import { ParaGrazInternalProvider } from "./ParaGrazProvider.js";
2
+ import "./chunk-M66XENHI.js";
3
+ import { toArray, ParaGrazConnector } from "./connector.js";
5
4
  export {
6
- AuthLayout,
7
- AuthMethod,
8
- Environment,
9
- OAuthMethod,
10
- ParaGrazInternalProvider,
11
- WalletType
5
+ ParaGrazConnector,
6
+ toArray
12
7
  };
package/package.json CHANGED
@@ -1,25 +1,37 @@
1
1
  {
2
2
  "name": "@getpara/graz-connector",
3
- "version": "0.1.0-alpha.5",
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
- "build": "rm -rf dist && yarn typegen && node ./scripts/build.mjs",
14
- "typegen": "tsc --emitDeclarationOnly"
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.3",
18
- "@cosmjs/encoding": "^0.32.3",
19
- "@cosmjs/proto-signing": "^0.32.3",
20
- "cosmjs-types": "0.9.0",
21
- "typescript": "5.1.6",
22
- "graz": "0.2.1",
23
- "@keplr-wallet/types": "0.12.221"
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
  }
@@ -0,0 +1,355 @@
1
+ import { fromBech32 } from '@cosmjs/encoding';
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';
9
+
10
+ export type ParaGrazConnectorEvents = {
11
+ onEnabled?: (chainIds: string[], connector: ParaGrazConnector) => void;
12
+ };
13
+
14
+ export interface ParaGrazConfig {
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];
22
+ }
23
+
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
+ }
37
+
38
+ protected async wallet() {
39
+ return this.connector.getFirstWallet();
40
+ }
41
+
42
+ async getAccounts(): Promise<readonly AccountData[]> {
43
+ const key = await this.connector.getKey(this.chainId);
44
+ return [
45
+ {
46
+ address: key.bech32Address,
47
+ algo: key.algo as Algo,
48
+ pubkey: key.pubKey,
49
+ },
50
+ ];
51
+ }
52
+
53
+ async signDirect(signerAddress: string, signDoc: SignDoc): Promise<DirectSignResponse> {
54
+ if (this.chainId !== signDoc.chainId) {
55
+ throw new Error(`Chain ID mismatch: expected ${this.chainId}, got ${signDoc.chainId}`);
56
+ }
57
+
58
+ const accounts = await this.getAccounts();
59
+ if (accounts.every(a => a.address !== signerAddress)) {
60
+ throw new Error(`Signer address ${signerAddress} not found in wallet`);
61
+ }
62
+
63
+ const signer = new ParaProtoSigner(this.para, this.prefix, (await this.wallet()).id);
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
+ }
79
+ }
80
+ }
81
+
82
+ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
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
+ }
99
+
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');
107
+ }
108
+ }
109
+
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;
114
+
115
+ while (true) {
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
+
124
+ await new Promise(r => setTimeout(r, delay));
125
+ delay = Math.min(delay * 1.5, MAX_DELAY);
126
+ }
127
+ }
128
+
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');
142
+ }
143
+
144
+ await new Promise(r => setTimeout(r, delay));
145
+ delay = Math.min(delay * 1.5, MAX_DELAY);
146
+ }
147
+ }
148
+
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;
153
+ }
154
+
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);
164
+ return;
165
+ }
166
+
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
+ }
184
+
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
+ }
194
+
195
+ async getFirstWallet(): Promise<ParaWallet> {
196
+ try {
197
+ const [wallet] = await this.waitForAccounts();
198
+ return wallet;
199
+ } catch (err) {
200
+ throw new Error('No Para wallet available');
201
+ }
202
+ }
203
+
204
+ getBech32Prefix(chainId: string): string {
205
+ const prefix = this.chains?.find(c => c.chainId === chainId)?.bech32Config?.bech32PrefixAccAddr || 'cosmos';
206
+ return prefix;
207
+ }
208
+
209
+ getParaWebClient(): ParaWeb {
210
+ return this.paraWebClient;
211
+ }
212
+
213
+ getConfig(): ParaGrazConfig {
214
+ return this.config;
215
+ }
216
+
217
+ protected buildHybridSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
218
+ const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
219
+ const directSigner = new ParaOfflineSigner(chainId, this);
220
+ return {
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;
225
+ }
226
+
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();
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
+ }
254
+ }
255
+
256
+ getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
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');
262
+ }
263
+
264
+ return new ParaAminoSigner(this.paraWebClient, this.getBech32Prefix(chainId), wallet.id);
265
+ }
266
+
267
+ getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
268
+ void this.ensureChainEnabled(chainId);
269
+ return this.buildHybridSigner(chainId);
270
+ }
271
+
272
+ async getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
273
+ void this.ensureChainEnabled(chainId);
274
+ return this.buildHybridSigner(chainId);
275
+ }
276
+
277
+ async signAmino(
278
+ chainId: string,
279
+ signer: string,
280
+ signDoc: StdSignDoc,
281
+ _signOptions?: KeplrSignOptions,
282
+ ): Promise<AminoSignResponse> {
283
+ await this.ensureChainEnabled(chainId);
284
+
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'}`);
292
+ }
293
+ }
294
+
295
+ async signDirect(
296
+ chainId: string,
297
+ signer: string,
298
+ signDoc: GrazSignDoc,
299
+ _signOptions?: KeplrSignOptions,
300
+ ): Promise<DirectSignResponse> {
301
+ await this.ensureChainEnabled(chainId);
302
+
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'}`);
325
+ }
326
+ }
327
+
328
+ async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
329
+ await this.ensureChainEnabled(chainId);
330
+
331
+ const encodedData =
332
+ typeof data === 'string' ? Buffer.from(data, 'utf-8').toString('base64') : Buffer.from(data).toString('base64');
333
+
334
+ const signDoc = {
335
+ chain_id: '',
336
+ account_number: '0',
337
+ sequence: '0',
338
+ fee: { gas: '0', amount: [] },
339
+ msgs: [
340
+ {
341
+ type: 'sign/MsgSignData',
342
+ value: { signer, data: encodedData },
343
+ },
344
+ ],
345
+ memo: '',
346
+ };
347
+
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'}`);
353
+ }
354
+ }
355
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,2 @@
1
- export { WalletType, AuthLayout, AuthMethod, OAuthMethod, Environment } from '@getpara/react-sdk';
2
- export { ParaGrazInternalProvider } from './ParaGrazProvider.js';
3
- export type { ParaGrazConfig, ParaGrazModalProps } from './ParaGrazProvider.js';
1
+ export { toArray, ParaGrazConnector } from './connector.js';
2
+ export type { ParaGrazConfig } from './connector.js';
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": ["**/*.ts", "**/*.tsx"],
12
- "exclude": ["node_modules", "dist"]
11
+ "include": ["src/**/*.ts", "src/**/*.tsx"],
12
+ "exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "__tests__"]
13
13
  }
@@ -1,33 +0,0 @@
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 type { OfflineAminoSigner, OfflineDirectSigner, AminoSignResponse, StdSignDoc, StdSignature } from '@keplr-wallet/types';
5
- export type ParaGrazModalProps = Omit<ParaModalProps, 'para'>;
6
- export interface ParaGrazConfig {
7
- apiKey: string;
8
- env: Environment;
9
- modalProps?: ParaGrazModalProps;
10
- }
11
- export declare class ParaGrazInternalProvider implements Omit<Wallet, 'experimentalSuggestChain'> {
12
- private paraWebClient;
13
- private config;
14
- private isModalClosed;
15
- constructor(config: ParaGrazConfig);
16
- closeModal: () => void;
17
- private waitForLogin;
18
- private waitForAccounts;
19
- enable(chainIds: string | string[]): Promise<void>;
20
- getParaWebClient(): ParaWeb;
21
- getConfig(): ParaGrazConfig;
22
- getKey(chainId: string): Promise<GrazKey>;
23
- getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner;
24
- getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner;
25
- getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner>;
26
- signAmino(chainId: string, signer: string, signDoc: StdSignDoc, signOptions?: any): Promise<AminoSignResponse>;
27
- signDirect(chainId: string, signer: string, signDoc: any, signOptions?: any): Promise<{
28
- signed: any;
29
- signature: StdSignature;
30
- }>;
31
- signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature>;
32
- disconnect(): Promise<void>;
33
- }
@@ -1,136 +0,0 @@
1
- "use client";
2
- import {
3
- __async
4
- } from "./chunk-IV3L3JVM.js";
5
- import ParaWeb from "@getpara/react-sdk";
6
- import { ParaProtoSigner } from "@getpara/cosmjs-v0-integration";
7
- import { fromBech32 } from "@cosmjs/encoding";
8
- import { renderModal } from "./connectorModal.js";
9
- const TEN_MINUTES_MS = 6e5;
10
- class ParaGrazInternalProvider {
11
- constructor(config) {
12
- this.closeModal = () => {
13
- this.isModalClosed = true;
14
- };
15
- if (!config || !config.apiKey || !config.env) {
16
- throw new Error("Para Connector: Missing API Key or Environment in config.");
17
- }
18
- this.config = config;
19
- this.paraWebClient = new ParaWeb(config.env, config.apiKey);
20
- this.isModalClosed = true;
21
- }
22
- waitForLogin() {
23
- return __async(this, arguments, function* (timeoutMs = TEN_MINUTES_MS) {
24
- const startTime = Date.now();
25
- while (Date.now() - startTime < timeoutMs) {
26
- if (yield this.paraWebClient.isFullyLoggedIn()) {
27
- return true;
28
- }
29
- if (this.isModalClosed) {
30
- throw new Error("user closed modal");
31
- }
32
- yield new Promise((resolve) => setTimeout(resolve, 2e3));
33
- }
34
- throw new Error("timed out waiting for user to log in");
35
- });
36
- }
37
- waitForAccounts(chainIds, timeoutMs = 5e3) {
38
- return __async(this, null, function* () {
39
- const startTime = Date.now();
40
- while (Date.now() - startTime < timeoutMs) {
41
- const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
42
- if (wallets && wallets.length > 0) {
43
- return true;
44
- }
45
- yield new Promise((resolve) => setTimeout(resolve, 500));
46
- }
47
- throw new Error("timed out waiting for accounts to load");
48
- });
49
- }
50
- enable(chainIds) {
51
- return __async(this, null, function* () {
52
- if (yield this.paraWebClient.isFullyLoggedIn()) {
53
- const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
54
- if (wallets && wallets.length > 0) {
55
- return;
56
- }
57
- }
58
- this.isModalClosed = false;
59
- renderModal(this.paraWebClient, this.config.modalProps, () => {
60
- this.isModalClosed = true;
61
- });
62
- yield this.waitForLogin();
63
- try {
64
- yield this.waitForAccounts(chainIds);
65
- } catch (error) {
66
- throw new Error("accounts not available after login");
67
- }
68
- });
69
- }
70
- getParaWebClient() {
71
- return this.paraWebClient;
72
- }
73
- getConfig() {
74
- return this.config;
75
- }
76
- getKey(chainId) {
77
- return __async(this, null, function* () {
78
- const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
79
- if (wallets.length === 0) {
80
- throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
81
- }
82
- const walletSigner = new ParaProtoSigner(this.paraWebClient, wallets[0].id);
83
- const accountData = yield walletSigner.getAccounts();
84
- if (accountData.length === 0) {
85
- throw new Error(`Para Connector: No accounts found for wallet ${wallets[0].id}`);
86
- }
87
- return {
88
- address: fromBech32(accountData[0].address).data,
89
- bech32Address: accountData[0].address,
90
- algo: accountData[0].algo,
91
- name: accountData[0].address,
92
- pubKey: accountData[0].pubkey,
93
- isKeystone: false,
94
- isNanoLedger: false
95
- };
96
- });
97
- }
98
- getOfflineSigner(chainId) {
99
- console.warn(`Para Connector: getOfflineSigner called for ${chainId} - Needs Implementation`);
100
- throw new Error("getOfflineSigner not implemented");
101
- }
102
- getOfflineSignerOnlyAmino(chainId) {
103
- console.warn(`Para Connector: getOfflineSignerOnlyAmino called for ${chainId} - Needs Implementation`);
104
- throw new Error("getOfflineSignerOnlyAmino not implemented");
105
- }
106
- getOfflineSignerAuto(chainId) {
107
- console.warn(`Para Connector: getOfflineSignerAuto called for ${chainId} - Needs Implementation`);
108
- throw new Error("getOfflineSignerAuto not implemented");
109
- }
110
- signAmino(chainId, signer, signDoc, signOptions) {
111
- return __async(this, null, function* () {
112
- console.warn(`Para Connector: signAmino called for ${chainId} - Needs Implementation`);
113
- throw new Error("signAmino not implemented");
114
- });
115
- }
116
- signDirect(chainId, signer, signDoc, signOptions) {
117
- return __async(this, null, function* () {
118
- console.warn(`Para Connector: signDirect called for ${chainId} - Needs Implementation`);
119
- throw new Error("signDirect not implemented");
120
- });
121
- }
122
- signArbitrary(chainId, signer, data) {
123
- return __async(this, null, function* () {
124
- console.warn(`Para Connector: signArbitrary called for ${chainId} - Needs Implementation`);
125
- throw new Error("signArbitrary not implemented");
126
- });
127
- }
128
- disconnect() {
129
- return __async(this, null, function* () {
130
- yield this.paraWebClient.logout();
131
- });
132
- }
133
- }
134
- export {
135
- ParaGrazInternalProvider
136
- };
@@ -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
- };
@@ -1,2 +0,0 @@
1
- import ParaWeb, { ParaModalProps } from '@getpara/react-sdk';
2
- export declare function renderModal(para: ParaWeb, modalProps: Partial<ParaModalProps>, onCloseArg: () => void): void;
@@ -1,36 +0,0 @@
1
- "use client";
2
- import {
3
- __async,
4
- __spreadProps,
5
- __spreadValues
6
- } from "./chunk-IV3L3JVM.js";
7
- import { jsx } from "react/jsx-runtime";
8
- import { ParaModal } from "@getpara/react-sdk";
9
- function renderModal(para, modalProps, onCloseArg) {
10
- const existingContainer = document.getElementById("para-modal");
11
- const container = existingContainer != null ? existingContainer : document.createElement("div");
12
- container.id = "para-modal";
13
- if (!existingContainer) {
14
- document.body.appendChild(container);
15
- }
16
- const onClose = () => {
17
- onCloseArg();
18
- modalProps.onClose && modalProps.onClose();
19
- render(false);
20
- };
21
- const render = (isOpen) => __async(this, null, function* () {
22
- const Modal = /* @__PURE__ */ jsx(ParaModal, __spreadProps(__spreadValues({}, modalProps), { onClose, para, isOpen }));
23
- try {
24
- const client = yield import("react-dom/client");
25
- const root = client.createRoot(container);
26
- root.render(Modal);
27
- } catch (e) {
28
- const ReactDOM = yield import("react-dom");
29
- ReactDOM.render(Modal, container);
30
- }
31
- });
32
- render(true);
33
- }
34
- export {
35
- renderModal
36
- };
@@ -1,165 +0,0 @@
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 type {
5
- OfflineAminoSigner,
6
- OfflineDirectSigner,
7
- AminoSignResponse,
8
- StdSignDoc,
9
- StdSignature,
10
- } from '@keplr-wallet/types';
11
- import { ParaAminoSigner, ParaProtoSigner } from '@getpara/cosmjs-v0-integration';
12
- import { fromBech32 } from '@cosmjs/encoding';
13
- import { renderModal } from './connectorModal.js';
14
-
15
- const TEN_MINUTES_MS = 600000;
16
-
17
- export type ParaGrazModalProps = Omit<ParaModalProps, 'para'>;
18
-
19
- export interface ParaGrazConfig {
20
- apiKey: string;
21
- env: Environment;
22
- modalProps?: ParaGrazModalProps;
23
- }
24
-
25
- export class ParaGrazInternalProvider implements Omit<Wallet, 'experimentalSuggestChain'> {
26
- private paraWebClient: ParaWeb;
27
- private config: ParaGrazConfig;
28
- private isModalClosed: boolean;
29
-
30
- constructor(config: ParaGrazConfig) {
31
- if (!config || !config.apiKey || !config.env) {
32
- throw new Error('Para Connector: Missing API Key or Environment in config.');
33
- }
34
- this.config = config;
35
- this.paraWebClient = new ParaWeb(config.env, config.apiKey);
36
- this.isModalClosed = true;
37
- }
38
-
39
- closeModal = () => {
40
- this.isModalClosed = true;
41
- };
42
-
43
- private async waitForLogin(timeoutMs = TEN_MINUTES_MS): Promise<boolean> {
44
- const startTime = Date.now();
45
- while (Date.now() - startTime < timeoutMs) {
46
- if (await this.paraWebClient.isFullyLoggedIn()) {
47
- return true;
48
- }
49
-
50
- if (this.isModalClosed) {
51
- throw new Error('user closed modal');
52
- }
53
-
54
- await new Promise(resolve => setTimeout(resolve, 2000));
55
- }
56
-
57
- throw new Error('timed out waiting for user to log in');
58
- }
59
-
60
- private async waitForAccounts(chainIds: string | string[], timeoutMs = 5000): Promise<boolean> {
61
- const startTime = Date.now();
62
- while (Date.now() - startTime < timeoutMs) {
63
- const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
64
- if (wallets && wallets.length > 0) {
65
- return true;
66
- }
67
- await new Promise(resolve => setTimeout(resolve, 500));
68
- }
69
-
70
- throw new Error('timed out waiting for accounts to load');
71
- }
72
-
73
- async enable(chainIds: string | string[]): Promise<void> {
74
- if (await this.paraWebClient.isFullyLoggedIn()) {
75
- const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
76
- if (wallets && wallets.length > 0) {
77
- return;
78
- }
79
- }
80
-
81
- this.isModalClosed = false;
82
- renderModal(this.paraWebClient, this.config.modalProps, () => {
83
- this.isModalClosed = true;
84
- });
85
-
86
- await this.waitForLogin();
87
-
88
- try {
89
- await this.waitForAccounts(chainIds);
90
- } catch (error) {
91
- throw new Error('accounts not available after login');
92
- }
93
- }
94
-
95
- getParaWebClient(): ParaWeb {
96
- return this.paraWebClient;
97
- }
98
-
99
- getConfig(): ParaGrazConfig {
100
- return this.config;
101
- }
102
-
103
- async getKey(chainId: string): Promise<GrazKey> {
104
- const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
105
-
106
- if (wallets.length === 0) {
107
- throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
108
- }
109
-
110
- const walletSigner = new ParaProtoSigner(this.paraWebClient, wallets[0].id);
111
- const accountData = await walletSigner.getAccounts();
112
- if (accountData.length === 0) {
113
- throw new Error(`Para Connector: No accounts found for wallet ${wallets[0].id}`);
114
- }
115
-
116
- return {
117
- address: fromBech32(accountData[0].address).data,
118
- bech32Address: accountData[0].address,
119
- algo: accountData[0].algo,
120
- name: accountData[0].address,
121
- pubKey: accountData[0].pubkey,
122
- isKeystone: false,
123
- isNanoLedger: false,
124
- };
125
- }
126
-
127
- getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner {
128
- console.warn(`Para Connector: getOfflineSigner called for ${chainId} - Needs Implementation`);
129
- throw new Error('getOfflineSigner not implemented');
130
- }
131
-
132
- getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
133
- console.warn(`Para Connector: getOfflineSignerOnlyAmino called for ${chainId} - Needs Implementation`);
134
- throw new Error('getOfflineSignerOnlyAmino not implemented');
135
- }
136
-
137
- getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
138
- console.warn(`Para Connector: getOfflineSignerAuto called for ${chainId} - Needs Implementation`);
139
- throw new Error('getOfflineSignerAuto not implemented');
140
- }
141
-
142
- async signAmino(chainId: string, signer: string, signDoc: StdSignDoc, signOptions?: any): Promise<AminoSignResponse> {
143
- console.warn(`Para Connector: signAmino called for ${chainId} - Needs Implementation`);
144
- throw new Error('signAmino not implemented');
145
- }
146
-
147
- async signDirect(
148
- chainId: string,
149
- signer: string,
150
- signDoc: any,
151
- signOptions?: any,
152
- ): Promise<{ signed: any; signature: StdSignature }> {
153
- console.warn(`Para Connector: signDirect called for ${chainId} - Needs Implementation`);
154
- throw new Error('signDirect not implemented');
155
- }
156
-
157
- async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
158
- console.warn(`Para Connector: signArbitrary called for ${chainId} - Needs Implementation`);
159
- throw new Error('signArbitrary not implemented');
160
- }
161
-
162
- async disconnect(): Promise<void> {
163
- await this.paraWebClient.logout();
164
- }
165
- }
@@ -1,32 +0,0 @@
1
- import ParaWeb, { ParaModal, ParaModalProps } from '@getpara/react-sdk';
2
-
3
- export function renderModal(para: ParaWeb, modalProps: Partial<ParaModalProps>, onCloseArg: () => void): void {
4
- const existingContainer = document.getElementById('para-modal');
5
- const container = existingContainer ?? document.createElement('div');
6
- container.id = 'para-modal';
7
-
8
- if (!existingContainer) {
9
- document.body.appendChild(container);
10
- }
11
-
12
- const onClose = () => {
13
- onCloseArg();
14
- modalProps.onClose && modalProps.onClose();
15
- render(false);
16
- };
17
-
18
- const render = async (isOpen: boolean) => {
19
- const Modal = <ParaModal {...modalProps} onClose={onClose} para={para} isOpen={isOpen} />;
20
-
21
- try {
22
- const client = await import('react-dom/client');
23
- const root = client.createRoot(container);
24
- root.render(Modal);
25
- } catch (e) {
26
- const ReactDOM = await import('react-dom');
27
- ReactDOM.render(Modal, container);
28
- }
29
- };
30
-
31
- render(true);
32
- }