@novasamatech/host-papp 0.5.0-7 → 0.5.0-9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/dist/adapters/identity/rpc.d.ts +3 -3
  2. package/dist/components/sso/index.d.ts +36 -0
  3. package/dist/components/sso/index.js +150 -0
  4. package/dist/components/sso/scale/handshake.d.ts +9 -0
  5. package/dist/components/sso/scale/handshake.js +10 -0
  6. package/dist/components/sso/types.d.ts +15 -0
  7. package/dist/components/sso/types.js +1 -0
  8. package/dist/components/user/index.d.ts +3 -3
  9. package/dist/components/user/userSessionStorage.d.ts +3 -3
  10. package/dist/components/user/userSessionStorage.js +1 -1
  11. package/dist/crypto.d.ts +23 -0
  12. package/dist/crypto.js +51 -0
  13. package/dist/helpers/state.d.ts +16 -0
  14. package/dist/helpers/state.js +51 -0
  15. package/dist/helpers/zipWith.d.ts +4 -0
  16. package/dist/helpers/zipWith.js +11 -0
  17. package/dist/identity/impl.d.ts +6 -0
  18. package/dist/identity/impl.js +68 -0
  19. package/dist/identity/rpcAdapter.d.ts +3 -0
  20. package/dist/identity/rpcAdapter.js +38 -0
  21. package/dist/identity/types.d.ts +22 -0
  22. package/dist/identity/types.js +1 -0
  23. package/dist/index.d.ts +4 -4
  24. package/dist/index.js +1 -7
  25. package/dist/modules/crypto.d.ts +4 -8
  26. package/dist/modules/crypto.js +10 -43
  27. package/dist/modules/secretStorage.d.ts +12 -9
  28. package/dist/modules/secretStorage.js +36 -32
  29. package/dist/modules/session/helpers.d.ts +1 -1
  30. package/dist/modules/session/helpers.js +2 -2
  31. package/dist/modules/session/session.js +18 -14
  32. package/dist/modules/statementStore.d.ts +2 -2
  33. package/dist/modules/statementStore.js +4 -2
  34. package/dist/modules/storageView.d.ts +6 -6
  35. package/dist/modules/transport/crypto.js +5 -3
  36. package/dist/modules/transport/transport.d.ts +17 -2
  37. package/dist/modules/transport/transport.js +15 -5
  38. package/dist/papp.d.ts +24 -13
  39. package/dist/papp.js +18 -37
  40. package/dist/sso/auth/impl.d.ts +48 -0
  41. package/dist/sso/auth/impl.js +148 -0
  42. package/dist/sso/auth/scale/handshake.d.ts +9 -0
  43. package/dist/sso/auth/scale/handshake.js +10 -0
  44. package/dist/sso/auth/types.d.ts +15 -0
  45. package/dist/sso/auth/types.js +1 -0
  46. package/dist/sso/session/impl.d.ts +23 -0
  47. package/dist/sso/session/impl.js +57 -0
  48. package/dist/sso/session/scale/remoteMessage.d.ts +10 -0
  49. package/dist/sso/session/scale/remoteMessage.js +13 -0
  50. package/dist/sso/session/sessionManager.d.ts +23 -0
  51. package/dist/sso/session/sessionManager.js +58 -0
  52. package/dist/sso/session/ssoSession.d.ts +8 -0
  53. package/dist/sso/session/ssoSession.js +5 -0
  54. package/dist/sso/session/ssoSessionStorage.d.ts +21 -0
  55. package/dist/sso/session/ssoSessionStorage.js +20 -0
  56. package/dist/sso/session/types.d.ts +6 -0
  57. package/dist/sso/session/types.js +1 -0
  58. package/dist/sso/session/userSessionStorage.d.ts +21 -0
  59. package/dist/sso/session/userSessionStorage.js +20 -0
  60. package/dist/sso/sessionManager/impl.d.ts +22 -0
  61. package/dist/sso/sessionManager/impl.js +71 -0
  62. package/dist/sso/sessionManager/repository/ssoSessionRepository.d.ts +22 -0
  63. package/dist/sso/sessionManager/repository/ssoSessionRepository.js +27 -0
  64. package/dist/sso/sessionManager/scale/remoteMessage.d.ts +23 -0
  65. package/dist/sso/sessionManager/scale/remoteMessage.js +14 -0
  66. package/dist/sso/sessionManager/ssoSession.d.ts +23 -0
  67. package/dist/sso/sessionManager/ssoSession.js +69 -0
  68. package/dist/sso/sessionManager/ssoSessionProver.d.ts +4 -0
  69. package/dist/sso/sessionManager/ssoSessionProver.js +35 -0
  70. package/dist/sso/sessionManager/types.d.ts +6 -0
  71. package/dist/sso/sessionManager/types.js +1 -0
  72. package/dist/sso/sessionManager/userSession.d.ts +24 -0
  73. package/dist/sso/sessionManager/userSession.js +75 -0
  74. package/dist/sso/ssoSessionProver.d.ts +4 -0
  75. package/dist/sso/ssoSessionProver.js +35 -0
  76. package/dist/sso/ssoSessionRepository.d.ts +18 -0
  77. package/dist/sso/ssoSessionRepository.js +27 -0
  78. package/dist/sso/userSecretRepository.d.ts +16 -0
  79. package/dist/sso/userSecretRepository.js +44 -0
  80. package/dist/sso/userSessionRepository.d.ts +18 -0
  81. package/dist/sso/userSessionRepository.js +27 -0
  82. package/package.json +5 -3
