Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: session integration #125

Merged
merged 42 commits into from
Nov 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
347dd39
feat: added inheritance server session management
irshadjsr21 Jul 18, 2024
b0f5a82
ci: fixed failing ci
irshadjsr21 Jul 20, 2024
600bd8b
fix(core): add device id for server response
vrockz747 Aug 5, 2024
1ecad99
feat: added encrypt messages operation
TejasvOnly Aug 9, 2024
d7469ab
feat: added decrypt messages operation
TejasvOnly Aug 9, 2024
641575d
chore: rename operation names
TejasvOnly Aug 12, 2024
dea90d2
Merge branch 'feat/inheritance/base' into feat/inheritance/encrypt-de…
TejasvOnly Aug 12, 2024
4f4096d
chore: resolve conflicts
TejasvOnly Aug 12, 2024
f069284
fix: removed length check on inheritance enc message
irshadjsr21 Aug 12, 2024
8a3f4b6
chore: update common submodule and usage
TejasvOnly Aug 13, 2024
f0393fc
chore: update submodule
TejasvOnly Aug 13, 2024
bfc6fe9
chore: update submodule and tests
TejasvOnly Aug 13, 2024
57538cb
chore: update submodule
TejasvOnly Aug 16, 2024
35500c2
feat: add flow status
TejasvOnly Aug 16, 2024
5a70eac
feat: add seed based wallet auth (#121)
vrockz747 Aug 29, 2024
567e5b8
feat: add pairing status in auth wallet flow
TejasvOnly Aug 30, 2024
29402fc
fix: remove inbetween acks from decryption flow (#122)
TejasvOnly Aug 30, 2024
8ef9a05
fix: update tests for auth wallet
TejasvOnly Sep 5, 2024
facce42
fix: update events in inheritance
TejasvOnly Sep 17, 2024
2e2374a
feat: added chunking for encryption flow
TejasvOnly Aug 31, 2024
3ae5068
feat: add chunking for decryption
TejasvOnly Sep 5, 2024
e0b4185
feat: add tags for inheritance messages (#124)
TejasvOnly Sep 20, 2024
bb4db94
Merge branch 'feat/inheritance/encrypt-decrypt-messages' into feat/in…
TejasvOnly Sep 3, 2024
d4976e2
feat: added chunking for encryption flow
TejasvOnly Aug 31, 2024
9a79df2
wip: test sessions in device
TejasvOnly Sep 3, 2024
ba7059d
feat: add chunking for decryption
TejasvOnly Sep 5, 2024
f41fd8d
wip: fix issue
TejasvOnly Sep 4, 2024
9a69fcb
Merge branch 'feat/inheritance/chunking' into feat/inheritance/sessio…
TejasvOnly Sep 10, 2024
70adca4
refactor: update session apis
TejasvOnly Sep 18, 2024
9f46e05
chore: rebase and update submodule
TejasvOnly Sep 20, 2024
0b857b9
refactor: session integration
irshadjsr21 Sep 21, 2024
b4b3660
fix: update chunking methods to send at least a single chunk
TejasvOnly Sep 23, 2024
70c4333
Merge branch 'fix/inheritance/chunking-for-empty-message' into feat/i…
irshadjsr21 Sep 23, 2024
c5d6b2f
feat: added chunking for encryption flow (#123)
TejasvOnly Oct 4, 2024
1fc7c2d
Merge branch 'feat/inheritance/encrypt-decrypt-messages' into feat/in…
TejasvOnly Oct 4, 2024
4309e40
chore: hardcode inheritance server api
TejasvOnly Oct 8, 2024
0723a9c
chore: add device session error msg (#133)
vrockz747 Nov 12, 2024
2c7c4b4
Merge branch 'feat/inheritance/base' into feat/inheritances/session/r…
TejasvOnly Nov 12, 2024
885c54e
fix: pass keyIndex to server
TejasvOnly Nov 21, 2024
6a1c7c0
chore: remove obsolete tests
TejasvOnly Nov 21, 2024
ba0e40c
chore: undo testing code
TejasvOnly Nov 21, 2024
c149ebb
Discard changes to apps/node/src/index.ts
TejasvOnly Nov 21, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/short-ghosts-fetch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@cypherock/sdk-core': patch
---

added inheritance session management
8 changes: 8 additions & 0 deletions packages/app-inheritance/src/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,14 @@ export class InheritanceApp {
return this.sdk.runOperation(() => operations.authWallet(this.sdk, params));
}

public async startSession() {
return this.sdk.runOperation(() => this.sdk.startSession());
}

public async closeSession() {
return this.sdk.runOperation(() => this.sdk.closeSession());
}

public async destroy() {
return this.sdk.destroy();
}
Expand Down
2 changes: 1 addition & 1 deletion packages/core/jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ module.exports = {
preset: 'ts-jest',
testEnvironment: 'node',
rootDir: '.',
testPathIgnorePatterns: ['/node_modules/', '/__fixtures__/', '/dist/'],
testPathIgnorePatterns: ['/node_modules/', '/__fixtures__/', '/__helpers__/', '/dist/'],
testMatch: [
'**/tests/**/*.[jt]s?(x)',
'**/__tests__/**/*.[jt]s?(x)',
Expand Down
1 change: 1 addition & 0 deletions packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
"dependencies": {
"@cypherock/sdk-interfaces": "workspace:^0.0.15",
"@cypherock/sdk-utils": "workspace:^0.0.18",
"axios": "^1.3.4",
"compare-versions": "6.0.0-rc.1",
"protobufjs": "^7.2.2",
"uuid": "^9.0.0"
Expand Down
54 changes: 54 additions & 0 deletions packages/core/src/__mocks__/commands.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
import { IDeviceConnection } from '@cypherock/sdk-interfaces';
import { jest } from '@jest/globals';
import { Status } from '../encoders/types';
import { PacketVersion } from '../utils';

type SendCommandType = (params: {
connection: IDeviceConnection;
rawData?: string;
protoData?: string;
version: PacketVersion;
sequenceNumber: number;
maxTries?: number;
timeout?: number;
}) => Promise<void>;

type WaitForResultType = (params: {
connection: IDeviceConnection;
sequenceNumber: number;
appletId: number;
onStatus?: (status: Status) => void;
version: PacketVersion;
options?: { interval?: number; timeout?: number; maxTries?: number };
allowCoreData?: boolean;
}) => Promise<Uint8Array>;

export const sendCommand: jest.Mock<SendCommandType> =
jest.fn<SendCommandType>();

export const waitForResult: jest.Mock<WaitForResultType> =
jest.fn<WaitForResultType>();

jest.mock('../operations/helpers/sendCommand', () => {
const originalModule: any = jest.requireActual(
'../operations/helpers/sendCommand',
);

return {
__esModule: true,
...originalModule,
sendCommand,
};
});

jest.mock('../operations/proto/waitForResult', () => {
const originalModule: any = jest.requireActual(
'../operations/proto/waitForResult',
);

return {
__esModule: true,
...originalModule,
waitForResult,
};
});
26 changes: 26 additions & 0 deletions packages/core/src/__mocks__/services.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { jest } from '@jest/globals';
import {
IInitiateServerSessionParams,
IInitiateServerSessionResult,
} from '../services/types';

type InitiateServerSessionType = (
params: IInitiateServerSessionParams,
) => Promise<IInitiateServerSessionResult>;
type StartServerSessionType = (params: { sessionId: string }) => Promise<void>;

export const initiateServerSession: jest.Mock<InitiateServerSessionType> =
jest.fn<InitiateServerSessionType>();
export const startServerSession: jest.Mock<StartServerSessionType> =
jest.fn<StartServerSessionType>();

jest.mock('../services', () => {
const originalModule: any = jest.requireActual('../services');

return {
__esModule: true,
...originalModule,
initiateServerSession,
startServerSession,
};
});
97 changes: 97 additions & 0 deletions packages/core/src/commands/closeSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
import {
DeviceAppError,
DeviceAppErrorType,
IDeviceConnection,
} from '@cypherock/sdk-interfaces';
import { assert, uint8ArrayToHex } from '@cypherock/sdk-utils';
import { DeepPartial, Msg } from '../encoders/proto/generated/core';
import { SessionCloseResponse } from '../encoders/proto/generated/session';
import { ISessionCloseResponse } from '../encoders/proto/generated/types';
import { Status } from '../encoders/types';
import { sendCommand } from '../operations/helpers';
import { waitForResult } from '../operations/proto';
import {
assertOrThrowInvalidResult,
PacketVersionMap,
parseCommonError,
} from '../utils';

export interface ICloseSessionParams {
connection: IDeviceConnection;
onStatus?: (status: Status) => void;
options?: { interval?: number; timeout?: number; maxTries?: number };
getSequenceNumber: () => Promise<number>;
getNewSequenceNumber: () => Promise<number>;
}

const sendSessionCommand = async (
params: ICloseSessionParams,
data: DeepPartial<Msg['sessionClose']>,
) => {
const { maxTries, timeout } = params.options ?? {};

const msgData = uint8ArrayToHex(
Msg.encode(Msg.create({ sessionClose: data })).finish(),
);

await sendCommand({
connection: params.connection,
protoData: msgData,
rawData: '',
version: PacketVersionMap.v3,
maxTries,
sequenceNumber: await params.getNewSequenceNumber(),
timeout,
});
};

const waitForSessionResult = async (
params: ICloseSessionParams,
): Promise<ISessionCloseResponse> => {
const { connection, onStatus, options } = params;

const version = PacketVersionMap.v3;

const result = await waitForResult({
connection,
appletId: 0,
sequenceNumber: await params.getSequenceNumber(),
version,
allowCoreData: true,
onStatus,
options,
});

let msg: Msg;
try {
msg = Msg.decode(result);
} catch (error) {
throw new DeviceAppError(DeviceAppErrorType.INVALID_MSG_FROM_DEVICE);
}

const response: SessionCloseResponse | undefined = msg.sessionClose?.response;

assertOrThrowInvalidResult(response);

if (response.commonError) {
parseCommonError(response.commonError);
}

return response;
};

export const closeSession = async (
params: ICloseSessionParams,
): Promise<void> => {
assert(params.connection, 'Invalid connection');
assert(params.getNewSequenceNumber, 'Invalid getNewSequenceNumber');

await sendSessionCommand(params, {
request: {
clear: {},
},
});

const { clear } = await waitForSessionResult(params);
assertOrThrowInvalidResult(clear);
};
Original file line number Diff line number Diff line change
Expand Up @@ -4,16 +4,17 @@ import {
IDeviceConnection,
} from '@cypherock/sdk-interfaces';
import { assert, uint8ArrayToHex } from '@cypherock/sdk-utils';
import { Msg, Status } from '../../encoders/proto/generated/core';
import { IAppVersionResultResponse } from '../../encoders/proto/generated/types';
import { AppVersionResponse } from '../../encoders/proto/generated/version';
import { Msg } from '../encoders/proto/generated/core';
import { IAppVersionResultResponse } from '../encoders/proto/generated/types';
import { AppVersionResponse } from '../encoders/proto/generated/version';
import { Status } from '../encoders/types';
import { sendCommand } from '../operations/helpers';
import { waitForResult } from '../operations/proto';
import {
assertOrThrowInvalidResult,
PacketVersionMap,
parseCommonError,
} from '../../utils';
import { sendCommand } from '../helpers';
import { waitForResult } from './waitForResult';
} from '../utils';

export interface IGetAppVersionsParams {
connection: IDeviceConnection;
Expand Down Expand Up @@ -60,13 +61,17 @@ export const getAppVersions = async ({
options,
});

let response: AppVersionResponse;
let msg: Msg;
try {
response = AppVersionResponse.decode(result);
msg = Msg.decode(result);
} catch (error) {
throw new DeviceAppError(DeviceAppErrorType.INVALID_MSG_FROM_DEVICE);
}

const response: AppVersionResponse | undefined = msg.appVersion?.response;

assertOrThrowInvalidResult(response);

if (response.commonError) {
parseCommonError(response.commonError);
}
Expand Down
3 changes: 3 additions & 0 deletions packages/core/src/commands/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './getAppVersions';
export * from './startSession';
export * from './closeSession';
130 changes: 130 additions & 0 deletions packages/core/src/commands/startSession.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import {
DeviceAppError,
DeviceAppErrorType,
IDeviceConnection,
} from '@cypherock/sdk-interfaces';
import { assert, hexToUint8Array, uint8ArrayToHex } from '@cypherock/sdk-utils';
import { DeepPartial, Msg } from '../encoders/proto/generated/core';
import { SessionStartResponse } from '../encoders/proto/generated/session';
import { ISessionStartResponse } from '../encoders/proto/generated/types';
import { Status } from '../encoders/types';
import { sendCommand } from '../operations/helpers';
import { waitForResult } from '../operations/proto';
import { initiateServerSession } from '../services';
import {
assertOrThrowInvalidResult,
PacketVersionMap,
parseCommonError,
} from '../utils';

export interface IStartSessionParams {
connection: IDeviceConnection;
onStatus?: (status: Status) => void;
options?: { interval?: number; timeout?: number; maxTries?: number };
getSequenceNumber: () => Promise<number>;
getNewSequenceNumber: () => Promise<number>;
}

export interface IStartSessionResult {
sessionId: string;
sessionAge: number;
}

const sendSessionCommand = async (
params: IStartSessionParams,
data: DeepPartial<Msg['sessionStart']>,
) => {
const { maxTries, timeout } = params.options ?? {};

const msgData = uint8ArrayToHex(
Msg.encode(Msg.create({ sessionStart: data })).finish(),
);

await sendCommand({
connection: params.connection,
protoData: msgData,
rawData: '',
version: PacketVersionMap.v3,
maxTries,
sequenceNumber: await params.getNewSequenceNumber(),
timeout,
});
};

const waitForSessionResult = async (
params: IStartSessionParams,
): Promise<ISessionStartResponse> => {
const { connection, onStatus, options } = params;

const version = PacketVersionMap.v3;

const result = await waitForResult({
connection,
appletId: 0,
sequenceNumber: await params.getSequenceNumber(),
version,
allowCoreData: true,
onStatus,
options,
});

let msg: Msg;
try {
msg = Msg.decode(result);
} catch (error) {
throw new DeviceAppError(DeviceAppErrorType.INVALID_MSG_FROM_DEVICE);
}

const response: SessionStartResponse | undefined = msg.sessionStart?.response;

assertOrThrowInvalidResult(response);

if (response.commonError) {
parseCommonError(response.commonError);
}

return response;
};

export const startSession = async (
params: IStartSessionParams,
): Promise<IStartSessionResult> => {
assert(params.connection, 'Invalid connection');
assert(params.getNewSequenceNumber, 'Invalid getNewSequenceNumber');

await sendSessionCommand(params, {
request: {
initiate: {},
},
});

const { confirmationInitiate } = await waitForSessionResult(params);
assertOrThrowInvalidResult(confirmationInitiate);

const serverInitiateResponse =
await initiateServerSession(confirmationInitiate);

await sendSessionCommand(params, {
request: {
start: {
sessionAge: serverInitiateResponse.sessionAge,
sessionRandomPublic: hexToUint8Array(
serverInitiateResponse.publicKey ?? '',
),
signature: hexToUint8Array(serverInitiateResponse.signature ?? ''),
deviceId: confirmationInitiate.deviceId,
},
},
});

const { confirmationStart } = await waitForSessionResult(params);
assertOrThrowInvalidResult(confirmationStart);

assert(serverInitiateResponse.sessionId, 'Invalid session ID from server');
assert(serverInitiateResponse.sessionAge, 'Invalid session age from server');

return {
sessionId: serverInitiateResponse.sessionId,
sessionAge: serverInitiateResponse.sessionAge,
};
};
Loading
Loading