Skip to content

Commit

Permalink
Refactor session config handling and cryptography logic for improved …
Browse files Browse the repository at this point in the history
…abstraction (#1059)
  • Loading branch information
bangtoven authored Nov 13, 2023
1 parent 23a78c8 commit 29786ef
Show file tree
Hide file tree
Showing 9 changed files with 409 additions and 283 deletions.
11 changes: 11 additions & 0 deletions asdf/packages/wallet-sdk/.eslintrc.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,15 @@ module.exports = {
pragma: "h",
},
},
rules: {
'no-useless-constructor': 'off',
},
overrides: [
{
files: ["**/*.test.*"],
rules: {
"@typescript-eslint/no-explicit-any": "off"
}
}
]
};
2 changes: 1 addition & 1 deletion asdf/packages/wallet-sdk/jest.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ export default {
'./src/connection/RxWebSocket.ts',
'./src/connection/WalletLinkConnection.ts',
'./src/connection/WalletLinkHTTP.ts',
'./src/connection/WalletLinkConnectionCipher.ts',
'./src/lib/ScopedLocalStorage.ts',
'./src/provider/CoinbaseWalletProvider.ts',
'./src/provider/FilterPolyfill.ts',
'./src/provider/SubscriptionManager.ts',
'./src/provider/WalletLinkRelayUI.ts',
'./src/relay/aes256gcm.ts',
'./src/relay/Session.ts',
'./src/relay/WalletSDKRelay.ts',
'./src/relay/WalletSDKRelayEventManager.ts',
Expand Down
11 changes: 11 additions & 0 deletions asdf/packages/wallet-sdk/src/connection/ServerMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,14 @@ export interface ServerMessageEvent extends ServerMessage {
event: string;
data: string;
}

export function isServerMessageEvent(msg: any): msg is ServerMessageEvent {
return (
msg &&
msg.type === 'Event' &&
typeof msg.sessionId === 'string' &&
typeof msg.eventId === 'string' &&
typeof msg.event === 'string' &&
typeof msg.data === 'string'
);
}
138 changes: 138 additions & 0 deletions asdf/packages/wallet-sdk/src/connection/WalletLinkConnection.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
import { ScopedLocalStorage } from '../lib/ScopedLocalStorage';
import { Session } from '../relay/Session';
import { APP_VERSION_KEY, WALLET_USER_NAME_KEY } from '../relay/WalletSDKRelayAbstract';
import { SessionConfig } from './SessionConfig';
import { WalletLinkConnection, WalletLinkConnectionUpdateListener } from './WalletLinkConnection';
import { WalletLinkConnectionCipher } from './WalletLinkConnectionCipher';

const decryptMock = jest.fn().mockImplementation((text) => Promise.resolve(`decrypted ${text}`));

jest.spyOn(WalletLinkConnectionCipher.prototype, 'decrypt').mockImplementation(decryptMock);

describe('WalletLinkConnection', () => {
const session = new Session(new ScopedLocalStorage('test'));

let connection: WalletLinkConnection;
let listener: WalletLinkConnectionUpdateListener;

beforeEach(() => {
jest.clearAllMocks();

connection = new WalletLinkConnection(session, 'http://link-api-url', {
linkedUpdated: jest.fn(),
connectedUpdated: jest.fn(),
handleResponseMessage: jest.fn(),
chainUpdated: jest.fn(),
accountUpdated: jest.fn(),
metadataUpdated: jest.fn(),
resetAndReload: jest.fn(),
});
listener = (connection as any).listener;
});

describe('incomingDataListener', () => {
it('should call handleSessionMetadataUpdated when session config is updated', async () => {
const handleSessionMetadataUpdatedSpy = jest.spyOn(
connection as any,
'handleSessionMetadataUpdated'
);

const sessionConfig: SessionConfig = {
webhookId: 'webhookId',
webhookUrl: 'webhookUrl',
metadata: {
WalletUsername: 'new username',
},
};

(connection as any).ws.incomingDataListener?.({
...sessionConfig,
type: 'SessionConfigUpdated',
});

expect(handleSessionMetadataUpdatedSpy).toHaveBeenCalledWith(sessionConfig.metadata);
});
});

describe('handleSessionMetadataUpdated', () => {
function invoke_handleSessionMetadataUpdated(metadata: SessionConfig['metadata']) {
(connection as any).handleSessionMetadataUpdated(metadata);
}

it('should call listner.metadataUpdated when WalletUsername updated', async () => {
const listener_metadataUpdatedSpy = jest.spyOn(listener, 'metadataUpdated');

const newUsername = 'new username';

invoke_handleSessionMetadataUpdated({ WalletUsername: newUsername });

expect(listener_metadataUpdatedSpy).toHaveBeenCalledWith(
WALLET_USER_NAME_KEY,
await decryptMock(newUsername)
);
});

it('should call listner.metadataUpdated when AppVersion updated', async () => {
const listener_metadataUpdatedSpy = jest.spyOn(listener, 'metadataUpdated');

const newAppVersion = 'new app version';

invoke_handleSessionMetadataUpdated({ AppVersion: newAppVersion });

expect(listener_metadataUpdatedSpy).toHaveBeenCalledWith(
APP_VERSION_KEY,
await decryptMock(newAppVersion)
);
});

it('should call listner.resetAndReload when __destroyed: 1 is received', async () => {
const listener_resetAndReloadSpy = jest.spyOn(listener, 'resetAndReload');

invoke_handleSessionMetadataUpdated({ __destroyed: '1' });

expect(listener_resetAndReloadSpy).toHaveBeenCalled();
});

it('should call listner.accountUpdated when Account updated', async () => {
const listener_accountUpdatedSpy = jest.spyOn(listener, 'accountUpdated');

const newAccount = 'new account';

invoke_handleSessionMetadataUpdated({ EthereumAddress: newAccount });

expect(listener_accountUpdatedSpy).toHaveBeenCalledWith(await decryptMock(newAccount));
});

describe('chain updates', () => {
it('should NOT call listner.chainUpdated when only one changed', async () => {
const listener_chainUpdatedSpy = jest.spyOn(listener, 'chainUpdated');

const chainIdUpdate = { ChainId: 'new chain id' };
const jsonRpcUrlUpdate = { JsonRpcUrl: 'new json rpc url' };

invoke_handleSessionMetadataUpdated(chainIdUpdate);
invoke_handleSessionMetadataUpdated(jsonRpcUrlUpdate);

await decryptMock(chainIdUpdate.ChainId);

expect(listener_chainUpdatedSpy).not.toHaveBeenCalled();
});

it('should call listner.chainUpdated when both ChainId and JsonRpcUrl changed', async () => {
const listener_chainUpdatedSpy = jest.spyOn(listener, 'chainUpdated');

const update = {
ChainId: 'new chain id',
JsonRpcUrl: 'new json rpc url',
};

invoke_handleSessionMetadataUpdated(update);

expect(listener_chainUpdatedSpy).toHaveBeenCalledWith(
await decryptMock(update.ChainId),
await decryptMock(update.JsonRpcUrl)
);
});
});
});
});
Loading

0 comments on commit 29786ef

Please sign in to comment.