@burnt-labs/abstraxion 0.1.0-alpha.21 → 0.1.0-alpha.23

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,5 +1,5 @@
1
1
 
2
- > @burnt-labs/abstraxion@0.1.0-alpha.21 build /home/runner/work/xion.js/xion.js/packages/abstraxion
2
+ > @burnt-labs/abstraxion@0.1.0-alpha.23 build /home/runner/work/xion.js/xion.js/packages/abstraxion
3
3
  > tsup
4
4
 
5
5
  CLI Building entry: src/index.ts
@@ -12,10 +12,10 @@
12
12
  CJS Build start
13
13
  DTS Build start
14
14
  ESM dist/index.css 7.41 KB
15
- ESM dist/index.mjs 11.29 KB
16
- ESM ⚡️ Build success in 1010ms
15
+ ESM dist/index.mjs 13.34 KB
16
+ ESM ⚡️ Build success in 943ms
17
17
  CJS dist/index.css 7.41 KB
18
- CJS dist/index.js 11.74 KB
19
- CJS ⚡️ Build success in 1011ms
20
- DTS ⚡️ Build success in 3364ms
21
- DTS dist/index.d.ts 2.23 KB
18
+ CJS dist/index.js 13.76 KB
19
+ CJS ⚡️ Build success in 943ms
20
+ DTS ⚡️ Build success in 3287ms
21
+ DTS dist/index.d.ts 2.30 KB
package/CHANGELOG.md CHANGED
@@ -1,12 +1,36 @@
1
1
  # @burnt-labs/abstraxion
2
2
 
