@getpara/graz-connector 0.1.0-alpha.4 → 0.1.0-alpha.6

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.
@@ -1,14 +1,21 @@
1
1
  import ParaWeb from '@getpara/react-sdk';
2
2
  import type { Environment, ParaModalProps } from '@getpara/react-sdk';
3
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'>;
4
+ import type { OfflineAminoSigner, OfflineDirectSigner, AminoSignResponse, StdSignDoc, StdSignature, DirectSignResponse, AccountData, SignDoc as KeplrSignDoc } from '@keplr-wallet/types';
5
+ import Long from 'long';
6
6
  export interface ParaGrazConfig {
7
7
  apiKey: string;
8
8
  env: Environment;
9
- modalProps?: ParaGrazModalProps;
9
+ modalProps?: ParaModalProps;
10
10
  }
11
- export declare class ParaGrazInternalProvider implements Omit<Wallet, 'experimentalSuggestChain'> {
11
+ export declare class ParaOfflineSigner implements OfflineDirectSigner {
12
+ private chainId;
13
+ private paraWebClient;
14
+ constructor(chainId: string, paraWebClient: ParaWeb);
15
+ getAccounts(): Promise<readonly AccountData[]>;
16
+ signDirect(signerAddress: string, signDoc: KeplrSignDoc): Promise<DirectSignResponse>;
17
+ }
18
+ export declare class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
12
19
  private paraWebClient;
13
20
  private config;
14
21
  private isModalClosed;
@@ -23,11 +30,15 @@ export declare class ParaGrazInternalProvider implements Omit<Wallet, 'experimen
23
30
  getOfflineSigner(chainId: string): OfflineAminoSigner & OfflineDirectSigner;
24
31
  getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner;
25
32
  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
- }>;
33
+ signAmino(chainId: string, signer: string, signDoc: StdSignDoc): Promise<AminoSignResponse>;
34
+ signDirect(chainId: string, signer: string, signDoc: {
35
+ bodyBytes?: Uint8Array;
36
+ authInfoBytes?: Uint8Array;
37
+ chainId?: string;
38
+ accountNumber?: Long;
39
+ }): Promise<DirectSignResponse>;
31
40
  signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature>;
32
41
  disconnect(): Promise<void>;
42
+ private ensureConnected;
43
+ private getBech32Prefix;
33
44
  }
