keychat-save 1.1.0 → 1.2.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/index.mjs +42 -2
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -21,10 +21,12 @@ import { join } from 'node:path'
|
|
|
21
21
|
|
|
22
22
|
const CONFIG_DIR = join(homedir(), '.keychat')
|
|
23
23
|
const WIF_PATH = join(CONFIG_DIR, 'identity.wif')
|
|
24
|
+
const INDEX_PATH = join(CONFIG_DIR, 'saves-index.md')
|
|
24
25
|
const BRIDGE = 'https://www.keychat.pro/api/bridge'
|
|
25
26
|
const SAVE_PREFIX = '4b534156' // "KSAV"
|
|
26
27
|
const VERSION = '01'
|
|
27
28
|
const SUB_UNIT_SATS = 125
|
|
29
|
+
const INDEX_MARKER = '\n\n## __SAVES_INDEX__\n'
|
|
28
30
|
|
|
29
31
|
// ── crypto ───────────────────────────────────────────────────────
|
|
30
32
|
function bytesToHex (bytes) {
|
|
@@ -147,7 +149,13 @@ async function cmdSave (label, body) {
|
|
|
147
149
|
const address = key.toPublicKey().toAddress()
|
|
148
150
|
const pubHex = key.toPublicKey().toString()
|
|
149
151
|
|
|
150
|
-
|
|
152
|
+
// Bundle the local saves index into every save body so any single save
|
|
153
|
+
// bootstraps the full chain on a fresh device.
|
|
154
|
+
let index = ''
|
|
155
|
+
try { index = readFileSync(INDEX_PATH, 'utf8') } catch {}
|
|
156
|
+
const fullBody = body + INDEX_MARKER + index
|
|
157
|
+
|
|
158
|
+
const envelope = JSON.stringify({ kv: 1, kind: 'save', label, body: fullBody })
|
|
151
159
|
const encrypted = encrypt(envelope, key, pubHex)
|
|
152
160
|
const cipherHex = bytesToHex(encrypted)
|
|
153
161
|
const timestamp = Math.floor(Date.now() / 1000).toString(16).padStart(8, '0')
|
|
@@ -187,6 +195,21 @@ async function cmdSave (label, body) {
|
|
|
187
195
|
await tx.sign()
|
|
188
196
|
|
|
189
197
|
const txid = await broadcast(tx.toHex())
|
|
198
|
+
|
|
199
|
+
// Prepend new entry to local saves index
|
|
200
|
+
const date = new Date().toISOString().slice(0, 10)
|
|
201
|
+
const computeCost = (totalCost / 500).toString()
|
|
202
|
+
const newRow = `| ${date} | ${label} | ${txid} | ${computeCost}C |\n`
|
|
203
|
+
let header = '# KeyChat saves index\n\n| Date | Label | TxID | Cost |\n|------|-------|------|------|\n'
|
|
204
|
+
let existing = ''
|
|
205
|
+
try {
|
|
206
|
+
const cur = readFileSync(INDEX_PATH, 'utf8')
|
|
207
|
+
// Strip header if present, keep existing rows
|
|
208
|
+
const tableStart = cur.indexOf('|------|-------|------|------|')
|
|
209
|
+
existing = tableStart >= 0 ? cur.slice(tableStart + '|------|-------|------|------|'.length).trim() + '\n' : cur
|
|
210
|
+
} catch {}
|
|
211
|
+
writeFileSync(INDEX_PATH, header + newRow + existing, { mode: 0o600 })
|
|
212
|
+
|
|
190
213
|
console.log(`Saved to chain!`)
|
|
191
214
|
console.log(` Label: ${label}`)
|
|
192
215
|
console.log(` Size: ${tx.toHex().length / 2} bytes`)
|
|
@@ -215,8 +238,25 @@ async function cmdLoadByTxid (txid) {
|
|
|
215
238
|
const env = JSON.parse(decrypted)
|
|
216
239
|
if (env.kind === 'save') { label = env.label || 'Untitled'; body = env.body || '' }
|
|
217
240
|
} catch {}
|
|
241
|
+
|
|
242
|
+
// Extract embedded saves index. Only write to local file if local is
|
|
243
|
+
// missing (fresh device bootstrap). Existing local index is left alone
|
|
244
|
+
// so loading an older save can't wipe out newer entries.
|
|
245
|
+
const idx = body.indexOf(INDEX_MARKER)
|
|
246
|
+
let userBody = body
|
|
247
|
+
if (idx >= 0) {
|
|
248
|
+
userBody = body.slice(0, idx)
|
|
249
|
+
const embeddedIndex = body.slice(idx + INDEX_MARKER.length).trim()
|
|
250
|
+
if (embeddedIndex && !existsSync(INDEX_PATH)) {
|
|
251
|
+
try {
|
|
252
|
+
writeFileSync(INDEX_PATH, embeddedIndex + '\n', { mode: 0o600 })
|
|
253
|
+
console.error(`(restored saves index to ${INDEX_PATH})`)
|
|
254
|
+
} catch {}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
218
258
|
console.log(`[${label}] — ${new Date(parseInt(tsHex, 16) * 1000).toLocaleString()}`)
|
|
219
|
-
console.log(
|
|
259
|
+
console.log(userBody)
|
|
220
260
|
}
|
|
221
261
|
|
|
222
262
|
async function cmdLoad (opts = {}) {
|