@novasamatech/host-papp 0.5.0-0 → 0.5.0-10

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 (184) hide show
  1. package/.papi/descriptors/dist/common-types.d.ts +8667 -0
  2. package/.papi/descriptors/dist/common.d.ts +1 -0
  3. package/.papi/descriptors/dist/descriptors-UUEW32EL.mjs +27 -0
  4. package/.papi/descriptors/dist/descriptors.d.ts +1 -0
  5. package/.papi/descriptors/dist/index.d.ts +10 -0
  6. package/.papi/descriptors/dist/index.js +237 -0
  7. package/.papi/descriptors/dist/index.mjs +148 -0
  8. package/.papi/descriptors/dist/metadataTypes-E4AQJDJR.mjs +6 -0
  9. package/.papi/descriptors/dist/metadataTypes.d.ts +2 -0
  10. package/.papi/descriptors/dist/people_lite.d.ts +7757 -0
  11. package/.papi/descriptors/dist/people_lite_metadata-EIVHV27X.mjs +6 -0
  12. package/.papi/descriptors/dist/people_lite_metadata.d.ts +2 -0
  13. package/.papi/descriptors/package.json +24 -0
  14. package/.papi/metadata/people_lite.scale +0 -0
  15. package/.papi/polkadot-api.json +15 -0
  16. package/dist/adapters/identity/rpc.d.ts +6 -4
  17. package/dist/adapters/identity/rpc.js +96 -26
  18. package/dist/adapters/identity/types.d.ts +3 -1
  19. package/dist/adapters/lazyClient/papi.js +5 -0
  20. package/dist/adapters/lazyClient/types.d.ts +1 -0
  21. package/dist/adapters/statement/rpc.js +58 -10
  22. package/dist/adapters/statement/types.d.ts +6 -3
  23. package/dist/adapters/storage/localStorage.js +26 -4
  24. package/dist/adapters/storage/memory.js +14 -4
  25. package/dist/adapters/storage/types.d.ts +5 -2
  26. package/dist/adapters/storage/types.js +1 -1
  27. package/dist/components/auth/codec.d.ts +9 -0
  28. package/dist/components/auth/codec.js +10 -0
  29. package/dist/components/auth/codecs.d.ts +9 -0
  30. package/dist/components/auth/codecs.js +10 -0
  31. package/dist/components/auth/index.d.ts +36 -0
  32. package/dist/components/auth/index.js +150 -0
  33. package/dist/components/auth/types.d.ts +15 -0
  34. package/dist/components/auth/types.js +1 -0
  35. package/dist/components/session.d.ts +34 -0
  36. package/dist/components/session.js +54 -0
  37. package/dist/components/sso/index.d.ts +36 -0
  38. package/dist/components/sso/index.js +150 -0
  39. package/dist/components/sso/scale/handshake.d.ts +9 -0
  40. package/dist/components/sso/scale/handshake.js +10 -0
  41. package/dist/components/sso/types.d.ts +15 -0
  42. package/dist/components/sso/types.js +1 -0
  43. package/dist/components/transport.d.ts +27 -0
  44. package/dist/components/transport.js +57 -0
  45. package/dist/components/user/codec.d.ts +16 -0
  46. package/dist/components/user/codec.js +13 -0
  47. package/dist/components/user/index.d.ts +22 -0
  48. package/dist/components/user/index.js +58 -0
  49. package/dist/components/user/ssoMessageStream.d.ts +10 -0
  50. package/dist/components/user/ssoMessageStream.js +8 -0
  51. package/dist/components/user/ssoSession.d.ts +5 -0
  52. package/dist/components/user/ssoSession.js +5 -0
  53. package/dist/components/user/storage.d.ts +27 -0
  54. package/dist/components/user/storage.js +143 -0
  55. package/dist/components/user/types.d.ts +6 -0
  56. package/dist/components/user/types.js +1 -0
  57. package/dist/components/user/userSessionStorage.d.ts +20 -0
  58. package/dist/components/user/userSessionStorage.js +24 -0
  59. package/dist/components/user.d.ts +74 -0
  60. package/dist/components/user.js +188 -0
  61. package/dist/constants.d.ts +2 -1
  62. package/dist/constants.js +5 -1
  63. package/dist/crypto.d.ts +29 -0
  64. package/dist/crypto.js +86 -0
  65. package/dist/helpers/abortError.d.ts +4 -0
  66. package/dist/helpers/abortError.js +8 -0
  67. package/dist/helpers/callbackRaceResolver.d.ts +1 -0
  68. package/dist/helpers/callbackRaceResolver.js +17 -0
  69. package/dist/helpers/result.d.ts +12 -0
  70. package/dist/helpers/result.js +15 -0
  71. package/dist/helpers/result.spec.d.ts +1 -0
  72. package/dist/helpers/result.spec.js +23 -0
  73. package/dist/helpers/state.d.ts +16 -0
  74. package/dist/helpers/state.js +51 -0
  75. package/dist/helpers/utils.d.ts +2 -1
  76. package/dist/helpers/utils.js +11 -2
  77. package/dist/helpers/zipWith.d.ts +4 -0
  78. package/dist/helpers/zipWith.js +11 -0
  79. package/dist/identity/impl.d.ts +6 -0
  80. package/dist/identity/impl.js +68 -0
  81. package/dist/identity/rpcAdapter.d.ts +3 -0
  82. package/dist/identity/rpcAdapter.js +46 -0
  83. package/dist/identity/types.d.ts +21 -0
  84. package/dist/identity/types.js +1 -0
  85. package/dist/index.d.ts +7 -3
  86. package/dist/index.js +2 -7
  87. package/dist/modules/crypto.d.ts +8 -9
  88. package/dist/modules/crypto.js +20 -42
  89. package/dist/modules/secretStorage.d.ts +13 -12
  90. package/dist/modules/secretStorage.js +34 -43
  91. package/dist/modules/session/helpers.d.ts +5 -0
  92. package/dist/modules/session/helpers.js +29 -0
  93. package/dist/modules/session/session.d.ts +12 -0
  94. package/dist/modules/session/session.js +50 -0
  95. package/dist/modules/session/types.d.ts +12 -0
  96. package/dist/modules/session/types.js +1 -0
  97. package/dist/modules/signIn.d.ts +32 -11
  98. package/dist/modules/signIn.js +98 -101
  99. package/dist/modules/state.d.ts +16 -0
  100. package/dist/modules/state.js +50 -0
  101. package/dist/modules/statementStore.d.ts +10 -11
  102. package/dist/modules/statementStore.js +16 -14
  103. package/dist/modules/statementTopic.d.ts +34 -0
  104. package/dist/modules/statementTopic.js +46 -0
  105. package/dist/modules/storageView.d.ts +25 -0
  106. package/dist/modules/storageView.js +51 -0
  107. package/dist/modules/syncStorage.d.ts +25 -0
  108. package/dist/modules/syncStorage.js +76 -0
  109. package/dist/modules/transport/codec.d.ts +24 -0
  110. package/dist/modules/transport/codec.js +36 -0
  111. package/dist/modules/transport/crypto.d.ts +2 -0
  112. package/dist/modules/transport/crypto.js +20 -0
  113. package/dist/modules/transport/transport.d.ts +42 -0
  114. package/dist/modules/transport/transport.js +66 -0
  115. package/dist/modules/user.d.ts +67 -0
  116. package/dist/modules/user.js +188 -0
  117. package/dist/modules/userManager.d.ts +15 -0
  118. package/dist/modules/userManager.js +105 -0
  119. package/dist/modules/userStorage.d.ts +19 -0
  120. package/dist/modules/userStorage.js +108 -0
  121. package/dist/modules/userStore.d.ts +15 -0
  122. package/dist/modules/userStore.js +105 -0
  123. package/dist/papp.d.ts +25 -13
  124. package/dist/papp.js +19 -50
  125. package/dist/sso/auth/attestationService.d.ts +18 -0
  126. package/dist/sso/auth/attestationService.js +171 -0
  127. package/dist/sso/auth/impl.d.ts +53 -0
  128. package/dist/sso/auth/impl.js +161 -0
  129. package/dist/sso/auth/scale/handshake.d.ts +9 -0
  130. package/dist/sso/auth/scale/handshake.js +10 -0
  131. package/dist/sso/auth/types.d.ts +17 -0
  132. package/dist/sso/auth/types.js +1 -0
  133. package/dist/sso/session/impl.d.ts +23 -0
  134. package/dist/sso/session/impl.js +57 -0
  135. package/dist/sso/session/scale/remoteMessage.d.ts +10 -0
  136. package/dist/sso/session/scale/remoteMessage.js +13 -0
  137. package/dist/sso/session/sessionManager.d.ts +23 -0
  138. package/dist/sso/session/sessionManager.js +58 -0
  139. package/dist/sso/session/ssoSession.d.ts +8 -0
  140. package/dist/sso/session/ssoSession.js +5 -0
  141. package/dist/sso/session/ssoSessionStorage.d.ts +21 -0
  142. package/dist/sso/session/ssoSessionStorage.js +20 -0
  143. package/dist/sso/session/types.d.ts +6 -0
  144. package/dist/sso/session/types.js +1 -0
  145. package/dist/sso/session/userSessionStorage.d.ts +21 -0
  146. package/dist/sso/session/userSessionStorage.js +20 -0
  147. package/dist/sso/sessionManager/attestationService.d.ts +5 -0
  148. package/dist/sso/sessionManager/attestationService.js +15 -0
  149. package/dist/sso/sessionManager/impl.d.ts +22 -0
  150. package/dist/sso/sessionManager/impl.js +71 -0
  151. package/dist/sso/sessionManager/repository/ssoSessionRepository.d.ts +22 -0
  152. package/dist/sso/sessionManager/repository/ssoSessionRepository.js +27 -0
  153. package/dist/sso/sessionManager/scale/hex.d.ts +1 -0
  154. package/dist/sso/sessionManager/scale/hex.js +3 -0
  155. package/dist/sso/sessionManager/scale/remoteMessage.d.ts +41 -0
  156. package/dist/sso/sessionManager/scale/remoteMessage.js +13 -0
  157. package/dist/sso/sessionManager/scale/signPayloadRequest.d.ts +19 -0
  158. package/dist/sso/sessionManager/scale/signPayloadRequest.js +19 -0
  159. package/dist/sso/sessionManager/scale/signPayloadResponse.d.ts +12 -0
  160. package/dist/sso/sessionManager/scale/signPayloadResponse.js +9 -0
  161. package/dist/sso/sessionManager/scale/signRequest.d.ts +19 -0
  162. package/dist/sso/sessionManager/scale/signRequest.js +19 -0
  163. package/dist/sso/sessionManager/scale/signResponse.d.ts +6 -0
  164. package/dist/sso/sessionManager/scale/signResponse.js +5 -0
  165. package/dist/sso/sessionManager/ssoSession.d.ts +23 -0
  166. package/dist/sso/sessionManager/ssoSession.js +69 -0
  167. package/dist/sso/sessionManager/ssoSessionProver.d.ts +4 -0
  168. package/dist/sso/sessionManager/ssoSessionProver.js +35 -0
  169. package/dist/sso/sessionManager/types.d.ts +6 -0
  170. package/dist/sso/sessionManager/types.js +1 -0
  171. package/dist/sso/sessionManager/userSession.d.ts +22 -0
  172. package/dist/sso/sessionManager/userSession.js +106 -0
  173. package/dist/sso/ssoSessionProver.d.ts +4 -0
  174. package/dist/sso/ssoSessionProver.js +35 -0
  175. package/dist/sso/ssoSessionRepository.d.ts +18 -0
  176. package/dist/sso/ssoSessionRepository.js +27 -0
  177. package/dist/sso/userSecretRepository.d.ts +17 -0
  178. package/dist/sso/userSecretRepository.js +45 -0
  179. package/dist/sso/userSessionRepository.d.ts +18 -0
  180. package/dist/sso/userSessionRepository.js +26 -0
  181. package/dist/structs.d.ts +10 -10
  182. package/dist/structs.js +17 -13
  183. package/dist/types.d.ts +1 -1
  184. package/package.json +14 -7
