Skip to content

Commit

Permalink
add disconnect options, modal options, callbackOptions to handle wall…
Browse files Browse the repository at this point in the history
…etconnect pairing delete
  • Loading branch information
liujun93 committed Jan 7, 2024
1 parent e44171d commit 5ad3dff
Show file tree
Hide file tree
Showing 16 changed files with 118 additions and 24 deletions.
11 changes: 8 additions & 3 deletions packages/core/src/bases/main-wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import {
ChainName,
ChainRecord,
DappEnv,
DisconnectOptions,
EndpointOptions,
IChainWallet,
IFRAME_WALLET_ID,
Expand Down Expand Up @@ -98,7 +99,7 @@ export abstract class MainWalletBase extends WalletBase {
}
}

protected onSetChainsDone(): void { }
protected onSetChainsDone(): void {}

private makeFinalEndpoints(chain: ChainRecord) {
const isTestNet = chain.name.includes('testnet');
Expand Down Expand Up @@ -236,11 +237,15 @@ export abstract class MainWalletBase extends WalletBase {
}
}

async disconnectAll(activeOnly = true, exclude?: ChainName) {
async disconnectAll(
activeOnly = true,
exclude?: ChainName,
options?: DisconnectOptions
) {
const chainWalletList = this.getChainWalletList(activeOnly);
for (const w of chainWalletList) {
if (w.chainName !== exclude) {
await w.disconnect();
await w.disconnect(false, options);
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions packages/core/src/bases/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
import EventEmitter from 'events';

import {
CallbackOptions,
Callbacks,
DisconnectOptions,
DownloadInfo,
IFRAME_WALLET_ID,
Mutable,
Expand Down Expand Up @@ -155,9 +157,12 @@ export abstract class WalletBase extends StateBase {
this.callbacks = { ...this.callbacks, ...callbacks };
}

protected _disconnect = async (sync?: boolean) => {
protected _disconnect = async (
sync?: boolean,
options?: DisconnectOptions
) => {
await this.callbacks?.beforeDisconnect?.();
await this.client?.disconnect?.();
await this.client?.disconnect?.(options);
if (this.clientMutable.state !== State.Error) {
this.reset();
}
Expand All @@ -171,8 +176,8 @@ export abstract class WalletBase extends StateBase {
await this.callbacks?.afterDisconnect?.();
};

disconnect = async (sync?: boolean) => {
await this._disconnect(sync);
disconnect = async (sync?: boolean, options?: DisconnectOptions) => {
await this._disconnect(sync, options);
};

setClientNotExist() {
Expand Down
22 changes: 18 additions & 4 deletions packages/core/src/repository.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ import { ChainWalletBase } from './bases/chain-wallet';
import { StateBase } from './bases/state';
import { NameService } from './name-service';
import {
CallbackOptions,
ChainRecord,
DappEnv,
DisconnectOptions,
ExtendedHttpEndpoint,
WalletName,
} from './types';
Expand All @@ -24,6 +26,7 @@ export class WalletRepo extends StateBase {
namespace = 'cosmos';
session: Session;
repelWallet = true;
private callbackOptions?: CallbackOptions;

constructor(chainRecord: ChainRecord, wallets: ChainWalletBase[] = []) {
super();
Expand All @@ -37,7 +40,10 @@ export class WalletRepo extends StateBase {
beforeConnect: async () => {
this.wallets.forEach(async (w2) => {
if (!w2.isWalletDisconnected && w2 !== w) {
await w2.disconnect();
await w2.disconnect(
false,
this.callbackOptions?.beforeConnect?.disconnect
);
}
});
},
Expand All @@ -46,6 +52,10 @@ export class WalletRepo extends StateBase {
}
}

setCallbackOptions(options?: CallbackOptions) {
this.callbackOptions = options;
}

setEnv(env?: DappEnv): void {
this._env = env;
this.wallets.forEach((w) => w.setEnv(env));
Expand Down Expand Up @@ -122,11 +132,15 @@ export class WalletRepo extends StateBase {
}
};

disconnect = async (walletName?: WalletName, sync: boolean = true) => {
disconnect = async (
walletName?: WalletName,
sync: boolean = true,
options?: DisconnectOptions
) => {
if (walletName) {
await this.getWallet(walletName)?.disconnect(sync);
await this.getWallet(walletName)?.disconnect(sync, options);
} else {
await this.current.disconnect(sync);
await this.current.disconnect(sync, options);
}
};

Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/types/common.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { CallbackOptions } from './wallet';

/* eslint-disable @typescript-eslint/no-explicit-any */
export enum State {
Init = 'Init',
Expand Down
3 changes: 2 additions & 1 deletion packages/core/src/types/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ import {
AppUrl,
BroadcastMode,
DirectSignDoc,
DisconnectOptions,
NameServiceName,
SignOptions,
SuggestToken,
Expand Down Expand Up @@ -67,7 +68,7 @@ export interface ChainWalletContext {
isWalletError: boolean;

connect: () => Promise<void>;
disconnect: () => Promise<void>;
disconnect: (options?: DisconnectOptions) => Promise<void>;
getRpcEndpoint: (isLazy?: boolean) => Promise<string | ExtendedHttpEndpoint>;
getRestEndpoint: (isLazy?: boolean) => Promise<string | ExtendedHttpEndpoint>;
getStargateClient: () => Promise<StargateClient>;
Expand Down
2 changes: 2 additions & 0 deletions packages/core/src/types/view.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { ChainWalletBase } from '../bases';
import { WalletRepo } from '../repository';
import { Dispatch } from './common';
import { ModalOptions } from './wallet';

export enum ModalView {
WalletList = 'WalletList',
Expand All @@ -22,6 +23,7 @@ export interface WalletViewProps {
onClose: () => void;
onReturn: () => void;
wallet: ChainWalletBase;
options?: ModalOptions;
}

interface RefObject<T> {
Expand Down
18 changes: 17 additions & 1 deletion packages/core/src/types/wallet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ export interface WalletClient {
appUrl?: Mutable<AppUrl>;

connect?: (chainIds: string | string[], options?: any) => Promise<void>; // called when chain wallet connect is called
disconnect?: () => Promise<void>; // called when wallet disconnect is called
disconnect?: (options?: DisconnectOptions) => Promise<void>; // called when wallet disconnect is called
on?: (type: string, listener: EventListenerOrEventListenerObject) => void;
off?: (type: string, listener: EventListenerOrEventListenerObject) => void;
enable?: (chainIds: string | string[]) => Promise<void>;
Expand Down Expand Up @@ -256,3 +256,19 @@ export interface NameServiceRegistry {
export interface WalletConnectOptions {
signClient: { projectId: string } & SignClientTypes.Options;
}

export interface DisconnectOptions {
walletconnect?: {
removeAllPairings?: boolean;
};
}

export interface ModalOptions {
mobile?: {
displayQRCodeEveryTime?: boolean; // if true, means remove all pairings when disconnect
};
}

export interface CallbackOptions {
beforeConnect?: { disconnect?: DisconnectOptions };
}
2 changes: 1 addition & 1 deletion packages/docs/pages/advanced.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,4 @@ Differences:

`WalletRepo` provides a different perspective from chain side to consider all chain wallets in addition to `MainWalletBase`. It's useful in some dapps that chain is the key point rather than wallet.

> So far `WalletRepo` is only used in [`WalletModal`](https://docs.cosmoskit.com/provider/chain-provider#walletmodal) properties.
So far `WalletRepo` is only used in [`WalletModal`](https://docs.cosmoskit.com/provider/chain-provider#walletmodal) properties.
6 changes: 6 additions & 0 deletions packages/docs/pages/provider/chain-provider.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,12 @@ function CosmosApp() {
}
```

### modalOptions

- `mobile.displayQRCodeEveryTime`

By default `false`. When set `true`, it'll cause all existing pairings be removed everytime wallet is disconnected. It corresponds to the `DisconnectOptions.walletconnect.removeAllPairings` in `disconnect` method.

### includeAllWalletsOnMobile

Optional property. By default `false`, which means on mobile only wallets with registry value of `mobileDisabled` (or returned value of `mobileDisabled` function) is `false` or `undefined` be displayed on wallet list page of default modal.
Expand Down
3 changes: 2 additions & 1 deletion packages/example/pages/_app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ function MyApp({ Component, pageProps }: AppProps) {
// ...snapWallet,
// ...ledgerWallets,
// ...web3AuthWallets,
// ...trustWallets,
...trustWallets,
// ...stationWallets,
...cosmostationWallets,
// ...omniWallets,
Expand Down Expand Up @@ -142,6 +142,7 @@ function MyApp({ Component, pageProps }: AppProps) {
// // Connected: CustomConnectedView,
// // }}
// walletModal={CustomModal}
// modalOptions={{ mobile: { displayQRCodeEveryTime: true } }}
>
<Component {...pageProps} />
</ChainProvider>
Expand Down
5 changes: 3 additions & 2 deletions packages/react-lite/src/hooks/useChain.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ChainContext, ChainName } from '@cosmos-kit/core';
import { ChainContext, ChainName, DisconnectOptions } from '@cosmos-kit/core';
import { useContext, useEffect, useState } from 'react';

import { walletContext } from '../provider';
Expand Down Expand Up @@ -64,7 +64,8 @@ export const useChain = (chainName: ChainName, sync = true): ChainContext => {
openView,
closeView,
connect: () => connect(void 0, sync),
disconnect: () => disconnect(void 0, sync),
disconnect: (options?: DisconnectOptions) =>
disconnect(void 0, sync, options),
getRpcEndpoint,
getRestEndpoint,
getStargateClient,
Expand Down
5 changes: 3 additions & 2 deletions packages/react-lite/src/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {
ChainWalletBase,
ChainWalletContext,
DisconnectOptions,
WalletStatus,
} from '@cosmos-kit/core';

Expand Down Expand Up @@ -75,8 +76,8 @@ export function getChainWalletContext(
isWalletError: status === 'Error',

connect: () => walletAssert(wallet?.connect, [void 0, sync], 'connect'),
disconnect: () =>
walletAssert(wallet?.disconnect, [void 0, sync], 'disconnect'),
disconnect: (options?: DisconnectOptions) =>
walletAssert(wallet?.disconnect, [void 0, sync, options], 'disconnect'),
getRpcEndpoint: (isLazy?: boolean) =>
walletAssert(wallet?.getRpcEndpoint, [isLazy], 'getRpcEndpoint'),
getRestEndpoint: (isLazy?: boolean) =>
Expand Down
7 changes: 6 additions & 1 deletion packages/react/src/modal/components/views/Connected.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,16 @@ export function ConnectedView({
onClose,
onReturn,
wallet,
options,
}: WalletViewProps): ModalViewImpl {
const { walletInfo, username, address } = wallet;

const onDisconnect = async () => {
await wallet.disconnect(true);
await wallet.disconnect(true, {
walletconnect: {
removeAllPairings: options?.mobile.displayQRCodeEveryTime,
},
});
};

const modalHead = (
Expand Down
19 changes: 16 additions & 3 deletions packages/react/src/modal/modal.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {
ModalOptions,
ModalView,
State,
WalletListViewProps,
Expand Down Expand Up @@ -42,6 +43,7 @@ export type ThemeCustomizationProps = ModalCustomizationProps &
export type WalletModalComponentProps = WalletModalProps &
ThemeCustomizationProps & {
modalViews: typeof defaultModalViews;
modalOptions?: ModalOptions;
includeAllWalletsOnMobile?: boolean;
};

Expand All @@ -50,6 +52,7 @@ export function WalletModal({
setOpen,
walletRepo,
modalViews,
modalOptions,
includeAllWalletsOnMobile,
overrides,
themeDefs,
Expand All @@ -68,6 +71,15 @@ export function WalletModal({
const [qrState, setQRState] = useState<State>(State.Init); // state of QRCode
const [qrMsg, setQRMsg] = useState<string>(''); // message of QRCode error

const disconnectOptions = {
walletconnect: {
removeAllPairings: modalOptions?.mobile?.displayQRCodeEveryTime,
},
};
walletRepo?.setCallbackOptions({
beforeConnect: { disconnect: disconnectOptions },
});

const current = walletRepo?.current;

(current?.client as any)?.setActions?.({
Expand Down Expand Up @@ -106,8 +118,8 @@ export function WalletModal({
case WalletStatus.NotExist:
setCurrentView((prev) =>
prev === ModalView.Connected
? ModalView.WalletList
: ModalView.NotExist
? ModalView.WalletList
: ModalView.NotExist
);
break;
case WalletStatus.Disconnected:
Expand All @@ -132,7 +144,7 @@ export function WalletModal({
const onCloseModal = useCallback(() => {
setOpen(false);
if (walletStatus === 'Connecting') {
current?.disconnect();
current?.disconnect(false, disconnectOptions);
}
}, [setOpen, walletStatus, current]);

Expand Down Expand Up @@ -176,6 +188,7 @@ export function WalletModal({
onClose: onCloseModal,
onReturn: onReturn,
wallet: current,
options: modalOptions,
} as WalletViewProps);
}
}
Expand Down
4 changes: 4 additions & 0 deletions packages/react/src/provider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
Logger,
LogLevel,
MainWalletBase,
ModalOptions,
NameServiceName,
SessionOptions,
SignerOptions,
Expand Down Expand Up @@ -33,6 +34,7 @@ export const ChainProvider = ({
disableIframe = false,
children,
modalTheme = {},
modalOptions,
}: {
chains: Chain[];
assetLists: AssetList[];
Expand All @@ -50,6 +52,7 @@ export const ChainProvider = ({
disableIframe?: boolean;
children: ReactNode;
modalTheme?: ThemeCustomizationProps;
modalOptions?: ModalOptions;
}) => {
const logger = useMemo(() => new Logger(logLevel), []);

Expand Down Expand Up @@ -91,6 +94,7 @@ export const ChainProvider = ({
...defaultModalViews,
...modalViews,
}}
modalOptions={modalOptions}
/>
),
[defaultModalViews]
Expand Down
Loading

0 comments on commit 5ad3dff

Please sign in to comment.