@morseai/sdk 0.1.0-beta.5 → 0.1.0-beta.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.
- package/LICENSE +22 -0
- package/README.md +5 -1
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +86 -7
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -7
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 MORSE Team
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
22
|
+
|
package/README.md
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
1
|
# MORSE SDK
|
|
2
2
|
|
|
3
|
+
[](https://badge.fury.io/js/%40morseai%2Fsdk)
|
|
4
|
+
[](https://opensource.org/licenses/MIT)
|
|
5
|
+
[](https://www.typescriptlang.org/)
|
|
6
|
+
|
|
3
7
|
TypeScript SDK for creating and accessing encrypted signals in the MORSE platform.
|
|
4
8
|
|
|
5
|
-
**Version:** 0.1.0-beta.
|
|
9
|
+
**Version:** 0.1.0-beta.7 (Beta Release)
|
|
6
10
|
|
|
7
11
|
> ⚠️ **Beta Notice**: This is a beta release. The API is stable but may have minor changes before the 1.0.0 release. Please report any issues you encounter.
|
|
8
12
|
|
package/dist/index.d.mts
CHANGED
|
@@ -103,7 +103,7 @@ interface CreateSignalResponse {
|
|
|
103
103
|
expiresAt: string;
|
|
104
104
|
}
|
|
105
105
|
interface CreateSignalResponseEncrypted extends CreateSignalResponse {
|
|
106
|
-
keyBase64
|
|
106
|
+
keyBase64?: string;
|
|
107
107
|
shareableLink: string;
|
|
108
108
|
}
|
|
109
109
|
interface OpenSignalResponse {
|
|
@@ -378,7 +378,7 @@ declare function getSignalUrl(baseUrl: string, signalId: string, keyBase64?: str
|
|
|
378
378
|
declare function extractSignalIdFromUrl(url: string): string | null;
|
|
379
379
|
|
|
380
380
|
declare function getCipherVersion(): string;
|
|
381
|
-
declare function generateShareableLink(baseUrl: string, signalId: string, keyBase64
|
|
381
|
+
declare function generateShareableLink(baseUrl: string, signalId: string, keyBase64?: string): string;
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
384
|
* MORSE SDK - X25519 + XChaCha20-Poly1305 Encryption
|
package/dist/index.d.ts
CHANGED
|
@@ -103,7 +103,7 @@ interface CreateSignalResponse {
|
|
|
103
103
|
expiresAt: string;
|
|
104
104
|
}
|
|
105
105
|
interface CreateSignalResponseEncrypted extends CreateSignalResponse {
|
|
106
|
-
keyBase64
|
|
106
|
+
keyBase64?: string;
|
|
107
107
|
shareableLink: string;
|
|
108
108
|
}
|
|
109
109
|
interface OpenSignalResponse {
|
|
@@ -378,7 +378,7 @@ declare function getSignalUrl(baseUrl: string, signalId: string, keyBase64?: str
|
|
|
378
378
|
declare function extractSignalIdFromUrl(url: string): string | null;
|
|
379
379
|
|
|
380
380
|
declare function getCipherVersion(): string;
|
|
381
|
-
declare function generateShareableLink(baseUrl: string, signalId: string, keyBase64
|
|
381
|
+
declare function generateShareableLink(baseUrl: string, signalId: string, keyBase64?: string): string;
|
|
382
382
|
|
|
383
383
|
/**
|
|
384
384
|
* MORSE SDK - X25519 + XChaCha20-Poly1305 Encryption
|
package/dist/index.js
CHANGED
|
@@ -32,6 +32,7 @@ __export(crypto_x25519_exports, {
|
|
|
32
32
|
deriveKeyPairFromWalletSignature: () => deriveKeyPairFromWalletSignature,
|
|
33
33
|
generateSignalId: () => generateSignalId,
|
|
34
34
|
openSharedSignal: () => openSharedSignal,
|
|
35
|
+
sealDataKey: () => sealDataKey,
|
|
35
36
|
verifyKeyCertificate: () => verifyKeyCertificate
|
|
36
37
|
});
|
|
37
38
|
async function getSodium() {
|
|
@@ -291,6 +292,54 @@ async function openSharedSignal(encryptedPayloadBase64, payloadNonceBase64, seal
|
|
|
291
292
|
);
|
|
292
293
|
return payload;
|
|
293
294
|
}
|
|
295
|
+
async function sealDataKey(dataKeyBytes, walletTarget, walletCreator, expiresAt, signalId, domain, chainId, signMessage) {
|
|
296
|
+
await getSodium();
|
|
297
|
+
const senderKeypair = sodium.crypto_box_keypair();
|
|
298
|
+
const recipientKeypair = await deriveKeyPairFromWalletSignature(
|
|
299
|
+
walletTarget,
|
|
300
|
+
domain,
|
|
301
|
+
chainId,
|
|
302
|
+
signMessage
|
|
303
|
+
);
|
|
304
|
+
const recipientPubKey = recipientKeypair.publicKey;
|
|
305
|
+
const sharedSecret = sodium.crypto_scalarmult(
|
|
306
|
+
senderKeypair.privateKey,
|
|
307
|
+
recipientPubKey
|
|
308
|
+
);
|
|
309
|
+
const salt = `MORSE_SEAL_${signalId}_v1`;
|
|
310
|
+
const info = "wrap_datakey";
|
|
311
|
+
const wrappingKey = await hkdfSha256(sharedSecret, salt, info, 32);
|
|
312
|
+
const sealedNonce = sodium.randombytes_buf(sodium.crypto_aead_xchacha20poly1305_ietf_NPUBBYTES);
|
|
313
|
+
const expiresAtInt = Math.floor(Number(expiresAt));
|
|
314
|
+
const abiCoder = ethers.ethers.AbiCoder.defaultAbiCoder();
|
|
315
|
+
const senderEphemeralPubKeyHex = ethers.ethers.zeroPadValue(ethers.ethers.hexlify(senderKeypair.publicKey), 32);
|
|
316
|
+
const aad = abiCoder.encode(
|
|
317
|
+
["string", "address", "address", "uint64", "string", "bytes32"],
|
|
318
|
+
[
|
|
319
|
+
signalId,
|
|
320
|
+
walletTarget.toLowerCase(),
|
|
321
|
+
walletCreator.toLowerCase(),
|
|
322
|
+
expiresAtInt,
|
|
323
|
+
exports.X25519_CIPHER_VERSION,
|
|
324
|
+
senderEphemeralPubKeyHex
|
|
325
|
+
]
|
|
326
|
+
);
|
|
327
|
+
const aadBytes = ethers.ethers.getBytes(aad);
|
|
328
|
+
const aadHash = ethers.ethers.keccak256(aad).slice(2);
|
|
329
|
+
const sealedDataKey = sodium.crypto_aead_xchacha20poly1305_ietf_encrypt(
|
|
330
|
+
dataKeyBytes,
|
|
331
|
+
aadBytes,
|
|
332
|
+
null,
|
|
333
|
+
sealedNonce,
|
|
334
|
+
wrappingKey
|
|
335
|
+
);
|
|
336
|
+
return {
|
|
337
|
+
sealedDataKey: Buffer.from(sealedDataKey).toString("base64"),
|
|
338
|
+
sealedNonce: Buffer.from(sealedNonce).toString("base64"),
|
|
339
|
+
senderEphemeralPublicKey: Buffer.from(senderKeypair.publicKey).toString("base64"),
|
|
340
|
+
aadHash
|
|
341
|
+
};
|
|
342
|
+
}
|
|
294
343
|
function generateSignalId() {
|
|
295
344
|
const bytes = new Uint8Array(16);
|
|
296
345
|
globalThis.crypto.getRandomValues(bytes);
|
|
@@ -628,7 +677,7 @@ async function decryptFile(encryptedData, ivBase64, key) {
|
|
|
628
677
|
return decrypted;
|
|
629
678
|
}
|
|
630
679
|
function generateShareableLink(baseUrl, signalId, keyBase64) {
|
|
631
|
-
return `${baseUrl}/view/${signalId}
|
|
680
|
+
return `${baseUrl}/view/${signalId}`;
|
|
632
681
|
}
|
|
633
682
|
|
|
634
683
|
// src/implementations/v1/MorseSDKV1.ts
|
|
@@ -1250,6 +1299,35 @@ var MorseSDKV1 = class {
|
|
|
1250
1299
|
async createPrivateSignalEncrypted(wallet, options) {
|
|
1251
1300
|
const key = await generateKey();
|
|
1252
1301
|
const keyBase64 = await exportKey(key);
|
|
1302
|
+
const signalId = options.signalId || generateSignalId();
|
|
1303
|
+
let expiresAtMs;
|
|
1304
|
+
if (options.expiresAt) {
|
|
1305
|
+
expiresAtMs = new Date(options.expiresAt).getTime();
|
|
1306
|
+
} else if (options.expiresIn) {
|
|
1307
|
+
const match = options.expiresIn.match(/^(\d+)([smhd])$/);
|
|
1308
|
+
if (!match) throw new Error("Invalid expiresIn format");
|
|
1309
|
+
const value = parseInt(match[1], 10);
|
|
1310
|
+
const unit = match[2];
|
|
1311
|
+
const multipliers = { s: 1e3, m: 6e4, h: 36e5, d: 864e5 };
|
|
1312
|
+
expiresAtMs = Date.now() + value * multipliers[unit];
|
|
1313
|
+
} else {
|
|
1314
|
+
expiresAtMs = Date.now() + 24 * 60 * 60 * 1e3;
|
|
1315
|
+
}
|
|
1316
|
+
const walletTarget = wallet.address;
|
|
1317
|
+
const walletCreator = wallet.address;
|
|
1318
|
+
const domain = "morse.app";
|
|
1319
|
+
const chainId = 8453;
|
|
1320
|
+
const keyBytes = this.base64ToUint8Array(keyBase64);
|
|
1321
|
+
const sealedBox = await sealDataKey(
|
|
1322
|
+
keyBytes,
|
|
1323
|
+
walletTarget.toLowerCase(),
|
|
1324
|
+
walletCreator.toLowerCase(),
|
|
1325
|
+
expiresAtMs,
|
|
1326
|
+
signalId,
|
|
1327
|
+
domain,
|
|
1328
|
+
chainId,
|
|
1329
|
+
wallet.signMessage
|
|
1330
|
+
);
|
|
1253
1331
|
let encryptedText;
|
|
1254
1332
|
let payloadNonce;
|
|
1255
1333
|
let fileOptions;
|
|
@@ -1276,6 +1354,7 @@ var MorseSDKV1 = class {
|
|
|
1276
1354
|
};
|
|
1277
1355
|
}
|
|
1278
1356
|
const signalOptions = {
|
|
1357
|
+
signalId,
|
|
1279
1358
|
walletTarget: options.walletTarget,
|
|
1280
1359
|
shareWithRecipient: options.shareWithRecipient,
|
|
1281
1360
|
mode: options.mode,
|
|
@@ -1284,16 +1363,18 @@ var MorseSDKV1 = class {
|
|
|
1284
1363
|
cipherVersion: getCipherVersion(),
|
|
1285
1364
|
encryptedText,
|
|
1286
1365
|
payloadNonce,
|
|
1366
|
+
sealedDataKey: sealedBox.sealedDataKey,
|
|
1367
|
+
sealedNonce: sealedBox.sealedNonce,
|
|
1368
|
+
senderEphemeralPublicKey: sealedBox.senderEphemeralPublicKey,
|
|
1369
|
+
aadHash: sealedBox.aadHash,
|
|
1287
1370
|
file: fileOptions,
|
|
1288
1371
|
onChainNotification: options.onChainNotification,
|
|
1289
|
-
expiresAt:
|
|
1290
|
-
expiresIn: options.expiresIn
|
|
1372
|
+
expiresAt: new Date(expiresAtMs).toISOString()
|
|
1291
1373
|
};
|
|
1292
1374
|
const result = await this.createSignal(wallet, signalOptions);
|
|
1293
|
-
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId
|
|
1375
|
+
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId);
|
|
1294
1376
|
return {
|
|
1295
1377
|
...result,
|
|
1296
|
-
keyBase64,
|
|
1297
1378
|
shareableLink
|
|
1298
1379
|
};
|
|
1299
1380
|
}
|
|
@@ -1391,8 +1472,6 @@ var MorseSDKV1 = class {
|
|
|
1391
1472
|
const shareableLink = `${FRONTEND_BASE_URL}/view/${result.signalId}`;
|
|
1392
1473
|
return {
|
|
1393
1474
|
...result,
|
|
1394
|
-
keyBase64: "",
|
|
1395
|
-
// No key needed for X25519 signals
|
|
1396
1475
|
shareableLink
|
|
1397
1476
|
};
|
|
1398
1477
|
}
|