@@ -0,0 +1,23 @@
1
+ import { err, errAsync, ok, okAsync } from 'neverthrow';
2
+ import { describe, expect, it } from 'vitest';
3
+ import { seq, seqAsync } from './result.js';
4
+ describe('Result', () => {
5
+ describe('seq', () => {
6
+ it('should concat ok values', () => {
7
+ expect(seq(ok(1), ok('2'))._unsafeUnwrap()).toEqual([1, '2']);
8
+ });
9
+ it('should fallback to err', () => {
10
+ expect(seq(ok(1), err('2')).orElse(ok)._unsafeUnwrap()).toEqual('2');
11
+ expect(seq(err(1), ok('2')).orElse(ok)._unsafeUnwrap()).toEqual(1);
12
+ });
13
+ });
14
+ describe('seqAsync', () => {
15
+ it('should concat ok values', async () => {
16
+ expect((await seqAsync(okAsync(1), okAsync('2')))._unsafeUnwrap()).toEqual([1, '2']);
17
+ });
18
+ it('should fallback to err', async () => {
19
+ await expect(seqAsync(okAsync(1), errAsync('2')).then(x => x._unsafeUnwrapErr())).resolves.toEqual('2');
20
+ await expect(seqAsync(errAsync(1), okAsync('2')).then(x => x._unsafeUnwrapErr())).resolves.toEqual(1);
21
+ });
22
+ });
23
+ });
@@ -0,0 +1,16 @@
1
+ type State<T> = ReturnType<typeof createState<T>>;
2
+ export declare function createState<T>(initial: T): {
3
+ read(): T;
4
+ write(value: T | ((prev: T) => T)): T;
5
+ reset(): void;
6
+ subscribe(fn: (value: T) => void): () => void;
7
+ onFirstSubscribe(callback: VoidFunction): import("nanoevents").Unsubscribe;
8
+ onLastUnsubscribe(callback: VoidFunction): import("nanoevents").Unsubscribe;
9
+ };
10
+ export declare function readonly<T>(state: State<T>): {
11
+ read: () => T;
12
+ subscribe: (fn: (value: T) => void) => () => void;
13
+ onFirstSubscribe: (callback: VoidFunction) => import("nanoevents").Unsubscribe;
14
+ onLastUnsubscribe: (callback: VoidFunction) => import("nanoevents").Unsubscribe;
15
+ };
16
+ export {};
@@ -0,0 +1,51 @@
1
+ import { createNanoEvents } from 'nanoevents';
2
+ export function createState(initial) {
3
+ const events = createNanoEvents();
4
+ let currentValue = initial;
5
+ return {
6
+ read() {
7
+ return currentValue;
8
+ },
9
+ write(value) {
10
+ const actialValue = typeof value === 'function' ? value(currentValue) : value;
11
+ if (currentValue !== actialValue) {
12
+ currentValue = actialValue;
13
+ events.emit('value', actialValue);
14
+ }
15
+ return actialValue;
16
+ },
17
+ reset() {
18
+ if (currentValue !== initial) {
19
+ currentValue = initial;
20
+ events.emit('value', initial);
21
+ }
22
+ },
23
+ subscribe(fn) {
24
+ if (!events.events.value || events.events.value.length === 0) {
25
+ events.emit('first');
26
+ }
27
+ const unsubscribe = events.on('value', fn);
28
+ fn(currentValue);
29
+ return () => {
30
+ unsubscribe();
31
+ if (!events.events.value || events.events.value.length === 0) {
32
+ events.emit('last');
33
+ }
34
+ };
35
+ },
36
+ onFirstSubscribe(callback) {
37
+ return events.on('first', callback);
38
+ },
39
+ onLastUnsubscribe(callback) {
40
+ return events.on('last', callback);
41
+ },
42
+ };
43
+ }
44
+ export function readonly(state) {
45
+ return {
46
+ read: state.read,
47
+ subscribe: state.subscribe,
48
+ onFirstSubscribe: state.onFirstSubscribe,
49
+ onLastUnsubscribe: state.onLastUnsubscribe,
50
+ };
51
+ }
@@ -1 +1,2 @@
1
- export declare function isAbortError(err: object): boolean;
1
+ export declare function toError(err: unknown): Error;
2
+ export declare function nonNullable<T>(value: T): value is Exclude<NonNullable<T>, void>;
@@ -1,3 +1,12 @@
1
- export function isAbortError(err) {
2
- return err && 'name' in err && err.name === 'AbortError';
1
+ export function toError(err) {
2
+ if (err instanceof Error) {
3
+ return err;
4
+ }
5
+ if (err) {
6
+ return new Error(err.toString());
7
+ }
8
+ return new Error('Unknown error occurred.');
9
+ }
10
+ export function nonNullable(value) {
11
+ return value !== null && value !== undefined;
3
12
  }
@@ -0,0 +1,4 @@
1
+ type InferArrayItem<T> = T extends Array<infer U> ? U : never;
2
+ type InferArgs<Args extends unknown[][]> = Args extends [infer Head, ...infer Tail extends unknown[][]] ? [InferArrayItem<Head>, ...InferArgs<Tail>] : [];
3
+ export declare function zipWith<const Args extends unknown[][], R>(arrays: Args, iteratee: (values: InferArgs<Args>) => R): R[];
4
+ export {};
@@ -0,0 +1,11 @@
1
+ export function zipWith(arrays, iteratee) {
2
+ if (arrays.length === 0)
3
+ return [];
4
+ const minLength = Math.min(...arrays.map(arr => arr.length));
5
+ const result = [];
6
+ for (let i = 0; i < minLength; i++) {
7
+ const values = arrays.map(arr => arr[i]);
8
+ result.push(iteratee(values));
9
+ }
10
+ return result;
11
+ }
@@ -0,0 +1,6 @@
1
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
2
+ import type { IdentityAdapter, IdentityRepository } from './types.js';
3
+ export declare function createIdentityRepository({ adapter, storage, }: {
4
+ adapter: IdentityAdapter;
5
+ storage: StorageAdapter;
6
+ }): IdentityRepository;
@@ -0,0 +1,68 @@
1
+ import { Result, ResultAsync, err, ok, okAsync } from 'neverthrow';
2
+ import { toError } from '../helpers/utils.js';
3
+ export function createIdentityRepository({ adapter, storage, }) {
4
+ const cachedRequester = createCachedIdentityRequester(storage, accountId => `identity_${accountId}`);
5
+ return {
6
+ getIdentity(accountId) {
7
+ return cachedRequester([accountId], adapter.readIdentities).map(map => map[accountId] ?? null);
8
+ },
9
+ getIdentities(accounts) {
10
+ return cachedRequester(accounts, adapter.readIdentities);
11
+ },
12
+ };
13
+ }
14
+ function createCachedIdentityRequester(storage, getKey) {
15
+ function readSingleCacheRecord(accountId) {
16
+ return storage.read(getKey(accountId)).andThen(raw => {
17
+ if (!raw) {
18
+ return ok(null);
19
+ }
20
+ try {
21
+ return ok(JSON.parse(raw));
22
+ }
23
+ catch (e) {
24
+ return err(toError(e));
25
+ }
26
+ });
27
+ }
28
+ function writeSingleCacheRecord(accountId, identity) {
29
+ if (identity === null) {
30
+ return okAsync(undefined);
31
+ }
32
+ return storage.write(getKey(accountId), JSON.stringify(identity));
33
+ }
34
+ function readCache(accounts) {
35
+ if (accounts.length === 0) {
36
+ return okAsync({});
37
+ }
38
+ const identities = ResultAsync.combine(accounts.map(readSingleCacheRecord));
39
+ return identities.map(identities => {
40
+ return Object.fromEntries(identities.map((x, i) => {
41
+ const accountId = accounts.at(i);
42
+ if (!accountId) {
43
+ throw new Error(`Identity not found`);
44
+ }
45
+ return [accountId, x];
46
+ }));
47
+ });
48
+ }
49
+ function writeCache(identities) {
50
+ return ResultAsync.combine(Object.entries(identities).map(args => writeSingleCacheRecord(...args))).map(() => identities);
51
+ }
52
+ return (accounts, request) => {
53
+ return readCache(accounts).andThen(existing => {
54
+ const emptyIdentities = Object.entries(existing)
55
+ .filter(([, identity]) => identity === null)
56
+ .map(([accountId]) => accountId);
57
+ if (emptyIdentities.length === 0) {
58
+ return okAsync(existing);
59
+ }
60
+ return request(accounts)
61
+ .andThen(writeCache)
62
+ .map(fetched => ({
63
+ ...existing,
64
+ ...fetched,
65
+ }));
66
+ });
67
+ };
68
+ }
@@ -0,0 +1,3 @@
1
+ import type { LazyClient } from '@novasamatech/statement-store';
2
+ import type { IdentityAdapter } from './types.js';
3
+ export declare function createIdentityRpcAdapter(lazyClient: LazyClient): IdentityAdapter;
@@ -0,0 +1,46 @@
1
+ import { AccountId } from '@polkadot-api/substrate-bindings';
2
+ import { errAsync, fromPromise, ok } from 'neverthrow';
3
+ import { toError } from '../helpers/utils.js';
4
+ import { zipWith } from '../helpers/zipWith.js';
5
+ export function createIdentityRpcAdapter(lazyClient) {
6
+ const accCodec = AccountId();
7
+ return {
8
+ readIdentities(accounts) {
9
+ const client = lazyClient.getClient();
10
+ const unsafeApi = client.getUnsafeApi();
11
+ const method = unsafeApi.query.Resources.Consumers;
12
+ if (!method) {
13
+ return errAsync(new Error('Method Resources.Consumers not found'));
14
+ }
15
+ const results = fromPromise(method.getValues(accounts.map(x => [accCodec.dec(x)])), toError);
16
+ return results.andThen(results => {
17
+ if (!results) {
18
+ return ok({});
19
+ }
20
+ return ok(Object.fromEntries(zipWith([accounts, results], x => x).map(([accountId, raw]) => {
21
+ if (!raw) {
22
+ return [accountId, null];
23
+ }
24
+ const credibility = raw.credibility.type == 'Lite'
25
+ ? {
26
+ type: 'Lite',
27
+ }
28
+ : {
29
+ type: 'Person',
30
+ alias: raw.credibility.value.alias.asHex(),
31
+ lastUpdate: raw.credibility.value.last_update.toString(),
32
+ };
33
+ return [
34
+ accountId,
35
+ {
36
+ accountId: accountId,
37
+ fullUsername: raw.full_username ? raw.full_username.asText() : null,
38
+ liteUsername: raw.lite_username.asText(),
39
+ credibility,
40
+ },
41
+ ];
42
+ })));
43
+ });
44
+ },
45
+ };
46
+ }
@@ -0,0 +1,21 @@
1
+ import type { ResultAsync } from 'neverthrow';
2
+ export type Credibility = {
3
+ type: 'Lite';
4
+ } | {
5
+ type: 'Person';
6
+ alias: `0x${string}`;
7
+ lastUpdate: string;
8
+ };
9
+ export type Identity = {
10
+ accountId: string;
11
+ fullUsername: string | null;
12
+ liteUsername: string;
13
+ credibility: Credibility;
14
+ };
15
+ export type IdentityAdapter = {
16
+ readIdentities(accounts: string[]): ResultAsync<Record<string, Identity | null>, Error>;
17
+ };
18
+ export type IdentityRepository = {
19
+ getIdentity(accountId: string): ResultAsync<Identity | null, Error>;
20
+ getIdentities(accounts: string[]): ResultAsync<Record<string, Identity | null>, Error>;
21
+ };
@@ -0,0 +1 @@
1
+ export {};
package/dist/index.d.ts CHANGED
@@ -1,4 +1,8 @@
1
+ export { SS_STABLE_STAGE_ENDPOINTS, SS_UNSTABLE_STAGE_ENDPOINTS } from './constants.js';
1
2
  export type { PappAdapter } from './papp.js';
2
- export type { SignInStatus } from './modules/signIn.js';
3
- export type { Identity } from './adapters/identity/types.js';
4
- export declare function createPappHostAdapter(appId: string, metadata: string): import("./papp.js").PappAdapter;
3
+ export { createPappAdapter } from './papp.js';
4
+ export type { AuthentificationStatus } from './sso/auth/types.js';
5
+ export type { UserSession } from './sso/sessionManager/userSession.js';
6
+ export type { Identity } from './identity/types.js';
7
+ export type { SignPayloadRequest } from './sso/sessionManager/scale/signPayloadRequest.js';
8
+ export type { SignPayloadResponse } from './sso/sessionManager/scale/signPayloadResponse.js';
package/dist/index.js CHANGED
@@ -1,7 +1,2 @@
1
- import { createPappAdapter } from './papp.js';
2
- export function createPappHostAdapter(appId, metadata) {
3
- return createPappAdapter({
4
- appId,
5
- metadata,
6
- });
7
- }
1
+ export { SS_STABLE_STAGE_ENDPOINTS, SS_UNSTABLE_STAGE_ENDPOINTS } from './constants.js';
2
+ export { createPappAdapter } from './papp.js';
@@ -4,21 +4,20 @@ export type SsPublicKey = Branded<Uint8Array, 'SsPublicKey'>;
4
4
  export type SsSecret = Branded<Uint8Array, 'SsSecret'>;
5
5
  export type EncrPublicKey = Branded<Uint8Array, 'EncrPublicKey'>;
6
6
  export type EncrSecret = Branded<Uint8Array, 'EncrSecret'>;
7
+ export type SharedSecret = Branded<Uint8Array, 'SharedSecret'>;
7
8
  export type SharedSession = Branded<Uint8Array, 'SharedSession'>;
9
+ export declare function BrandedBytesCodec<T extends Uint8Array>(length?: number): Codec<T>;
8
10
  export declare const SsPubKey: Codec<SsPublicKey>;
9
11
  export declare const EncrPubKey: Codec<EncrPublicKey>;
10
12
  export declare function stringToBytes(str: string): Uint8Array<ArrayBuffer>;
11
13
  export declare function bytesToString(bytes: Uint8Array): string;
12
- export declare function mergeBytes(...bytes: Uint8Array[]): Uint8Array<ArrayBuffer>;
13
14
  export declare const SS_SECRET_SEED_SIZE = 32;
14
- export declare function createSsSecret(seed: Uint8Array): SsSecret;
15
+ export declare function createSsSecret(seed?: Uint8Array): SsSecret;
16
+ export declare function createSsHardDerivation(secret: SsSecret, derivation: string | number): SsSecret;
15
17
  export declare function getSsPub(secret: SsSecret): SsPublicKey;
18
+ export declare function signWithSsSecret(secret: SsSecret, message: Uint8Array): Uint8Array<ArrayBufferLike>;
19
+ export declare function verifyWithSsSecret(message: Uint8Array, signature: Uint8Array, publicKey: Uint8Array): boolean;
16
20
  export declare const ENCR_SECRET_SEED_SIZE = 48;
17
- export declare function createEncrSecret(seed: Uint8Array): EncrSecret;
21
+ export declare function createEncrSecret(seed?: Uint8Array): EncrSecret;
18
22
  export declare function getEncrPub(secret: EncrSecret): EncrPublicKey;
19
- export declare function createRandomSeed(suffix: string, size: number): Uint8Array<ArrayBufferLike>;
20
- export declare function createStableSeed(value: string, size: number): Uint8Array<ArrayBufferLike>;
21
- export declare function khash(secret: Uint8Array, message: Uint8Array): Uint8Array<ArrayBufferLike>;
22
- export declare function createSharedSecret(secret: EncrSecret, publicKey: Uint8Array): Uint8Array<ArrayBufferLike>;
23
- export declare function createSymmetricKey(sharedSecret: Uint8Array): Uint8Array<ArrayBuffer>;
24
- export declare function decrypt(secret: Uint8Array, message: Uint8Array): Uint8Array<ArrayBufferLike>;
23
+ export declare function createSharedSecret(secret: EncrSecret, publicKey: Uint8Array): SharedSecret;
@@ -1,17 +1,13 @@
1
- import { gcm } from '@noble/ciphers/aes.js';
2
1
  import { p256 } from '@noble/curves/nist.js';
3
- import { blake2b } from '@noble/hashes/blake2.js';
4
- import { hkdf } from '@noble/hashes/hkdf.js';
5
- import { sha256 } from '@noble/hashes/sha2.js';
6
2
  import { randomBytes } from '@noble/hashes/utils.js';
7
- import { getPublicKey as sr25519GetPublicKey, secretFromSeed as sr25519SecretFromSeed } from '@scure/sr25519';
8
- import { Bytes } from 'scale-ts';
3
+ import { HDKD as sr25519HDKD, getPublicKey as sr25519GetPublicKey, secretFromSeed as sr25519SecretFromSeed, sign as sr25519Sign, verify as sr25519Verify, } from '@scure/sr25519';
4
+ import { Bytes, str, u32 } from 'scale-ts';
9
5
  // schemas
10
- function brandedBytesCodec(length) {
6
+ export function BrandedBytesCodec(length) {
11
7
  return Bytes(length);
12
8
  }
13
- export const SsPubKey = brandedBytesCodec(32);
14
- export const EncrPubKey = brandedBytesCodec(65);
9
+ export const SsPubKey = BrandedBytesCodec(32);
10
+ export const EncrPubKey = BrandedBytesCodec(65);
15
11
  // helpers
16
12
  const textEncoder = new TextEncoder();
17
13
  const textDecoder = new TextDecoder();
@@ -21,53 +17,35 @@ export function stringToBytes(str) {
21
17
  export function bytesToString(bytes) {
22
18
  return textDecoder.decode(bytes);
23
19
  }
24
- export function mergeBytes(...bytes) {
25
- const len = bytes.reduce((l, b) => l + b.length, 0);
26
- const merged = new Uint8Array(len);
27
- let offset = 0;
28
- for (const arr of bytes) {
29
- merged.set(arr, offset);
30
- offset += arr.length;
31
- }
32
- return merged;
33
- }
34
20
  // statement store key pair
35
21
  export const SS_SECRET_SEED_SIZE = 32;
36
- export function createSsSecret(seed) {
22
+ export function createSsSecret(seed = randomBytes(SS_SECRET_SEED_SIZE)) {
37
23
  return sr25519SecretFromSeed(seed);
38
24
  }
25
+ export function createSsHardDerivation(secret, derivation) {
26
+ const chainCode = new Uint8Array(32);
27
+ chainCode.set(typeof derivation === 'string' ? str.enc(derivation) : u32.enc(derivation));
28
+ return sr25519HDKD.secretHard(secret, chainCode);
29
+ }
39
30
  export function getSsPub(secret) {
40
31
  return sr25519GetPublicKey(secret);
41
32
  }
33
+ export function signWithSsSecret(secret, message) {
34
+ return sr25519Sign(secret, message);
35
+ }
36
+ export function verifyWithSsSecret(message, signature, publicKey) {
37
+ return sr25519Verify(message, signature, publicKey);
38
+ }
42
39
  // encryption key pair
43
40
  export const ENCR_SECRET_SEED_SIZE = 48;
44
- export function createEncrSecret(seed) {
41
+ export function createEncrSecret(seed = randomBytes(ENCR_SECRET_SEED_SIZE)) {
45
42
  const { secretKey } = p256.keygen(seed);
46
43
  return secretKey;
47
44
  }
48
45
  export function getEncrPub(secret) {
49
46
  return p256.getPublicKey(secret, false);
50
47
  }
51
- // helpers
52
- export function createRandomSeed(suffix, size) {
53
- return blake2b(mergeBytes(randomBytes(128), stringToBytes(suffix)), { dkLen: size });
54
- }
55
- export function createStableSeed(value, size) {
56
- return blake2b(stringToBytes(value), { dkLen: size });
57
- }
58
- export function khash(secret, message) {
59
- return blake2b(message, { dkLen: 256 / 8, key: secret });
60
- }
61
48
  export function createSharedSecret(secret, publicKey) {
62
- return p256.getSharedSecret(secret, publicKey);
63
- }
64
- export function createSymmetricKey(sharedSecret) {
65
- return sharedSecret.slice(1, 33);
66
- }
67
- export function decrypt(secret, message) {
68
- const nonce = message.slice(0, 12);
69
- const cipherText = message.slice(12);
70
- const aesKey = hkdf(sha256, secret, new Uint8Array(), new Uint8Array(), 32);
71
- const aes = gcm(aesKey, nonce);
72
- return aes.decrypt(cipherText);
49
+ // slicing first byte: @noble/curves adds y offset at the start
50
+ return p256.getSharedSecret(secret, publicKey).slice(1, 33);
73
51
  }
@@ -1,14 +1,15 @@
1
- import type { StorageAdapter } from '../adapters/storage/types.js';
2
- import type { SessionTopic } from '../types.js';
1
+ import type { StorageAdapter } from '@novasamatech/storage-adapter';
2
+ import type { ResultAsync } from 'neverthrow';
3
+ import type { CodecType } from 'scale-ts';
3
4
  import type { EncrSecret, SsSecret } from './crypto.js';
4
- export type SecretStorage = {
5
- readSsSecret(): Promise<SsSecret | null>;
6
- writeSsSecret(value: SsSecret): Promise<boolean>;
7
- readEncrSecret(): Promise<EncrSecret | null>;
8
- writeEncrSecret(value: EncrSecret): Promise<boolean>;
9
- readSessionTopic(): Promise<SessionTopic | null>;
10
- writeSessionTopic(value: SessionTopic): Promise<boolean>;
11
- readPappAccountId(): Promise<string | null>;
12
- writePappAccountId(value: string): Promise<boolean>;
5
+ type UserSecrets = CodecType<typeof UserSecretsCodec>;
6
+ declare const UserSecretsCodec: import("scale-ts").Codec<{
7
+ SsSecret: SsSecret;
8
+ EncrSecret: EncrSecret;
9
+ }>;
10
+ export declare function createSecretStorage(salt: string, storage: StorageAdapter): {
11
+ read(sessionId: string): ResultAsync<UserSecrets | null, Error>;
12
+ write(sessionId: string, value: UserSecrets): ResultAsync<void, Error>;
13
+ clear(sessionId: string): ResultAsync<void, Error>;
13
14
  };
14
- export declare function createSecretStorage(appId: string, storage: StorageAdapter): SecretStorage;
15
+ export {};
@@ -1,53 +1,44 @@
1
1
  import { gcm } from '@noble/ciphers/aes.js';
2
2
  import { blake2b } from '@noble/hashes/blake2.js';
3
3
  import { fromHex, toHex } from '@polkadot-api/utils';
4
- import { bytesToString, stringToBytes } from './crypto.js';
5
- export function createSecretStorage(appId, storage) {
6
- const ssSecret = rwBytes('SsSecret', appId, storage);
7
- const encrSecret = rwBytes('EncrSecret', appId, storage);
8
- const sessionTopic = rwBytes('SessionTopic', appId, storage);
9
- const pappAccountId = rwString('PappAccountId', appId, storage);
10
- return {
11
- readSsSecret: ssSecret.read,
12
- writeSsSecret: ssSecret.write,
13
- readEncrSecret: encrSecret.read,
14
- writeEncrSecret: encrSecret.write,
15
- readSessionTopic: sessionTopic.read,
16
- writeSessionTopic: sessionTopic.write,
17
- readPappAccountId: pappAccountId.read,
18
- writePappAccountId: pappAccountId.write,
19
- };
20
- }
21
- const withAppId = (appId, key) => `${appId}_${key}`;
22
- const rwBytes = (key, appId, storage) => ({
23
- async read() {
24
- const value = await storage.read(withAppId(appId, key));
25
- if (value) {
26
- const aes = getAes(appId);
27
- return aes.decrypt(fromHex(value));
28
- }
29
- else {
4
+ import { fromThrowable } from 'neverthrow';
5
+ import { Struct } from 'scale-ts';
6
+ import { toError } from '../helpers/utils.js';
7
+ import { BrandedBytesCodec, stringToBytes } from './crypto.js';
8
+ const UserSecretsCodec = Struct({
9
+ SsSecret: BrandedBytesCodec(),
10
+ EncrSecret: BrandedBytesCodec(),
11
+ });
12
+ export function createSecretStorage(salt, storage) {
13
+ const baseKey = 'UserSecrets';
14
+ const encode = fromThrowable(UserSecretsCodec.enc, toError);
15
+ const decode = fromThrowable((value) => (value ? UserSecretsCodec.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) {
30
22
  return null;
31
23
  }
32
- },
33
- write(value) {
34
- const aes = getAes(appId);
35
- return storage.write(withAppId(appId, key), toHex(aes.encrypt(value)));
36
- },
37
- });
38
- const rwString = (key, appId, storage) => {
39
- const bytes = rwBytes(key, appId, storage);
24
+ const aes = getAes(salt);
25
+ return aes.decrypt(fromHex(value));
26
+ }, toError);
40
27
  return {
41
- async read() {
42
- const value = await bytes.read();
43
- return value ? bytesToString(value) : null;
28
+ read(sessionId) {
29
+ return storage.read(createKey(baseKey, sessionId)).andThen(decrypt).andThen(decode);
44
30
  },
45
- write(value) {
46
- const b = stringToBytes(value);
47
- return bytes.write(b);
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));
48
38
  },
49
39
  };
50
- };
51
- function getAes(appId) {
52
- return gcm(blake2b(stringToBytes(appId), { dkLen: 16 }), blake2b(stringToBytes('nonce'), { dkLen: 32 }));
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 }));
53
44
  }
@@ -0,0 +1,5 @@
1
+ import type { Account } from './types.js';
2
+ export declare function createSessionId(sharedSecret: Uint8Array, accountA: Account, accountB: Account): Uint8Array<ArrayBufferLike>;
3
+ export declare function createRequestChannel(session: Uint8Array): Uint8Array<ArrayBufferLike>;
4
+ export declare function createResponseChannel(session: Uint8Array): Uint8Array<ArrayBufferLike>;
5
+ export declare function createAccount(accountId: Uint8Array, publicKey: Uint8Array, pin?: string): Account;
@@ -0,0 +1,29 @@
1
+ import { mergeUint8 } from '@polkadot-api/utils';
2
+ import { khash, stringToBytes } from '../crypto.js';
3
+ export function createSessionId(sharedSecret, accountA, accountB) {
4
+ const sessionPrefix = stringToBytes('session');
5
+ const pinSeparator = stringToBytes('/');
6
+ function makePin(pin) {
7
+ return pin ? mergeUint8([pinSeparator, stringToBytes(pin)]) : pinSeparator;
8
+ }
9
+ const accountSessionParams = mergeUint8([
10
+ accountA.accountId,
11
+ accountB.accountId,
12
+ makePin(accountA.pin),
13
+ makePin(accountB.pin),
14
+ ]);
15
+ return khash(sharedSecret, mergeUint8(sessionPrefix, accountSessionParams));
16
+ }
17
+ export function createRequestChannel(session) {
18
+ return khash(session, stringToBytes('request'));
19
+ }
20
+ export function createResponseChannel(session) {
21
+ return khash(session, stringToBytes('response'));
22
+ }
23
+ export function createAccount(accountId, publicKey, pin) {
24
+ return {
25
+ accountId,
26
+ publicKey,
27
+ pin,
28
+ };
29
+ }
@@ -0,0 +1,12 @@
1
+ import type { Codec } from 'scale-ts';
2
+ import type { StorageAdapter } from '../../adapters/storage/types.js';
3
+ import type { Transport } from '../transport/transport.js';
4
+ import type { Account, Session } from './types.js';
5
+ export type SessionParams<T extends Codec<any>> = {
6
+ ownAccount: Account;
7
+ peerAccount: Account;
8
+ transport: Transport;
9
+ storage: StorageAdapter;
10
+ codec: T;
11
+ };
12
+ export declare function createSession<T extends Codec<any>>({ ownAccount, peerAccount, transport, storage, codec, }: SessionParams<T>): Session<T>;