@oxy.so/core 7.13.0 → 7.14.0
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/dist/cjs/api/follows.js +12 -11
- package/dist/cjs/api/users.js +1 -1
- package/dist/cjs/crypto/aead.js +3 -3
- package/dist/cjs/crypto/contentHash.js +4 -4
- package/dist/cjs/crypto/identityDerivations.js +5 -5
- package/dist/cjs/crypto/identityLink.js +3 -3
- package/dist/cjs/crypto/identityProof.js +3 -3
- package/dist/cjs/crypto/index.js +2 -2
- package/dist/cjs/crypto/kdf.js +3 -3
- package/dist/cjs/crypto/polyfill.js +13 -13
- package/dist/cjs/crypto/recoveryPhrase.js +12 -12
- package/dist/cjs/crypto/registrationPow.js +4 -4
- package/dist/cjs/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/cjs/i18n/locales/en-US.js +0 -2
- package/dist/cjs/i18n/locales/es-ES.js +0 -2
- package/dist/cjs/index.js +2 -2
- package/dist/cjs/utils/identityCacheSweep.js +9 -1
- package/dist/esm/api/follows.js +12 -11
- package/dist/esm/api/users.js +2 -2
- package/dist/esm/crypto/aead.js +1 -1
- package/dist/esm/crypto/contentHash.js +2 -2
- package/dist/esm/crypto/identityDerivations.js +2 -2
- package/dist/esm/crypto/identityLink.js +2 -2
- package/dist/esm/crypto/identityProof.js +2 -2
- package/dist/esm/crypto/index.js +2 -2
- package/dist/esm/crypto/kdf.js +2 -2
- package/dist/esm/crypto/polyfill.js +13 -13
- package/dist/esm/crypto/recoveryPhrase.js +1 -1
- package/dist/esm/crypto/registrationPow.js +3 -3
- package/dist/esm/i18n/locales/compact/es-ES.generated.js +1 -1
- package/dist/esm/i18n/locales/en-US.js +0 -2
- package/dist/esm/i18n/locales/es-ES.js +0 -2
- package/dist/esm/index.js +2 -2
- package/dist/esm/utils/identityCacheSweep.js +8 -1
- package/dist/types/crypto/polyfill.d.ts +13 -13
- package/dist/types/crypto/registrationPow.d.ts +1 -1
- package/dist/types/i18n/locales/en-US.d.ts +0 -2
- package/dist/types/i18n/locales/es-ES.d.ts +0 -2
- package/dist/types/utils/identityCacheSweep.d.ts +5 -0
- package/package.json +8 -8
- package/src/api/follows.ts +21 -12
- package/src/api/users.ts +6 -2
- package/src/crypto/aead.ts +1 -1
- package/src/crypto/contentHash.ts +2 -2
- package/src/crypto/identityDerivations.ts +2 -2
- package/src/crypto/identityLink.ts +2 -2
- package/src/crypto/identityProof.ts +2 -2
- package/src/crypto/index.ts +2 -2
- package/src/crypto/kdf.ts +2 -2
- package/src/crypto/polyfill.ts +13 -13
- package/src/crypto/recoveryPhrase.ts +1 -1
- package/src/crypto/registrationPow.ts +3 -3
- package/src/i18n/locales/compact/es-ES.generated.ts +1 -1
- package/src/i18n/locales/en-US.ts +0 -2
- package/src/i18n/locales/es-ES.ts +0 -2
- package/src/index.ts +2 -2
- package/src/utils/identityCacheSweep.ts +9 -1
package/dist/cjs/api/follows.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.FollowsApi = void 0;
|
|
4
4
|
const apiUtils_1 = require("../utils/apiUtils");
|
|
5
|
-
const
|
|
5
|
+
const identityCacheSweep_1 = require("../utils/identityCacheSweep");
|
|
6
6
|
const GRAPH_TTL = 2 * 60 * 1000;
|
|
7
7
|
const STATUS_TTL = 60 * 1000;
|
|
8
8
|
/**
|
|
@@ -17,7 +17,7 @@ class FollowsApi {
|
|
|
17
17
|
// ── People ───────────────────────────────────────────────────────────────
|
|
18
18
|
/** Follow a user. */
|
|
19
19
|
async follow(userId) {
|
|
20
|
-
const result = await this.ctx.request('POST',
|
|
20
|
+
const result = await this.ctx.request('POST', `${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/follow`, undefined, { cache: false });
|
|
21
21
|
this.invalidate([userId]);
|
|
22
22
|
return result;
|
|
23
23
|
}
|
|
@@ -31,7 +31,7 @@ class FollowsApi {
|
|
|
31
31
|
}
|
|
32
32
|
/** Unfollow a user. */
|
|
33
33
|
async unfollow(userId) {
|
|
34
|
-
const result = await this.ctx.request('DELETE',
|
|
34
|
+
const result = await this.ctx.request('DELETE', `${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/follow`, undefined, { cache: false });
|
|
35
35
|
this.invalidate([userId]);
|
|
36
36
|
return result;
|
|
37
37
|
}
|
|
@@ -45,7 +45,7 @@ class FollowsApi {
|
|
|
45
45
|
}
|
|
46
46
|
/** Whether the signed-in user follows `userId`. Cached 1 minute, busted by every write. */
|
|
47
47
|
async status(userId) {
|
|
48
|
-
return this.ctx.request('GET',
|
|
48
|
+
return this.ctx.request('GET', `${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/follow-status`, undefined, {
|
|
49
49
|
cache: true,
|
|
50
50
|
cacheTTL: STATUS_TTL,
|
|
51
51
|
});
|
|
@@ -75,12 +75,12 @@ class FollowsApi {
|
|
|
75
75
|
* `limit`/`offset`/`sort` combination is its own cache entry (2 minutes).
|
|
76
76
|
*/
|
|
77
77
|
async followers(userId, params) {
|
|
78
|
-
const { data, total, hasMore } = await this.userPage(
|
|
78
|
+
const { data, total, hasMore } = await this.userPage(`${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/followers`, params);
|
|
79
79
|
return { followers: data, total, hasMore };
|
|
80
80
|
}
|
|
81
81
|
/** Who a user follows. `sort` as in `followers`. */
|
|
82
82
|
async following(userId, params) {
|
|
83
|
-
const { data, total, hasMore } = await this.userPage(
|
|
83
|
+
const { data, total, hasMore } = await this.userPage(`${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/following`, params);
|
|
84
84
|
return { following: data, total, hasMore };
|
|
85
85
|
}
|
|
86
86
|
/**
|
|
@@ -88,7 +88,7 @@ class FollowsApi {
|
|
|
88
88
|
* `userId`.
|
|
89
89
|
*/
|
|
90
90
|
async mutuals(userId, params) {
|
|
91
|
-
const { data, total, hasMore } = await this.userPage(
|
|
91
|
+
const { data, total, hasMore } = await this.userPage(`${(0, identityCacheSweep_1.oxyUserByIdPath)(userId)}/mutuals`, params);
|
|
92
92
|
return { mutuals: data, total, hasMore };
|
|
93
93
|
}
|
|
94
94
|
/**
|
|
@@ -223,16 +223,17 @@ class FollowsApi {
|
|
|
223
223
|
const keys = ['GET:/users/me/graph'];
|
|
224
224
|
const prefixes = ['GET:/profiles/username/', 'GET:/profiles/resolve'];
|
|
225
225
|
for (const id of targetUserIds) {
|
|
226
|
-
|
|
226
|
+
const user = (0, identityCacheSweep_1.oxyUserByIdPath)(id);
|
|
227
|
+
keys.push(`GET:${user}/follow-status`);
|
|
227
228
|
// Profiles embed the viewer-relative `relationship`.
|
|
228
|
-
keys.push(
|
|
229
|
+
keys.push((0, identityCacheSweep_1.oxyUserByIdCacheKey)(id));
|
|
229
230
|
// The target gained or lost a follower, and "followers you know" with it.
|
|
230
|
-
prefixes.push(`GET
|
|
231
|
+
prefixes.push(`GET:${user}/followers`, `GET:${user}/mutuals`);
|
|
231
232
|
}
|
|
232
233
|
// The viewer's own following list changed.
|
|
233
234
|
const viewerId = this.ctx.oxy.session.userId;
|
|
234
235
|
if (viewerId)
|
|
235
|
-
prefixes.push(`GET
|
|
236
|
+
prefixes.push(`GET:${(0, identityCacheSweep_1.oxyUserByIdPath)(viewerId)}/following`);
|
|
236
237
|
this.ctx.http.invalidateCache({ keys, prefixes });
|
|
237
238
|
}
|
|
238
239
|
}
|
package/dist/cjs/api/users.js
CHANGED
|
@@ -62,7 +62,7 @@ class UsersApi {
|
|
|
62
62
|
* registry-fresh read that neither serves nor overwrites a cached entry.
|
|
63
63
|
*/
|
|
64
64
|
async get(userId, options) {
|
|
65
|
-
const user = await this.ctx.request('GET',
|
|
65
|
+
const user = await this.ctx.request('GET', (0, identityCacheSweep_1.oxyUserByIdPath)(userId), undefined, {
|
|
66
66
|
cache: options?.cache ?? true,
|
|
67
67
|
cacheTTL: PROFILE_TTL,
|
|
68
68
|
});
|
package/dist/cjs/crypto/aead.js
CHANGED
|
@@ -27,7 +27,7 @@ exports.decryptAead = decryptAead;
|
|
|
27
27
|
// Loading the polyfill guarantees `globalThis.crypto.getRandomValues` exists on
|
|
28
28
|
// every platform (native crypto on web/Node; expo-crypto-backed shim on RN).
|
|
29
29
|
require("./polyfill");
|
|
30
|
-
const
|
|
30
|
+
const chacha_js_1 = require("@noble/ciphers/chacha.js");
|
|
31
31
|
/** Key length for XChaCha20-Poly1305, in bytes (256-bit). */
|
|
32
32
|
exports.AEAD_KEY_LENGTH = 32;
|
|
33
33
|
/** Nonce length for XChaCha20-Poly1305, in bytes (192-bit). */
|
|
@@ -55,7 +55,7 @@ function randomNonce() {
|
|
|
55
55
|
function encryptAead(key, plaintext, aad) {
|
|
56
56
|
assertKey(key);
|
|
57
57
|
const nonce = randomNonce();
|
|
58
|
-
const ciphertext = (0,
|
|
58
|
+
const ciphertext = (0, chacha_js_1.xchacha20poly1305)(key, nonce, aad).encrypt(plaintext);
|
|
59
59
|
return { nonce, ciphertext };
|
|
60
60
|
}
|
|
61
61
|
/**
|
|
@@ -75,5 +75,5 @@ function decryptAead(key, nonce, ciphertext, aad) {
|
|
|
75
75
|
if (nonce.length !== exports.AEAD_NONCE_LENGTH) {
|
|
76
76
|
throw new Error(`AEAD nonce must be ${exports.AEAD_NONCE_LENGTH} bytes, got ${nonce.length}`);
|
|
77
77
|
}
|
|
78
|
-
return (0,
|
|
78
|
+
return (0, chacha_js_1.xchacha20poly1305)(key, nonce, aad).decrypt(ciphertext);
|
|
79
79
|
}
|
|
@@ -9,14 +9,14 @@ exports.createContentHasher = createContentHasher;
|
|
|
9
9
|
* directly: `@noble/hashes` must load after this entry's polyfill, and through
|
|
10
10
|
* the ONE lazy root, so it never lands in an app's startup JavaScript.
|
|
11
11
|
*/
|
|
12
|
-
const
|
|
13
|
-
const
|
|
12
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
13
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
14
14
|
function createContentHasher() {
|
|
15
|
-
const hash =
|
|
15
|
+
const hash = sha2_js_1.sha256.create();
|
|
16
16
|
return {
|
|
17
17
|
update: (chunk) => {
|
|
18
18
|
hash.update(chunk);
|
|
19
19
|
},
|
|
20
|
-
digestHex: () => (0,
|
|
20
|
+
digestHex: () => (0, utils_js_1.bytesToHex)(hash.digest()),
|
|
21
21
|
};
|
|
22
22
|
}
|
|
@@ -17,8 +17,8 @@ exports.deriveScopedSeedFromKey = deriveScopedSeedFromKey;
|
|
|
17
17
|
exports.deriveSocialReceiveKey = deriveSocialReceiveKey;
|
|
18
18
|
exports.signSocialReceiveDigest = signSocialReceiveDigest;
|
|
19
19
|
exports.authChallengeDigest = authChallengeDigest;
|
|
20
|
-
const
|
|
21
|
-
const
|
|
20
|
+
const hmac_js_1 = require("@noble/hashes/hmac.js");
|
|
21
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
22
22
|
const secp256k1_1 = require("@oxy.so/protocol/secp256k1");
|
|
23
23
|
const kdf_1 = require("./kdf");
|
|
24
24
|
/**
|
|
@@ -73,11 +73,11 @@ function deriveSocialReceiveKey(privateKeyHex, index) {
|
|
|
73
73
|
}
|
|
74
74
|
const privateKey = (0, secp256k1_1.normalizeSecp256k1PrivateKey)(privateKeyHex);
|
|
75
75
|
const parentPublic = hexToBytes((0, secp256k1_1.deriveSecp256k1PublicKey)(privateKey, true));
|
|
76
|
-
const chainCode = (0,
|
|
76
|
+
const chainCode = (0, hmac_js_1.hmac)(sha2_js_1.sha256, utf8(exports.SOCIAL_RECEIVE_CHAIN_CODE_KEY), parentPublic);
|
|
77
77
|
const data = new Uint8Array(37);
|
|
78
78
|
data.set(parentPublic, 0);
|
|
79
79
|
new DataView(data.buffer).setUint32(33, index, false);
|
|
80
|
-
const i = (0,
|
|
80
|
+
const i = (0, hmac_js_1.hmac)(sha2_js_1.sha512, chainCode, data);
|
|
81
81
|
const childPrivate = (0, secp256k1_1.tweakAddSecp256k1PrivateKey)(privateKey, bytesToHex(i.slice(0, 32)));
|
|
82
82
|
return { privateKey: childPrivate, publicKey: (0, secp256k1_1.deriveSecp256k1PublicKey)(childPrivate, true) };
|
|
83
83
|
}
|
|
@@ -101,5 +101,5 @@ function signSocialReceiveDigest(privateKeyHex, index, digestHex) {
|
|
|
101
101
|
* format is the one `POST /auth/verify` checks, unchanged.
|
|
102
102
|
*/
|
|
103
103
|
function authChallengeDigest(publicKey, challenge, timestamp) {
|
|
104
|
-
return bytesToHex((0,
|
|
104
|
+
return bytesToHex((0, sha2_js_1.sha256)(utf8(`auth:${publicKey}:${challenge}:${timestamp}`)));
|
|
105
105
|
}
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
*/
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.deriveIdentityLinkCode = deriveIdentityLinkCode;
|
|
11
|
-
const
|
|
12
|
-
const
|
|
11
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
12
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
13
13
|
const DOMAIN = 'oxy-identity-link-code/v1';
|
|
14
14
|
function deriveIdentityLinkCode(linkId, publicKey) {
|
|
15
|
-
const digest = (0,
|
|
15
|
+
const digest = (0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)(`${DOMAIN}|${linkId}|${publicKey.trim().toLowerCase()}`));
|
|
16
16
|
const value = ((digest[0] << 24) | (digest[1] << 16) | (digest[2] << 8) | digest[3]) >>> 0;
|
|
17
17
|
return String(value % 1000000).padStart(6, '0');
|
|
18
18
|
}
|
|
@@ -10,13 +10,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
10
10
|
exports.digestIdentityPayload = digestIdentityPayload;
|
|
11
11
|
exports.signIdentityProof = signIdentityProof;
|
|
12
12
|
require("./polyfill");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
14
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
15
15
|
const sign_1 = require("@oxy.so/protocol/sign");
|
|
16
16
|
const client_1 = require("@oxy.so/contracts/client");
|
|
17
17
|
/** SHA-256 hex of the canonical JSON of `payload` — the `payloadDigest` claim. */
|
|
18
18
|
function digestIdentityPayload(payload) {
|
|
19
|
-
return (0,
|
|
19
|
+
return (0, utils_js_1.bytesToHex)((0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)((0, client_1.canonicalJson)(payload))));
|
|
20
20
|
}
|
|
21
21
|
/** Sign `claims` with the root, producing the proof as it travels. */
|
|
22
22
|
async function signIdentityProof(identity, claims) {
|
package/dist/cjs/crypto/index.js
CHANGED
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
*/
|
|
14
14
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
15
|
exports.verifySignature = exports.signMessage = exports.loadCommonsIdentityBridge = exports.canonicalize = exports.createContentHasher = exports.solveRegistrationPow = exports.deriveIdentityLinkCode = exports.signIdentityProof = exports.digestIdentityPayload = exports.authChallengeDigest = exports.signSocialReceiveDigest = exports.deriveSocialReceiveKey = exports.deriveScopedSeedFromKey = exports.MAX_SOCIAL_RECEIVE_INDEX = exports.SOCIAL_RECEIVE_CHAIN_CODE_KEY = exports.SCOPED_SEED_KDF_SALT = exports.deriveSharedSecret = exports.AEAD_NONCE_LENGTH = exports.AEAD_KEY_LENGTH = exports.decryptAead = exports.encryptAead = exports.hkdfSha256 = exports.BACKUP_KDF_ENCRYPTION_INFO = exports.RecoveryPhraseService = exports.SignatureService = exports.updateIdentityMarker = exports.readIdentityMarker = exports.IdentityUnavailableError = exports.IdentityPersistError = exports.IdentityAlreadyExistsError = exports.KeyManager = void 0;
|
|
16
|
-
// MUST stay the first import:
|
|
17
|
-
//
|
|
16
|
+
// MUST stay the first import: the shim has to exist before any module below
|
|
17
|
+
// evaluates or draws randomness (see `./polyfill`).
|
|
18
18
|
require("./polyfill");
|
|
19
19
|
var keyManager_1 = require("./keyManager");
|
|
20
20
|
Object.defineProperty(exports, "KeyManager", { enumerable: true, get: function () { return keyManager_1.KeyManager; } });
|
package/dist/cjs/crypto/kdf.js
CHANGED
|
@@ -12,8 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
14
|
exports.hkdfSha256 = hkdfSha256;
|
|
15
|
-
const
|
|
16
|
-
const
|
|
15
|
+
const hkdf_js_1 = require("@noble/hashes/hkdf.js");
|
|
16
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
17
17
|
/**
|
|
18
18
|
* Derive `length` bytes of keying material from `ikm` using HKDF-SHA256
|
|
19
19
|
* (RFC 5869 — extract-then-expand).
|
|
@@ -35,5 +35,5 @@ function hkdfSha256(ikm, salt, info, length) {
|
|
|
35
35
|
if (length > 255 * 32) {
|
|
36
36
|
throw new Error('hkdfSha256: length must not exceed 8160 bytes (255 * 32)');
|
|
37
37
|
}
|
|
38
|
-
return (0,
|
|
38
|
+
return (0, hkdf_js_1.hkdf)(sha2_js_1.sha256, ikm, salt, info, length);
|
|
39
39
|
}
|
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
* global WebCrypto, and a `require('node:crypto')` here made web bundlers ship
|
|
19
19
|
* Node's crypto, stream and buffer polyfills (~600 KB) to every browser.
|
|
20
20
|
*
|
|
21
|
-
* # Evaluation order — this module must import NOTHING that
|
|
21
|
+
* # Evaluation order — this module must import NOTHING that reaches a crypto library
|
|
22
22
|
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
* on
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
* to `buffer` and `@oxy.so/protocol/random`,
|
|
33
|
-
* and `index.ts` imports this file first.
|
|
34
|
-
* guards both halves.
|
|
23
|
+
* ES imports are evaluated before the importing module's body, so every module
|
|
24
|
+
* this file imports runs BEFORE the shim below is installed. This file used to
|
|
25
|
+
* import `@oxy.so/protocol`'s root entry, which reaches `@noble/curves` →
|
|
26
|
+
* `@noble/hashes` through the envelope signer, and `@noble/hashes` 1.x read
|
|
27
|
+
* `globalThis.crypto` once, at evaluation: on Hermes (no `globalThis.crypto` at
|
|
28
|
+
* startup) it captured `undefined` before the shim existed, and every identity
|
|
29
|
+
* creation on Android failed with `crypto.getRandomValues must be defined`.
|
|
30
|
+
* Noble 2.x reads the global on every call, so that capture is gone, but the
|
|
31
|
+
* shim still has to exist before any module body that reads it runs. Its
|
|
32
|
+
* imports are therefore limited to `buffer` and `@oxy.so/protocol/random`,
|
|
33
|
+
* both free of crypto libraries, and `index.ts` imports this file first.
|
|
34
|
+
* `__tests__/polyfillOrder.test.ts` guards both halves.
|
|
35
35
|
*
|
|
36
36
|
*/
|
|
37
37
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
exports.RecoveryPhraseService = exports.BACKUP_MATERIAL_LENGTH = exports.BACKUP_KDF_LOOKUP_INFO = exports.BACKUP_KDF_ENCRYPTION_INFO = exports.BACKUP_KDF_SALT = void 0;
|
|
18
18
|
const bip39_1 = require("@scure/bip39");
|
|
19
|
-
const
|
|
19
|
+
const english_js_1 = require("@scure/bip39/wordlists/english.js");
|
|
20
20
|
const keyManager_1 = require("./keyManager");
|
|
21
21
|
const kdf_1 = require("./kdf");
|
|
22
22
|
/**
|
|
@@ -59,7 +59,7 @@ class RecoveryPhraseService {
|
|
|
59
59
|
*/
|
|
60
60
|
static async generateIdentityWithRecovery(options) {
|
|
61
61
|
// Generate 128-bit entropy for 12-word mnemonic
|
|
62
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
62
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 128);
|
|
63
63
|
// Derive private key from mnemonic
|
|
64
64
|
// Using the seed directly as the private key (simplified approach)
|
|
65
65
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
@@ -83,7 +83,7 @@ class RecoveryPhraseService {
|
|
|
83
83
|
*/
|
|
84
84
|
static async generateIdentityWithRecovery24(options) {
|
|
85
85
|
// Generate 256-bit entropy for 24-word mnemonic
|
|
86
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
86
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 256);
|
|
87
87
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
88
88
|
const privateKeyHex = toHex(seed.subarray(0, 32));
|
|
89
89
|
const publicKey = await keyManager_1.KeyManager.importKeyPair(privateKeyHex, {
|
|
@@ -109,7 +109,7 @@ class RecoveryPhraseService {
|
|
|
109
109
|
* committed anywhere — if it is lost the account becomes unrecoverable.
|
|
110
110
|
*/
|
|
111
111
|
static async derivePendingIdentity() {
|
|
112
|
-
const mnemonic = (0, bip39_1.generateMnemonic)(
|
|
112
|
+
const mnemonic = (0, bip39_1.generateMnemonic)(english_js_1.wordlist, 128);
|
|
113
113
|
const seed = await (0, bip39_1.mnemonicToSeed)(mnemonic);
|
|
114
114
|
const privateKey = toHex(seed.subarray(0, 32));
|
|
115
115
|
const publicKey = keyManager_1.KeyManager.derivePublicKey(privateKey);
|
|
@@ -130,7 +130,7 @@ class RecoveryPhraseService {
|
|
|
130
130
|
*/
|
|
131
131
|
static async derivePrivateKeyFromPhrase(phrase) {
|
|
132
132
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
133
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
133
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
134
134
|
throw new Error('Invalid recovery phrase');
|
|
135
135
|
}
|
|
136
136
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -155,7 +155,7 @@ class RecoveryPhraseService {
|
|
|
155
155
|
*/
|
|
156
156
|
static async deriveBackupMaterial(phrase) {
|
|
157
157
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
158
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
158
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
159
159
|
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
160
160
|
}
|
|
161
161
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -175,7 +175,7 @@ class RecoveryPhraseService {
|
|
|
175
175
|
static async restoreFromPhrase(phrase, options) {
|
|
176
176
|
// Normalize and validate the phrase
|
|
177
177
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
178
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
178
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
179
179
|
throw new Error('Invalid recovery phrase. Please check the words and try again.');
|
|
180
180
|
}
|
|
181
181
|
// Derive the same private key from the mnemonic
|
|
@@ -192,26 +192,26 @@ class RecoveryPhraseService {
|
|
|
192
192
|
*/
|
|
193
193
|
static validatePhrase(phrase) {
|
|
194
194
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
195
|
-
return (0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
195
|
+
return (0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist);
|
|
196
196
|
}
|
|
197
197
|
/**
|
|
198
198
|
* Get the word list for autocomplete/validation
|
|
199
199
|
*/
|
|
200
200
|
static getWordList() {
|
|
201
|
-
return
|
|
201
|
+
return english_js_1.wordlist;
|
|
202
202
|
}
|
|
203
203
|
/**
|
|
204
204
|
* Check if a word is valid in the BIP39 word list
|
|
205
205
|
*/
|
|
206
206
|
static isValidWord(word) {
|
|
207
|
-
return
|
|
207
|
+
return english_js_1.wordlist.includes(word.toLowerCase());
|
|
208
208
|
}
|
|
209
209
|
/**
|
|
210
210
|
* Get suggestions for a partial word
|
|
211
211
|
*/
|
|
212
212
|
static getSuggestions(partial, limit = 5) {
|
|
213
213
|
const lowerPartial = partial.toLowerCase();
|
|
214
|
-
return
|
|
214
|
+
return english_js_1.wordlist.filter((word) => word.startsWith(lowerPartial)).slice(0, limit);
|
|
215
215
|
}
|
|
216
216
|
/**
|
|
217
217
|
* Derive the public key from a phrase without storing
|
|
@@ -219,7 +219,7 @@ class RecoveryPhraseService {
|
|
|
219
219
|
*/
|
|
220
220
|
static async derivePublicKeyFromPhrase(phrase) {
|
|
221
221
|
const normalizedPhrase = phrase.trim().toLowerCase();
|
|
222
|
-
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase,
|
|
222
|
+
if (!(0, bip39_1.validateMnemonic)(normalizedPhrase, english_js_1.wordlist)) {
|
|
223
223
|
throw new Error('Invalid recovery phrase');
|
|
224
224
|
}
|
|
225
225
|
const seed = await (0, bip39_1.mnemonicToSeed)(normalizedPhrase);
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
11
|
exports.solveRegistrationPow = solveRegistrationPow;
|
|
12
12
|
require("./polyfill");
|
|
13
|
-
const
|
|
14
|
-
const
|
|
13
|
+
const sha2_js_1 = require("@noble/hashes/sha2.js");
|
|
14
|
+
const utils_js_1 = require("@noble/hashes/utils.js");
|
|
15
15
|
const protocol_1 = require("@oxy.so/protocol");
|
|
16
16
|
/**
|
|
17
17
|
* How many attempts the grind loop runs before yielding to the event loop.
|
|
@@ -31,7 +31,7 @@ function yieldToEventLoop() {
|
|
|
31
31
|
* Grind a nonce for `publicKey`/`timestamp` that clears
|
|
32
32
|
* {@link REGISTRATION_POW_DIFFICULTY_BITS}, returned as a decimal counter.
|
|
33
33
|
*
|
|
34
|
-
* Hashes with `@noble/hashes/sha256` — pure JS, synchronous, identical output
|
|
34
|
+
* Hashes with `@noble/hashes/sha2.js`'s `sha256` — pure JS, synchronous, identical output
|
|
35
35
|
* on web/Node/React Native with no native module and no per-attempt bridge
|
|
36
36
|
* crossing (see the difficulty constant's own doc for why that distinction is
|
|
37
37
|
* the whole point). Nonces are sequential (0, 1, 2, …) rather than random: the
|
|
@@ -42,7 +42,7 @@ function yieldToEventLoop() {
|
|
|
42
42
|
async function solveRegistrationPow(publicKey, timestamp) {
|
|
43
43
|
for (let nonce = 0;; nonce += 1) {
|
|
44
44
|
const candidate = String(nonce);
|
|
45
|
-
const digest = (0,
|
|
45
|
+
const digest = (0, utils_js_1.bytesToHex)((0, sha2_js_1.sha256)((0, utils_js_1.utf8ToBytes)((0, protocol_1.registrationPowMessage)(publicKey, timestamp, candidate))));
|
|
46
46
|
if ((0, protocol_1.meetsRegistrationPowDifficulty)(digest, protocol_1.REGISTRATION_POW_DIFFICULTY_BITS)) {
|
|
47
47
|
return candidate;
|
|
48
48
|
}
|