Skip to content

Commit

Permalink
91 feat add a persistence layer to store the address (#102)
Browse files Browse the repository at this point in the history
* feat: persist address in local storage

* feat: dapp kit context provider

* feat: context object stored in local storage

* fix: connected address badge and modal test

* feat: not persistent context property

* test: dapp kit context initialization
  • Loading branch information
Valazan authored Nov 29, 2023
1 parent a77ed29 commit 53b5d0c
Show file tree
Hide file tree
Showing 16 changed files with 227 additions and 23 deletions.
2 changes: 1 addition & 1 deletion apps/sample-angular-app/src/app/app.component.html
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<vwk-connect-button-with-modal mode="DARK"></vwk-connect-button-with-modal>
<vwk-vechain-dapp-connect-kit mode="DARK"></vwk-vechain-dapp-connect-kit>
4 changes: 2 additions & 2 deletions apps/sample-vanilla-app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
<script crossorigin type="module" src="index.js"></script>
</head>
<body>
<vwk-connect-button-with-modal
<vwk-vechain-dapp-connect-kit
mode="DARK"
></vwk-connect-button-with-modal>
></vwk-vechain-dapp-connect-kit>
</body>
</html>
4 changes: 2 additions & 2 deletions apps/sample-vue-app/src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@
<ConnexProvider>
<img alt="Vue logo" src="./assets/logo.png" />
<div id="app">
<vwk-connect-button-with-modal
<vwk-vechain-dapp-connect-kit
mode="DARK"
></vwk-connect-button-with-modal>
></vwk-vechain-dapp-connect-kit>
</div>
</ConnexProvider>
</template>
Expand Down
1 change: 1 addition & 0 deletions packages/dapp-kit-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
"watch": "tsup --watch"
},
"dependencies": {
"@lit/context": "^1.1.0",
"@vechain/picasso": "2.1.1",
"@vechainfoundation/dapp-kit": "*",
"@wagmi/core": "^1.4.5",
Expand Down
4 changes: 4 additions & 0 deletions packages/dapp-kit-ui/src/components/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import './base';
import './provider';
import './vwk-connect-modal';
import './vwk-connect-button';
import './vwk-connect-button-with-modal';
Expand All @@ -8,8 +9,10 @@ import './vwk-connected-address-badge-with-modal';
import './vwk-source-card';
import './vwk-fonts';
import './vwk-wallet-connect-qrcode';
import './vwk-vechain-dapp-connect-kit';

export * from './base';
export * from './provider';
export * from './vwk-connect-modal';
export * from './vwk-connect-button';
export * from './vwk-connect-button-with-modal';
Expand All @@ -19,3 +22,4 @@ export * from './vwk-connected-address-badge-with-modal';
export * from './vwk-source-card';
export * from './vwk-fonts';
export * from './vwk-wallet-connect-qrcode';
export * from './vwk-vechain-dapp-connect-kit';
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { provide } from '@lit/context';
import { LitElement, type TemplateResult, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import {
type DappKitContext,
dappKitContext,
getDappKitContext,
} from '../dapp-kit-context';

@customElement('dapp-kit-context-provider')
export class DappKitContextProvider extends LitElement {
@provide({ context: dappKitContext })
@property({ attribute: false })
dappKitContext: DappKitContext = {
options: {
notPersistentContext: false,
},
address: '',
};

@property({ type: Boolean })
notPersistentContext = false;

// Use the `connectedCallback` lifecycle hook to retrieve the stored address
connectedCallback(): void {
super.connectedCallback();
this.dappKitContext = getDappKitContext(this.notPersistentContext);
}

render(): TemplateResult {
return html`<slot></slot>`;
}
}

declare global {
interface HTMLElementTagNameMap {
'dapp-kit-context-provider': DappKitContextProvider;
}
}
44 changes: 44 additions & 0 deletions packages/dapp-kit-ui/src/components/provider/dapp-kit-context.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { createContext } from '@lit/context';

interface DappKitContextOptions {
notPersistentContext: boolean;
}

interface DappKitContext {
options: DappKitContextOptions;
address: string;
}

const dappKitContext = createContext<DappKitContext>(
Symbol('dapp-kit-context'),
);

const storeDappKitContext = function (context: DappKitContext): void {
localStorage.setItem('dapp-kit-context-object', JSON.stringify(context));
};

const getDappKitContext = function (
notPersistentContext = false,
): DappKitContext {
const dappKitContextObject = localStorage.getItem(
'dapp-kit-context-object',
);

if (notPersistentContext || !dappKitContextObject) {
return {
options: {
notPersistentContext,
},
address: '',
};
}

return JSON.parse(dappKitContextObject) as DappKitContext;
};

export {
dappKitContext,
type DappKitContext,
storeDappKitContext,
getDappKitContext,
};
2 changes: 2 additions & 0 deletions packages/dapp-kit-ui/src/components/provider/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './dapp-kit-context';
export * from './dapp-kit-context-provider';
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
import type { TemplateResult } from 'lit';
import { html, LitElement } from 'lit';
import { consume } from '@lit/context';
import { LitElement, type TemplateResult, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import type { WalletManager } from '@vechainfoundation/dapp-kit';
import type { SourceInfo, Theme, ThemeMode } from '../../constants';
import { dappKitContext, storeDappKitContext } from '../provider';
import { DAppKit } from '../../client';
import type { SourceInfo, Theme, ThemeMode } from '../../constants';

@customElement('vwk-connect-button-with-modal')
export class ConnectButtonWithModal extends LitElement {
@consume({ context: dappKitContext })
@property({ attribute: false })
dappKitContext = {
options: {
notPersistentContext: false,
},
address: '',
};

@property()
override title = 'Connect Wallet';

Expand All @@ -19,9 +29,6 @@ export class ConnectButtonWithModal extends LitElement {
@property({ type: Boolean })
open = false;

@property({ type: String })
address?: string;

private get wallet(): WalletManager {
return DAppKit.connex.wallet;
}
Expand All @@ -32,8 +39,9 @@ export class ConnectButtonWithModal extends LitElement {
this.wallet.setSource(source.id);
this.wallet
.connect()
// eslint-disable-next-line no-console
.then((res) => (this.address = res.account))
.then((res) => {
this.updateAddress(res.account);
})
.finally(() => {
this.open = false;
});
Expand All @@ -43,20 +51,19 @@ export class ConnectButtonWithModal extends LitElement {
@property({ type: Function })
onDisconnectClick = (): void => {
this.wallet.disconnect().finally(() => {
this.address = undefined;
this.updateAddress('');
});
};

override render(): TemplateResult {
return html`
<div>
<vwk-fonts></vwk-fonts>
${this.address
${this.dappKitContext.address
? html`<vwk-connected-address-badge-with-modal
.mode=${this.mode}
.theme=${this.theme}
.address=${this.address}
.address=${this.dappKitContext.address}
.onDisconnectClick=${this.onDisconnectClick}
></vwk-connected-address-badge-with-modal>`
: html`<vwk-connect-button
Expand All @@ -76,6 +83,17 @@ export class ConnectButtonWithModal extends LitElement {
`;
}

private updateAddress = (address: string): void => {
this.dappKitContext.address = address;

// store the context object in local storage if the context is persistent
if (!this.dappKitContext.options.notPersistentContext) {
storeDappKitContext(this.dappKitContext);
}
// render the component again after the address is updated
this.requestUpdate();
};

private handleOpen = (): void => {
DAppKit.connex.wallet.disconnect().finally(() => {
this.open = true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,19 @@ export class ConnectModal extends LitElement {
color: ${Colors.LightGrey};
}
`;

@property({ type: Boolean })
open = false;

@property({ type: Function })
onSourceClick?: (source?: SourceInfo) => void = undefined;

@property()
mode: ThemeMode = 'LIGHT';

@property()
theme: Theme = 'DEFAULT';

@property()
walletConnectQRcode?: string = undefined;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { LitElement, css, html } from 'lit';
import { LitElement, type TemplateResult, css, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import { Colors, ThemeMode } from '../../constants';
import { Colors, type ThemeMode } from '../../constants';
import { friendlyAddress, getPicassoImage } from '../../utils/account';

@customElement('vwk-connected-address-badge')
Expand Down Expand Up @@ -57,7 +57,7 @@ export class ConnectedAddressBadge extends LitElement {
@property({ type: Function })
onClick? = undefined;

render() {
render(): TemplateResult {
return html` <div
class="wallet-badge ${this.mode}"
@click=${this.onClick}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { LitElement, type TemplateResult, html } from 'lit';
import { customElement, property } from 'lit/decorators.js';
import type { Theme, ThemeMode } from '../../constants';

@customElement('vwk-vechain-dapp-connect-kit')
export class VechainDappConnectKit extends LitElement {
@property({ type: String })
mode: ThemeMode = 'LIGHT';

@property({ type: String })
theme: Theme = 'DEFAULT';

@property({ type: Boolean })
notPersistentContext = false;

render(): TemplateResult {
return html`<dapp-kit-context-provider
?notPersistentContext=${this.notPersistentContext}
><vwk-connect-button-with-modal
mode="DARK"
></vwk-connect-button-with-modal
></dapp-kit-context-provider>`;
}
}

declare global {
interface HTMLElementTagNameMap {
'vwk-vechain-dapp-connect-kit': VechainDappConnectKit;
}
}
5 changes: 3 additions & 2 deletions packages/dapp-kit-ui/test/connect-button-with-modal.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,8 @@ describe('connect-button-with-modal', () => {
// testing the connected address badge

// mock a connection to the wallet by setting the address
element.address = '0x00000';
element.dappKitContext.address = '0x00000';
element.requestUpdate();

const connectedAddressBadgeWithModal =
(await elementQueries.getConnectedAddressBadgeWithModal()) as ConnectedAddressBadgeWithModal;
Expand All @@ -87,6 +88,6 @@ describe('connect-button-with-modal', () => {

await element.updateComplete;

expect(element.address).toBeUndefined();
expect(element.dappKitContext.address).toBe('');
});
});
12 changes: 12 additions & 0 deletions packages/dapp-kit-ui/test/helpers/element-queries.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
ConnectedAddressBadge,
ConnectedAddressBadgeWithModal,
ConnectedAddressModal,
DappKitContextProvider,
SourceCard,
} from '../../src';

Expand Down Expand Up @@ -53,6 +54,16 @@ const getConnectedAddressBadgeWithModal = (
);
};

const getDappKitContextProvider = (): Promise<
DappKitContextProvider | undefined | null
> => {
return performQueryWithTimeout(2000, () =>
window.document.body
.querySelector('vwk-vechain-dapp-connect-kit')
?.shadowRoot?.querySelector('dapp-kit-context-provider'),
);
};

const getConnectedAddressBadge = (
timeout = 2000,
): Promise<ConnectedAddressBadge | undefined | null> => {
Expand Down Expand Up @@ -115,4 +126,5 @@ export const elementQueries = {
getConnectedAddressBadgeWithModal,
getConnectedAddressBadge,
getConnectedAddressModal,
getDappKitContextProvider,
};
34 changes: 34 additions & 0 deletions packages/dapp-kit-ui/test/vechain-dapp-connect-kit.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { beforeEach, describe, expect, it } from 'vitest';

import { DAppKit, DappKitContextProvider, VechainDappConnectKit } from '../src';
import { elementQueries } from './helpers/element-queries';

describe('connect-button-with-modal', () => {
beforeEach(() => {
DAppKit.configure({ nodeUrl: 'https://mainnet.vechain.org/' });
});

it('Should callback with source when user clicks a wallet and should render the connected address badge once connected', async () => {
const element: VechainDappConnectKit = window.document.createElement(
'vwk-vechain-dapp-connect-kit',
);

window.document.body.appendChild(element);

// testing the dapp kit context provider

// set a not persistent context
element.notPersistentContext = true;

const dappKitContextProvider =
(await elementQueries.getDappKitContextProvider()) as DappKitContextProvider;

expect(dappKitContextProvider).toBeDefined();

// check if the context is not persistent
expect(dappKitContextProvider.notPersistentContext).toBe(true);

expect(dappKitContextProvider.dappKitContext).toBeDefined();
expect(dappKitContextProvider.dappKitContext.address).toBe('');
});
});
Loading

0 comments on commit 53b5d0c

Please sign in to comment.