@novasamatech/host-papp 0.5.0-9 → 0.5.1
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.
- package/.papi/descriptors/dist/common-types.d.ts +8667 -0
- package/.papi/descriptors/dist/common.d.ts +1 -0
- package/.papi/descriptors/dist/descriptors-UUEW32EL.mjs +27 -0
- package/.papi/descriptors/dist/descriptors.d.ts +1 -0
- package/.papi/descriptors/dist/index.d.ts +10 -0
- package/.papi/descriptors/dist/index.js +237 -0
- package/.papi/descriptors/dist/index.mjs +148 -0
- package/.papi/descriptors/dist/metadataTypes-E4AQJDJR.mjs +6 -0
- package/.papi/descriptors/dist/metadataTypes.d.ts +2 -0
- package/.papi/descriptors/dist/people_lite.d.ts +7757 -0
- package/.papi/descriptors/dist/people_lite_metadata-EIVHV27X.mjs +6 -0
- package/.papi/descriptors/dist/people_lite_metadata.d.ts +2 -0
- package/.papi/descriptors/generated.json +1 -0
- package/.papi/descriptors/package.json +24 -0
- package/.papi/metadata/people_lite.scale +0 -0
- package/.papi/polkadot-api.json +15 -0
- package/dist/constants.d.ts +2 -2
- package/dist/constants.js +2 -2
- package/dist/crypto.d.ts +11 -5
- package/dist/crypto.js +47 -11
- package/dist/helpers/abortError.d.ts +0 -1
- package/dist/helpers/abortError.js +0 -3
- package/dist/identity/rpcAdapter.js +13 -5
- package/dist/identity/types.d.ts +3 -4
- package/dist/index.d.ts +4 -1
- package/dist/index.js +1 -0
- package/dist/papp.js +3 -3
- package/dist/sso/auth/attestationService.d.ts +18 -0
- package/dist/sso/auth/attestationService.js +171 -0
- package/dist/sso/auth/impl.d.ts +36 -5
- package/dist/sso/auth/impl.js +94 -56
- package/dist/sso/auth/types.d.ts +15 -2
- package/dist/sso/sessionManager/scale/hex.d.ts +1 -0
- package/dist/sso/sessionManager/scale/hex.js +3 -0
- package/dist/sso/sessionManager/scale/remoteMessage.d.ts +30 -12
- package/dist/sso/sessionManager/scale/remoteMessage.js +10 -11
- package/dist/sso/sessionManager/scale/signPayloadRequest.d.ts +20 -0
- package/dist/sso/sessionManager/scale/signPayloadRequest.js +20 -0
- package/dist/sso/sessionManager/scale/signPayloadResponse.d.ts +14 -0
- package/dist/sso/sessionManager/scale/signPayloadResponse.js +10 -0
- package/dist/sso/sessionManager/userSession.d.ts +5 -7
- package/dist/sso/sessionManager/userSession.js +53 -12
- package/dist/sso/userSecretRepository.d.ts +1 -0
- package/dist/sso/userSecretRepository.js +2 -1
- package/dist/sso/userSessionRepository.js +0 -1
- package/package.json +12 -9
- package/dist/adapters/identity/rpc.d.ts +0 -6
- package/dist/adapters/identity/rpc.js +0 -101
- package/dist/adapters/identity/types.d.ts +0 -10
- package/dist/adapters/identity/types.js +0 -1
- package/dist/adapters/lazyClient/papi.d.ts +0 -3
- package/dist/adapters/lazyClient/papi.js +0 -17
- package/dist/adapters/lazyClient/types.d.ts +0 -5
- package/dist/adapters/lazyClient/types.js +0 -1
- package/dist/adapters/statement/rpc.d.ts +0 -3
- package/dist/adapters/statement/rpc.js +0 -93
- package/dist/adapters/statement/types.d.ts +0 -9
- package/dist/adapters/statement/types.js +0 -1
- package/dist/adapters/storage/localStorage.d.ts +0 -2
- package/dist/adapters/storage/localStorage.js +0 -34
- package/dist/adapters/storage/memory.d.ts +0 -2
- package/dist/adapters/storage/memory.js +0 -22
- package/dist/adapters/storage/types.d.ts +0 -7
- package/dist/adapters/storage/types.js +0 -1
- package/dist/adapters/transport/rpc.d.ts +0 -3
- package/dist/adapters/transport/rpc.js +0 -51
- package/dist/adapters/transport/types.d.ts +0 -6
- package/dist/adapters/transport/types.js +0 -1
- package/dist/components/auth/codec.d.ts +0 -9
- package/dist/components/auth/codec.js +0 -10
- package/dist/components/auth/codecs.d.ts +0 -9
- package/dist/components/auth/codecs.js +0 -10
- package/dist/components/auth/index.d.ts +0 -36
- package/dist/components/auth/index.js +0 -150
- package/dist/components/auth/types.d.ts +0 -15
- package/dist/components/auth/types.js +0 -1
- package/dist/components/session.d.ts +0 -34
- package/dist/components/session.js +0 -54
- package/dist/components/sso/index.d.ts +0 -36
- package/dist/components/sso/index.js +0 -150
- package/dist/components/sso/scale/handshake.d.ts +0 -9
- package/dist/components/sso/scale/handshake.js +0 -10
- package/dist/components/sso/types.d.ts +0 -15
- package/dist/components/sso/types.js +0 -1
- package/dist/components/transport.d.ts +0 -27
- package/dist/components/transport.js +0 -57
- package/dist/components/user/codec.d.ts +0 -16
- package/dist/components/user/codec.js +0 -13
- package/dist/components/user/index.d.ts +0 -22
- package/dist/components/user/index.js +0 -58
- package/dist/components/user/ssoMessageStream.d.ts +0 -10
- package/dist/components/user/ssoMessageStream.js +0 -8
- package/dist/components/user/ssoSession.d.ts +0 -5
- package/dist/components/user/ssoSession.js +0 -5
- package/dist/components/user/storage.d.ts +0 -27
- package/dist/components/user/storage.js +0 -143
- package/dist/components/user/types.d.ts +0 -6
- package/dist/components/user/types.js +0 -1
- package/dist/components/user/userSessionStorage.d.ts +0 -20
- package/dist/components/user/userSessionStorage.js +0 -24
- package/dist/components/user.d.ts +0 -74
- package/dist/components/user.js +0 -188
- package/dist/helpers/result.d.ts +0 -12
- package/dist/helpers/result.js +0 -15
- package/dist/helpers/result.spec.d.ts +0 -1
- package/dist/helpers/result.spec.js +0 -23
- package/dist/helpers.d.ts +0 -1
- package/dist/helpers.js +0 -3
- package/dist/modules/accounts.d.ts +0 -1
- package/dist/modules/accounts.js +0 -2
- package/dist/modules/crypto.d.ts +0 -23
- package/dist/modules/crypto.js +0 -51
- package/dist/modules/secretStorage.d.ts +0 -15
- package/dist/modules/secretStorage.js +0 -44
- package/dist/modules/session/helpers.d.ts +0 -5
- package/dist/modules/session/helpers.js +0 -29
- package/dist/modules/session/session.d.ts +0 -12
- package/dist/modules/session/session.js +0 -50
- package/dist/modules/session/types.d.ts +0 -12
- package/dist/modules/session/types.js +0 -1
- package/dist/modules/signIn.d.ts +0 -67
- package/dist/modules/signIn.js +0 -188
- package/dist/modules/state.d.ts +0 -16
- package/dist/modules/state.js +0 -50
- package/dist/modules/statementStore.d.ts +0 -12
- package/dist/modules/statementStore.js +0 -22
- package/dist/modules/statementTopic.d.ts +0 -34
- package/dist/modules/statementTopic.js +0 -46
- package/dist/modules/storageView.d.ts +0 -25
- package/dist/modules/storageView.js +0 -51
- package/dist/modules/syncStorage.d.ts +0 -25
- package/dist/modules/syncStorage.js +0 -76
- package/dist/modules/transport/codec.d.ts +0 -24
- package/dist/modules/transport/codec.js +0 -36
- package/dist/modules/transport/crypto.d.ts +0 -2
- package/dist/modules/transport/crypto.js +0 -20
- package/dist/modules/transport/transport.d.ts +0 -42
- package/dist/modules/transport/transport.js +0 -66
- package/dist/modules/user.d.ts +0 -67
- package/dist/modules/user.js +0 -188
- package/dist/modules/userManager.d.ts +0 -15
- package/dist/modules/userManager.js +0 -105
- package/dist/modules/userStorage.d.ts +0 -19
- package/dist/modules/userStorage.js +0 -108
- package/dist/modules/userStore.d.ts +0 -15
- package/dist/modules/userStore.js +0 -105
- package/dist/sso/session/impl.d.ts +0 -23
- package/dist/sso/session/impl.js +0 -57
- package/dist/sso/session/scale/remoteMessage.d.ts +0 -10
- package/dist/sso/session/scale/remoteMessage.js +0 -13
- package/dist/sso/session/sessionManager.d.ts +0 -23
- package/dist/sso/session/sessionManager.js +0 -58
- package/dist/sso/session/ssoSession.d.ts +0 -8
- package/dist/sso/session/ssoSession.js +0 -5
- package/dist/sso/session/ssoSessionStorage.d.ts +0 -21
- package/dist/sso/session/ssoSessionStorage.js +0 -20
- package/dist/sso/session/types.d.ts +0 -6
- package/dist/sso/session/types.js +0 -1
- package/dist/sso/session/userSessionStorage.d.ts +0 -21
- package/dist/sso/session/userSessionStorage.js +0 -20
- package/dist/sso/sessionManager/repository/ssoSessionRepository.d.ts +0 -22
- package/dist/sso/sessionManager/repository/ssoSessionRepository.js +0 -27
- package/dist/sso/sessionManager/ssoSession.d.ts +0 -23
- package/dist/sso/sessionManager/ssoSession.js +0 -69
- package/dist/sso/sessionManager/ssoSessionProver.d.ts +0 -4
- package/dist/sso/sessionManager/ssoSessionProver.js +0 -35
- package/dist/sso/ssoSessionRepository.d.ts +0 -18
- package/dist/sso/ssoSessionRepository.js +0 -27
- package/dist/structs.d.ts +0 -24
- package/dist/structs.js +0 -36
package/dist/sso/auth/impl.js
CHANGED
|
@@ -1,33 +1,57 @@
|
|
|
1
1
|
import { createAccountId, createEncryption, createLocalSessionAccount, createRemoteSessionAccount, khash, } from '@novasamatech/statement-store';
|
|
2
2
|
import { mergeUint8, toHex } from '@polkadot-api/utils';
|
|
3
|
+
import { generateMnemonic } from '@polkadot-labs/hdkd-helpers';
|
|
3
4
|
import { Result, ResultAsync, err, fromPromise, fromThrowable, ok } from 'neverthrow';
|
|
4
|
-
import { createEncrSecret, createSharedSecret,
|
|
5
|
+
import { createEncrSecret, createSharedSecret, deriveSr25519Account, getEncrPub, stringToBytes } from '../../crypto.js';
|
|
5
6
|
import { AbortError } from '../../helpers/abortError.js';
|
|
6
7
|
import { createState, readonly } from '../../helpers/state.js';
|
|
7
8
|
import { toError } from '../../helpers/utils.js';
|
|
8
9
|
import { createStoredUserSession } from '../userSessionRepository.js';
|
|
10
|
+
import { createAliceVerifier, createAttestationService } from './attestationService.js';
|
|
9
11
|
import { HandshakeData, HandshakeResponsePayload, HandshakeResponseSensitiveData } from './scale/handshake.js';
|
|
10
|
-
export function createAuth({ metadata, statementStore, ssoSessionRepository, userSecretRepository }) {
|
|
11
|
-
const
|
|
12
|
-
|
|
12
|
+
export function createAuth({ metadata, statementStore, ssoSessionRepository, userSecretRepository, lazyClient, }) {
|
|
13
|
+
const attestationStatus = createState({ step: 'none' });
|
|
14
|
+
const pairingStatus = createState({ step: 'none' });
|
|
15
|
+
let authResult = null;
|
|
13
16
|
let abort = null;
|
|
14
|
-
function
|
|
15
|
-
|
|
17
|
+
function attestAccount(account, signal) {
|
|
18
|
+
const attestationService = createAttestationService(lazyClient);
|
|
19
|
+
const verifier = createAliceVerifier();
|
|
20
|
+
const username = attestationService.claimUsername();
|
|
21
|
+
attestationStatus.write({ step: 'attestation', username });
|
|
22
|
+
return attestationService
|
|
23
|
+
.grantVerifierAllowance(verifier)
|
|
24
|
+
.andThrough(() => processSignal(signal))
|
|
25
|
+
.andThen(() => attestationService.registerLitePerson(username, account, verifier))
|
|
26
|
+
.andThrough(() => processSignal(signal))
|
|
16
27
|
.andTee(() => {
|
|
17
|
-
|
|
28
|
+
attestationStatus.write({ step: 'finished' });
|
|
18
29
|
})
|
|
19
|
-
.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
30
|
+
.orTee(e => {
|
|
31
|
+
if (!(e instanceof AbortError)) {
|
|
32
|
+
attestationStatus.write({ step: 'attestationError', message: e.message });
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function handshake(account, signal) {
|
|
37
|
+
const localAccount = createLocalSessionAccount(createAccountId(account.publicKey));
|
|
38
|
+
pairingStatus.write({ step: 'initial' });
|
|
39
|
+
const encrKeys = createEncrKeys(account.entropy);
|
|
40
|
+
const handshakePayload = encrKeys.andThen(({ publicKey }) => createHandshakePayloadV1({
|
|
41
|
+
ssPublicKey: account.publicKey,
|
|
42
|
+
encrPublicKey: publicKey,
|
|
43
|
+
metadata,
|
|
44
|
+
}));
|
|
45
|
+
const handshakeTopic = encrKeys.andThen(({ publicKey }) => createHandshakeTopic(localAccount, publicKey));
|
|
46
|
+
const dataPrepared = Result.combine([handshakePayload, handshakeTopic, encrKeys]).andTee(([payload]) => pairingStatus.write({ step: 'pairing', payload: createDeeplink(payload) }));
|
|
47
|
+
return dataPrepared.asyncAndThen(([, handshakeTopic, encrKeys]) => {
|
|
48
|
+
const pappResponse = waitForStatements(callback => statementStore.subscribeStatements([handshakeTopic], callback), signal, (statements, resolve) => {
|
|
25
49
|
for (const statement of statements) {
|
|
26
50
|
if (!statement.data)
|
|
27
51
|
continue;
|
|
28
52
|
const session = retrieveSession({
|
|
29
53
|
localAccount,
|
|
30
|
-
encrSecret,
|
|
54
|
+
encrSecret: encrKeys.secret,
|
|
31
55
|
payload: statement.data.asBytes(),
|
|
32
56
|
}).unwrapOr(null);
|
|
33
57
|
if (session) {
|
|
@@ -35,36 +59,57 @@ export function createAuth({ metadata, statementStore, ssoSessionRepository, use
|
|
|
35
59
|
break;
|
|
36
60
|
}
|
|
37
61
|
}
|
|
38
|
-
})
|
|
39
|
-
const secretesSaved = pappResponse.andThen(({ id }) =>
|
|
62
|
+
});
|
|
63
|
+
const secretesSaved = pappResponse.andThen(({ id }) => {
|
|
64
|
+
return userSecretRepository.write(id, {
|
|
65
|
+
ssSecret: account.secret,
|
|
66
|
+
encrSecret: encrKeys.secret,
|
|
67
|
+
entropy: account.entropy,
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
// secrets and sso session should be chained, or it can produce an incorrect state
|
|
40
71
|
const userCreated = secretesSaved.andThen(() => pappResponse.andThen(ssoSessionRepository.add));
|
|
41
|
-
const
|
|
42
|
-
return
|
|
43
|
-
.orElse(e => (AbortError.isAbortError(e) ? ok(null) : err(toError(e))))
|
|
72
|
+
const sessionReceived = ResultAsync.combine([userCreated, secretesSaved]).map(([session]) => session);
|
|
73
|
+
return sessionReceived
|
|
44
74
|
.andTee(session => {
|
|
45
|
-
|
|
75
|
+
pairingStatus.write(session ? { step: 'finished', session } : { step: 'none' });
|
|
46
76
|
})
|
|
47
77
|
.orTee(e => {
|
|
48
|
-
|
|
78
|
+
if (!(e instanceof AbortError)) {
|
|
79
|
+
pairingStatus.write({ step: 'pairingError', message: e.message });
|
|
80
|
+
}
|
|
49
81
|
});
|
|
50
82
|
});
|
|
51
83
|
}
|
|
52
84
|
const authModule = {
|
|
53
|
-
|
|
85
|
+
pairingStatus: readonly(pairingStatus),
|
|
86
|
+
attestationStatus: readonly(attestationStatus),
|
|
54
87
|
authenticate() {
|
|
55
|
-
if (
|
|
56
|
-
return
|
|
88
|
+
if (authResult) {
|
|
89
|
+
return authResult;
|
|
57
90
|
}
|
|
58
91
|
abort = new AbortController();
|
|
59
|
-
|
|
60
|
-
|
|
92
|
+
const account = deriveSr25519Account(generateMnemonic(), '//wallet//sso');
|
|
93
|
+
authResult = ResultAsync.combine([handshake(account, abort.signal), attestAccount(account, abort.signal)])
|
|
94
|
+
.map(([session]) => session)
|
|
95
|
+
.orElse(e => (e instanceof AbortError ? ok(null) : err(e)))
|
|
96
|
+
.andTee(() => {
|
|
97
|
+
abort = null;
|
|
98
|
+
})
|
|
99
|
+
.orTee(() => {
|
|
100
|
+
authResult = null;
|
|
101
|
+
abort = null;
|
|
102
|
+
});
|
|
103
|
+
return authResult;
|
|
61
104
|
},
|
|
62
105
|
abortAuthentication() {
|
|
63
106
|
if (abort) {
|
|
64
|
-
authResults = null;
|
|
65
|
-
authStatus.reset();
|
|
66
107
|
abort.abort(new AbortError('Aborted by user.'));
|
|
108
|
+
abort = null;
|
|
67
109
|
}
|
|
110
|
+
authResult = null;
|
|
111
|
+
pairingStatus.reset();
|
|
112
|
+
attestationStatus.reset();
|
|
68
113
|
},
|
|
69
114
|
};
|
|
70
115
|
return authModule;
|
|
@@ -86,6 +131,13 @@ function parseHandshakePayload(payload) {
|
|
|
86
131
|
throw new Error('Unsupported handshake payload version');
|
|
87
132
|
}
|
|
88
133
|
}
|
|
134
|
+
const createEncrKeys = fromThrowable((entropy) => {
|
|
135
|
+
const secret = createEncrSecret(entropy);
|
|
136
|
+
return {
|
|
137
|
+
secret,
|
|
138
|
+
publicKey: getEncrPub(secret),
|
|
139
|
+
};
|
|
140
|
+
}, toError);
|
|
89
141
|
function retrieveSession({ payload, encrSecret, localAccount, }) {
|
|
90
142
|
const { encrypted, tmpKey } = parseHandshakePayload(payload);
|
|
91
143
|
const symmetricKey = createSharedSecret(encrSecret, tmpKey);
|
|
@@ -98,40 +150,17 @@ function retrieveSession({ payload, encrSecret, localAccount, }) {
|
|
|
98
150
|
return createStoredUserSession(localAccount, peerAccount);
|
|
99
151
|
});
|
|
100
152
|
}
|
|
101
|
-
const getSsKeys = fromThrowable(() => {
|
|
102
|
-
const ssSecret = createSsHardDerivation(createSsSecret(), '//wallet//sso');
|
|
103
|
-
return {
|
|
104
|
-
ssSecret: ssSecret,
|
|
105
|
-
ssPublicKey: getSsPub(ssSecret),
|
|
106
|
-
};
|
|
107
|
-
}, toError);
|
|
108
|
-
const getEncrKeys = fromThrowable(() => {
|
|
109
|
-
const encrSecret = createEncrSecret();
|
|
110
|
-
return {
|
|
111
|
-
encrSecret,
|
|
112
|
-
encrPublicKey: getEncrPub(encrSecret),
|
|
113
|
-
};
|
|
114
|
-
}, toError);
|
|
115
|
-
function getSecretKeys() {
|
|
116
|
-
return Result.combine([getSsKeys(), getEncrKeys()]).map(([ss, encr]) => ({
|
|
117
|
-
...ss,
|
|
118
|
-
...encr,
|
|
119
|
-
}));
|
|
120
|
-
}
|
|
121
153
|
function createDeeplink(payload) {
|
|
122
154
|
return `polkadotapp://pair?handshake=${toHex(payload)}`;
|
|
123
155
|
}
|
|
124
|
-
function waitForStatements(subscribe,
|
|
156
|
+
function waitForStatements(subscribe, signal, callback) {
|
|
125
157
|
return fromPromise(new Promise((resolve, reject) => {
|
|
126
158
|
const unsubscribe = subscribe(statements => {
|
|
127
|
-
|
|
159
|
+
const abortError = processSignal(signal).match(() => null, e => e);
|
|
160
|
+
if (abortError) {
|
|
128
161
|
unsubscribe();
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
}
|
|
132
|
-
catch (e) {
|
|
133
|
-
reject(e);
|
|
134
|
-
}
|
|
162
|
+
reject(abortError);
|
|
163
|
+
return;
|
|
135
164
|
}
|
|
136
165
|
try {
|
|
137
166
|
callback(statements, value => {
|
|
@@ -146,3 +175,12 @@ function waitForStatements(subscribe, abortSignal, callback) {
|
|
|
146
175
|
});
|
|
147
176
|
}), toError);
|
|
148
177
|
}
|
|
178
|
+
function processSignal(signal) {
|
|
179
|
+
try {
|
|
180
|
+
signal.throwIfAborted();
|
|
181
|
+
return ok();
|
|
182
|
+
}
|
|
183
|
+
catch (e) {
|
|
184
|
+
return err(toError(e));
|
|
185
|
+
}
|
|
186
|
+
}
|
package/dist/sso/auth/types.d.ts
CHANGED
|
@@ -1,15 +1,28 @@
|
|
|
1
1
|
import type { StoredUserSession } from '../userSessionRepository.js';
|
|
2
|
-
export type
|
|
2
|
+
export type PairingStatus = {
|
|
3
3
|
step: 'none';
|
|
4
4
|
} | {
|
|
5
5
|
step: 'initial';
|
|
6
|
+
} | {
|
|
7
|
+
step: 'attestation';
|
|
6
8
|
} | {
|
|
7
9
|
step: 'pairing';
|
|
8
10
|
payload: string;
|
|
9
11
|
} | {
|
|
10
|
-
step: '
|
|
12
|
+
step: 'pairingError';
|
|
11
13
|
message: string;
|
|
12
14
|
} | {
|
|
13
15
|
step: 'finished';
|
|
14
16
|
session: StoredUserSession;
|
|
15
17
|
};
|
|
18
|
+
export type AttestationStatus = {
|
|
19
|
+
step: 'none';
|
|
20
|
+
} | {
|
|
21
|
+
step: 'attestation';
|
|
22
|
+
username: string;
|
|
23
|
+
} | {
|
|
24
|
+
step: 'attestationError';
|
|
25
|
+
message: string;
|
|
26
|
+
} | {
|
|
27
|
+
step: 'finished';
|
|
28
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const hexCodec: import("scale-ts").Codec<`0x${string}`>;
|
|
@@ -1,13 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
value: {
|
|
4
|
-
tag: "Disconnected";
|
|
5
|
-
value: undefined;
|
|
6
|
-
} | {
|
|
7
|
-
tag: "SigningRequest";
|
|
8
|
-
value: Uint8Array<ArrayBufferLike>;
|
|
9
|
-
};
|
|
10
|
-
}>;
|
|
1
|
+
import type { CodecType } from 'scale-ts';
|
|
2
|
+
export type RemoteMessage = CodecType<typeof RemoteMessageCodec>;
|
|
11
3
|
export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
12
4
|
messageId: string;
|
|
13
5
|
data: {
|
|
@@ -16,8 +8,34 @@ export declare const RemoteMessageCodec: import("scale-ts").Codec<{
|
|
|
16
8
|
tag: "Disconnected";
|
|
17
9
|
value: undefined;
|
|
18
10
|
} | {
|
|
19
|
-
tag: "
|
|
20
|
-
value:
|
|
11
|
+
tag: "SignRequest";
|
|
12
|
+
value: {
|
|
13
|
+
address: string;
|
|
14
|
+
blockHash: `0x${string}`;
|
|
15
|
+
blockNumber: `0x${string}`;
|
|
16
|
+
era: `0x${string}`;
|
|
17
|
+
genesisHash: `0x${string}`;
|
|
18
|
+
method: `0x${string}`;
|
|
19
|
+
nonce: `0x${string}`;
|
|
20
|
+
specVersion: `0x${string}`;
|
|
21
|
+
tip: `0x${string}`;
|
|
22
|
+
transactionVersion: `0x${string}`;
|
|
23
|
+
signedExtensions: string[];
|
|
24
|
+
version: number;
|
|
25
|
+
assetId: `0x${string}` | undefined;
|
|
26
|
+
metadataHash: `0x${string}` | undefined;
|
|
27
|
+
mode: number | undefined;
|
|
28
|
+
withSignedTransaction: boolean | undefined;
|
|
29
|
+
};
|
|
30
|
+
} | {
|
|
31
|
+
tag: "SignResponse";
|
|
32
|
+
value: {
|
|
33
|
+
respondingTo: string;
|
|
34
|
+
payload: import("scale-ts").ResultPayload<{
|
|
35
|
+
signature: Uint8Array<ArrayBufferLike>;
|
|
36
|
+
signedTransaction: Uint8Array<ArrayBufferLike> | undefined;
|
|
37
|
+
}, string>;
|
|
38
|
+
};
|
|
21
39
|
};
|
|
22
40
|
};
|
|
23
41
|
}>;
|
|
@@ -1,14 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
Disconnected: _void,
|
|
5
|
-
// TODO implement
|
|
6
|
-
SigningRequest: Bytes(),
|
|
7
|
-
// TODO implement
|
|
8
|
-
// SigningResponse: Bytes(),
|
|
9
|
-
}),
|
|
10
|
-
});
|
|
1
|
+
import { Enum, Struct, _void, str } from 'scale-ts';
|
|
2
|
+
import { SignPayloadRequestCodec } from './signPayloadRequest.js';
|
|
3
|
+
import { SignPayloadResponseCodec } from './signPayloadResponse.js';
|
|
11
4
|
export const RemoteMessageCodec = Struct({
|
|
12
5
|
messageId: str,
|
|
13
|
-
data:
|
|
6
|
+
data: Enum({
|
|
7
|
+
v1: Enum({
|
|
8
|
+
Disconnected: _void,
|
|
9
|
+
SignRequest: SignPayloadRequestCodec,
|
|
10
|
+
SignResponse: SignPayloadResponseCodec,
|
|
11
|
+
}),
|
|
12
|
+
}),
|
|
14
13
|
});
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { CodecType } from 'scale-ts';
|
|
2
|
+
export type SignPayloadRequest = CodecType<typeof SignPayloadRequestCodec>;
|
|
3
|
+
export declare const SignPayloadRequestCodec: import("scale-ts").Codec<{
|
|
4
|
+
address: string;
|
|
5
|
+
blockHash: `0x${string}`;
|
|
6
|
+
blockNumber: `0x${string}`;
|
|
7
|
+
era: `0x${string}`;
|
|
8
|
+
genesisHash: `0x${string}`;
|
|
9
|
+
method: `0x${string}`;
|
|
10
|
+
nonce: `0x${string}`;
|
|
11
|
+
specVersion: `0x${string}`;
|
|
12
|
+
tip: `0x${string}`;
|
|
13
|
+
transactionVersion: `0x${string}`;
|
|
14
|
+
signedExtensions: string[];
|
|
15
|
+
version: number;
|
|
16
|
+
assetId: `0x${string}` | undefined;
|
|
17
|
+
metadataHash: `0x${string}` | undefined;
|
|
18
|
+
mode: number | undefined;
|
|
19
|
+
withSignedTransaction: boolean | undefined;
|
|
20
|
+
}>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Option, Struct, Vector, bool, str, u32 } from 'scale-ts';
|
|
2
|
+
import { hexCodec } from './hex.js';
|
|
3
|
+
export const SignPayloadRequestCodec = Struct({
|
|
4
|
+
address: str,
|
|
5
|
+
blockHash: hexCodec,
|
|
6
|
+
blockNumber: hexCodec,
|
|
7
|
+
era: hexCodec,
|
|
8
|
+
genesisHash: hexCodec,
|
|
9
|
+
method: hexCodec,
|
|
10
|
+
nonce: hexCodec,
|
|
11
|
+
specVersion: hexCodec,
|
|
12
|
+
tip: hexCodec,
|
|
13
|
+
transactionVersion: hexCodec,
|
|
14
|
+
signedExtensions: Vector(str),
|
|
15
|
+
version: u32,
|
|
16
|
+
assetId: Option(hexCodec),
|
|
17
|
+
metadataHash: Option(hexCodec),
|
|
18
|
+
mode: Option(u32),
|
|
19
|
+
withSignedTransaction: Option(bool),
|
|
20
|
+
});
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CodecType } from 'scale-ts';
|
|
2
|
+
export type SignPayloadResponseData = CodecType<typeof SignPayloadResponseDataCodec>;
|
|
3
|
+
export declare const SignPayloadResponseDataCodec: import("scale-ts").Codec<{
|
|
4
|
+
signature: Uint8Array<ArrayBufferLike>;
|
|
5
|
+
signedTransaction: Uint8Array<ArrayBufferLike> | undefined;
|
|
6
|
+
}>;
|
|
7
|
+
export type SignPayloadResponse = CodecType<typeof SignPayloadResponseCodec>;
|
|
8
|
+
export declare const SignPayloadResponseCodec: import("scale-ts").Codec<{
|
|
9
|
+
respondingTo: string;
|
|
10
|
+
payload: import("scale-ts").ResultPayload<{
|
|
11
|
+
signature: Uint8Array<ArrayBufferLike>;
|
|
12
|
+
signedTransaction: Uint8Array<ArrayBufferLike> | undefined;
|
|
13
|
+
}, string>;
|
|
14
|
+
}>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { Bytes, Option, Result, Struct, str } from 'scale-ts';
|
|
2
|
+
export const SignPayloadResponseDataCodec = Struct({
|
|
3
|
+
signature: Bytes(),
|
|
4
|
+
signedTransaction: Option(Bytes()),
|
|
5
|
+
});
|
|
6
|
+
export const SignPayloadResponseCodec = Struct({
|
|
7
|
+
// referencing to RemoteMessage.messageId
|
|
8
|
+
respondingTo: str,
|
|
9
|
+
payload: Result(SignPayloadResponseDataCodec, str),
|
|
10
|
+
});
|
|
@@ -4,14 +4,12 @@ import { ResultAsync } from 'neverthrow';
|
|
|
4
4
|
import type { CodecType } from 'scale-ts';
|
|
5
5
|
import type { Callback } from '../../types.js';
|
|
6
6
|
import type { StoredUserSession } from '../userSessionRepository.js';
|
|
7
|
-
import { RemoteMessageCodec
|
|
7
|
+
import { RemoteMessageCodec } from './scale/remoteMessage.js';
|
|
8
|
+
import type { SignPayloadRequest } from './scale/signPayloadRequest.js';
|
|
9
|
+
import type { SignPayloadResponseData } from './scale/signPayloadResponse.js';
|
|
8
10
|
export type UserSession = StoredUserSession & {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}, Error>;
|
|
12
|
-
sendDisconnectMessage(): ResultAsync<{
|
|
13
|
-
requestId: string;
|
|
14
|
-
}, Error>;
|
|
11
|
+
sendDisconnectMessage(): ResultAsync<void, Error>;
|
|
12
|
+
signPayload(payload: SignPayloadRequest): ResultAsync<SignPayloadResponseData, Error>;
|
|
15
13
|
subscribe(callback: Callback<CodecType<typeof RemoteMessageCodec>, ResultAsync<boolean, Error>>): VoidFunction;
|
|
16
14
|
dispose(): void;
|
|
17
15
|
};
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { createSession } from '@novasamatech/statement-store';
|
|
2
2
|
import { fieldListView } from '@novasamatech/storage-adapter';
|
|
3
|
+
import { AccountId } from '@polkadot-api/substrate-bindings';
|
|
4
|
+
import { toHex } from '@polkadot-api/utils';
|
|
3
5
|
import { nanoid } from 'nanoid';
|
|
4
|
-
import { ResultAsync, okAsync } from 'neverthrow';
|
|
5
|
-
import { RemoteMessageCodec
|
|
6
|
+
import { ResultAsync, err, errAsync, ok, okAsync } from 'neverthrow';
|
|
7
|
+
import { RemoteMessageCodec } from './scale/remoteMessage.js';
|
|
6
8
|
export function createUserSession({ userSession, statementStore, encryption, storage, prover, }) {
|
|
7
9
|
const session = createSession({
|
|
8
10
|
localAccount: userSession.localAccount,
|
|
@@ -16,20 +18,58 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
16
18
|
key: `sso_processed_${userSession.id}`,
|
|
17
19
|
from: JSON.parse,
|
|
18
20
|
to: JSON.stringify,
|
|
19
|
-
initial: [],
|
|
20
21
|
});
|
|
21
22
|
return {
|
|
22
23
|
id: userSession.id,
|
|
23
24
|
localAccount: userSession.localAccount,
|
|
24
25
|
remoteAccount: userSession.remoteAccount,
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
signPayload(payload) {
|
|
27
|
+
const accountId = AccountId();
|
|
28
|
+
if (toHex(accountId.enc(payload.address)) !== toHex(userSession.remoteAccount.accountId)) {
|
|
29
|
+
return errAsync(new Error(`Invalid address, got ${payload.address}`));
|
|
30
|
+
}
|
|
31
|
+
const messageId = nanoid();
|
|
32
|
+
const request = session.request(RemoteMessageCodec, {
|
|
33
|
+
messageId,
|
|
34
|
+
data: {
|
|
35
|
+
tag: 'v1',
|
|
36
|
+
value: {
|
|
37
|
+
tag: 'SignRequest',
|
|
38
|
+
value: payload,
|
|
39
|
+
},
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
const responseFilter = (message) => {
|
|
43
|
+
return (message.data.tag === 'v1' &&
|
|
44
|
+
message.data.value.tag === 'SignResponse' &&
|
|
45
|
+
message.data.value.value.respondingTo === messageId);
|
|
46
|
+
};
|
|
47
|
+
return request
|
|
48
|
+
.andThen(() => session.waitForRequestMessage(RemoteMessageCodec, responseFilter))
|
|
49
|
+
.andThen(message => {
|
|
50
|
+
const { data } = message.payload;
|
|
51
|
+
switch (data.tag) {
|
|
52
|
+
case 'v1': {
|
|
53
|
+
switch (data.value.tag) {
|
|
54
|
+
case 'SignResponse':
|
|
55
|
+
if (data.value.value.payload.success) {
|
|
56
|
+
return ok(data.value.value.payload.value);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
return err(new Error(data.value.value.payload.value));
|
|
60
|
+
}
|
|
61
|
+
default:
|
|
62
|
+
return err(new Error(`Incorrect sign response: ${data.value.tag}`));
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
default:
|
|
66
|
+
return err(new Error(`Unsupported message version ${data.tag}`));
|
|
67
|
+
}
|
|
29
68
|
});
|
|
30
69
|
},
|
|
31
70
|
sendDisconnectMessage() {
|
|
32
|
-
return session
|
|
71
|
+
return session
|
|
72
|
+
.submitRequestMessage(RemoteMessageCodec, {
|
|
33
73
|
messageId: nanoid(),
|
|
34
74
|
data: {
|
|
35
75
|
tag: 'v1',
|
|
@@ -38,23 +78,24 @@ export function createUserSession({ userSession, statementStore, encryption, sto
|
|
|
38
78
|
value: undefined,
|
|
39
79
|
},
|
|
40
80
|
},
|
|
41
|
-
})
|
|
81
|
+
})
|
|
82
|
+
.map(() => undefined);
|
|
42
83
|
},
|
|
43
84
|
subscribe(callback) {
|
|
44
85
|
return session.subscribe(RemoteMessageCodec, messages => {
|
|
45
86
|
processedMessages.read().andThen(processed => {
|
|
46
87
|
const results = messages.map(message => {
|
|
47
88
|
if (message.type === 'request') {
|
|
48
|
-
const isMessageProcessed = processed.includes(message.
|
|
89
|
+
const isMessageProcessed = processed.includes(message.payload.messageId);
|
|
49
90
|
if (isMessageProcessed) {
|
|
50
91
|
return okAsync({ processed: false });
|
|
51
92
|
}
|
|
52
|
-
return callback(message.
|
|
93
|
+
return callback(message.payload)
|
|
53
94
|
.orTee(error => {
|
|
54
95
|
console.error('Error while processing sso messsage:', error);
|
|
55
96
|
})
|
|
56
97
|
.orElse(() => okAsync(false))
|
|
57
|
-
.map(processed => (processed ? { processed, message: message.
|
|
98
|
+
.map(processed => (processed ? { processed, message: message.payload } : { processed }));
|
|
58
99
|
}
|
|
59
100
|
return okAsync({ processed: false });
|
|
60
101
|
});
|
|
@@ -6,6 +6,7 @@ type StoredUserSecrets = CodecType<typeof StoredUserSecretsCodec>;
|
|
|
6
6
|
declare const StoredUserSecretsCodec: import("scale-ts").Codec<{
|
|
7
7
|
ssSecret: SsSecret;
|
|
8
8
|
encrSecret: EncrSecret;
|
|
9
|
+
entropy: Uint8Array<ArrayBufferLike>;
|
|
9
10
|
}>;
|
|
10
11
|
export type UserSecretRepository = ReturnType<typeof createUserSecretRepository>;
|
|
11
12
|
export declare function createUserSecretRepository(salt: string, storage: StorageAdapter): {
|
|
@@ -2,12 +2,13 @@ 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
4
|
import { fromThrowable } from 'neverthrow';
|
|
5
|
-
import { Struct } from 'scale-ts';
|
|
5
|
+
import { Bytes, Struct } from 'scale-ts';
|
|
6
6
|
import { BrandedBytesCodec, stringToBytes } from '../crypto.js';
|
|
7
7
|
import { toError } from '../helpers/utils.js';
|
|
8
8
|
const StoredUserSecretsCodec = Struct({
|
|
9
9
|
ssSecret: BrandedBytesCodec(),
|
|
10
10
|
encrSecret: BrandedBytesCodec(),
|
|
11
|
+
entropy: Bytes(),
|
|
11
12
|
});
|
|
12
13
|
export function createUserSecretRepository(salt, storage) {
|
|
13
14
|
const baseKey = 'UserSecrets';
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@novasamatech/host-papp",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.5.
|
|
4
|
+
"version": "0.5.1",
|
|
5
5
|
"description": "Polkadot app integration",
|
|
6
6
|
"license": "Apache-2.0",
|
|
7
7
|
"repository": {
|
|
@@ -21,22 +21,25 @@
|
|
|
21
21
|
},
|
|
22
22
|
"files": [
|
|
23
23
|
"dist",
|
|
24
|
+
".papi",
|
|
24
25
|
"README.md"
|
|
25
26
|
],
|
|
26
27
|
"dependencies": {
|
|
27
|
-
"@
|
|
28
|
-
"@novasamatech/statement-store": "0.5.0-9",
|
|
29
|
-
"@novasamatech/storage-adapter": "0.5.0-9",
|
|
30
|
-
"@polkadot-api/substrate-bindings": "^0.16.5",
|
|
31
|
-
"@scure/sr25519": "1.0.0",
|
|
28
|
+
"@noble/ciphers": "2.1.1",
|
|
32
29
|
"@noble/curves": "2.0.1",
|
|
33
30
|
"@noble/hashes": "2.0.1",
|
|
34
|
-
"@
|
|
35
|
-
"
|
|
31
|
+
"@novasamatech/host-api": "0.5.1",
|
|
32
|
+
"@novasamatech/statement-store": "0.5.1",
|
|
33
|
+
"@novasamatech/storage-adapter": "0.5.1",
|
|
34
|
+
"@polkadot-api/substrate-bindings": "^0.16.5",
|
|
35
|
+
"@polkadot-labs/hdkd-helpers": "^0.0.27",
|
|
36
|
+
"@scure/sr25519": "1.0.0",
|
|
36
37
|
"nanoevents": "9.1.0",
|
|
37
38
|
"nanoid": "5.1.6",
|
|
38
39
|
"neverthrow": "^8.2.0",
|
|
39
|
-
"
|
|
40
|
+
"polkadot-api": "^1.23.2",
|
|
41
|
+
"scale-ts": "1.6.1",
|
|
42
|
+
"verifiablejs": "1.1.0"
|
|
40
43
|
},
|
|
41
44
|
"publishConfig": {
|
|
42
45
|
"access": "public"
|
|
@@ -1,6 +0,0 @@
|
|
|
1
|
-
import type { LazyClient } from '@novasamatech/statement-store';
|
|
2
|
-
import type { StorageAdapter } from '@novasamatech/storage-adapter';
|
|
3
|
-
import { ResultAsync } from 'neverthrow';
|
|
4
|
-
import type { Identity, IdentityAdapter } from './types.js';
|
|
5
|
-
export declare function createCachedIdentityRequester(storage: StorageAdapter, getKey: (accountId: string) => string, request: (accounts: string[]) => ResultAsync<(Identity | null)[], Error>): (accounts: string[]) => ResultAsync<Record<string, Identity | null>, Error>;
|
|
6
|
-
export declare function createIdentityRpcAdapter(lazyClient: LazyClient, storage: StorageAdapter): IdentityAdapter;
|