@@ -0,0 +1,304 @@
1
+ "use client";
2
+ import {
3
+ __async,
4
+ __spreadProps,
5
+ __spreadValues
6
+ } from "./chunk-IV3L3JVM.js";
7
+ import ParaWeb from "@getpara/react-sdk";
8
+ import { getChainInfo } from "graz";
9
+ import { ParaAminoSigner, ParaProtoSigner } from "@getpara/cosmjs-v0-integration";
10
+ import { fromBech32 } from "@cosmjs/encoding";
11
+ import { renderModal } from "./connectorModal.js";
12
+ import Long from "long";
13
+ const TEN_MINUTES_MS = 6e5;
14
+ class ParaOfflineSigner {
15
+ constructor(chainId, paraWebClient) {
16
+ this.chainId = chainId;
17
+ this.paraWebClient = paraWebClient;
18
+ }
19
+ getAccounts() {
20
+ return __async(this, null, function* () {
21
+ const key = yield getKey(this.paraWebClient, this.chainId);
22
+ return [
23
+ {
24
+ address: key.address,
25
+ algo: key.algo,
26
+ pubkey: key.pubkey
27
+ }
28
+ ];
29
+ });
30
+ }
31
+ signDirect(signerAddress, signDoc) {
32
+ return __async(this, null, function* () {
33
+ if (this.chainId !== signDoc.chainId) {
34
+ throw new Error("Chain ID does not match signer chain ID");
35
+ }
36
+ const accounts = yield this.getAccounts();
37
+ if (accounts.find((account) => account.address !== signerAddress)) {
38
+ throw new Error("Signer address does not match wallet address");
39
+ }
40
+ const convertedSignDoc = {
41
+ bodyBytes: signDoc.bodyBytes,
42
+ authInfoBytes: signDoc.authInfoBytes,
43
+ chainId: signDoc.chainId,
44
+ accountNumber: typeof signDoc.accountNumber === "string" ? signDoc.accountNumber : signDoc.accountNumber.toString()
45
+ };
46
+ const result = yield requestSignature(this.paraWebClient, this.chainId, signerAddress, convertedSignDoc);
47
+ return {
48
+ signed: {
49
+ bodyBytes: result.signed.bodyBytes,
50
+ authInfoBytes: result.signed.authInfoBytes,
51
+ chainId: result.signed.chainId,
52
+ accountNumber: Long.fromString(result.signed.accountNumber.toString())
53
+ },
54
+ signature: result.signature
55
+ };
56
+ });
57
+ }
58
+ }
59
+ class ParaGrazConnector {
60
+ constructor(config) {
61
+ this.closeModal = () => {
62
+ this.isModalClosed = true;
63
+ };
64
+ if (!config || !config.apiKey || !config.env) {
65
+ throw new Error("Para Connector: Missing API Key or Environment in config.");
66
+ }
67
+ this.config = config;
68
+ this.paraWebClient = new ParaWeb(config.env, config.apiKey);
69
+ this.isModalClosed = true;
70
+ }
71
+ waitForLogin() {
72
+ return __async(this, arguments, function* (timeoutMs = TEN_MINUTES_MS) {
73
+ const startTime = Date.now();
74
+ while (Date.now() - startTime < timeoutMs) {
75
+ if (yield this.paraWebClient.isFullyLoggedIn()) {
76
+ return true;
77
+ }
78
+ if (this.isModalClosed) {
79
+ throw new Error("user closed modal");
80
+ }
81
+ yield new Promise((resolve) => setTimeout(resolve, 2e3));
82
+ }
83
+ throw new Error("timed out waiting for user to log in");
84
+ });
85
+ }
86
+ waitForAccounts(chainIds, timeoutMs = 5e3) {
87
+ return __async(this, null, function* () {
88
+ const startTime = Date.now();
89
+ while (Date.now() - startTime < timeoutMs) {
90
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
91
+ if (wallets && wallets.length > 0) {
92
+ return true;
93
+ }
94
+ yield new Promise((resolve) => setTimeout(resolve, 500));
95
+ }
96
+ throw new Error("timed out waiting for accounts to load");
97
+ });
98
+ }
99
+ enable(chainIds) {
100
+ return __async(this, null, function* () {
101
+ if (yield this.paraWebClient.isFullyLoggedIn()) {
102
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
103
+ if (wallets && wallets.length > 0) {
104
+ return;
105
+ }
106
+ }
107
+ this.isModalClosed = false;
108
+ renderModal(this.paraWebClient, this.config.modalProps, () => {
109
+ this.isModalClosed = true;
110
+ });
111
+ yield this.waitForLogin();
112
+ try {
113
+ yield this.waitForAccounts(chainIds);
114
+ } catch (error) {
115
+ throw new Error("accounts not available after login");
116
+ }
117
+ });
118
+ }
119
+ getParaWebClient() {
120
+ return this.paraWebClient;
121
+ }
122
+ getConfig() {
123
+ return this.config;
124
+ }
125
+ getKey(chainId) {
126
+ return __async(this, null, function* () {
127
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
128
+ if (wallets.length === 0) {
129
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
130
+ }
131
+ const bech32Prefix = this.getBech32Prefix(chainId);
132
+ const walletSigner = new ParaProtoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
133
+ const accountData = yield walletSigner.getAccounts();
134
+ if (accountData.length === 0) {
135
+ throw new Error(`Para Connector: No accounts found for wallet ${wallets[0].id}`);
136
+ }
137
+ const account = accountData[0];
138
+ return {
139
+ address: fromBech32(account.address).data,
140
+ bech32Address: account.address,
141
+ algo: account.algo,
142
+ name: account.address,
143
+ pubKey: account.pubkey,
144
+ isKeystone: false,
145
+ isNanoLedger: false
146
+ };
147
+ });
148
+ }
149
+ getOfflineSigner(chainId) {
150
+ const aminoSigner = this.getOfflineSignerOnlyAmino(chainId);
151
+ const directSigner = new ParaOfflineSigner(chainId, this.paraWebClient);
152
+ const combinedSigner = {
153
+ getAccounts: () => directSigner.getAccounts(),
154
+ signAmino: (signerAddress, signDoc) => aminoSigner.signAmino(signerAddress, signDoc),
155
+ signDirect: (signerAddress, signDoc) => directSigner.signDirect(signerAddress, signDoc)
156
+ };
157
+ return combinedSigner;
158
+ }
159
+ getOfflineSignerOnlyAmino(chainId) {
160
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
161
+ if (wallets.length === 0) {
162
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
163
+ }
164
+ const bech32Prefix = this.getBech32Prefix(chainId);
165
+ return new ParaAminoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
166
+ }
167
+ getOfflineSignerAuto(chainId) {
168
+ return Promise.resolve(this.getOfflineSignerOnlyAmino(chainId));
169
+ }
170
+ signAmino(chainId, signer, signDoc) {
171
+ return __async(this, null, function* () {
172
+ yield this.ensureConnected();
173
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
174
+ if (wallets.length === 0) {
175
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
176
+ }
177
+ const bech32Prefix = this.getBech32Prefix(chainId);
178
+ const walletSigner = new ParaAminoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
179
+ return walletSigner.signAmino(signer, signDoc);
180
+ });
181
+ }
182
+ signDirect(chainId, signer, signDoc) {
183
+ return __async(this, null, function* () {
184
+ yield this.ensureConnected();
185
+ const wallets = Object.values(this.paraWebClient.getWalletsByType("COSMOS"));
186
+ if (wallets.length === 0) {
187
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
188
+ }
189
+ const convertedSignDoc = {
190
+ bodyBytes: signDoc.bodyBytes || new Uint8Array(),
191
+ authInfoBytes: signDoc.authInfoBytes || new Uint8Array(),
192
+ chainId: signDoc.chainId || chainId,
193
+ accountNumber: signDoc.accountNumber ? signDoc.accountNumber.toString() : "0"
194
+ };
195
+ const bech32Prefix = this.getBech32Prefix(chainId);
196
+ const walletSigner = new ParaProtoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
197
+ const result = yield walletSigner.signDirect(signer, __spreadProps(__spreadValues({}, convertedSignDoc), {
198
+ accountNumber: BigInt(convertedSignDoc.accountNumber)
199
+ }));
200
+ return {
201
+ signed: {
202
+ bodyBytes: result.signed.bodyBytes,
203
+ authInfoBytes: result.signed.authInfoBytes,
204
+ chainId: result.signed.chainId,
205
+ accountNumber: Long.fromString(result.signed.accountNumber.toString())
206
+ },
207
+ signature: result.signature
208
+ };
209
+ });
210
+ }
211
+ signArbitrary(chainId, signer, data) {
212
+ return __async(this, null, function* () {
213
+ yield this.ensureConnected();
214
+ let encodedData;
215
+ let isADR36WithString = false;
216
+ if (typeof data === "string") {
217
+ encodedData = Buffer.from(data).toString("base64");
218
+ isADR36WithString = true;
219
+ } else {
220
+ encodedData = Buffer.from(data).toString("base64");
221
+ }
222
+ const signDoc = {
223
+ chain_id: "",
224
+ account_number: "0",
225
+ sequence: "0",
226
+ fee: {
227
+ gas: "0",
228
+ amount: []
229
+ },
230
+ msgs: [
231
+ {
232
+ type: "sign/MsgSignData",
233
+ value: {
234
+ signer,
235
+ data: encodedData
236
+ }
237
+ }
238
+ ],
239
+ memo: ""
240
+ };
241
+ const response = yield this.signAmino(chainId, signer, signDoc);
242
+ return response.signature;
243
+ });
244
+ }
245
+ disconnect() {
246
+ return __async(this, null, function* () {
247
+ yield this.paraWebClient.logout();
248
+ });
249
+ }
250
+ ensureConnected() {
251
+ return __async(this, null, function* () {
252
+ const isConnected = yield this.paraWebClient.isFullyLoggedIn();
253
+ if (!isConnected) {
254
+ throw new Error("Wallet is not connected, please connect first");
255
+ }
256
+ });
257
+ }
258
+ getBech32Prefix(chainId) {
259
+ var _a;
260
+ const chainInfo = getChainInfo({ chainId });
261
+ if ((_a = chainInfo == null ? void 0 : chainInfo.bech32Config) == null ? void 0 : _a.bech32PrefixAccAddr) {
262
+ return chainInfo.bech32Config.bech32PrefixAccAddr;
263
+ }
264
+ return "cosmos";
265
+ }
266
+ }
267
+ function getKey(paraWebClient, chainId) {
268
+ return __async(this, null, function* () {
269
+ var _a;
270
+ const wallets = Object.values(paraWebClient.getWalletsByType("COSMOS"));
271
+ if (wallets.length < 1) {
272
+ throw Error("No wallets available");
273
+ }
274
+ const chainInfo = getChainInfo({ chainId });
275
+ const bech32Prefix = ((_a = chainInfo == null ? void 0 : chainInfo.bech32Config) == null ? void 0 : _a.bech32PrefixAccAddr) || "cosmos";
276
+ const walletSigner = new ParaProtoSigner(paraWebClient, bech32Prefix, wallets[0].id);
277
+ const accountData = (yield walletSigner.getAccounts())[0];
278
+ if (!accountData) {
279
+ throw new Error("No account data found");
280
+ }
281
+ return accountData;
282
+ });
283
+ }
284
+ function requestSignature(paraWebClient, chainId, signerAddress, signDoc) {
285
+ return __async(this, null, function* () {
286
+ var _a;
287
+ const isConnected = yield paraWebClient.isFullyLoggedIn();
288
+ if (!isConnected) {
289
+ throw new Error("Wallet is not connected, please connect first");
290
+ }
291
+ const wallets = Object.values(paraWebClient.getWalletsByType("COSMOS"));
292
+ if (wallets.length === 0) {
293
+ throw new Error("No wallets available");
294
+ }
295
+ const chainInfo = getChainInfo({ chainId });
296
+ const bech32Prefix = ((_a = chainInfo == null ? void 0 : chainInfo.bech32Config) == null ? void 0 : _a.bech32PrefixAccAddr) || "cosmos";
297
+ const walletSigner = new ParaProtoSigner(paraWebClient, bech32Prefix, wallets[0].id);
298
+ return walletSigner.signDirect(signerAddress, signDoc);
299
+ });
300
+ }
301
+ export {
302
+ ParaGrazConnector,
303
+ ParaOfflineSigner
304
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,3 @@
1
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';
2
+ export { ParaGrazConnector } from './connector.js';
3
+ export type { ParaGrazConfig } from './connector.js';
package/dist/index.js CHANGED
@@ -1,12 +1,12 @@
1
1
  "use client";
2
2
  import "./chunk-IV3L3JVM.js";
3
3
  import { WalletType, AuthLayout, AuthMethod, OAuthMethod, Environment } from "@getpara/react-sdk";
4
- import { ParaGrazInternalProvider } from "./ParaGrazProvider.js";
4
+ import { ParaGrazConnector } from "./connector.js";
5
5
  export {
6
6
  AuthLayout,
7
7
  AuthMethod,
8
8
  Environment,
9
9
  OAuthMethod,
10
- ParaGrazInternalProvider,
10
+ ParaGrazConnector,
11
11
  WalletType
12
12
  };
package/package.json CHANGED
@@ -1,10 +1,9 @@
1
1
  {
2
2
  "name": "@getpara/graz-connector",
3
- "version": "0.1.0-alpha.4",
4
- "main": "dist/cjs/index.js",
5
- "module": "dist/esm/index.js",
6
- "types": "dist/types/index.d.ts",
7
- "typings": "dist/types/index.d.ts",
3
+ "version": "0.1.0-alpha.6",
4
+ "type": "module",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
8
7
  "sideEffects": false,
9
8
  "dependencies": {
10
9
  "@getpara/react-sdk": "1.11.0",
@@ -0,0 +1,370 @@
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
+ import { fromBech32 } from '@cosmjs/encoding';
19
+ import { renderModal } from './connectorModal.js';
20
+ import Long from 'long';
21
+
22
+ const TEN_MINUTES_MS = 600000;
23
+
24
+ export interface ParaGrazConfig {
25
+ apiKey: string;
26
+ env: Environment;
27
+ modalProps?: ParaModalProps;
28
+ }
29
+
30
+ export class ParaOfflineSigner implements OfflineDirectSigner {
31
+ private chainId: string;
32
+ private paraWebClient: ParaWeb;
33
+
34
+ constructor(chainId: string, paraWebClient: ParaWeb) {
35
+ this.chainId = chainId;
36
+ this.paraWebClient = paraWebClient;
37
+ }
38
+
39
+ async getAccounts(): Promise<readonly AccountData[]> {
40
+ const key = await getKey(this.paraWebClient, this.chainId);
41
+ return [
42
+ {
43
+ address: key.address,
44
+ algo: key.algo as Algo,
45
+ pubkey: key.pubkey,
46
+ },
47
+ ];
48
+ }
49
+
50
+ async signDirect(signerAddress: string, signDoc: KeplrSignDoc): Promise<DirectSignResponse> {
51
+ if (this.chainId !== signDoc.chainId) {
52
+ throw new Error('Chain ID does not match signer chain ID');
53
+ }
54
+
55
+ const accounts = await this.getAccounts();
56
+ if (accounts.find(account => account.address !== signerAddress)) {
57
+ throw new Error('Signer address does not match wallet address');
58
+ }
59
+
60
+ const convertedSignDoc = {
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
+
69
+ return {
70
+ signed: {
71
+ bodyBytes: result.signed.bodyBytes,
72
+ authInfoBytes: result.signed.authInfoBytes,
73
+ chainId: result.signed.chainId,
74
+ accountNumber: Long.fromString(result.signed.accountNumber.toString()),
75
+ },
76
+ signature: result.signature,
77
+ };
78
+ }
79
+ }
80
+
81
+ export class ParaGrazConnector implements Omit<Wallet, 'experimentalSuggestChain'> {
82
+ private paraWebClient: ParaWeb;
83
+ private config: ParaGrazConfig;
84
+ private isModalClosed: boolean;
85
+
86
+ constructor(config: ParaGrazConfig) {
87
+ if (!config || !config.apiKey || !config.env) {
88
+ throw new Error('Para Connector: Missing API Key or Environment in config.');
89
+ }
90
+ this.config = config;
91
+ this.paraWebClient = new ParaWeb(config.env, config.apiKey);
92
+ this.isModalClosed = true;
93
+ }
94
+
95
+ closeModal = () => {
96
+ this.isModalClosed = true;
97
+ };
98
+
99
+ private async waitForLogin(timeoutMs = TEN_MINUTES_MS): Promise<boolean> {
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));
111
+ }
112
+
113
+ throw new Error('timed out waiting for user to log in');
114
+ }
115
+
116
+ private async waitForAccounts(chainIds: string | string[], timeoutMs = 5000): Promise<boolean> {
117
+ const startTime = Date.now();
118
+ while (Date.now() - startTime < timeoutMs) {
119
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
120
+ if (wallets && wallets.length > 0) {
121
+ return true;
122
+ }
123
+ await new Promise(resolve => setTimeout(resolve, 500));
124
+ }
125
+
126
+ throw new Error('timed out waiting for accounts to load');
127
+ }
128
+
129
+ async enable(chainIds: string | string[]): Promise<void> {
130
+ if (await this.paraWebClient.isFullyLoggedIn()) {
131
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
132
+ if (wallets && wallets.length > 0) {
133
+ return;
134
+ }
135
+ }
136
+
137
+ this.isModalClosed = false;
138
+ renderModal(this.paraWebClient, this.config.modalProps, () => {
139
+ this.isModalClosed = true;
140
+ });
141
+
142
+ await this.waitForLogin();
143
+
144
+ try {
145
+ await this.waitForAccounts(chainIds);
146
+ } catch (error) {
147
+ throw new Error('accounts not available after login');
148
+ }
149
+ }
150
+
151
+ getParaWebClient(): ParaWeb {
152
+ return this.paraWebClient;
153
+ }
154
+
155
+ getConfig(): ParaGrazConfig {
156
+ return this.config;
157
+ }
158
+
159
+ async getKey(chainId: string): Promise<GrazKey> {
160
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
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];
176
+ return {
177
+ address: fromBech32(account.address).data,
178
+ bech32Address: account.address,
179
+ algo: account.algo,
180
+ name: account.address,
181
+ pubKey: account.pubkey,
182
+ isKeystone: false,
183
+ isNanoLedger: false,
184
+ };
185
+ }
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
+ getOfflineSignerOnlyAmino(chainId: string): OfflineAminoSigner {
201
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
202
+ if (wallets.length === 0) {
203
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
204
+ }
205
+
206
+ const bech32Prefix = this.getBech32Prefix(chainId);
207
+
208
+ return new ParaAminoSigner(this.paraWebClient, bech32Prefix, wallets[0].id);
209
+ }
210
+
211
+ getOfflineSignerAuto(chainId: string): Promise<OfflineAminoSigner | OfflineDirectSigner> {
212
+ return Promise.resolve(this.getOfflineSignerOnlyAmino(chainId));
213
+ }
214
+
215
+ async signAmino(chainId: string, signer: string, signDoc: StdSignDoc): Promise<AminoSignResponse> {
216
+ await this.ensureConnected();
217
+
218
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
219
+ if (wallets.length === 0) {
220
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
221
+ }
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
+ }
229
+
230
+ async signDirect(
231
+ chainId: string,
232
+ signer: string,
233
+ signDoc: {
234
+ bodyBytes?: Uint8Array;
235
+ authInfoBytes?: Uint8Array;
236
+ chainId?: string;
237
+ accountNumber?: Long;
238
+ },
239
+ ): Promise<DirectSignResponse> {
240
+ await this.ensureConnected();
241
+
242
+ const wallets = Object.values(this.paraWebClient.getWalletsByType('COSMOS'));
243
+ if (wallets.length === 0) {
244
+ throw new Error(`Para Connector: No wallets found for chainId ${chainId}`);
245
+ }
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
+ }
273
+
274
+ async signArbitrary(chainId: string, signer: string, data: string | Uint8Array): Promise<StdSignature> {
275
+ await this.ensureConnected();
276
+
277
+ let encodedData: string;
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
+
287
+ const signDoc = {
288
+ chain_id: '',
289
+ account_number: '0',
290
+ sequence: '0',
291
+ fee: {
292
+ gas: '0',
293
+ amount: [],
294
+ },
295
+ msgs: [
296
+ {
297
+ type: 'sign/MsgSignData',
298
+ value: {
299
+ signer,
300
+ data: encodedData,
301
+ },
302
+ },
303
+ ],
304
+ memo: '',
305
+ };
306
+
307
+ const response = await this.signAmino(chainId, signer, signDoc);
308
+
309
+ return response.signature;
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;
327
+ }
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
+ }
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
+ }
package/src/index.ts CHANGED
@@ -1,3 +1,3 @@
1
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';
2
+ export { ParaGrazConnector } from './connector.js';
3
+ export type { ParaGrazConfig } from './connector.js';
@@ -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,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
- }