@@ -0,0 +1,23 @@
1
+ export declare const RemoteMessageDataCodec: import("scale-ts").Codec<{
2
+ tag: "v1";
3
+ value: {
4
+ tag: "Disconnected";
5
+ value: undefined;
6
+ } | {
7
+ tag: "SigningRequest";
8
+ value: Uint8Array<ArrayBufferLike>;
9
+ };
10
+ }>;
11
+ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
12
+ messageId: string;
13
+ data: {
14
+ tag: "v1";
15
+ value: {
16
+ tag: "Disconnected";
17
+ value: undefined;
18
+ } | {
19
+ tag: "SigningRequest";
20
+ value: Uint8Array<ArrayBufferLike>;
21
+ };
22
+ };
23
+ }>;
@@ -0,0 +1,14 @@
1
+ import { Bytes, Enum, Struct, _void, str } from 'scale-ts';
2
+ export const RemoteMessageDataCodec = Enum({
3
+ v1: Enum({
4
+ Disconnected: _void,
5
+ // TODO implement
6
+ SigningRequest: Bytes(),
7
+ // TODO implement
8
+ // SigningResponse: Bytes(),
9
+ }),
10
+ });
11
+ export const RemoteMessageCodec = Struct({
12
+ messageId: str,
13
+ data: RemoteMessageDataCodec,
14
+ });
@@ -0,0 +1,23 @@
1
+ import type { Encryption, StatementProver, StatementStoreAdapter } from '@novasamatech/statement-store';
2
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
3
+ import { ResultAsync } from 'neverthrow';
4
+ import type { CodecType } from 'scale-ts';
5
+ import type { Callback } from '../../types.js';
6
+ import type { UserSession } from '../ssoSessionRepository.js';
7
+ import { RemoteMessageCodec, RemoteMessageDataCodec } from './scale/remoteMessage.js';
8
+ export type SsoSession = ReturnType<typeof createSsoSession>;
9
+ export declare function createSsoSession({ userSession, statementStore, encryption, storage, prover, }: {
10
+ userSession: UserSession;
11
+ statementStore: StatementStoreAdapter;
12
+ encryption: Encryption;
13
+ storage: StorageAdapter;
14
+ prover: StatementProver;
15
+ }): {
16
+ request(message: CodecType<typeof RemoteMessageDataCodec>): ResultAsync<{
17
+ requestId: string;
18
+ }, Error>;
19
+ sendDisconnectMessage(): ResultAsync<{
20
+ requestId: string;
21
+ }, Error>;
22
+ subscribe(callback: Callback<CodecType<typeof RemoteMessageCodec>, ResultAsync<boolean, Error>>): VoidFunction;
23
+ };
@@ -0,0 +1,69 @@
1
+ import { createSession } from '@novasamatech/statement-store';
2
+ import { fieldListView } from '@novasamatech/storage-adapter';
3
+ import { nanoid } from 'nanoid';
4
+ import { ResultAsync, okAsync } from 'neverthrow';
5
+ import { RemoteMessageCodec, RemoteMessageDataCodec } from './scale/remoteMessage.js';
6
+ export function createSsoSession({ userSession, statementStore, encryption, storage, prover, }) {
7
+ const session = createSession({
8
+ localAccount: userSession.local,
9
+ remoteAccount: userSession.remote,
10
+ statementStore,
11
+ encryption,
12
+ prover,
13
+ });
14
+ const processedMessages = fieldListView({
15
+ storage,
16
+ key: `sso_processed_${userSession.id}`,
17
+ from: JSON.parse,
18
+ to: JSON.stringify,
19
+ initial: [],
20
+ });
21
+ return {
22
+ request(message) {
23
+ return session.submitRequest(RemoteMessageCodec, {
24
+ messageId: nanoid(),
25
+ data: message,
26
+ });
27
+ },
28
+ sendDisconnectMessage() {
29
+ return session.submitRequest(RemoteMessageCodec, {
30
+ messageId: nanoid(),
31
+ data: {
32
+ tag: 'v1',
33
+ value: {
34
+ tag: 'Disconnected',
35
+ value: undefined,
36
+ },
37
+ },
38
+ });
39
+ },
40
+ subscribe(callback) {
41
+ return session.subscribe(RemoteMessageCodec, messages => {
42
+ processedMessages.read().andThen(processed => {
43
+ const results = messages.map(message => {
44
+ if (message.type === 'request') {
45
+ const isMessageProcessed = processed.includes(message.data.messageId);
46
+ if (isMessageProcessed) {
47
+ return okAsync({ processed: false });
48
+ }
49
+ return callback(message.data)
50
+ .orTee(error => {
51
+ console.error('Error while processing sso messsage:', error);
52
+ })
53
+ .orElse(() => okAsync(false))
54
+ .map(processed => (processed ? { processed, message: message.data } : { processed }));
55
+ }
56
+ return okAsync({ processed: false });
57
+ });
58
+ return ResultAsync.combine(results).andThen(results => {
59
+ const newMessages = results.filter(x => x.processed).map(x => x.message.messageId);
60
+ if (newMessages.length > 0) {
61
+ return processedMessages.mutate(x => x.concat(newMessages));
62
+ }
63
+ return okAsync();
64
+ });
65
+ });
66
+ });
67
+ },
68
+ };
69
+ }
@@ -0,0 +1,4 @@
1
+ import type { StatementProver } from '@novasamatech/statement-store';
2
+ import type { UserSession } from '../ssoSessionRepository.js';
3
+ import type { UserSecretRepository } from '../userSecretRepository.js';
4
+ export declare function createSsoStatementProver(userSession: UserSession, userSecretRepository: UserSecretRepository): StatementProver;
@@ -0,0 +1,35 @@
1
+ import { getStatementSigner, statementCodec } from '@polkadot-api/sdk-statement';
2
+ import { err, errAsync, fromThrowable, ok, okAsync } from 'neverthrow';
3
+ import { compact } from 'scale-ts';
4
+ import { toError } from '../../helpers/utils.js';
5
+ import { getSsPub, signWithSsSecret, verifyWithSsSecret } from '../../modules/crypto.js';
6
+ const verify = fromThrowable(verifyWithSsSecret, toError);
7
+ export function createSsoStatementProver(userSession, userSecretRepository) {
8
+ const secret = userSecretRepository
9
+ .read(userSession.id)
10
+ .andThen(secrets => (secrets ? ok(secrets) : err(new Error(`Secrets for session ${userSession.id} not found.`))))
11
+ .map(x => x.ssSecret);
12
+ return {
13
+ generateMessageProof(statement) {
14
+ return secret.map(secret => {
15
+ const signer = getStatementSigner(getSsPub(secret), 'sr25519', data => signWithSsSecret(secret, data));
16
+ return signer.sign(statement);
17
+ });
18
+ },
19
+ verifyMessageProof(statement) {
20
+ const { proof, ...unsigned } = statement;
21
+ if (!proof) {
22
+ // TODO should we pass check when proof is not presented?
23
+ return okAsync(true);
24
+ }
25
+ const encoded = statementCodec.enc(unsigned);
26
+ const compactLen = compact.enc(compact.dec(encoded)).length;
27
+ switch (proof.type) {
28
+ case 'sr25519':
29
+ return verify(encoded.slice(compactLen), proof.value.signature.asBytes(), proof.value.signer.asBytes()).asyncAndThen(x => okAsync(x));
30
+ default:
31
+ return errAsync(new Error(`Proof type ${proof.type} is not supported.`));
32
+ }
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,6 @@
1
+ import type { EncrSecret, SharedSecret, SsSecret } from '../../crypto.js';
2
+ export type UserSecrets = {
3
+ sharedSecret: SharedSecret;
4
+ encr: EncrSecret;
5
+ ss: SsSecret;
6
+ };
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,24 @@
1
+ import type { Encryption, StatementProver, StatementStoreAdapter } from '@novasamatech/statement-store';
2
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
3
+ import { ResultAsync } from 'neverthrow';
4
+ import type { CodecType } from 'scale-ts';
5
+ import type { Callback } from '../../types.js';
6
+ import type { StoredUserSession } from '../userSessionRepository.js';
7
+ import { RemoteMessageCodec, RemoteMessageDataCodec } from './scale/remoteMessage.js';
8
+ export type UserSession = StoredUserSession & {
9
+ request(message: CodecType<typeof RemoteMessageDataCodec>): ResultAsync<{
10
+ requestId: string;
11
+ }, Error>;
12
+ sendDisconnectMessage(): ResultAsync<{
13
+ requestId: string;
14
+ }, Error>;
15
+ subscribe(callback: Callback<CodecType<typeof RemoteMessageCodec>, ResultAsync<boolean, Error>>): VoidFunction;
16
+ dispose(): void;
17
+ };
18
+ export declare function createUserSession({ userSession, statementStore, encryption, storage, prover, }: {
19
+ userSession: StoredUserSession;
20
+ statementStore: StatementStoreAdapter;
21
+ encryption: Encryption;
22
+ storage: StorageAdapter;
23
+ prover: StatementProver;
24
+ }): UserSession;
@@ -0,0 +1,75 @@
1
+ import { createSession } from '@novasamatech/statement-store';
2
+ import { fieldListView } from '@novasamatech/storage-adapter';
3
+ import { nanoid } from 'nanoid';
4
+ import { ResultAsync, okAsync } from 'neverthrow';
5
+ import { RemoteMessageCodec, RemoteMessageDataCodec } from './scale/remoteMessage.js';
6
+ export function createUserSession({ userSession, statementStore, encryption, storage, prover, }) {
7
+ const session = createSession({
8
+ localAccount: userSession.localAccount,
9
+ remoteAccount: userSession.remoteAccount,
10
+ statementStore,
11
+ encryption,
12
+ prover,
13
+ });
14
+ const processedMessages = fieldListView({
15
+ storage,
16
+ key: `sso_processed_${userSession.id}`,
17
+ from: JSON.parse,
18
+ to: JSON.stringify,
19
+ initial: [],
20
+ });
21
+ return {
22
+ id: userSession.id,
23
+ localAccount: userSession.localAccount,
24
+ remoteAccount: userSession.remoteAccount,
25
+ request(message) {
26
+ return session.submitRequest(RemoteMessageCodec, {
27
+ messageId: nanoid(),
28
+ data: message,
29
+ });
30
+ },
31
+ sendDisconnectMessage() {
32
+ return session.submitRequest(RemoteMessageCodec, {
33
+ messageId: nanoid(),
34
+ data: {
35
+ tag: 'v1',
36
+ value: {
37
+ tag: 'Disconnected',
38
+ value: undefined,
39
+ },
40
+ },
41
+ });
42
+ },
43
+ subscribe(callback) {
44
+ return session.subscribe(RemoteMessageCodec, messages => {
45
+ processedMessages.read().andThen(processed => {
46
+ const results = messages.map(message => {
47
+ if (message.type === 'request') {
48
+ const isMessageProcessed = processed.includes(message.data.messageId);
49
+ if (isMessageProcessed) {
50
+ return okAsync({ processed: false });
51
+ }
52
+ return callback(message.data)
53
+ .orTee(error => {
54
+ console.error('Error while processing sso messsage:', error);
55
+ })
56
+ .orElse(() => okAsync(false))
57
+ .map(processed => (processed ? { processed, message: message.data } : { processed }));
58
+ }
59
+ return okAsync({ processed: false });
60
+ });
61
+ return ResultAsync.combine(results).andThen(results => {
62
+ const newMessages = results.filter(x => x.processed).map(x => x.message.messageId);
63
+ if (newMessages.length > 0) {
64
+ return processedMessages.mutate(x => x.concat(newMessages));
65
+ }
66
+ return okAsync();
67
+ });
68
+ });
69
+ });
70
+ },
71
+ dispose() {
72
+ return session.dispose();
73
+ },
74
+ };
75
+ }
@@ -0,0 +1,4 @@
1
+ import type { StatementProver } from '@novasamatech/statement-store';
2
+ import type { UserSecretRepository } from './userSecretRepository.js';
3
+ import type { StoredUserSession } from './userSessionRepository.js';
4
+ export declare function createSsoStatementProver(userSession: StoredUserSession, userSecretRepository: UserSecretRepository): StatementProver;
@@ -0,0 +1,35 @@
1
+ import { getStatementSigner, statementCodec } from '@polkadot-api/sdk-statement';
2
+ import { err, errAsync, fromThrowable, ok, okAsync } from 'neverthrow';
3
+ import { compact } from 'scale-ts';
4
+ import { getSsPub, signWithSsSecret, verifyWithSsSecret } from '../crypto.js';
5
+ import { toError } from '../helpers/utils.js';
6
+ const verify = fromThrowable(verifyWithSsSecret, toError);
7
+ export function createSsoStatementProver(userSession, userSecretRepository) {
8
+ const secret = userSecretRepository
9
+ .read(userSession.id)
10
+ .andThen(secrets => (secrets ? ok(secrets) : err(new Error(`Secrets for session ${userSession.id} not found.`))))
11
+ .map(x => x.ssSecret);
12
+ return {
13
+ generateMessageProof(statement) {
14
+ return secret.map(secret => {
15
+ const signer = getStatementSigner(getSsPub(secret), 'sr25519', data => signWithSsSecret(secret, data));
16
+ return signer.sign(statement);
17
+ });
18
+ },
19
+ verifyMessageProof(statement) {
20
+ const { proof, ...unsigned } = statement;
21
+ if (!proof) {
22
+ // TODO should we pass check when proof is not presented?
23
+ return okAsync(true);
24
+ }
25
+ const encoded = statementCodec.enc(unsigned);
26
+ const compactLen = compact.enc(compact.dec(encoded)).length;
27
+ switch (proof.type) {
28
+ case 'sr25519':
29
+ return verify(encoded.slice(compactLen), proof.value.signature.asBytes(), proof.value.signer.asBytes()).asyncAndThen(x => okAsync(x));
30
+ default:
31
+ return errAsync(new Error(`Proof type ${proof.type} is not supported.`));
32
+ }
33
+ },
34
+ };
35
+ }
@@ -0,0 +1,18 @@
1
+ import type { LocalSessionAccount, RemoteSessionAccount } from '@novasamatech/statement-store';
2
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
3
+ export type SsoSessionRepository = ReturnType<typeof createSsoSessionRepository>;
4
+ export type UserSession = {
5
+ id: string;
6
+ local: LocalSessionAccount;
7
+ remote: RemoteSessionAccount;
8
+ };
9
+ export declare function createUserSession(localAccount: LocalSessionAccount, remoteAccount: RemoteSessionAccount): UserSession;
10
+ export declare const createSsoSessionRepository: (storage: StorageAdapter) => {
11
+ add(value: UserSession): import("neverthrow").ResultAsync<UserSession, Error>;
12
+ filter(fn: (value: UserSession) => boolean): import("neverthrow").ResultAsync<UserSession[], Error>;
13
+ mutate(fn: (value: UserSession[]) => UserSession[]): import("neverthrow").ResultAsync<UserSession[], Error>;
14
+ read(): import("neverthrow").ResultAsync<UserSession[], Error>;
15
+ write(value: UserSession[]): import("neverthrow").ResultAsync<UserSession[], Error> | import("neverthrow").ResultAsync<null, Error>;
16
+ clear(): import("neverthrow").ResultAsync<void, Error>;
17
+ subscribe(fn: (value: UserSession[]) => void): VoidFunction;
18
+ };
@@ -0,0 +1,27 @@
1
+ import { LocalSessionAccountCodec, RemoteSessionAccountCodec } from '@novasamatech/statement-store';
2
+ import { fieldListView } from '@novasamatech/storage-adapter';
3
+ import { fromHex, toHex } from '@polkadot-api/utils';
4
+ import { nanoid } from 'nanoid';
5
+ import { Struct, Vector, str } from 'scale-ts';
6
+ const userSessionCodec = Struct({
7
+ id: str,
8
+ local: LocalSessionAccountCodec,
9
+ remote: RemoteSessionAccountCodec,
10
+ });
11
+ export function createUserSession(localAccount, remoteAccount) {
12
+ return {
13
+ id: nanoid(12),
14
+ local: localAccount,
15
+ remote: remoteAccount,
16
+ };
17
+ }
18
+ const userSessionsCodec = Vector(userSessionCodec);
19
+ export const createSsoSessionRepository = (storage) => {
20
+ return fieldListView({
21
+ storage,
22
+ key: 'SsoSessions',
23
+ initial: [],
24
+ from: x => userSessionsCodec.dec(fromHex(x)),
25
+ to: x => toHex(userSessionsCodec.enc(x)),
26
+ });
27
+ };
@@ -0,0 +1,16 @@
1
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
2
+ import type { ResultAsync } from 'neverthrow';
3
+ import type { CodecType } from 'scale-ts';
4
+ import type { EncrSecret, SsSecret } from '../crypto.js';
5
+ type StoredUserSecrets = CodecType<typeof StoredUserSecretsCodec>;
6
+ declare const StoredUserSecretsCodec: import("scale-ts").Codec<{
7
+ ssSecret: SsSecret;
8
+ encrSecret: EncrSecret;
9
+ }>;
10
+ export type UserSecretRepository = ReturnType<typeof createUserSecretRepository>;
11
+ export declare function createUserSecretRepository(salt: string, storage: StorageAdapter): {
12
+ read(sessionId: string): ResultAsync<StoredUserSecrets | null, Error>;
13
+ write(sessionId: string, value: StoredUserSecrets): ResultAsync<void, Error>;
14
+ clear(sessionId: string): ResultAsync<void, Error>;
15
+ };
16
+ export {};
@@ -0,0 +1,44 @@
1
+ import { gcm } from '@noble/ciphers/aes.js';
2
+ import { blake2b } from '@noble/hashes/blake2.js';
3
+ import { fromHex, toHex } from '@polkadot-api/utils';
4
+ import { fromThrowable } from 'neverthrow';
5
+ import { Struct } from 'scale-ts';
6
+ import { BrandedBytesCodec, stringToBytes } from '../crypto.js';
7
+ import { toError } from '../helpers/utils.js';
8
+ const StoredUserSecretsCodec = Struct({
9
+ ssSecret: BrandedBytesCodec(),
10
+ encrSecret: BrandedBytesCodec(),
11
+ });
12
+ export function createUserSecretRepository(salt, storage) {
13
+ const baseKey = 'UserSecrets';
14
+ const encode = fromThrowable(StoredUserSecretsCodec.enc, toError);
15
+ const decode = fromThrowable((value) => (value ? StoredUserSecretsCodec.dec(value) : null), toError);
16
+ const encrypt = fromThrowable((value) => {
17
+ const aes = getAes(salt);
18
+ return toHex(aes.encrypt(value));
19
+ }, toError);
20
+ const decrypt = fromThrowable((value) => {
21
+ if (value === null) {
22
+ return null;
23
+ }
24
+ const aes = getAes(salt);
25
+ return aes.decrypt(fromHex(value));
26
+ }, toError);
27
+ return {
28
+ read(sessionId) {
29
+ return storage.read(createKey(baseKey, sessionId)).andThen(decrypt).andThen(decode);
30
+ },
31
+ write(sessionId, value) {
32
+ return encode(value)
33
+ .andThen(encrypt)
34
+ .asyncAndThen(value => storage.write(createKey(baseKey, sessionId), value));
35
+ },
36
+ clear(sessionId) {
37
+ return storage.clear(createKey(baseKey, sessionId));
38
+ },
39
+ };
40
+ }
41
+ const createKey = (key, context) => `${key}_${context}`;
42
+ function getAes(salt) {
43
+ return gcm(blake2b(stringToBytes(salt), { dkLen: 16 }), blake2b(stringToBytes('nonce'), { dkLen: 32 }));
44
+ }
@@ -0,0 +1,18 @@
1
+ import type { LocalSessionAccount, RemoteSessionAccount } from '@novasamatech/statement-store';
2
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
3
+ export type UserSessionRepository = ReturnType<typeof createUserSessionRepository>;
4
+ export type StoredUserSession = {
5
+ id: string;
6
+ localAccount: LocalSessionAccount;
7
+ remoteAccount: RemoteSessionAccount;
8
+ };
9
+ export declare function createStoredUserSession(localAccount: LocalSessionAccount, remoteAccount: RemoteSessionAccount): StoredUserSession;
10
+ export declare const createUserSessionRepository: (storage: StorageAdapter) => {
11
+ add(value: StoredUserSession): import("neverthrow").ResultAsync<StoredUserSession, Error>;
12
+ filter(fn: (value: StoredUserSession) => boolean): import("neverthrow").ResultAsync<StoredUserSession[], Error>;
13
+ mutate(fn: (value: StoredUserSession[]) => StoredUserSession[]): import("neverthrow").ResultAsync<StoredUserSession[], Error>;
14
+ read(): import("neverthrow").ResultAsync<StoredUserSession[], Error>;
15
+ write(value: StoredUserSession[]): import("neverthrow").ResultAsync<StoredUserSession[], Error> | import("neverthrow").ResultAsync<null, Error>;
16
+ clear(): import("neverthrow").ResultAsync<void, Error>;
17
+ subscribe(fn: (value: StoredUserSession[]) => void): VoidFunction;
18
+ };
@@ -0,0 +1,27 @@
1
+ import { LocalSessionAccountCodec, RemoteSessionAccountCodec } from '@novasamatech/statement-store';
2
+ import { fieldListView } from '@novasamatech/storage-adapter';
3
+ import { fromHex, toHex } from '@polkadot-api/utils';
4
+ import { nanoid } from 'nanoid';
5
+ import { Struct, Vector, str } from 'scale-ts';
6
+ const storedUserSessionCodec = Struct({
7
+ id: str,
8
+ localAccount: LocalSessionAccountCodec,
9
+ remoteAccount: RemoteSessionAccountCodec,
10
+ });
11
+ export function createStoredUserSession(localAccount, remoteAccount) {
12
+ return {
13
+ id: nanoid(12),
14
+ localAccount: localAccount,
15
+ remoteAccount: remoteAccount,
16
+ };
17
+ }
18
+ export const createUserSessionRepository = (storage) => {
19
+ const codec = Vector(storedUserSessionCodec);
20
+ return fieldListView({
21
+ storage,
22
+ key: 'SsoSessions',
23
+ initial: [],
24
+ from: x => codec.dec(fromHex(x)),
25
+ to: x => toHex(codec.enc(x)),
26
+ });
27
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@novasamatech/host-papp",
3
3
  "type": "module",
4
- "version": "0.5.0-7",
4
+ "version": "0.5.0-9",
5
5
  "description": "Polkadot app integration",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -24,7 +24,9 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@polkadot-api/sdk-statement": "^0.2.0",
27
+ "@novasamatech/host-api": "0.5.0-9",
28
+ "@novasamatech/statement-store": "0.5.0-9",
29
+ "@novasamatech/storage-adapter": "0.5.0-9",
28
30
  "@polkadot-api/substrate-bindings": "^0.16.5",
29
31
  "@scure/sr25519": "1.0.0",
30
32
  "@noble/curves": "2.0.1",
@@ -33,7 +35,7 @@
33
35
  "polkadot-api": "^1.23.1",
34
36
  "nanoevents": "9.1.0",
35
37
  "nanoid": "5.1.6",
36
- "neverthrow": "8.2.0",
38
+ "neverthrow": "^8.2.0",
37
39
  "scale-ts": "1.6.1"
38
40
  },
39
41
  "publishConfig": {