3
+ ## 0.1.0-alpha.23
4
+
5
+ ### Minor Changes
6
+
7
+ - [#53](https://github.com/burnt-labs/xion.js/pull/53) [`2257a1f`](https://github.com/burnt-labs/xion.js/commit/2257a1f5249a1efaa6f7d15522ee330981ae8952) Thanks [@justinbarry](https://github.com/justinbarry)! - Add getAccount method in GranteeSignerClient to parse abstractaccount.v1.AbstractAccount type accounts
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [[`2257a1f`](https://github.com/burnt-labs/xion.js/commit/2257a1f5249a1efaa6f7d15522ee330981ae8952)]:
12
+ - @burnt-labs/signers@0.1.0-alpha.4
13
+
14
+ ## 0.1.0-alpha.22
15
+
16
+ ### Minor Changes
17
+
18
+ - [#42](https://github.com/burnt-labs/xion.js/pull/42) [`6a6fdd2`](https://github.com/burnt-labs/xion.js/commit/6a6fdd253a1dc81873d271d2ac5e87100ef18ff1) Thanks [@BurntVal](https://github.com/BurntVal)! - remove unnecessary packages from abstraxion and optimize modal backdrop
19
+
20
+ - [#47](https://github.com/burnt-labs/xion.js/pull/47) [`dd8680f`](https://github.com/burnt-labs/xion.js/commit/dd8680f6bc18e15a531993be048e9db83d79b488) Thanks [@BurntVal](https://github.com/BurntVal)! - persistence and related state cleanup
21
+
22
+ ### Patch Changes
23
+
24
+ - Updated dependencies [[`6a6fdd2`](https://github.com/burnt-labs/xion.js/commit/6a6fdd253a1dc81873d271d2ac5e87100ef18ff1)]:
25
+ - @burnt-labs/ui@0.1.0-alpha.4
26
+
3
27
  ## 0.1.0-alpha.21
4
28
 
5
29
  ### Minor Changes
6
30
 
7
31
  - [#41](https://github.com/burnt-labs/xion.js/pull/41) [`a269cdf`](https://github.com/burnt-labs/xion.js/commit/a269cdf88722408e91b643d12ce4181ce26296f3) Thanks [@BurntVal](https://github.com/BurntVal)! - abstraxion dynamic url for grant creation on dashboard
8
32
 
9
- - [#44](https://github.com/burnt-labs/xion.js/pull/44) [`56b9f87`](https://github.com/burnt-labs/xion.js/commit/56b9f87482a7210072eaa279960d1ff01ad5b4e0) Thanks [@justinbarry](https://github.com/justinbarry)! - Add grantee signer client to seamlessly handle grantor/grantee relationships
33
+ - [#44](https://github.com/burnt-labs/xion.js/pull/44) [`56b9f87`](https://github.com/burnt-labs/xion.js/commit/56b9f87482a7210072eaa279960d1ff01ad5b4e0) Thanks [@justinbarry](https://github.com/justinbarry)! - Add grantee signer client to seamlessly handle granter/grantee relationships
10
34
 
11
35
  ### Patch Changes
12
36
 
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import { SigningCosmWasmClient, SigningCosmWasmClientOptions, DeliverTxResponse } from '@cosmjs/cosmwasm-stargate';
2
2
  import { OfflineSigner, EncodeObject } from '@cosmjs/proto-signing';
3
- import { StdFee, SignerData } from '@cosmjs/stargate';
3
+ import { Account, StdFee, SignerData } from '@cosmjs/stargate';
4
4
  import { TxRaw } from 'cosmjs-types/cosmos/tx/v1beta1/tx';
5
5
  import { HttpEndpoint, TendermintClient } from '@cosmjs/tendermint-rpc';
6
6
 
@@ -28,15 +28,16 @@ interface useAbstraxionAccountProps {
28
28
  declare const useAbstraxionAccount: () => useAbstraxionAccountProps;
29
29
 
30
30
  interface GranteeSignerOptions {
31
- readonly grantorAddress: string;
31
+ readonly granterAddress: string;
32
32
  readonly granteeAddress: string;
33
33
  }
34
34
  declare class GranteeSignerClient extends SigningCosmWasmClient {
35
- protected readonly grantorAddress: string;
35
+ protected readonly granterAddress: string;
36
36
  protected readonly granteeAddress: string;
37
37
  static connectWithSigner(endpoint: string | HttpEndpoint, signer: OfflineSigner, options: SigningCosmWasmClientOptions & GranteeSignerOptions): Promise<GranteeSignerClient>;
38
38
  static createWithSigner(cometClient: TendermintClient, signer: OfflineSigner, options: SigningCosmWasmClientOptions & GranteeSignerOptions): Promise<GranteeSignerClient>;
39
- protected constructor(cometClient: TendermintClient | undefined, signer: OfflineSigner, { grantorAddress, granteeAddress, ...options }: SigningCosmWasmClientOptions & GranteeSignerOptions);
39
+ protected constructor(cometClient: TendermintClient | undefined, signer: OfflineSigner, { granterAddress, granteeAddress, ...options }: SigningCosmWasmClientOptions & GranteeSignerOptions);
40
+ getAccount(searchAddress: string): Promise<Account | null>;
40
41
  signAndBroadcast(signerAddress: string, messages: readonly EncodeObject[], fee: StdFee | "auto" | number, memo?: string): Promise<DeliverTxResponse>;
41
42
  sign(signerAddress: string, messages: readonly EncodeObject[], fee: StdFee, memo: string, explicitSignerData?: SignerData): Promise<TxRaw>;
42
43
  }
package/dist/index.js CHANGED
@@ -5,10 +5,12 @@ var react = require('react');
5
5
  var ui = require('@burnt-labs/ui');
6
6
  var jsxRuntime = require('react/jsx-runtime');
7
7
  var cosmjs = require('graz/dist/cosmjs');
8
+ var protoSigning = require('@cosmjs/proto-signing');
8
9
  var constants = require('@burnt-labs/constants');
9
10
  var cosmwasmStargate = require('@cosmjs/cosmwasm-stargate');
10
11
  var tx = require('cosmjs-types/cosmos/authz/v1beta1/tx');
11
12
  var tendermintRpc = require('@cosmjs/tendermint-rpc');
13
+ var signers = require('@burnt-labs/signers');
12
14
 
13
15
  // src/index.ts
14
16
  var AbstraxionContext = react.createContext(
@@ -23,7 +25,7 @@ var AbstraxionContextProvider = ({
23
25
  const [isConnected, setIsConnected] = react.useState(false);
24
26
  const [isConnecting, setIsConnecting] = react.useState(false);
25
27
  const [abstraxionAccount, setAbstraxionAccount] = react.useState(void 0);
26
- const [grantorAddress, setGrantorAddress] = react.useState("");
28
+ const [granterAddress, setgranterAddress] = react.useState("");
27
29
  return /* @__PURE__ */ jsxRuntime.jsx(
28
30
  AbstraxionContext.Provider,
29
31
  {
@@ -36,8 +38,8 @@ var AbstraxionContextProvider = ({
36
38
  setAbstraxionError,
37
39
  abstraxionAccount,
38
40
  setAbstraxionAccount,
39
- grantorAddress,
40
- setGrantorAddress,
41
+ granterAddress,
42
+ setgranterAddress,
41
43
  contracts,
42
44
  dashboardUrl
43
45
  },
@@ -57,11 +59,16 @@ function AbstraxionSignin() {
57
59
  setIsConnecting,
58
60
  setIsConnected,
59
61
  setAbstraxionAccount,
60
- setGrantorAddress,
62
+ setgranterAddress,
61
63
  contracts,
62
64
  dashboardUrl
63
65
  } = react.useContext(AbstraxionContext);
64
66
  const isMounted = react.useRef(false);
67
+ const [tempAccountAddress, setTempAccountAddress] = react.useState("");
68
+ function configuregranter(address) {
69
+ setgranterAddress(address);
70
+ localStorage.setItem("xion-authz-granter-account", address);
71
+ }
65
72
  function openDashboardTab(userAddress, contracts2) {
66
73
  const urlParams = new URLSearchParams();
67
74
  urlParams.set("grantee", userAddress);
@@ -77,13 +84,10 @@ function AbstraxionSignin() {
77
84
  localStorage.setItem("xion-authz-temp-account", serializedKeypair);
78
85
  return keypair;
79
86
  }
80
- async function pollForGrants(keypair) {
81
- if (!keypair) {
82
- throw new Error("No keypair");
87
+ async function pollForGrants(address) {
88
+ if (!address) {
89
+ throw new Error("No keypair address");
83
90
  }
84
- setIsConnecting(true);
85
- const accounts = await keypair.getAccounts();
86
- const address = accounts[0].address;
87
91
  const shouldContinue = true;
88
92
  while (shouldContinue) {
89
93
  try {
@@ -96,38 +100,44 @@ function AbstraxionSignin() {
96
100
  );
97
101
  const data = await res.json();
98
102
  if (data.grants?.length > 0) {
103
+ setIsConnecting(true);
99
104
  const granterAddresses = data.grants.map((grant) => grant.granter);
100
105
  const uniqueGranters = [...new Set(granterAddresses)];
101
106
  if (uniqueGranters.length > 1) {
102
107
  console.error("More than one granter found. Taking first.");
103
108
  }
104
- setGrantorAddress(uniqueGranters[0]);
109
+ configuregranter(uniqueGranters[0]);
105
110
  break;
106
111
  }
107
112
  } catch (error) {
108
- console.log("There was an error polling for grants: ", error);
113
+ throw error;
109
114
  }
110
115
  }
111
- setIsConnecting(false);
112
- setIsConnected(true);
113
- setAbstraxionAccount(keypair);
114
116
  }
115
117
  react.useEffect(() => {
116
118
  async function onStartup() {
117
- const existingKeypair = localStorage.getItem("xion-authz-temp-account");
118
- let keypair;
119
- if (existingKeypair) {
120
- keypair = await cosmjs.DirectSecp256k1HdWallet.deserialize(
121
- existingKeypair,
122
- "abstraxion"
123
- );
124
- } else {
125
- keypair = await generateAndStoreTempAccount();
119
+ try {
120
+ const existingKeypair = localStorage.getItem("xion-authz-temp-account");
121
+ let keypair;
122
+ if (existingKeypair) {
123
+ keypair = await cosmjs.DirectSecp256k1HdWallet.deserialize(
124
+ existingKeypair,
125
+ "abstraxion"
126
+ );
127
+ } else {
128
+ keypair = await generateAndStoreTempAccount();
129
+ }
130
+ const accounts = await keypair.getAccounts();
131
+ const address = accounts[0].address;
132
+ setTempAccountAddress(address);
133
+ openDashboardTab(address, contracts);
134
+ await pollForGrants(address);
135
+ setIsConnecting(false);
136
+ setIsConnected(true);
137
+ setAbstraxionAccount(keypair);
138
+ } catch (error) {
139
+ console.log("Something went wrong: ", error);
126
140
  }
127
- const accounts = await keypair.getAccounts();
128
- const address = accounts[0].address;
129
- openDashboardTab(address, contracts);
130
- pollForGrants(keypair);
131
141
  }
132
142
  if (!isMounted.current) {
133
143
  onStartup();
@@ -140,7 +150,14 @@ function AbstraxionSignin() {
140
150
  /* @__PURE__ */ jsxRuntime.jsx("h2", { className: "ui-w-full ui-tracking-tighter ui-text-sm ui-mb-4 ui-text-neutral-500", children: "Please switch to the newly opened tab and enter your credentials to securely complete your account creation" })
141
151
  ] }),
142
152
  /* @__PURE__ */ jsxRuntime.jsx(ui.BrowserIcon, {}),
143
- /* @__PURE__ */ jsxRuntime.jsx(ui.Button, { structure: "naked", children: "Have a Problem? Try Again" })
153
+ /* @__PURE__ */ jsxRuntime.jsx(
154
+ ui.Button,
155
+ {
156
+ onClick: () => openDashboardTab(tempAccountAddress, contracts),
157
+ structure: "naked",
158
+ children: "Have a Problem? Try Again"
159
+ }
160
+ )
144
161
  ] });
145
162
  }
146
163
  var Loading = () => {
@@ -169,13 +186,15 @@ function ErrorDisplay() {
169
186
  )
170
187
  ] });
171
188
  }
172
- function Connected() {
173
- const { setIsConnected } = react.useContext(
174
- AbstraxionContext
175
- );
189
+ function Connected({ onClose }) {
190
+ const { setIsConnected, setAbstraxionAccount, setgranterAddress } = react.useContext(AbstraxionContext);
176
191
  function handleLogout() {
177
- localStorage.removeItem("xion-authz-temp-account");
178
192
  setIsConnected(false);
193
+ localStorage.removeItem("xion-authz-temp-account");
194
+ localStorage.removeItem("xion-authz-granter-account");
195
+ setAbstraxionAccount(void 0);
196
+ setgranterAddress("");
197
+ onClose();
179
198
  }
180
199
  return /* @__PURE__ */ jsxRuntime.jsx(ui.ModalSection, { children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "ui-flex ui-flex-col ui-h-full ui-w-full ui-items-center ui-justify-center ui-text-white", children: [
181
200
  /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "ui-tracking-tighter ui-text-3xl ui-font-bold ui-text-white ui-uppercase ui-mb-3", children: "Connected" }),
@@ -198,7 +217,7 @@ function Abstraxion({
198
217
  }, [onClose]);
199
218
  if (!isOpen)
200
219
  return null;
201
- return /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DialogContent, { children: abstraxionError ? /* @__PURE__ */ jsxRuntime.jsx(ErrorDisplay, {}) : isConnecting ? /* @__PURE__ */ jsxRuntime.jsx(Loading, {}) : isConnected ? /* @__PURE__ */ jsxRuntime.jsx(Connected, {}) : /* @__PURE__ */ jsxRuntime.jsx(AbstraxionSignin, {}) }) });
220
+ return /* @__PURE__ */ jsxRuntime.jsx(ui.Dialog, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsxRuntime.jsx(ui.DialogContent, { children: abstraxionError ? /* @__PURE__ */ jsxRuntime.jsx(ErrorDisplay, {}) : isConnecting ? /* @__PURE__ */ jsxRuntime.jsx(Loading, {}) : isConnected ? /* @__PURE__ */ jsxRuntime.jsx(Connected, { onClose }) : /* @__PURE__ */ jsxRuntime.jsx(AbstraxionSignin, {}) }) });
202
221
  }
203
222
  function AbstraxionProvider({
204
223
  children,
@@ -214,18 +233,53 @@ function AbstraxionProvider({
214
233
  );
215
234
  }
216
235
  var useAbstraxionAccount = () => {
217
- const { isConnected, grantorAddress } = react.useContext(
218
- AbstraxionContext
219
- );
236
+ const {
237
+ isConnected,
238
+ granterAddress,
239
+ abstraxionAccount,
240
+ isConnecting,
241
+ setgranterAddress,
242
+ setAbstraxionAccount,
243
+ setIsConnected,
244
+ setIsConnecting
245
+ } = react.useContext(AbstraxionContext);
246
+ react.useEffect(() => {
247
+ async function configureAccount() {
248
+ setIsConnecting(true);
249
+ const tempKeypair = localStorage.getItem("xion-authz-temp-account");
250
+ if (tempKeypair) {
251
+ const deserializedKeypair = await protoSigning.DirectSecp256k1HdWallet.deserialize(
252
+ tempKeypair,
253
+ "abstraxion"
254
+ );
255
+ setAbstraxionAccount(deserializedKeypair);
256
+ const granterAccount = localStorage.getItem(
257
+ "xion-authz-granter-account"
258
+ );
259
+ if (granterAccount) {
260
+ setgranterAddress(granterAccount);
261
+ setIsConnected(true);
262
+ }
263
+ } else {
264
+ localStorage.removeItem("xion-authz-granter-account");
265
+ setAbstraxionAccount(void 0);
266
+ setgranterAddress("");
267
+ }
268
+ setIsConnecting(false);
269
+ }
270
+ if (!isConnecting && !abstraxionAccount && !granterAddress) {
271
+ configureAccount();
272
+ }
273
+ }, [isConnected, abstraxionAccount, granterAddress]);
220
274
  return {
221
275
  data: {
222
- bech32Address: grantorAddress
276
+ bech32Address: granterAddress
223
277
  },
224
278
  isConnected
225
279
  };
226
280
  };
227
281
  var GranteeSignerClient = class extends cosmwasmStargate.SigningCosmWasmClient {
228
- grantorAddress;
282
+ granterAddress;
229
283
  granteeAddress;
230
284
  static async connectWithSigner(endpoint, signer, options) {
231
285
  const tmClient = await tendermintRpc.Tendermint37Client.connect(endpoint);
@@ -235,22 +289,29 @@ var GranteeSignerClient = class extends cosmwasmStargate.SigningCosmWasmClient {
235
289
  return new GranteeSignerClient(cometClient, signer, options);
236
290
  }
237
291
  constructor(cometClient, signer, {
238
- grantorAddress,
292
+ granterAddress,
239
293
  granteeAddress,
240
294
  ...options
241
295
  }) {
242
296
  super(cometClient, signer, options);
243
- if (grantorAddress === void 0) {
244
- throw new Error("grantorAddress is required");
297
+ if (granterAddress === void 0) {
298
+ throw new Error("granterAddress is required");
245
299
  }
246
- this.grantorAddress = grantorAddress;
300
+ this.granterAddress = granterAddress;
247
301
  if (granteeAddress === void 0) {
248
302
  throw new Error("granteeAddress is required");
249
303
  }
250
304
  this.granteeAddress = granteeAddress;
251
305
  }
306
+ async getAccount(searchAddress) {
307
+ const account = await this.forceGetQueryClient().auth.account(searchAddress);
308
+ if (!account) {
309
+ return null;
310
+ }
311
+ return signers.customAccountFromAny(account);
312
+ }
252
313
  async signAndBroadcast(signerAddress, messages, fee, memo = "") {
253
- if (signerAddress === this.grantorAddress) {
314
+ if (signerAddress === this.granterAddress) {
254
315
  signerAddress = this.granteeAddress;
255
316
  messages = [
256
317
  {
@@ -265,7 +326,7 @@ var GranteeSignerClient = class extends cosmwasmStargate.SigningCosmWasmClient {
265
326
  return super.signAndBroadcast(signerAddress, messages, fee, memo);
266
327
  }
267
328
  async sign(signerAddress, messages, fee, memo, explicitSignerData) {
268
- if (signerAddress === this.grantorAddress) {
329
+ if (signerAddress === this.granterAddress) {
269
330
  signerAddress = this.granteeAddress;
270
331
  messages = [
271
332
  {
@@ -283,7 +344,7 @@ var GranteeSignerClient = class extends cosmwasmStargate.SigningCosmWasmClient {
283
344
 
284
345
  // src/hooks/useAbstraxionSigningClient.ts
285
346
  var useAbstraxionSigningClient = () => {
286
- const { isConnected, abstraxionAccount, grantorAddress } = react.useContext(
347
+ const { isConnected, abstraxionAccount, granterAddress } = react.useContext(
287
348
  AbstraxionContext
288
349
  );
289
350
  const [abstractClient, setAbstractClient] = react.useState(void 0);
@@ -293,6 +354,9 @@ var useAbstraxionSigningClient = () => {
293
354
  if (!abstraxionAccount) {
294
355
  throw new Error("No account found.");
295
356
  }
357
+ if (!granterAddress) {
358
+ throw new Error("No granter found.");
359
+ }
296
360
  const granteeAddress = await abstraxionAccount.getAccounts().then((accounts) => {
297
361
  if (accounts.length === 0) {
298
362
  throw new Error("No account found.");
@@ -304,19 +368,18 @@ var useAbstraxionSigningClient = () => {
304
368
  abstraxionAccount,
305
369
  {
306
370
  gasPrice: cosmjs.GasPrice.fromString("0uxion"),
307
- grantorAddress,
371
+ granterAddress,
308
372
  granteeAddress
309
373
  }
310
374
  );
311
375
  setAbstractClient(directClient);
312
376
  } catch (error) {
313
377
  console.log("Something went wrong: ", error);
378
+ setAbstractClient(void 0);
314
379
  }
315
380
  }
316
- if (isConnected && abstraxionAccount) {
317
- getSigner();
318
- }
319
- }, [abstraxionAccount, isConnected]);
381
+ getSigner();
382
+ }, [isConnected, abstraxionAccount, granterAddress]);
320
383
  return { client: abstractClient };
321
384
  };
322
385
 
package/dist/index.mjs CHANGED
@@ -2,11 +2,13 @@ import '@burnt-labs/ui/styles.css';
2
2
  import { createContext, useContext, useEffect, useState, useRef } from 'react';
3
3
  import { Dialog, DialogContent, ModalSection, BrowserIcon, Button, Spinner } from '@burnt-labs/ui';
4
4
  import { jsx, jsxs } from 'react/jsx-runtime';
5
- import { GasPrice, DirectSecp256k1HdWallet } from 'graz/dist/cosmjs';
5
+ import { GasPrice, DirectSecp256k1HdWallet as DirectSecp256k1HdWallet$1 } from 'graz/dist/cosmjs';
6
+ import { DirectSecp256k1HdWallet } from '@cosmjs/proto-signing';
6
7
  import { testnetChainInfo } from '@burnt-labs/constants';
7
8
  import { SigningCosmWasmClient } from '@cosmjs/cosmwasm-stargate';
8
9
  import { MsgExec } from 'cosmjs-types/cosmos/authz/v1beta1/tx';
9
10
  import { Tendermint37Client } from '@cosmjs/tendermint-rpc';
11
+ import { customAccountFromAny } from '@burnt-labs/signers';
10
12
 
11
13
  // src/index.ts
12
14
  var AbstraxionContext = createContext(
@@ -21,7 +23,7 @@ var AbstraxionContextProvider = ({
21
23
  const [isConnected, setIsConnected] = useState(false);
22
24
  const [isConnecting, setIsConnecting] = useState(false);
23
25
  const [abstraxionAccount, setAbstraxionAccount] = useState(void 0);
24
- const [grantorAddress, setGrantorAddress] = useState("");
26
+ const [granterAddress, setgranterAddress] = useState("");
25
27
  return /* @__PURE__ */ jsx(
26
28
  AbstraxionContext.Provider,
27
29
  {
@@ -34,8 +36,8 @@ var AbstraxionContextProvider = ({
34
36
  setAbstraxionError,
35
37
  abstraxionAccount,
36
38
  setAbstraxionAccount,
37
- grantorAddress,
38
- setGrantorAddress,
39
+ granterAddress,
40
+ setgranterAddress,
39
41
  contracts,
40
42
  dashboardUrl
41
43
  },
@@ -55,11 +57,16 @@ function AbstraxionSignin() {
55
57
  setIsConnecting,
56
58
  setIsConnected,
57
59
  setAbstraxionAccount,
58
- setGrantorAddress,
60
+ setgranterAddress,
59
61
  contracts,
60
62
  dashboardUrl
61
63
  } = useContext(AbstraxionContext);
62
64
  const isMounted = useRef(false);
65
+ const [tempAccountAddress, setTempAccountAddress] = useState("");
66
+ function configuregranter(address) {
67
+ setgranterAddress(address);
68
+ localStorage.setItem("xion-authz-granter-account", address);
69
+ }
63
70
  function openDashboardTab(userAddress, contracts2) {
64
71
  const urlParams = new URLSearchParams();
65
72
  urlParams.set("grantee", userAddress);
@@ -68,20 +75,17 @@ function AbstraxionSignin() {
68
75
  window.open(`${dashboardUrl}?${urlParams}`, "_blank");
69
76
  }
70
77
  async function generateAndStoreTempAccount() {
71
- const keypair = await DirectSecp256k1HdWallet.generate(12, {
78
+ const keypair = await DirectSecp256k1HdWallet$1.generate(12, {
72
79
  prefix: "xion"
73
80
  });
74
81
  const serializedKeypair = await keypair.serialize("abstraxion");
75
82
  localStorage.setItem("xion-authz-temp-account", serializedKeypair);
76
83
  return keypair;
77
84
  }
78
- async function pollForGrants(keypair) {
79
- if (!keypair) {
80
- throw new Error("No keypair");
85
+ async function pollForGrants(address) {
86
+ if (!address) {
87
+ throw new Error("No keypair address");
81
88
  }
82
- setIsConnecting(true);
83
- const accounts = await keypair.getAccounts();
84
- const address = accounts[0].address;
85
89
  const shouldContinue = true;
86
90
  while (shouldContinue) {
87
91
  try {
@@ -94,38 +98,44 @@ function AbstraxionSignin() {
94
98
  );
95
99
  const data = await res.json();
96
100
  if (data.grants?.length > 0) {
101
+ setIsConnecting(true);
97
102
  const granterAddresses = data.grants.map((grant) => grant.granter);
98
103
  const uniqueGranters = [...new Set(granterAddresses)];
99
104
  if (uniqueGranters.length > 1) {
100
105
  console.error("More than one granter found. Taking first.");
101
106
  }
102
- setGrantorAddress(uniqueGranters[0]);
107
+ configuregranter(uniqueGranters[0]);
103
108
  break;
104
109
  }
105
110
  } catch (error) {
106
- console.log("There was an error polling for grants: ", error);
111
+ throw error;
107
112
  }
108
113
  }
109
- setIsConnecting(false);
110
- setIsConnected(true);
111
- setAbstraxionAccount(keypair);
112
114
  }
113
115
  useEffect(() => {
114
116
  async function onStartup() {
115
- const existingKeypair = localStorage.getItem("xion-authz-temp-account");
116
- let keypair;
117
- if (existingKeypair) {
118
- keypair = await DirectSecp256k1HdWallet.deserialize(
119
- existingKeypair,
120
- "abstraxion"
121
- );
122
- } else {
123
- keypair = await generateAndStoreTempAccount();
117
+ try {
118
+ const existingKeypair = localStorage.getItem("xion-authz-temp-account");
119
+ let keypair;
120
+ if (existingKeypair) {
121
+ keypair = await DirectSecp256k1HdWallet$1.deserialize(
122
+ existingKeypair,
123
+ "abstraxion"
124
+ );
125
+ } else {
126
+ keypair = await generateAndStoreTempAccount();
127
+ }
128
+ const accounts = await keypair.getAccounts();
129
+ const address = accounts[0].address;
130
+ setTempAccountAddress(address);
131
+ openDashboardTab(address, contracts);
132
+ await pollForGrants(address);
133
+ setIsConnecting(false);
134
+ setIsConnected(true);
135
+ setAbstraxionAccount(keypair);
136
+ } catch (error) {
137
+ console.log("Something went wrong: ", error);
124
138
  }
125
- const accounts = await keypair.getAccounts();
126
- const address = accounts[0].address;
127
- openDashboardTab(address, contracts);
128
- pollForGrants(keypair);
129
139
  }
130
140
  if (!isMounted.current) {
131
141
  onStartup();
@@ -138,7 +148,14 @@ function AbstraxionSignin() {
138
148
  /* @__PURE__ */ jsx("h2", { className: "ui-w-full ui-tracking-tighter ui-text-sm ui-mb-4 ui-text-neutral-500", children: "Please switch to the newly opened tab and enter your credentials to securely complete your account creation" })
139
149
  ] }),
140
150
  /* @__PURE__ */ jsx(BrowserIcon, {}),
141
- /* @__PURE__ */ jsx(Button, { structure: "naked", children: "Have a Problem? Try Again" })
151
+ /* @__PURE__ */ jsx(
152
+ Button,
153
+ {
154
+ onClick: () => openDashboardTab(tempAccountAddress, contracts),
155
+ structure: "naked",
156
+ children: "Have a Problem? Try Again"
157
+ }
158
+ )
142
159
  ] });
143
160
  }
144
161
  var Loading = () => {
@@ -167,13 +184,15 @@ function ErrorDisplay() {
167
184
  )
168
185
  ] });
169
186
  }
170
- function Connected() {
171
- const { setIsConnected } = useContext(
172
- AbstraxionContext
173
- );
187
+ function Connected({ onClose }) {
188
+ const { setIsConnected, setAbstraxionAccount, setgranterAddress } = useContext(AbstraxionContext);
174
189
  function handleLogout() {
175
- localStorage.removeItem("xion-authz-temp-account");
176
190
  setIsConnected(false);
191
+ localStorage.removeItem("xion-authz-temp-account");
192
+ localStorage.removeItem("xion-authz-granter-account");
193
+ setAbstraxionAccount(void 0);
194
+ setgranterAddress("");
195
+ onClose();
177
196
  }
178
197
  return /* @__PURE__ */ jsx(ModalSection, { children: /* @__PURE__ */ jsxs("div", { className: "ui-flex ui-flex-col ui-h-full ui-w-full ui-items-center ui-justify-center ui-text-white", children: [
179
198
  /* @__PURE__ */ jsx("h1", { className: "ui-tracking-tighter ui-text-3xl ui-font-bold ui-text-white ui-uppercase ui-mb-3", children: "Connected" }),
@@ -196,7 +215,7 @@ function Abstraxion({
196
215
  }, [onClose]);
197
216
  if (!isOpen)
198
217
  return null;
199
- return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsx(DialogContent, { children: abstraxionError ? /* @__PURE__ */ jsx(ErrorDisplay, {}) : isConnecting ? /* @__PURE__ */ jsx(Loading, {}) : isConnected ? /* @__PURE__ */ jsx(Connected, {}) : /* @__PURE__ */ jsx(AbstraxionSignin, {}) }) });
218
+ return /* @__PURE__ */ jsx(Dialog, { open: isOpen, onOpenChange: onClose, children: /* @__PURE__ */ jsx(DialogContent, { children: abstraxionError ? /* @__PURE__ */ jsx(ErrorDisplay, {}) : isConnecting ? /* @__PURE__ */ jsx(Loading, {}) : isConnected ? /* @__PURE__ */ jsx(Connected, { onClose }) : /* @__PURE__ */ jsx(AbstraxionSignin, {}) }) });
200
219
  }
201
220
  function AbstraxionProvider({
202
221
  children,
@@ -212,18 +231,53 @@ function AbstraxionProvider({
212
231
  );
213
232
  }
214
233
  var useAbstraxionAccount = () => {
215
- const { isConnected, grantorAddress } = useContext(
216
- AbstraxionContext
217
- );
234
+ const {
235
+ isConnected,
236
+ granterAddress,
237
+ abstraxionAccount,
238
+ isConnecting,
239
+ setgranterAddress,
240
+ setAbstraxionAccount,
241
+ setIsConnected,
242
+ setIsConnecting
243
+ } = useContext(AbstraxionContext);
244
+ useEffect(() => {
245
+ async function configureAccount() {
246
+ setIsConnecting(true);
247
+ const tempKeypair = localStorage.getItem("xion-authz-temp-account");
248
+ if (tempKeypair) {
249
+ const deserializedKeypair = await DirectSecp256k1HdWallet.deserialize(
250
+ tempKeypair,
251
+ "abstraxion"
252
+ );
253
+ setAbstraxionAccount(deserializedKeypair);
254
+ const granterAccount = localStorage.getItem(
255
+ "xion-authz-granter-account"
256
+ );
257
+ if (granterAccount) {
258
+ setgranterAddress(granterAccount);
259
+ setIsConnected(true);
260
+ }
261
+ } else {
262
+ localStorage.removeItem("xion-authz-granter-account");
263
+ setAbstraxionAccount(void 0);
264
+ setgranterAddress("");
265
+ }
266
+ setIsConnecting(false);
267
+ }
268
+ if (!isConnecting && !abstraxionAccount && !granterAddress) {
269
+ configureAccount();
270
+ }
271
+ }, [isConnected, abstraxionAccount, granterAddress]);
218
272
  return {
219
273
  data: {
220
- bech32Address: grantorAddress
274
+ bech32Address: granterAddress
221
275
  },
222
276
  isConnected
223
277
  };
224
278
  };
225
279
  var GranteeSignerClient = class extends SigningCosmWasmClient {
226
- grantorAddress;
280
+ granterAddress;
227
281
  granteeAddress;
228
282
  static async connectWithSigner(endpoint, signer, options) {
229
283
  const tmClient = await Tendermint37Client.connect(endpoint);
@@ -233,22 +287,29 @@ var GranteeSignerClient = class extends SigningCosmWasmClient {
233
287
  return new GranteeSignerClient(cometClient, signer, options);
234
288
  }
235
289
  constructor(cometClient, signer, {
236
- grantorAddress,
290
+ granterAddress,
237
291
  granteeAddress,
238
292
  ...options
239
293
  }) {
240
294
  super(cometClient, signer, options);
241
- if (grantorAddress === void 0) {
242
- throw new Error("grantorAddress is required");
295
+ if (granterAddress === void 0) {
296
+ throw new Error("granterAddress is required");
243
297
  }
244
- this.grantorAddress = grantorAddress;
298
+ this.granterAddress = granterAddress;
245
299
  if (granteeAddress === void 0) {
246
300
  throw new Error("granteeAddress is required");
247
301
  }
248
302
  this.granteeAddress = granteeAddress;
249
303
  }
304
+ async getAccount(searchAddress) {
305
+ const account = await this.forceGetQueryClient().auth.account(searchAddress);
306
+ if (!account) {
307
+ return null;
308
+ }
309
+ return customAccountFromAny(account);
310
+ }
250
311
  async signAndBroadcast(signerAddress, messages, fee, memo = "") {
251
- if (signerAddress === this.grantorAddress) {
312
+ if (signerAddress === this.granterAddress) {
252
313
  signerAddress = this.granteeAddress;
253
314
  messages = [
254
315
  {
@@ -263,7 +324,7 @@ var GranteeSignerClient = class extends SigningCosmWasmClient {
263
324
  return super.signAndBroadcast(signerAddress, messages, fee, memo);
264
325
  }
265
326
  async sign(signerAddress, messages, fee, memo, explicitSignerData) {
266
- if (signerAddress === this.grantorAddress) {
327
+ if (signerAddress === this.granterAddress) {
267
328
  signerAddress = this.granteeAddress;
268
329
  messages = [
269
330
  {
@@ -281,7 +342,7 @@ var GranteeSignerClient = class extends SigningCosmWasmClient {
281
342
 
282
343
  // src/hooks/useAbstraxionSigningClient.ts
283
344
  var useAbstraxionSigningClient = () => {
284
- const { isConnected, abstraxionAccount, grantorAddress } = useContext(
345
+ const { isConnected, abstraxionAccount, granterAddress } = useContext(
285
346
  AbstraxionContext
286
347
  );
287
348
  const [abstractClient, setAbstractClient] = useState(void 0);
@@ -291,6 +352,9 @@ var useAbstraxionSigningClient = () => {
291
352
  if (!abstraxionAccount) {
292
353
  throw new Error("No account found.");
293
354
  }
355
+ if (!granterAddress) {
356
+ throw new Error("No granter found.");
357
+ }
294
358
  const granteeAddress = await abstraxionAccount.getAccounts().then((accounts) => {
295
359
  if (accounts.length === 0) {
296
360
  throw new Error("No account found.");
@@ -302,19 +366,18 @@ var useAbstraxionSigningClient = () => {
302
366
  abstraxionAccount,
303
367
  {
304
368
  gasPrice: GasPrice.fromString("0uxion"),
305
- grantorAddress,
369
+ granterAddress,
306
370
  granteeAddress
307
371
  }
308
372
  );
309
373
  setAbstractClient(directClient);
310
374
  } catch (error) {
311
375
  console.log("Something went wrong: ", error);
376
+ setAbstractClient(void 0);
312
377
  }
313
378
  }
314
- if (isConnected && abstraxionAccount) {
315
- getSigner();
316
- }
317
- }, [abstraxionAccount, isConnected]);
379
+ getSigner();
380
+ }, [isConnected, abstraxionAccount, granterAddress]);
318
381
  return { client: abstractClient };
319
382
  };
320
383
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@burnt-labs/abstraxion",
3
- "version": "0.1.0-alpha.21",
3
+ "version": "0.1.0-alpha.23",
4
4
  "sideEffects": [
5
5
  "**/*.css"
6
6
  ],
@@ -31,20 +31,17 @@
31
31
  "@burnt-labs/tsconfig": "0.0.1-alpha.0"
32
32
  },
33
33
  "dependencies": {
34
- "@apollo/client": "^3.8.8",
35
34
  "@cosmjs/cosmwasm-stargate": "^0.31.3",
36
35
  "@cosmjs/proto-signing": "^0.31.3",
37
36
  "@cosmjs/stargate": "^0.31.3",
38
37
  "cosmjs-types": "^0.8.0",
39
38
  "@cosmjs/tendermint-rpc": "^0.31.1",
40
- "@stytch/nextjs": "^14.0.0",
41
- "@stytch/vanilla-js": "^3.2.1",
42
39
  "@types/react-dom": "^18.2.18",
43
40
  "graz": "^0.0.51",
44
41
  "jose": "^5.1.3",
45
42
  "@burnt-labs/constants": "0.0.1-alpha.2",
46
- "@burnt-labs/signers": "0.1.0-alpha.3",
47
- "@burnt-labs/ui": "0.0.1-alpha.3"
43
+ "@burnt-labs/signers": "0.1.0-alpha.4",
44
+ "@burnt-labs/ui": "0.1.0-alpha.4"
48
45
  },
49
46
  "scripts": {
50
47
  "build": "tsup",
@@ -4,7 +4,7 @@ import {
4
4
  SigningCosmWasmClientOptions,
5
5
  } from "@cosmjs/cosmwasm-stargate";
6
6
  import { EncodeObject, OfflineSigner } from "@cosmjs/proto-signing";
7
- import { SignerData, StdFee } from "@cosmjs/stargate";
7
+ import type { Account, SignerData, StdFee } from "@cosmjs/stargate";
8
8
  import type { TxRaw } from "cosmjs-types/cosmos/tx/v1beta1/tx";
9
9
  import { MsgExec } from "cosmjs-types/cosmos/authz/v1beta1/tx";
10
10
  import {
@@ -12,14 +12,15 @@ import {
12
12
  Tendermint37Client,
13
13
  TendermintClient,
14
14
  } from "@cosmjs/tendermint-rpc";
15
+ import { customAccountFromAny } from "@burnt-labs/signers";
15
16
 
16
17
  interface GranteeSignerOptions {
17
- readonly grantorAddress: string;
18
+ readonly granterAddress: string;
18
19
  readonly granteeAddress: string;
19
20
  }
20
21
 
21
22
  export class GranteeSignerClient extends SigningCosmWasmClient {
22
- protected readonly grantorAddress: string;
23
+ protected readonly granterAddress: string;
23
24
  protected readonly granteeAddress: string;
24
25
 
25
26
  public static async connectWithSigner(
@@ -43,16 +44,16 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
43
44
  cometClient: TendermintClient | undefined,
44
45
  signer: OfflineSigner,
45
46
  {
46
- grantorAddress,
47
+ granterAddress,
47
48
  granteeAddress,
48
49
  ...options
49
50
  }: SigningCosmWasmClientOptions & GranteeSignerOptions,
50
51
  ) {
51
52
  super(cometClient, signer, options);
52
- if (grantorAddress === undefined) {
53
- throw new Error("grantorAddress is required");
53
+ if (granterAddress === undefined) {
54
+ throw new Error("granterAddress is required");
54
55
  }
55
- this.grantorAddress = grantorAddress;
56
+ this.granterAddress = granterAddress;
56
57
 
57
58
  if (granteeAddress === undefined) {
58
59
  throw new Error("granteeAddress is required");
@@ -60,14 +61,23 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
60
61
  this.granteeAddress = granteeAddress;
61
62
  }
62
63
 
64
+ public async getAccount(searchAddress: string): Promise<Account | null> {
65
+ const account =
66
+ await this.forceGetQueryClient().auth.account(searchAddress);
67
+ if (!account) {
68
+ return null;
69
+ }
70
+ return customAccountFromAny(account);
71
+ }
72
+
63
73
  public async signAndBroadcast(
64
74
  signerAddress: string,
65
75
  messages: readonly EncodeObject[],
66
76
  fee: StdFee | "auto" | number,
67
77
  memo = "",
68
78
  ): Promise<DeliverTxResponse> {
69
- // Figure out if the signerAddress is a grantor
70
- if (signerAddress === this.grantorAddress) {
79
+ // Figure out if the signerAddress is a granter
80
+ if (signerAddress === this.granterAddress) {
71
81
  signerAddress = this.granteeAddress;
72
82
  // Wrap the signerAddress in a MsgExec
73
83
  messages = [
@@ -91,8 +101,8 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
91
101
  memo: string,
92
102
  explicitSignerData?: SignerData,
93
103
  ): Promise<TxRaw> {
94
- // Figure out if the signerAddress is a grantor
95
- if (signerAddress === this.grantorAddress) {
104
+ // Figure out if the signerAddress is a granter
105
+ if (signerAddress === this.granterAddress) {
96
106
  signerAddress = this.granteeAddress;
97
107
  // Wrap the signerAddress in a MsgExec
98
108
  messages = [
@@ -1,14 +1,10 @@
1
1
  "use client";
2
2
  import { useContext, useEffect } from "react";
3
- import { GrazProvider } from "graz";
4
- import { StytchProvider } from "@stytch/nextjs";
5
- import { ApolloProvider } from "@apollo/client";
6
3
  import { Dialog, DialogContent } from "@burnt-labs/ui";
7
4
  import {
8
5
  AbstraxionContext,
9
6
  AbstraxionContextProvider,
10
7
  } from "../AbstraxionContext";
11
- import { apolloClient, stytchClient } from "../../lib";
12
8
  import { AbstraxionSignin } from "../AbstraxionSignin";
13
9
  import { Loading } from "../Loading";
14
10
  import { ErrorDisplay } from "../ErrorDisplay";
@@ -46,7 +42,7 @@ export function Abstraxion({
46
42
  ) : isConnecting ? (
47
43
  <Loading />
48
44
  ) : isConnected ? (
49
- <Connected />
45
+ <Connected onClose={onClose} />
50
46
  ) : (
51
47
  <AbstraxionSignin />
52
48
  )}
@@ -10,8 +10,8 @@ export interface AbstraxionContextProps {
10
10
  setAbstraxionError: React.Dispatch<React.SetStateAction<string>>;
11
11
  abstraxionAccount: DirectSecp256k1HdWallet | undefined;
12
12
  setAbstraxionAccount: React.Dispatch<DirectSecp256k1HdWallet | undefined>;
13
- grantorAddress: string;
14
- setGrantorAddress: React.Dispatch<React.SetStateAction<string>>;
13
+ granterAddress: string;
14
+ setgranterAddress: React.Dispatch<React.SetStateAction<string>>;
15
15
  contracts?: string[];
16
16
  dashboardUrl?: string;
17
17
  }
@@ -35,7 +35,7 @@ export const AbstraxionContextProvider = ({
35
35
  const [abstraxionAccount, setAbstraxionAccount] = useState<
36
36
  DirectSecp256k1HdWallet | undefined
37
37
  >(undefined);
38
- const [grantorAddress, setGrantorAddress] = useState("");
38
+ const [granterAddress, setgranterAddress] = useState("");
39
39
 
40
40
  return (
41
41
  <AbstraxionContext.Provider
@@ -48,8 +48,8 @@ export const AbstraxionContextProvider = ({
48
48
  setAbstraxionError,
49
49
  abstraxionAccount,
50
50
  setAbstraxionAccount,
51
- grantorAddress,
52
- setGrantorAddress,
51
+ granterAddress,
52
+ setgranterAddress,
53
53
  contracts,
54
54
  dashboardUrl,
55
55
  }}
@@ -1,5 +1,5 @@
1
1
  "use client";
2
- import { useContext, useEffect, useRef } from "react";
2
+ import { useContext, useEffect, useRef, useState } from "react";
3
3
  import { DirectSecp256k1HdWallet } from "graz/dist/cosmjs";
4
4
  import { Button, ModalSection, BrowserIcon } from "@burnt-labs/ui";
5
5
  import { wait } from "@/utils/wait";
@@ -47,12 +47,18 @@ export function AbstraxionSignin(): JSX.Element {
47
47
  setIsConnecting,
48
48
  setIsConnected,
49
49
  setAbstraxionAccount,
50
- setGrantorAddress,
50
+ setgranterAddress,
51
51
  contracts,
52
52
  dashboardUrl,
53
53
  } = useContext(AbstraxionContext);
54
54
 
55
55
  const isMounted = useRef(false);
56
+ const [tempAccountAddress, setTempAccountAddress] = useState("");
57
+
58
+ function configuregranter(address: string) {
59
+ setgranterAddress(address);
60
+ localStorage.setItem("xion-authz-granter-account", address);
61
+ }
56
62
 
57
63
  function openDashboardTab(userAddress: string, contracts?: string[]): void {
58
64
  const urlParams = new URLSearchParams();
@@ -73,16 +79,11 @@ export function AbstraxionSignin(): JSX.Element {
73
79
  return keypair;
74
80
  }
75
81
 
76
- async function pollForGrants(
77
- keypair: DirectSecp256k1HdWallet,
78
- ): Promise<void> {
79
- if (!keypair) {
80
- throw new Error("No keypair");
82
+ async function pollForGrants(address: string): Promise<void> {
83
+ if (!address) {
84
+ throw new Error("No keypair address");
81
85
  }
82
- setIsConnecting(true);
83
86
 
84
- const accounts = await keypair.getAccounts();
85
- const address = accounts[0].address;
86
87
  const shouldContinue = true;
87
88
  while (shouldContinue) {
88
89
  try {
@@ -95,41 +96,46 @@ export function AbstraxionSignin(): JSX.Element {
95
96
  );
96
97
  const data = (await res.json()) as GrantsResponse;
97
98
  if (data.grants?.length > 0) {
99
+ setIsConnecting(true);
98
100
  const granterAddresses = data.grants.map((grant) => grant.granter);
99
101
  const uniqueGranters = [...new Set(granterAddresses)];
100
102
  if (uniqueGranters.length > 1) {
101
103
  console.error("More than one granter found. Taking first.");
102
104
  }
103
105
 
104
- setGrantorAddress(uniqueGranters[0]);
106
+ configuregranter(uniqueGranters[0]);
105
107
  break;
106
108
  }
107
109
  } catch (error) {
108
- console.log("There was an error polling for grants: ", error);
110
+ throw error;
109
111
  }
110
112
  }
111
-
112
- setIsConnecting(false);
113
- setIsConnected(true);
114
- setAbstraxionAccount(keypair);
115
113
  }
116
114
 
117
115
  useEffect(() => {
118
116
  async function onStartup() {
119
- const existingKeypair = localStorage.getItem("xion-authz-temp-account");
120
- let keypair;
121
- if (existingKeypair) {
122
- keypair = await DirectSecp256k1HdWallet.deserialize(
123
- existingKeypair,
124
- "abstraxion",
125
- );
126
- } else {
127
- keypair = await generateAndStoreTempAccount();
117
+ try {
118
+ const existingKeypair = localStorage.getItem("xion-authz-temp-account");
119
+ let keypair;
120
+ if (existingKeypair) {
121
+ keypair = await DirectSecp256k1HdWallet.deserialize(
122
+ existingKeypair,
123
+ "abstraxion",
124
+ );
125
+ } else {
126
+ keypair = await generateAndStoreTempAccount();
127
+ }
128
+ const accounts = await keypair.getAccounts();
129
+ const address = accounts[0].address;
130
+ setTempAccountAddress(address);
131
+ openDashboardTab(address, contracts);
132
+ await pollForGrants(address);
133
+ setIsConnecting(false);
134
+ setIsConnected(true);
135
+ setAbstraxionAccount(keypair);
136
+ } catch (error) {
137
+ console.log("Something went wrong: ", error);
128
138
  }
129
- const accounts = await keypair.getAccounts();
130
- const address = accounts[0].address;
131
- openDashboardTab(address, contracts);
132
- pollForGrants(keypair);
133
139
  }
134
140
 
135
141
  if (!isMounted.current) {
@@ -151,7 +157,12 @@ export function AbstraxionSignin(): JSX.Element {
151
157
  </h2>
152
158
  </div>
153
159
  <BrowserIcon />
154
- <Button structure="naked">Have a Problem? Try Again</Button>
160
+ <Button
161
+ onClick={() => openDashboardTab(tempAccountAddress, contracts)}
162
+ structure="naked"
163
+ >
164
+ Have a Problem? Try Again
165
+ </Button>
155
166
  </ModalSection>
156
167
  );
157
168
  }
@@ -5,14 +5,17 @@ import {
5
5
  AbstraxionContextProps,
6
6
  } from "../AbstraxionContext";
7
7
 
8
- export function Connected() {
9
- const { setIsConnected } = useContext(
10
- AbstraxionContext,
11
- ) as AbstraxionContextProps;
8
+ export function Connected({ onClose }: { onClose: VoidFunction }) {
9
+ const { setIsConnected, setAbstraxionAccount, setgranterAddress } =
10
+ useContext(AbstraxionContext) as AbstraxionContextProps;
12
11
 
13
12
  function handleLogout() {
14
- localStorage.removeItem("xion-authz-temp-account");
15
13
  setIsConnected(false);
14
+ localStorage.removeItem("xion-authz-temp-account");
15
+ localStorage.removeItem("xion-authz-granter-account");
16
+ setAbstraxionAccount(undefined);
17
+ setgranterAddress("");
18
+ onClose();
16
19
  }
17
20
 
18
21
  return (
@@ -1,8 +1,9 @@
1
- import { useContext } from "react";
1
+ import { useContext, useEffect } from "react";
2
2
  import {
3
3
  AbstraxionContext,
4
4
  AbstraxionContextProps,
5
5
  } from "@/src/components/AbstraxionContext";
6
+ import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";
6
7
 
7
8
  export interface AbstraxionAccount {
8
9
  bech32Address: string;
@@ -14,13 +15,51 @@ export interface useAbstraxionAccountProps {
14
15
  }
15
16
 
16
17
  export const useAbstraxionAccount = (): useAbstraxionAccountProps => {
17
- const { isConnected, grantorAddress } = useContext(
18
- AbstraxionContext,
19
- ) as AbstraxionContextProps;
18
+ const {
19
+ isConnected,
20
+ granterAddress,
21
+ abstraxionAccount,
22
+ isConnecting,
23
+ setgranterAddress,
24
+ setAbstraxionAccount,
25
+ setIsConnected,
26
+ setIsConnecting,
27
+ } = useContext(AbstraxionContext) as AbstraxionContextProps;
28
+
29
+ useEffect(() => {
30
+ async function configureAccount() {
31
+ setIsConnecting(true);
32
+ const tempKeypair = localStorage.getItem("xion-authz-temp-account");
33
+ if (tempKeypair) {
34
+ const deserializedKeypair = await DirectSecp256k1HdWallet.deserialize(
35
+ tempKeypair,
36
+ "abstraxion",
37
+ );
38
+ setAbstraxionAccount(deserializedKeypair);
39
+ const granterAccount = localStorage.getItem(
40
+ "xion-authz-granter-account",
41
+ );
42
+ if (granterAccount) {
43
+ setgranterAddress(granterAccount);
44
+ setIsConnected(true);
45
+ }
46
+ } else {
47
+ // Wipe granter even if it exists, clean context
48
+ localStorage.removeItem("xion-authz-granter-account");
49
+ setAbstraxionAccount(undefined);
50
+ setgranterAddress("");
51
+ }
52
+ setIsConnecting(false);
53
+ }
54
+
55
+ if (!isConnecting && !abstraxionAccount && !granterAddress) {
56
+ configureAccount();
57
+ }
58
+ }, [isConnected, abstraxionAccount, granterAddress]);
20
59
 
21
60
  return {
22
61
  data: {
23
- bech32Address: grantorAddress,
62
+ bech32Address: granterAddress,
24
63
  },
25
64
  isConnected: isConnected,
26
65
  };
@@ -8,7 +8,7 @@ import {
8
8
  import { GranteeSignerClient } from "@/src/GranteeSignerClient.ts";
9
9
 
10
10
  export const useAbstraxionSigningClient = () => {
11
- const { isConnected, abstraxionAccount, grantorAddress } = useContext(
11
+ const { isConnected, abstraxionAccount, granterAddress } = useContext(
12
12
  AbstraxionContext,
13
13
  ) as AbstraxionContextProps;
14
14
 
@@ -22,6 +22,10 @@ export const useAbstraxionSigningClient = () => {
22
22
  if (!abstraxionAccount) {
23
23
  throw new Error("No account found.");
24
24
  }
25
+
26
+ if (!granterAddress) {
27
+ throw new Error("No granter found.");
28
+ }
25
29
  const granteeAddress = await abstraxionAccount
26
30
  .getAccounts()
27
31
  .then((accounts) => {
@@ -36,7 +40,7 @@ export const useAbstraxionSigningClient = () => {
36
40
  abstraxionAccount,
37
41
  {
38
42
  gasPrice: GasPrice.fromString("0uxion"),
39
- grantorAddress,
43
+ granterAddress,
40
44
  granteeAddress,
41
45
  },
42
46
  );
@@ -44,13 +48,12 @@ export const useAbstraxionSigningClient = () => {
44
48
  setAbstractClient(directClient);
45
49
  } catch (error) {
46
50
  console.log("Something went wrong: ", error);
51
+ setAbstractClient(undefined);
47
52
  }
48
53
  }
49
54
 
50
- if (isConnected && abstraxionAccount) {
51
- getSigner();
52
- }
53
- }, [abstraxionAccount, isConnected]);
55
+ getSigner();
56
+ }, [isConnected, abstraxionAccount, granterAddress]);
54
57
 
55
58
  return { client: abstractClient };
56
59
  };
package/src/lib.ts DELETED
@@ -1,15 +0,0 @@
1
- import { ApolloClient, InMemoryCache } from "@apollo/client";
2
- import { createStytchHeadlessClient } from "@stytch/nextjs/headless";
3
- import { StytchHeadlessClient } from "@stytch/vanilla-js/dist/index.headless";
4
-
5
- // TODO: Temporarily hard-coded
6
- export const stytchClient: StytchHeadlessClient = createStytchHeadlessClient(
7
- "public-token-live-87901ec3-ef19-48ca-b3f4-842be750181b",
8
- );
9
-
10
- // TODO: Refactor to be dynamic. Local dev uri must be device IP.
11
- export const apolloClient = new ApolloClient({
12
- uri: "https://api.subquery.network/sq/burnt-labs/xion-indexer",
13
- cache: new InMemoryCache(),
14
- assumeImmutableResults: true,
15
- });