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

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 (94) hide show
  1. package/dist/adapters/identity/rpc.d.ts +4 -2
  2. package/dist/adapters/identity/rpc.js +96 -26
  3. package/dist/adapters/identity/types.d.ts +3 -1
  4. package/dist/adapters/lazyClient/papi.js +5 -0
  5. package/dist/adapters/lazyClient/types.d.ts +1 -0
  6. package/dist/adapters/statement/rpc.js +58 -10
  7. package/dist/adapters/statement/types.d.ts +6 -3
  8. package/dist/adapters/storage/localStorage.js +26 -4
  9. package/dist/adapters/storage/memory.js +14 -4
  10. package/dist/adapters/storage/types.d.ts +5 -2
  11. package/dist/adapters/storage/types.js +1 -1
  12. package/dist/components/auth/codec.d.ts +9 -0
  13. package/dist/components/auth/codec.js +10 -0
  14. package/dist/components/auth/codecs.d.ts +9 -0
  15. package/dist/components/auth/codecs.js +10 -0
  16. package/dist/components/auth/index.d.ts +36 -0
  17. package/dist/components/auth/index.js +150 -0
  18. package/dist/components/auth/types.d.ts +15 -0
  19. package/dist/components/auth/types.js +1 -0
  20. package/dist/components/session.d.ts +34 -0
  21. package/dist/components/session.js +54 -0
  22. package/dist/components/transport.d.ts +27 -0
  23. package/dist/components/transport.js +57 -0
  24. package/dist/components/user/codec.d.ts +16 -0
  25. package/dist/components/user/codec.js +13 -0
  26. package/dist/components/user/index.d.ts +22 -0
  27. package/dist/components/user/index.js +58 -0
  28. package/dist/components/user/ssoMessageStream.d.ts +10 -0
  29. package/dist/components/user/ssoMessageStream.js +8 -0
  30. package/dist/components/user/ssoSession.d.ts +5 -0
  31. package/dist/components/user/ssoSession.js +5 -0
  32. package/dist/components/user/storage.d.ts +27 -0
  33. package/dist/components/user/storage.js +143 -0
  34. package/dist/components/user/types.d.ts +6 -0
  35. package/dist/components/user/types.js +1 -0
  36. package/dist/components/user/userSessionStorage.d.ts +20 -0
  37. package/dist/components/user/userSessionStorage.js +24 -0
  38. package/dist/components/user.d.ts +74 -0
  39. package/dist/components/user.js +188 -0
  40. package/dist/constants.d.ts +2 -1
  41. package/dist/constants.js +5 -1
  42. package/dist/helpers/abortError.d.ts +4 -0
  43. package/dist/helpers/abortError.js +8 -0
  44. package/dist/helpers/callbackRaceResolver.d.ts +1 -0
  45. package/dist/helpers/callbackRaceResolver.js +17 -0
  46. package/dist/helpers/result.d.ts +12 -0
  47. package/dist/helpers/result.js +15 -0
  48. package/dist/helpers/result.spec.d.ts +1 -0
  49. package/dist/helpers/result.spec.js +23 -0
  50. package/dist/helpers/utils.d.ts +2 -1
  51. package/dist/helpers/utils.js +11 -2
  52. package/dist/index.d.ts +2 -1
  53. package/dist/modules/crypto.d.ts +5 -2
  54. package/dist/modules/crypto.js +16 -5
  55. package/dist/modules/secretStorage.d.ts +7 -9
  56. package/dist/modules/secretStorage.js +20 -33
  57. package/dist/modules/session/helpers.d.ts +5 -0
  58. package/dist/modules/session/helpers.js +29 -0
  59. package/dist/modules/session/session.d.ts +12 -0
  60. package/dist/modules/session/session.js +46 -0
  61. package/dist/modules/session/types.d.ts +12 -0
  62. package/dist/modules/session/types.js +1 -0
  63. package/dist/modules/signIn.d.ts +32 -11
  64. package/dist/modules/signIn.js +95 -95
  65. package/dist/modules/state.d.ts +16 -0
  66. package/dist/modules/state.js +50 -0
  67. package/dist/modules/statementStore.d.ts +10 -11
  68. package/dist/modules/statementStore.js +14 -14
  69. package/dist/modules/statementTopic.d.ts +34 -0
  70. package/dist/modules/statementTopic.js +46 -0
  71. package/dist/modules/storageView.d.ts +25 -0
  72. package/dist/modules/storageView.js +51 -0
  73. package/dist/modules/syncStorage.d.ts +25 -0
  74. package/dist/modules/syncStorage.js +76 -0
  75. package/dist/modules/transport/codec.d.ts +24 -0
  76. package/dist/modules/transport/codec.js +36 -0
  77. package/dist/modules/transport/crypto.d.ts +2 -0
  78. package/dist/modules/transport/crypto.js +18 -0
  79. package/dist/modules/transport/transport.d.ts +27 -0
  80. package/dist/modules/transport/transport.js +56 -0
  81. package/dist/modules/user.d.ts +67 -0
  82. package/dist/modules/user.js +188 -0
  83. package/dist/modules/userManager.d.ts +15 -0
  84. package/dist/modules/userManager.js +105 -0
  85. package/dist/modules/userStorage.d.ts +19 -0
  86. package/dist/modules/userStorage.js +108 -0
  87. package/dist/modules/userStore.d.ts +15 -0
  88. package/dist/modules/userStore.js +105 -0
  89. package/dist/papp.d.ts +8 -7
  90. package/dist/papp.js +19 -31
  91. package/dist/structs.d.ts +10 -10
  92. package/dist/structs.js +17 -13
  93. package/dist/types.d.ts +1 -1
  94. package/package.json +8 -6
