mirror of
https://github.com/Permissionless-Software-Foundation/psf-memo.git
synced 2026-09-21 16:52:01 -07:00
Reply, topic message, add-poll-option, poll-vote, and create-poll now broadcast each protocol field as its own OP_RETURN script push instead of combining them into one push. The indexer requires three pushes for reply, topic message, and poll children, and accepts four for create-poll; the combined form was rejected or misparsed. hex.js builds the txid and text as separate pushes, and a new memo-multipush adapter teaches minimal-slp-wallet's single-push sendOpReturn to expand an array of fields into separate pushes. Acceptance step handlers assert the individual pushes, and unit/property tests cover the new shape. By coder.
89 lines
2.8 KiB
JavaScript
89 lines
2.8 KiB
JavaScript
/*
|
|
Unit tests for the hex helpers used by Memo poll actions.
|
|
|
|
Memo actions that embed a parent poll txid use hexToBytes to decode the
|
|
64-character hex txid into 32 raw bytes. These direct tests pin the length
|
|
and hex-validity guards independently of the memo-poll broadcast path that
|
|
also reaches hexToBytes through buildTxidTextPushes.
|
|
*/
|
|
|
|
'use strict'
|
|
|
|
const test = require('node:test')
|
|
const assert = require('node:assert/strict')
|
|
const { hexToBytes, buildTxidTextPushes, txidToWireBytes } = require('../../src/services/hex')
|
|
|
|
// A non-palindromic txid so a missing byte reversal is observable.
|
|
const DISPLAY_TXID = '0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef'
|
|
const WIRE_HEX = 'efcdab8967452301efcdab8967452301efcdab8967452301efcdab8967452301'
|
|
|
|
test('hexToBytes decodes exactly 64 hex characters into 32 bytes', () => {
|
|
const bytes = hexToBytes('ab'.repeat(32))
|
|
|
|
assert.ok(bytes instanceof Uint8Array)
|
|
assert.equal(bytes.length, 32)
|
|
assert.equal(bytes[0], 0xab)
|
|
})
|
|
|
|
test('hexToBytes rejects a string of the wrong length', () => {
|
|
// 60 characters: the correct string type but not the required 64.
|
|
assert.throws(
|
|
() => hexToBytes('ab'.repeat(30)),
|
|
/64-character hex string/
|
|
)
|
|
// 128 characters: over-length.
|
|
assert.throws(
|
|
() => hexToBytes('ab'.repeat(64)),
|
|
/64-character hex string/
|
|
)
|
|
})
|
|
|
|
test('hexToBytes rejects a non-hex character', () => {
|
|
// 64 characters, but 'z' and 'g' are not valid hex digits.
|
|
assert.throws(
|
|
() => hexToBytes('zz'.repeat(32)),
|
|
/valid hex string/
|
|
)
|
|
assert.throws(
|
|
() => hexToBytes('gg'.repeat(32)),
|
|
/valid hex string/
|
|
)
|
|
})
|
|
|
|
test('hexToBytes rejects a non-string value', () => {
|
|
assert.throws(
|
|
() => hexToBytes(null, 32, 'Poll txid'),
|
|
/Poll txid must be a 64-character hex string/
|
|
)
|
|
})
|
|
|
|
test('buildTxidTextPushes returns the txid and text as separate pushes', () => {
|
|
const pushes = buildTxidTextPushes('ab'.repeat(32), 'hi')
|
|
|
|
assert.equal(pushes.length, 2)
|
|
assert.equal(Buffer.from(pushes[0]).length, 32)
|
|
assert.equal(Buffer.from(pushes[0])[0], 0xab)
|
|
assert.equal(Buffer.from(pushes[1]).toString('utf8'), 'hi')
|
|
})
|
|
|
|
test('txidToWireBytes reverses the display txid into little-endian wire order', () => {
|
|
const bytes = txidToWireBytes(DISPLAY_TXID)
|
|
|
|
assert.ok(bytes instanceof Uint8Array)
|
|
assert.equal(Buffer.from(bytes).toString('hex'), WIRE_HEX)
|
|
})
|
|
|
|
test('txidToWireBytes rejects an invalid txid', () => {
|
|
assert.throws(
|
|
() => txidToWireBytes('zz'.repeat(32)),
|
|
/valid hex string/
|
|
)
|
|
})
|
|
|
|
test('buildTxidTextPushes embeds the txid in little-endian wire order', () => {
|
|
const pushes = buildTxidTextPushes(DISPLAY_TXID, 'hi')
|
|
|
|
assert.equal(Buffer.from(pushes[0]).toString('hex'), WIRE_HEX)
|
|
assert.equal(Buffer.from(pushes[1]).toString('utf8'), 'hi')
|
|
})
|