@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.
- package/.turbo/turbo-build.log +7 -7
- package/CHANGELOG.md +25 -1
- package/dist/index.d.ts +5 -4
- package/dist/index.js +115 -52
- package/dist/index.mjs +117 -54
- package/package.json +3 -6
- package/src/GranteeSignerClient.ts +21 -11
- package/src/components/Abstraxion/index.tsx +1 -5
- package/src/components/AbstraxionContext/index.tsx +5 -5
- package/src/components/AbstraxionSignin/index.tsx +41 -30
- package/src/components/Connected/Connected.tsx +8 -5
- package/src/hooks/useAbstraxionAccount.ts +44 -5
- package/src/hooks/useAbstraxionSigningClient.ts +9 -6
- package/src/lib.ts +0 -15
package/.turbo/turbo-build.log
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
|
|
2
|
-
> @burnt-labs/abstraxion@0.1.0-alpha.
|
|
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
|
[34mCLI[39m Building entry: src/index.ts
|
|
@@ -12,10 +12,10 @@
|
|
|
12
12
|
[34mCJS[39m Build start
|
|
13
13
|
[34mDTS[39m Build start
|
|
14
14
|
[32mESM[39m [1mdist/index.css [22m[32m7.41 KB[39m
|
|
15
|
-
[32mESM[39m [1mdist/index.mjs [22m[
|
|
16
|
-
[32mESM[39m ⚡️ Build success in
|
|
15
|
+
[32mESM[39m [1mdist/index.mjs [22m[32m13.34 KB[39m
|
|
16
|
+
[32mESM[39m ⚡️ Build success in 943ms
|
|
17
17
|
[32mCJS[39m [1mdist/index.css [22m[32m7.41 KB[39m
|
|
18
|
-
[32mCJS[39m [1mdist/index.js [22m[
|
|
19
|
-
[32mCJS[39m ⚡️ Build success in
|
|
20
|
-
[32mDTS[39m ⚡️ Build success in
|
|
21
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.
|
|
18
|
+
[32mCJS[39m [1mdist/index.js [22m[32m13.76 KB[39m
|
|
19
|
+
[32mCJS[39m ⚡️ Build success in 943ms
|
|
20
|
+
[32mDTS[39m ⚡️ Build success in 3287ms
|
|
21
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m2.30 KB[39m
|
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
|
|
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
|
|
31
|
+
readonly granterAddress: string;
|
|
32
32
|
readonly granteeAddress: string;
|
|
33
33
|
}
|
|
34
34
|
declare class GranteeSignerClient extends SigningCosmWasmClient {
|
|
35
|
-
protected readonly
|
|
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, {
|
|
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 [
|
|
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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
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(
|
|
81
|
-
if (!
|
|
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
|
-
|
|
109
|
+
configuregranter(uniqueGranters[0]);
|
|
105
110
|
break;
|
|
106
111
|
}
|
|
107
112
|
} catch (error) {
|
|
108
|
-
|
|
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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
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(
|
|
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 {
|
|
218
|
-
|
|
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:
|
|
276
|
+
bech32Address: granterAddress
|
|
223
277
|
},
|
|
224
278
|
isConnected
|
|
225
279
|
};
|
|
226
280
|
};
|
|
227
281
|
var GranteeSignerClient = class extends cosmwasmStargate.SigningCosmWasmClient {
|
|
228
|
-
|
|
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
|
-
|
|
292
|
+
granterAddress,
|
|
239
293
|
granteeAddress,
|
|
240
294
|
...options
|
|
241
295
|
}) {
|
|
242
296
|
super(cometClient, signer, options);
|
|
243
|
-
if (
|
|
244
|
-
throw new Error("
|
|
297
|
+
if (granterAddress === void 0) {
|
|
298
|
+
throw new Error("granterAddress is required");
|
|
245
299
|
}
|
|
246
|
-
this.
|
|
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.
|
|
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.
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
317
|
-
|
|
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 [
|
|
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
|
-
|
|
38
|
-
|
|
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
|
-
|
|
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(
|
|
79
|
-
if (!
|
|
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
|
-
|
|
107
|
+
configuregranter(uniqueGranters[0]);
|
|
103
108
|
break;
|
|
104
109
|
}
|
|
105
110
|
} catch (error) {
|
|
106
|
-
|
|
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
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
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(
|
|
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 {
|
|
216
|
-
|
|
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:
|
|
274
|
+
bech32Address: granterAddress
|
|
221
275
|
},
|
|
222
276
|
isConnected
|
|
223
277
|
};
|
|
224
278
|
};
|
|
225
279
|
var GranteeSignerClient = class extends SigningCosmWasmClient {
|
|
226
|
-
|
|
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
|
-
|
|
290
|
+
granterAddress,
|
|
237
291
|
granteeAddress,
|
|
238
292
|
...options
|
|
239
293
|
}) {
|
|
240
294
|
super(cometClient, signer, options);
|
|
241
|
-
if (
|
|
242
|
-
throw new Error("
|
|
295
|
+
if (granterAddress === void 0) {
|
|
296
|
+
throw new Error("granterAddress is required");
|
|
243
297
|
}
|
|
244
|
-
this.
|
|
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.
|
|
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.
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
315
|
-
|
|
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.
|
|
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.
|
|
47
|
-
"@burnt-labs/ui": "0.0
|
|
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
|
|
18
|
+
readonly granterAddress: string;
|
|
18
19
|
readonly granteeAddress: string;
|
|
19
20
|
}
|
|
20
21
|
|
|
21
22
|
export class GranteeSignerClient extends SigningCosmWasmClient {
|
|
22
|
-
protected readonly
|
|
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
|
-
|
|
47
|
+
granterAddress,
|
|
47
48
|
granteeAddress,
|
|
48
49
|
...options
|
|
49
50
|
}: SigningCosmWasmClientOptions & GranteeSignerOptions,
|
|
50
51
|
) {
|
|
51
52
|
super(cometClient, signer, options);
|
|
52
|
-
if (
|
|
53
|
-
throw new Error("
|
|
53
|
+
if (granterAddress === undefined) {
|
|
54
|
+
throw new Error("granterAddress is required");
|
|
54
55
|
}
|
|
55
|
-
this.
|
|
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
|
|
70
|
-
if (signerAddress === this.
|
|
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
|
|
95
|
-
if (signerAddress === this.
|
|
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
|
-
|
|
14
|
-
|
|
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 [
|
|
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
|
-
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
78
|
-
|
|
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
|
-
|
|
106
|
+
configuregranter(uniqueGranters[0]);
|
|
105
107
|
break;
|
|
106
108
|
}
|
|
107
109
|
} catch (error) {
|
|
108
|
-
|
|
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
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
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
|
|
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 } =
|
|
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 {
|
|
18
|
-
|
|
19
|
-
|
|
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:
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
51
|
-
|
|
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
|
-
});
|