Skip to content

Commit

Permalink
feat: add TM2 wallet provider type to the SDK (#7)
Browse files Browse the repository at this point in the history
  • Loading branch information
jinoosss authored Sep 9, 2024
1 parent b9d9957 commit ee6954b
Show file tree
Hide file tree
Showing 23 changed files with 1,167 additions and 55 deletions.
6 changes: 5 additions & 1 deletion packages/sdk/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,11 @@
},
"dependencies": {
"@gnolang/gno-js-client": "^1.3.0",
"@gnolang/tm2-js-client": "^1.2.1"
"@gnolang/tm2-js-client": "^1.2.1",
"@web3auth/base": "^8.12.4",
"@web3auth/base-provider": "^8.12.4",
"@web3auth/no-modal": "^8.12.4",
"@web3auth/openlogin-adapter": "^8.12.4"
},
"devDependencies": {
"@types/eslint": "^9",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,20 @@ import {
} from '../../__mocks__/mock-wallet-provider';
import { ConnectionManager, ConnectionState } from '../../connection';
import { SDKConnectionConfigure } from '../../types/config.types';
import { isTM2WalletProvider } from '../../utils/provider.utils';

jest.mock('../../utils/provider.utils', () => ({
isTM2WalletProvider: jest.fn(),
}));

describe('ConnectionManager', () => {
let connectionManager: ConnectionManager;
let config: SDKConnectionConfigure;

beforeEach(() => {
defineGlobalMock();
// Is not TM2WalletProvider
(isTM2WalletProvider as unknown as jest.Mock).mockReturnValue(false);
config = { isSession: true };

// Initialize ConnectionManager with a real instance of ConnectionStateManager
Expand Down
71 changes: 51 additions & 20 deletions packages/sdk/src/core/connection/connection-manager.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
import { WalletProvider } from '../providers';
import { GnoWalletProvider } from '../../providers/gno-wallet';
import { TM2WalletProvider, WalletProvider } from '../providers';
import { WalletConnectionEvent, WalletResponseStatus } from '../types';
import { SDKConnectionConfigure } from '../types/config.types';
import { isTM2WalletProvider } from '../utils/provider.utils';
import { ConnectionState, ConnectionStateManager } from './connection-state';

export class ConnectionManager {
private stateManager: ConnectionStateManager;
private listeners: ((event: WalletConnectionEvent) => void)[];

constructor(
private provider: WalletProvider,
private provider: WalletProvider | TM2WalletProvider,
private config: SDKConnectionConfigure
) {
this.listeners = [];
Expand All @@ -20,6 +22,39 @@ export class ConnectionManager {
}

async connectWallet(): Promise<void> {
if (isTM2WalletProvider(this.provider)) {
return this.connectTM2Wallet();
}
return this.connectAdenaWallet();
}

disconnectWallet(): void {
if (this.provider instanceof GnoWalletProvider) {
this.provider.disconnect();
}
this.disconnect();
}

getConnectionState(): ConnectionState {
return this.stateManager.getState();
}

getWalletProvider(): WalletProvider {
if (this.stateManager.getState() !== ConnectionState.CONNECTED) {
throw new Error('not connect wallet');
}
return this.provider;
}

on(listener: (connection: WalletConnectionEvent) => void): void {
this.listeners.push(listener);
}

off(listener: (connection: WalletConnectionEvent) => void): void {
this.listeners = this.listeners.filter((l) => l !== listener);
}

private async connectAdenaWallet(): Promise<void> {
if (this.getConnectionState() !== ConnectionState.CONNECTED) {
this.stateManager.setState(ConnectionState.CONNECTING);
}
Expand All @@ -46,27 +81,23 @@ export class ConnectionManager {
this.stateManager.setState(ConnectionState.DISCONNECTED);
}

disconnectWallet(): void {
this.disconnect();
}

getConnectionState(): ConnectionState {
return this.stateManager.getState();
}

getWalletProvider(): WalletProvider {
if (this.stateManager.getState() !== ConnectionState.CONNECTED) {
throw new Error('not connect wallet');
private async connectTM2Wallet(): Promise<void> {
if (this.getConnectionState() !== ConnectionState.CONNECTED) {
this.stateManager.setState(ConnectionState.CONNECTING);
}
return this.provider;
}

on(listener: (connection: WalletConnectionEvent) => void): void {
this.listeners.push(listener);
}
try {
const connected = await (this.provider as TM2WalletProvider).connect();
if (connected) {
this.connect();
return;
}
} catch (error) {
this.stateManager.setState(ConnectionState.ERROR);
throw error;
}

off(listener: (connection: WalletConnectionEvent) => void): void {
this.listeners = this.listeners.filter((l) => l !== listener);
this.stateManager.setState(ConnectionState.DISCONNECTED);
}

private connect() {
Expand Down
23 changes: 23 additions & 0 deletions packages/sdk/src/core/methods/connect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import { ConnectionManager } from '../connection';
import { ConnectOptions, ConnectResponse } from '../types/methods';
import { isTM2WalletProvider } from '../utils/provider.utils';

export const connect = async (
connectionManager: ConnectionManager,
connectionOptions: ConnectOptions = {}
): Promise<ConnectResponse> => {
try {
await connectionManager.connectWallet();
} catch (e) {
const openWalletLink =
!isTM2WalletProvider(connectionManager.getWalletProvider()) && !!connectionOptions.walletDownloadUrl;
if (openWalletLink) {
openLink(connectionOptions.walletDownloadUrl!);
}
console.error(e);
}
};

const openLink = (url: string): void => {
window?.open(url, '_blank');
};
6 changes: 6 additions & 0 deletions packages/sdk/src/core/methods/disconnect.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ConnectionManager } from '../connection';
import { DisconnectResponse } from '../types/methods';

export const disconnect = (connectionManager: ConnectionManager): DisconnectResponse => {
connectionManager.disconnectWallet();
};
6 changes: 6 additions & 0 deletions packages/sdk/src/core/methods/get-connection-state.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { ConnectionManager } from '../connection';
import { GetConnectionState } from '../types/methods/get-connection-state.types';

export const getConnectionState = (connectionManager: ConnectionManager): GetConnectionState => {
return connectionManager.getConnectionState();
};
5 changes: 5 additions & 0 deletions packages/sdk/src/core/methods/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
export * from './add-establish';
export * from './add-network';
export * from './broadcast-transaction';
export * from './connect';
export * from './disconnect';
export * from './get-account';
export * from './get-connection-state';
export * from './is-connected';
export * from './off-connection-change';
export * from './on-change-account';
export * from './on-change-network';
export * from './on-connection-change';
export * from './sign-transaction';
export * from './switch-network';
9 changes: 9 additions & 0 deletions packages/sdk/src/core/methods/off-connection-change.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ConnectionManager } from '../connection';
import { OffConnectionChangeOptions, OffConnectionChangeResponse } from '../types/methods/off-connection-change';

export const offConnectionChange = (
connectionManager: ConnectionManager,
options: OffConnectionChangeOptions
): OffConnectionChangeResponse => {
return connectionManager.off(options.callback);
};
9 changes: 9 additions & 0 deletions packages/sdk/src/core/methods/on-connection-change.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { ConnectionManager } from '../connection';
import { OnConnectionChangeOptions, OnConnectionChangeResponse } from '../types/methods/on-connection-change';

export const onConnectionChange = (
connectionManager: ConnectionManager,
options: OnConnectionChangeOptions
): OnConnectionChangeResponse => {
return connectionManager.on(options.callback);
};
1 change: 1 addition & 0 deletions packages/sdk/src/core/providers/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
export * from './tm2-wallet';
export * from './wallet';
7 changes: 7 additions & 0 deletions packages/sdk/src/core/providers/tm2-wallet.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { WalletProvider } from './wallet';

export interface TM2WalletProvider extends WalletProvider {
connect(): Promise<boolean>;

disconnect(): Promise<boolean>;
}
33 changes: 16 additions & 17 deletions packages/sdk/src/core/sdk/adena-sdk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@ import {
addEstablish,
addNetwork,
broadcastTransaction,
connect,
disconnect,
getAccount,
getConnectionState,
isConnected,
offConnectionChange,
onChangeAccount,
onChangeNetwork,
onConnectionChange,
signTransaction,
switchNetwork,
} from '../methods';
import { WalletProvider } from '../providers';
import { SDKConfigure } from '../types/config.types';
import { SDKConfigure } from '../types';
import {
AddEstablishOptions,
AddEstablishResponse,
Expand All @@ -21,17 +26,19 @@ import {
BroadcastTransactionResponse,
GetAccountResponse,
IsConnectedResponse,
OffConnectionChangeOptions,
OffConnectionChangeResponse,
OnChangeAccountOptions,
OnChangeAccountResponse,
OnChangeNetworkOptions,
OnChangeNetworkResponse,
OnConnectionChangeOptions,
OnConnectionChangeResponse,
SignTransactionOptions,
SignTransactionResponse,
SwitchNetworkOptions,
SwitchNetworkResponse,
} from '../types/methods';
import { OffConnectionChangeOptions, OffConnectionChangeResponse } from '../types/methods/off-connection-change';
import { OnConnectionChangeOptions, OnConnectionChangeResponse } from '../types/methods/on-connection-change';

const DEFAULT_ADENA_URL = 'https://www.adena.app';

Expand Down Expand Up @@ -60,28 +67,24 @@ export class AdenaSDK {
return this.connectionManager.getWalletProvider();
}

async connectWallet(): Promise<void> {
return this.connectionManager.connectWallet().catch(() => {
if (this.config.walletDownloadUrl) {
this.openLink(this.config.walletDownloadUrl);
}
});
connectWallet(): Promise<void> {
return connect(this.connectionManager, this.config);
}

disconnectWallet(): void {
this.connectionManager.disconnectWallet();
return disconnect(this.connectionManager);
}

getConnectionState(): ConnectionState {
return this.connectionManager.getConnectionState();
return getConnectionState(this.connectionManager);
}

onConnectionChange(options: OnConnectionChangeOptions): OnConnectionChangeResponse {
return this.connectionManager.on(options.callback);
return onConnectionChange(this.connectionManager, options);
}

offConnectionChange(options: OffConnectionChangeOptions): OffConnectionChangeResponse {
return this.connectionManager.off(options.callback);
return offConnectionChange(this.connectionManager, options);
}

isConnected(): Promise<IsConnectedResponse> {
Expand Down Expand Up @@ -119,8 +122,4 @@ export class AdenaSDK {
onChangeNetwork(options: OnChangeNetworkOptions): OnChangeNetworkResponse {
return onChangeNetwork(this.walletProvider, options);
}

private openLink(url: string): void {
window?.open(url, '_blank');
}
}
1 change: 1 addition & 0 deletions packages/sdk/src/core/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './account.types';
export * from './config.types';
export * from './transaction.types';
export * from './wallet.types';
5 changes: 5 additions & 0 deletions packages/sdk/src/core/types/methods/connect.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export interface ConnectOptions {
walletDownloadUrl?: string;
}

export type ConnectResponse = void;
1 change: 1 addition & 0 deletions packages/sdk/src/core/types/methods/disconnect.types.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type DisconnectResponse = void;
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
import { ConnectionState } from '../../connection';

export type GetConnectionState = ConnectionState;
4 changes: 4 additions & 0 deletions packages/sdk/src/core/types/methods/index.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
export * from './add-establish.types';
export * from './add-network.types';
export * from './broadcast-transaction.types';
export * from './connect.types';
export * from './disconnect.types';
export * from './get-account.types';
export * from './is-connected.types';
export * from './off-connection-change';
export * from './on-change-account.types';
export * from './on-change-network.types';
export * from './on-connection-change';
export * from './sign-transaction.types';
export * from './switch-network.types';
1 change: 1 addition & 0 deletions packages/sdk/src/providers/adena-wallet/adena-wallet.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Tx } from '@gnolang/tm2-js-client';

import { makeResponseMessage } from '../../core';
import { WalletProvider } from '../../core/providers';
import { AccountInfo, WalletResponseFailureType, WalletResponseSuccessType } from '../../core/types';
Expand Down
Loading

0 comments on commit ee6954b

Please sign in to comment.