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.
Files changed (2) hide show
  1. package/index.mjs +42 -2
  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
- const envelope = JSON.stringify({ kv: 1, kind: 'save', label, body })
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(body)
259
+ console.log(userBody)
220
260
  }
221
261
 
222
262
  async function cmdLoad (opts = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "keychat-save",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Save and load files to BSV blockchain via KeyChat",
5
5
  "type": "module",
6
6
  "bin": {