@morseai/sdk 0.1.0-beta.6 → 0.1.0-beta.8
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/README.md +1 -1
- package/dist/index.d.mts +10 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.js +85 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +85 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
|
|
7
7
|
TypeScript SDK for creating and accessing encrypted signals in the MORSE platform.
|
|
8
8
|
|
|
9
|
-
**Version:** 0.1.0-beta.
|
|
9
|
+
**Version:** 0.1.0-beta.8 (Beta Release)
|
|
10
10
|
|
|
11
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.
|
|
12
12
|
|
package/dist/index.d.mts
CHANGED
|
@@ -73,6 +73,16 @@ interface CreateSignalOptionsEncrypted {
|
|
|
73
73
|
enabled: boolean;
|
|
74
74
|
network: string;
|
|
75
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* Domain for key derivation (optional, defaults to "morseai.tech")
|
|
78
|
+
* Should match the domain used when opening the signal
|
|
79
|
+
*/
|
|
80
|
+
domain?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Chain ID for key derivation (optional, defaults to 8453 for Base)
|
|
83
|
+
* Should match the chain ID used when opening the signal
|
|
84
|
+
*/
|
|
85
|
+
chainId?: number;
|
|
76
86
|
/**
|
|
77
87
|
* Specific expiration date and time (ISO 8601 format).
|
|
78
88
|
* Use this for custom expiration dates.
|
package/dist/index.d.ts
CHANGED
|
@@ -73,6 +73,16 @@ interface CreateSignalOptionsEncrypted {
|
|
|
73
73
|
enabled: boolean;
|
|
74
74
|
network: string;
|
|
75
75
|
};
|
|
76
|
+
/**
|
|
77
|
+
* Domain for key derivation (optional, defaults to "morseai.tech")
|
|
78
|
+
* Should match the domain used when opening the signal
|
|
79
|
+
*/
|
|
80
|
+
domain?: string;
|
|
81
|
+
/**
|
|
82
|
+
* Chain ID for key derivation (optional, defaults to 8453 for Base)
|
|
83
|
+
* Should match the chain ID used when opening the signal
|
|
84
|
+
*/
|
|
85
|
+
chainId?: number;
|
|
76
86
|
/**
|
|
77
87
|
* Specific expiration date and time (ISO 8601 format).
|
|
78
88
|
* Use this for custom expiration dates.
|
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);
|
|
@@ -1249,7 +1298,36 @@ var MorseSDKV1 = class {
|
|
|
1249
1298
|
}
|
|
1250
1299
|
async createPrivateSignalEncrypted(wallet, options) {
|
|
1251
1300
|
const key = await generateKey();
|
|
1252
|
-
await exportKey(key);
|
|
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 = options.domain || "morseai.tech";
|
|
1319
|
+
const chainId = options.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,10 +1363,13 @@ 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
1375
|
const shareableLink = generateShareableLink(FRONTEND_BASE_URL, result.signalId);
|