@@ -0,0 +1,108 @@
1
+ import { err, ok, seq } from '../helpers/result.js';
2
+ import { createSecretStorage } from './secretStorage.js';
3
+ import { reactiveStorage } from './syncStorage.js';
4
+ export const createUserStorage = (appId, storage) => {
5
+ const secretStorage = createSecretStorage(appId, storage);
6
+ const usersStorage = createSessionsStorage(storage);
7
+ const selectedUserStorage = createSelectedUserStorage(storage);
8
+ const store = {
9
+ sessions: {
10
+ async read(accountId) {
11
+ const user = await secretStorage.readSessionTopic(accountId).then(existingSessionTopic => existingSessionTopic.map(sessionTopic => {
12
+ return sessionTopic ? { sessionTopic, accountId } : null;
13
+ }));
14
+ await user
15
+ .andThen(v => (v ? ok(undefined) : err('User not found')))
16
+ .orElsePromise(() => store.sessions.remove(accountId));
17
+ return user;
18
+ },
19
+ async readSelectedUser() {
20
+ const selectedUser = await selectedUserStorage.read();
21
+ return selectedUser.andThenPromise(async (selectedUser) => {
22
+ if (selectedUser === null) {
23
+ return ok(null);
24
+ }
25
+ const user = await store.sessions.read(selectedUser);
26
+ return user.andThenPromise(async (user) => {
27
+ if (user === null) {
28
+ await selectedUserStorage.clear();
29
+ }
30
+ return ok(user);
31
+ });
32
+ });
33
+ },
34
+ async create(user) {
35
+ return (await usersStorage.add(user.accountId)).andThenPromise(async () => seq(await selectedUserStorage.write(user.accountId), await secretStorage.writeSessionTopic(user.accountId, user.sessionTopic)).map(() => user));
36
+ },
37
+ async remove(accountId) {
38
+ const op = seq(await selectedUserStorage.read(), await usersStorage.remove(accountId));
39
+ return op.andThenPromise(async ([selectedUser, users]) => {
40
+ if (selectedUser === accountId) {
41
+ const nextSelectedUser = users.at(0);
42
+ if (nextSelectedUser) {
43
+ await selectedUserStorage.write(nextSelectedUser);
44
+ }
45
+ else {
46
+ await selectedUserStorage.clear();
47
+ }
48
+ }
49
+ return secretStorage.clearSessionTopic(accountId);
50
+ });
51
+ },
52
+ },
53
+ accounts: {
54
+ async read() {
55
+ return usersStorage.read();
56
+ },
57
+ async select(accountId) {
58
+ return selectedUserStorage.write(accountId);
59
+ },
60
+ },
61
+ };
62
+ return store;
63
+ };
64
+ const createSessionsStorage = (storage) => {
65
+ const reactive = reactiveStorage({
66
+ storage,
67
+ key: 'Users',
68
+ autosync: true,
69
+ initial: [],
70
+ from: x => JSON.parse(x),
71
+ to: x => JSON.stringify(x),
72
+ });
73
+ return {
74
+ async read() {
75
+ return reactive.read();
76
+ },
77
+ async add(user) {
78
+ const users = await reactive.read();
79
+ return users.andThenPromise(async (users) => {
80
+ if (users.some(x => x === user)) {
81
+ throw new Error(`User ${user} already exists.`);
82
+ }
83
+ const newUsers = users.concat(user);
84
+ return reactive.write(newUsers).then(x => x.map(() => newUsers));
85
+ });
86
+ },
87
+ async remove(user) {
88
+ const users = await reactive.read();
89
+ return users.andThenPromise(async (users) => {
90
+ const newUsers = users.filter(x => x !== user);
91
+ if (newUsers.length !== users.length) {
92
+ return reactive.write(newUsers).then(x => x.map(() => newUsers));
93
+ }
94
+ return ok([]);
95
+ });
96
+ },
97
+ };
98
+ };
99
+ const createSelectedUserStorage = (storage) => {
100
+ return reactiveStorage({
101
+ storage,
102
+ key: 'SelectedUser',
103
+ autosync: true,
104
+ initial: null,
105
+ from: x => x,
106
+ to: x => x,
107
+ });
108
+ };
@@ -0,0 +1,15 @@
1
+ import type { StorageAdapter } from '../adapters/storage/types.js';
2
+ import type { Result } from '../helpers/result.js';
3
+ import type { SessionTopic } from '../types.js';
4
+ export type UserSession = {
5
+ accountId: string;
6
+ sessionTopic: SessionTopic;
7
+ };
8
+ export declare const createUserStore: (appId: string, storage: StorageAdapter) => {
9
+ readSelectedUserSession(): Promise<Result<UserSession | null>>;
10
+ readUserSession(accountId: string): Promise<Result<UserSession | null>>;
11
+ createUserSession(user: UserSession): Promise<Result<UserSession>>;
12
+ removeUserSession(accountId: string): Promise<Result<void, Error>>;
13
+ readAccounts(): Promise<Result<string[], Error>>;
14
+ selectAccount(accountId: string): Promise<Result<void, Error>>;
15
+ };
@@ -0,0 +1,105 @@
1
+ import { err, ok, seq } from '../helpers/result.js';
2
+ import { createSecretStorage } from './secretStorage.js';
3
+ export const createUserStore = (appId, storage) => {
4
+ const secretStorage = createSecretStorage(appId, storage);
5
+ const usersStorage = createUserStorage(storage);
6
+ const selectedUserStorage = createSelectedUserStorage(storage);
7
+ const manager = {
8
+ async readSelectedUserSession() {
9
+ const selectedUser = await selectedUserStorage.read();
10
+ return selectedUser.andThenPromise(async (selectedUser) => {
11
+ if (selectedUser === null) {
12
+ return ok(null);
13
+ }
14
+ const user = await manager.readUserSession(selectedUser);
15
+ return user.andThenPromise(async (user) => {
16
+ if (user === null) {
17
+ await selectedUserStorage.clear();
18
+ }
19
+ return ok(user);
20
+ });
21
+ });
22
+ },
23
+ async readUserSession(accountId) {
24
+ const user = await secretStorage.readSessionTopic(accountId).then(existingSessionTopic => existingSessionTopic.map(sessionTopic => {
25
+ return sessionTopic ? { sessionTopic, accountId } : null;
26
+ }));
27
+ await user
28
+ .andThen(v => (v ? ok(undefined) : err('User not found')))
29
+ .orElsePromise(() => manager.removeUserSession(accountId));
30
+ return user;
31
+ },
32
+ async createUserSession(user) {
33
+ return (await usersStorage.add(user.accountId)).andThenPromise(async () => seq(await selectedUserStorage.write(user.accountId), await secretStorage.writeSessionTopic(user.accountId, user.sessionTopic)).map(() => user));
34
+ },
35
+ async removeUserSession(accountId) {
36
+ const op = seq(await selectedUserStorage.read(), await usersStorage.remove(accountId));
37
+ return op.andThenPromise(async ([selectedUser, users]) => {
38
+ if (selectedUser === accountId) {
39
+ const nextSelectedUser = users.at(0);
40
+ if (nextSelectedUser) {
41
+ await selectedUserStorage.write(nextSelectedUser);
42
+ }
43
+ else {
44
+ await selectedUserStorage.clear();
45
+ }
46
+ }
47
+ return secretStorage.clearSessionTopic(accountId);
48
+ });
49
+ },
50
+ async readAccounts() {
51
+ return usersStorage.read();
52
+ },
53
+ async selectAccount(accountId) {
54
+ return selectedUserStorage.write(accountId);
55
+ },
56
+ };
57
+ return manager;
58
+ };
59
+ const createUserStorage = (storage) => {
60
+ const KEY = 'Users';
61
+ return {
62
+ async read() {
63
+ const users = await storage.read(KEY);
64
+ return users.map(users => {
65
+ return users === null ? [] : JSON.parse(users);
66
+ });
67
+ },
68
+ async add(user) {
69
+ const usersRaw = await storage.read(KEY);
70
+ const users = usersRaw.map(x => (x ? JSON.parse(x) : []));
71
+ return users.andThenPromise(async (users) => {
72
+ if (users.some(x => x === user)) {
73
+ throw new Error(`User ${user} already exists.`);
74
+ }
75
+ const newUsers = users.concat(user);
76
+ return storage.write(KEY, JSON.stringify(newUsers)).then(x => x.map(() => newUsers));
77
+ });
78
+ },
79
+ async remove(user) {
80
+ const usersRaw = await storage.read(KEY);
81
+ const users = usersRaw.map(x => (x ? JSON.parse(x) : []));
82
+ return users.andThenPromise(async (users) => {
83
+ const newUsers = users.filter(x => x !== user);
84
+ if (newUsers.length !== users.length) {
85
+ return storage.write(KEY, JSON.stringify(newUsers)).then(x => x.map(() => newUsers));
86
+ }
87
+ return ok([]);
88
+ });
89
+ },
90
+ };
91
+ };
92
+ const createSelectedUserStorage = (storage) => {
93
+ const KEY = 'SelectedUser';
94
+ return {
95
+ read() {
96
+ return storage.read(KEY);
97
+ },
98
+ write(accountId) {
99
+ return storage.write(KEY, accountId);
100
+ },
101
+ clear() {
102
+ return storage.clear(KEY);
103
+ },
104
+ };
105
+ };
package/dist/papp.d.ts CHANGED
@@ -1,14 +1,15 @@
1
+ import type { ResultAsync } from 'neverthrow';
1
2
  import type { Identity, IdentityAdapter } from './adapters/identity/types.js';
