Skip to content

Commit

Permalink
Merge pull request #47 from burnt-labs/feat/persistence
Browse files Browse the repository at this point in the history
Persistence
  • Loading branch information
BurntVal authored Jan 18, 2024
2 parents 495fede + f04dd46 commit 58d8664
Show file tree
Hide file tree
Showing 10 changed files with 125 additions and 64 deletions.
2 changes: 1 addition & 1 deletion .changeset/tasty-masks-kiss.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
"@burnt-labs/abstraxion": minor
---

Add grantee signer client to seamlessly handle grantor/grantee relationships
Add grantee signer client to seamlessly handle granter/grantee relationships
5 changes: 5 additions & 0 deletions .changeset/tough-dolls-count.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@burnt-labs/abstraxion": minor
---

persistence and related state cleanup
2 changes: 1 addition & 1 deletion packages/abstraxion/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

- [#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

- [#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
- [#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

### Patch Changes

Expand Down
20 changes: 10 additions & 10 deletions packages/abstraxion/src/GranteeSignerClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import {
} from "@cosmjs/tendermint-rpc";

interface GranteeSignerOptions {
readonly grantorAddress: string;
readonly granterAddress: string;
readonly granteeAddress: string;
}

export class GranteeSignerClient extends SigningCosmWasmClient {
protected readonly grantorAddress: string;
protected readonly granterAddress: string;
protected readonly granteeAddress: string;

public static async connectWithSigner(
Expand All @@ -43,16 +43,16 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
cometClient: TendermintClient | undefined,
signer: OfflineSigner,
{
grantorAddress,
granterAddress,
granteeAddress,
...options
}: SigningCosmWasmClientOptions & GranteeSignerOptions,
) {
super(cometClient, signer, options);
if (grantorAddress === undefined) {
throw new Error("grantorAddress is required");
if (granterAddress === undefined) {
throw new Error("granterAddress is required");
}
this.grantorAddress = grantorAddress;
this.granterAddress = granterAddress;

if (granteeAddress === undefined) {
throw new Error("granteeAddress is required");
Expand All @@ -66,8 +66,8 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
fee: StdFee | "auto" | number,
memo = "",
): Promise<DeliverTxResponse> {
// Figure out if the signerAddress is a grantor
if (signerAddress === this.grantorAddress) {
// Figure out if the signerAddress is a granter
if (signerAddress === this.granterAddress) {
signerAddress = this.granteeAddress;
// Wrap the signerAddress in a MsgExec
messages = [
Expand All @@ -91,8 +91,8 @@ export class GranteeSignerClient extends SigningCosmWasmClient {
memo: string,
explicitSignerData?: SignerData,
): Promise<TxRaw> {
// Figure out if the signerAddress is a grantor
if (signerAddress === this.grantorAddress) {
// Figure out if the signerAddress is a granter
if (signerAddress === this.granterAddress) {
signerAddress = this.granteeAddress;
// Wrap the signerAddress in a MsgExec
messages = [
Expand Down
2 changes: 1 addition & 1 deletion packages/abstraxion/src/components/Abstraxion/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ export function Abstraxion({
) : isConnecting ? (
<Loading />
) : isConnected ? (
<Connected />
<Connected onClose={onClose} />
) : (
<AbstraxionSignin />
)}
Expand Down
10 changes: 5 additions & 5 deletions packages/abstraxion/src/components/AbstraxionContext/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ export interface AbstraxionContextProps {
setAbstraxionError: React.Dispatch<React.SetStateAction<string>>;
abstraxionAccount: DirectSecp256k1HdWallet | undefined;
setAbstraxionAccount: React.Dispatch<DirectSecp256k1HdWallet | undefined>;
grantorAddress: string;
setGrantorAddress: React.Dispatch<React.SetStateAction<string>>;
granterAddress: string;
setgranterAddress: React.Dispatch<React.SetStateAction<string>>;
contracts?: string[];
dashboardUrl?: string;
}
Expand All @@ -35,7 +35,7 @@ export const AbstraxionContextProvider = ({
const [abstraxionAccount, setAbstraxionAccount] = useState<
DirectSecp256k1HdWallet | undefined
>(undefined);
const [grantorAddress, setGrantorAddress] = useState("");
const [granterAddress, setgranterAddress] = useState("");

return (
<AbstraxionContext.Provider
Expand All @@ -48,8 +48,8 @@ export const AbstraxionContextProvider = ({
setAbstraxionError,
abstraxionAccount,
setAbstraxionAccount,
grantorAddress,
setGrantorAddress,
granterAddress,
setgranterAddress,
contracts,
dashboardUrl,
}}
Expand Down
71 changes: 41 additions & 30 deletions packages/abstraxion/src/components/AbstraxionSignin/index.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"use client";
import { useContext, useEffect, useRef } from "react";
import { useContext, useEffect, useRef, useState } from "react";
import { DirectSecp256k1HdWallet } from "graz/dist/cosmjs";
import { Button, ModalSection, BrowserIcon } from "@burnt-labs/ui";
import { wait } from "@/utils/wait";
Expand Down Expand Up @@ -47,12 +47,18 @@ export function AbstraxionSignin(): JSX.Element {
setIsConnecting,
setIsConnected,
setAbstraxionAccount,
setGrantorAddress,
setgranterAddress,
contracts,
dashboardUrl,
} = useContext(AbstraxionContext);

const isMounted = useRef(false);
const [tempAccountAddress, setTempAccountAddress] = useState("");

function configuregranter(address: string) {
setgranterAddress(address);
localStorage.setItem("xion-authz-granter-account", address);
}

function openDashboardTab(userAddress: string, contracts?: string[]): void {
const urlParams = new URLSearchParams();
Expand All @@ -73,16 +79,11 @@ export function AbstraxionSignin(): JSX.Element {
return keypair;
}

async function pollForGrants(
keypair: DirectSecp256k1HdWallet,
): Promise<void> {
if (!keypair) {
throw new Error("No keypair");
async function pollForGrants(address: string): Promise<void> {
if (!address) {
throw new Error("No keypair address");
}
setIsConnecting(true);

const accounts = await keypair.getAccounts();
const address = accounts[0].address;
const shouldContinue = true;
while (shouldContinue) {
try {
Expand All @@ -95,41 +96,46 @@ export function AbstraxionSignin(): JSX.Element {
);
const data = (await res.json()) as GrantsResponse;
if (data.grants?.length > 0) {
setIsConnecting(true);
const granterAddresses = data.grants.map((grant) => grant.granter);
const uniqueGranters = [...new Set(granterAddresses)];
if (uniqueGranters.length > 1) {
console.error("More than one granter found. Taking first.");
}

setGrantorAddress(uniqueGranters[0]);
configuregranter(uniqueGranters[0]);
break;
}
} catch (error) {
console.log("There was an error polling for grants: ", error);
throw error;
}
}

setIsConnecting(false);
setIsConnected(true);
setAbstraxionAccount(keypair);
}

useEffect(() => {
async function onStartup() {
const existingKeypair = localStorage.getItem("xion-authz-temp-account");
let keypair;
if (existingKeypair) {
keypair = await DirectSecp256k1HdWallet.deserialize(
existingKeypair,
"abstraxion",
);
} else {
keypair = await generateAndStoreTempAccount();
try {
const existingKeypair = localStorage.getItem("xion-authz-temp-account");
let keypair;
if (existingKeypair) {
keypair = await DirectSecp256k1HdWallet.deserialize(
existingKeypair,
"abstraxion",
);
} else {
keypair = await generateAndStoreTempAccount();
}
const accounts = await keypair.getAccounts();
const address = accounts[0].address;
setTempAccountAddress(address);
openDashboardTab(address, contracts);
await pollForGrants(address);
setIsConnecting(false);
setIsConnected(true);
setAbstraxionAccount(keypair);
} catch (error) {
console.log("Something went wrong: ", error);
}
const accounts = await keypair.getAccounts();
const address = accounts[0].address;
openDashboardTab(address, contracts);
pollForGrants(keypair);
}

if (!isMounted.current) {
Expand All @@ -151,7 +157,12 @@ export function AbstraxionSignin(): JSX.Element {
</h2>
</div>
<BrowserIcon />
<Button structure="naked">Have a Problem? Try Again</Button>
<Button
onClick={() => openDashboardTab(tempAccountAddress, contracts)}
structure="naked"
>
Have a Problem? Try Again
</Button>
</ModalSection>
);
}
13 changes: 8 additions & 5 deletions packages/abstraxion/src/components/Connected/Connected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,17 @@ import {
AbstraxionContextProps,
} from "../AbstraxionContext";

export function Connected() {
const { setIsConnected } = useContext(
AbstraxionContext,
) as AbstraxionContextProps;
export function Connected({ onClose }: { onClose: VoidFunction }) {
const { setIsConnected, setAbstraxionAccount, setgranterAddress } =
useContext(AbstraxionContext) as AbstraxionContextProps;

function handleLogout() {
localStorage.removeItem("xion-authz-temp-account");
setIsConnected(false);
localStorage.removeItem("xion-authz-temp-account");
localStorage.removeItem("xion-authz-granter-account");
setAbstraxionAccount(undefined);
setgranterAddress("");
onClose();
}

return (
Expand Down
49 changes: 44 additions & 5 deletions packages/abstraxion/src/hooks/useAbstraxionAccount.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import { useContext } from "react";
import { useContext, useEffect } from "react";
import {
AbstraxionContext,
AbstraxionContextProps,
} from "@/src/components/AbstraxionContext";
import { DirectSecp256k1HdWallet } from "@cosmjs/proto-signing";

export interface AbstraxionAccount {
bech32Address: string;
Expand All @@ -14,13 +15,51 @@ export interface useAbstraxionAccountProps {
}

export const useAbstraxionAccount = (): useAbstraxionAccountProps => {
const { isConnected, grantorAddress } = useContext(
AbstraxionContext,
) as AbstraxionContextProps;
const {
isConnected,
granterAddress,
abstraxionAccount,
isConnecting,
setgranterAddress,
setAbstraxionAccount,
setIsConnected,
setIsConnecting,
} = useContext(AbstraxionContext) as AbstraxionContextProps;

useEffect(() => {
async function configureAccount() {
setIsConnecting(true);
const tempKeypair = localStorage.getItem("xion-authz-temp-account");
if (tempKeypair) {
const deserializedKeypair = await DirectSecp256k1HdWallet.deserialize(
tempKeypair,
"abstraxion",
);
setAbstraxionAccount(deserializedKeypair);
const granterAccount = localStorage.getItem(
"xion-authz-granter-account",
);
if (granterAccount) {
setgranterAddress(granterAccount);
setIsConnected(true);
}
} else {
// Wipe granter even if it exists, clean context
localStorage.removeItem("xion-authz-granter-account");
setAbstraxionAccount(undefined);
setgranterAddress("");
}
setIsConnecting(false);
}

if (!isConnecting && !abstraxionAccount && !granterAddress) {
configureAccount();
}
}, [isConnected, abstraxionAccount, granterAddress]);

return {
data: {
bech32Address: grantorAddress,
bech32Address: granterAddress,
},
isConnected: isConnected,
};
Expand Down
15 changes: 9 additions & 6 deletions packages/abstraxion/src/hooks/useAbstraxionSigningClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import {
import { GranteeSignerClient } from "@/src/GranteeSignerClient.ts";

export const useAbstraxionSigningClient = () => {
const { isConnected, abstraxionAccount, grantorAddress } = useContext(
const { isConnected, abstraxionAccount, granterAddress } = useContext(
AbstraxionContext,
) as AbstraxionContextProps;

Expand All @@ -22,6 +22,10 @@ export const useAbstraxionSigningClient = () => {
if (!abstraxionAccount) {
throw new Error("No account found.");
}

if (!granterAddress) {
throw new Error("No granter found.");
}
const granteeAddress = await abstraxionAccount
.getAccounts()
.then((accounts) => {
Expand All @@ -36,21 +40,20 @@ export const useAbstraxionSigningClient = () => {
abstraxionAccount,
{
gasPrice: GasPrice.fromString("0uxion"),
grantorAddress,
granterAddress,
granteeAddress,
},
);

setAbstractClient(directClient);
} catch (error) {
console.log("Something went wrong: ", error);
setAbstractClient(undefined);
}
}

if (isConnected && abstraxionAccount) {
getSigner();
}
}, [abstraxionAccount, isConnected]);
getSigner();
}, [isConnected, abstraxionAccount, granterAddress]);

return { client: abstractClient };
};

0 comments on commit 58d8664

Please sign in to comment.