2
3
  import type { StatementAdapter } from './adapters/statement/types.js';
3
4
  import type { StorageAdapter } from './adapters/storage/types.js';
4
- import type { SignInStatus } from './modules/signIn.js';
5
+ import type { AuthComponent } from './components/auth/index.js';
6
+ import type { UserSessionsComponent } from './components/user/index.js';
5
7
  export type PappAdapter = {
6
- auth: {
7
- signIn(): Promise<Identity | null>;
8
- abortSignIn(): void;
9
- getCurrentUser(): Promise<Identity | null>;
10
- getSignInStatus(): SignInStatus;
11
- onSignInStatusChange(callback: (status: SignInStatus) => void): VoidFunction;
8
+ sso: AuthComponent;
9
+ sessions: UserSessionsComponent;
10
+ identity: {
11
+ getIdentity(accountId: string): ResultAsync<Identity | null, Error>;
12
+ getIdentities(accounts: string[]): ResultAsync<Record<string, Identity | null>, Error>;
12
13
  };
13
14
  };
14
15
  type Adapters = {
package/dist/papp.js CHANGED
@@ -3,8 +3,11 @@ import { createIdentityRpcAdapter } from './adapters/identity/rpc.js';
3
3
  import { createPapiLazyClient } from './adapters/lazyClient/papi.js';
4
4
  import { createPapiStatementAdapter } from './adapters/statement/rpc.js';
5
5
  import { createLocalStorageAdapter } from './adapters/storage/localStorage.js';
6
- import { SS_ENDPOINTS } from './constants.js';
7
- import { createSignInFlow } from './modules/signIn.js';
6
+ import { createAuthComponent } from './components/auth/index.js';
7
+ import { createUserSessionsComponent } from './components/user/index.js';
8
+ import { createUserSessionStorage } from './components/user/userSessionStorage.js';
9
+ import { SS_PROD_ENDPOINTS } from './constants.js';
10
+ import { createTransport } from './modules/transport/transport.js';
8
11
  export function createPappAdapter({ appId, metadata, adapters }) {
9
12
  let statements;
10
13
  let identities;
@@ -15,40 +18,25 @@ export function createPappAdapter({ appId, metadata, adapters }) {
15
18
  storage = adapters.storage;
16
19
  }
17
20
  else {
18
- const lazyPapiAdapter = createPapiLazyClient(getWsProvider(SS_ENDPOINTS));
21
+ const lazyPapiAdapter = createPapiLazyClient(getWsProvider(SS_PROD_ENDPOINTS));
19
22
  storage = createLocalStorageAdapter(appId);
20
23
  identities = createIdentityRpcAdapter(lazyPapiAdapter, storage);
21
24
  statements = createPapiStatementAdapter(lazyPapiAdapter);
22
25
  }
23
- const signInFlow = createSignInFlow({ appId, metadata, statements, storage });
24
- const papp = {
25
- auth: {
26
- signIn() {
27
- return signInFlow.signIn().then(result => {
28
- if (result) {
29
- return identities.getIdentity(result.pappAccountId);
30
- }
31
- return null;
32
- });
33
- },
34
- getCurrentUser() {
35
- return signInFlow.getSignedUser().then(result => {
36
- if (result) {
37
- return identities.getIdentity(result.pappAccountId);
38
- }
39
- return null;
40
- });
41
- },
42
- getSignInStatus() {
43
- return signInFlow.getSignInStatus();
44
- },
45
- onSignInStatusChange(callback) {
46
- return signInFlow.onStatusChange(callback);
47
- },
48
- abortSignIn() {
49
- return signInFlow.abortSignIn();
50
- },
26
+ const transport = createTransport({ adapter: statements });
27
+ const userSessionStorage = createUserSessionStorage({ storage });
28
+ const identityComponent = {
29
+ getIdentity(accountId) {
30
+ return identities.readIdentities([accountId]).map(map => map[accountId] ?? null);
31
+ },
32
+ getIdentities(accounts) {
33
+ return identities.readIdentities(accounts);
51
34
  },
52
35
  };
36
+ const papp = {
37
+ sso: createAuthComponent({ appId, metadata, transport, userSessionStorage }),
38
+ sessions: createUserSessionsComponent({ transport, storage, userSessionStorage }),
39
+ identity: identityComponent,
40
+ };
53
41
  return papp;
54
42
  }
package/dist/structs.d.ts CHANGED
@@ -1,24 +1,24 @@
1
- type TransportError = 'decryptionFailed' | 'decodingFailed' | 'unknown';
2
- export declare const ResponseCode: import("scale-ts").Codec<TransportError>;
3
- export declare const RequestV1: import("scale-ts").Codec<{
1
+ import type { Codec } from 'scale-ts';
2
+ export type TransportError = 'decryptionFailed' | 'decodingFailed' | 'unknown';
3
+ export declare const TransportErrorCodec: Codec<TransportError>;
4
+ export declare const Request: <T>(data: Codec<T>) => Codec<{
4
5
  requestId: string;
5
- data: Uint8Array<ArrayBufferLike>;
6
+ data: T[];
6
7
  }>;
7
- export declare const ResponseV1: import("scale-ts").Codec<{
8
+ export declare const Response: Codec<{
8
9
  requestId: string;
9
10
  responseCode: TransportError;
10
11
  }>;
11
- export declare const StatementData: import("scale-ts").Codec<{
12
- tag: "requestV1";
12
+ export declare const StatementData: <T>(data: Codec<T>) => Codec<{
13
+ tag: "request";
13
14
  value: {
14
15
  requestId: string;
15
- data: Uint8Array<ArrayBufferLike>;
16
+ data: T[];
16
17
  };
17
18
  } | {
18
- tag: "responseV1";
19
+ tag: "response";
19
20
  value: {
20
21
  requestId: string;
21
22
  responseCode: TransportError;
22
23
  };
23
24
  }>;
24
- export {};
package/dist/structs.js CHANGED
@@ -1,12 +1,12 @@
1
- import { Bytes, Enum, Struct, enhanceCodec, str, u8 } from 'scale-ts';
2
- export const ResponseCode = enhanceCodec(u8, error => {
1
+ import { Enum, Struct, Vector, enhanceCodec, str, u8 } from 'scale-ts';
2
+ export const TransportErrorCodec = enhanceCodec(u8, error => {
3
3
  switch (error) {
4
4
  case 'decryptionFailed':
5
5
  return 1;
6
6
  case 'decodingFailed':
7
7
  return 2;
8
8
  case 'unknown':
9
- return -1;
9
+ return 255;
10
10
  }
11
11
  }, code => {
12
12
  switch (code) {
@@ -18,15 +18,19 @@ export const ResponseCode = enhanceCodec(u8, error => {
18
18
  return 'unknown';
19
19
  }
20
20
  });
21
- export const RequestV1 = Struct({
21
+ export const Request = (data) => {
22
+ return Struct({
23
+ requestId: str,
24
+ data: Vector(data),
25
+ });
26
+ };
27
+ export const Response = Struct({
22
28
  requestId: str,
23
- data: Bytes(),
24
- });
25
- export const ResponseV1 = Struct({
26
- requestId: str,
27
- responseCode: ResponseCode,
28
- });
29
- export const StatementData = Enum({
30
- requestV1: RequestV1,
31
- responseV1: ResponseV1,
29
+ responseCode: TransportErrorCodec,
32
30
  });
31
+ export const StatementData = (data) => {
32
+ return Enum({
33
+ request: Request(data),
34
+ response: Response,
35
+ });
36
+ };
package/dist/types.d.ts CHANGED
@@ -2,5 +2,5 @@ declare const __brand: unique symbol;
2
2
  export type Branded<T, K extends string> = T & {
3
3
  [__brand]: K;
4
4
  };
5
- export type SessionTopic = Branded<Uint8Array, 'SessionTopic'>;
5
+ export type Callback<T, R = unknown> = (value: T) => R;
6
6
  export {};
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-5",
4
+ "version": "0.5.0-7",
5
5
  "description": "Polkadot app integration",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -24,14 +24,16 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@polkadot-api/utils": "0.2.0",
28
- "@polkadot-api/sdk-statement": "0.2.0",
29
- "@scure/sr25519": "0.3.0",
27
+ "@polkadot-api/sdk-statement": "^0.2.0",
28
+ "@polkadot-api/substrate-bindings": "^0.16.5",
29
+ "@scure/sr25519": "1.0.0",
30
30
  "@noble/curves": "2.0.1",
31
31
  "@noble/hashes": "2.0.1",
32
- "@noble/ciphers": "2.0.1",
33
- "polkadot-api": "1.22.0",
32
+ "@noble/ciphers": "2.1.1",
33
+ "polkadot-api": "^1.23.1",
34
34
  "nanoevents": "9.1.0",
35
+ "nanoid": "5.1.6",
36
+ "neverthrow": "8.2.0",
35
37
  "scale-ts": "1.6.1"
36
38
  },
37
39
  "publishConfig": {