Spec P3 poll actions: create poll, add option, vote

By specifier.
This commit is contained in:
Chris Troutner
2026-08-28 14:11:14 -07:00
parent 25de2d9eb7
commit 5d7ce7601b
5 changed files with 260 additions and 0 deletions
+54
View File
@@ -0,0 +1,54 @@
# Scenarios: Poll Create - 1, Poll Create - 2, Poll Create - 3, Poll Create - 4
#
# The poll composer broadcasts a Memo create-poll action (0x6d10). The
# payload is a poll_type byte, an option_count byte, and the question text.
# The question is limited to 209 bytes. The composer counts bytes (not
# characters) so the remaining count reflects the question text. Options are
# added by separate add-poll-option actions (0x6d13).
Feature: Poll Create
Background:
Given a wallet authenticated for the address bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d
Given the wallet has spendable output to pay the transaction fee
Scenario Outline: Poll Create - 1 a valid poll is broadcast with the question and option count
When I compose a poll with the question "<question>" and <option_count> options
When I submit the poll
Then the app broadcasts an OP_RETURN transaction with the Memo create-poll prefix for the question "<question>"
Then the app broadcasts an OP_RETURN transaction with the Memo create-poll prefix carrying <option_count> options
Examples:
| question | option_count |
| which is better? | 2 |
| what should we build next? | 3 |
| a valid question with several words and punctuation. | 2 |
Scenario Outline: Poll Create - 2 an empty question is rejected
When I compose a poll with the question "<question>" and 2 options
When I submit the poll
Then the poll composer shows a validation error
Then the app does not broadcast any transaction
Examples:
| question |
| |
Scenario Outline: Poll Create - 3 an over-long question is rejected
When I compose a poll with the question "<question>" and 2 options
When I submit the poll
Then the poll composer shows a length error
Then the app does not broadcast any transaction
Examples:
| question |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
Scenario Outline: Poll Create - 4 the byte counter counts down from the question limit
When I compose a poll with the question "<question>" and 2 options
Then the poll composer shows a remaining byte count of <count>
Examples:
| question | count |
| | 209 |
| hello | 204 |
| é | 207 |
+58
View File
@@ -0,0 +1,58 @@
# Scenarios: Poll Option - 1, Poll Option - 2, Poll Option - 3, Poll Option - 4
#
# The add-option composer broadcasts a Memo add-poll-option action (0x6d13).
# The payload is the poll's 32-byte txid followed by the option text. The
# option text is limited to 184 bytes. The composer counts bytes (not
# characters) so the remaining count reflects the option text.
Feature: Poll Option
Background:
Given a wallet authenticated for the address bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d
Given the wallet has spendable output to pay the transaction fee
Given a poll with the txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Scenario Outline: Poll Option - 1 a valid option is broadcast for the poll
When I open the poll with txid <txid>
When I compose an option with the text "<option>"
When I submit the option
Then the app broadcasts an OP_RETURN transaction with the Memo add-poll-option prefix for the poll <txid>
Then the poll shows the new option with the text "<option>"
Examples:
| txid | option |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | definitely |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | a valid option with several words and punctuation. |
Scenario Outline: Poll Option - 2 an empty option is rejected
When I open the poll with txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
When I compose an option with the text "<option>"
When I submit the option
Then the add-option composer shows a validation error
Then the app does not broadcast any transaction
Examples:
| option |
| |
Scenario Outline: Poll Option - 3 an over-long option is rejected
When I open the poll with txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
When I compose an option with the text "<option>"
When I submit the option
Then the add-option composer shows a length error
Then the app does not broadcast any transaction
Examples:
| option |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
Scenario Outline: Poll Option - 4 the byte counter counts down from the option limit
When I open the poll with txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
When I compose an option with the text "<option>"
Then the add-option composer shows a remaining byte count of <count>
Examples:
| option | count |
| | 184 |
| yes | 181 |
| é | 182 |
+45
View File
@@ -0,0 +1,45 @@
# Scenarios: Poll Vote - 1, Poll Vote - 2, Poll Vote - 3
#
# The vote composer broadcasts a Memo poll-vote action (0x6d14). The payload
# is the poll's 32-byte txid followed by a comment. The comment is limited to
# 184 bytes.
Feature: Poll Vote
Background:
Given a wallet authenticated for the address bitcoincash:qqlrzp23w08434twmvr4fxw672whkjy0py26r63g3d
Given the wallet has spendable output to pay the transaction fee
Given a poll with the txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Scenario Outline: Poll Vote - 1 a valid vote is broadcast for the poll
When I open the poll with txid <txid>
When I vote with the comment "<comment>"
When I submit the vote
Then the app broadcasts an OP_RETURN transaction with the Memo poll-vote prefix for the poll <txid>
Then the poll shows my vote with the comment "<comment>"
Examples:
| txid | comment |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | I choose this one |
Scenario Outline: Poll Vote - 2 an empty comment is rejected
When I open the poll with txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
When I vote with the comment "<comment>"
When I submit the vote
Then the vote composer shows a validation error
Then the app does not broadcast any transaction
Examples:
| comment |
| |
Scenario Outline: Poll Vote - 3 an over-long comment is rejected
When I open the poll with txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
When I vote with the comment "<comment>"
When I submit the vote
Then the vote composer shows a length error
Then the app does not broadcast any transaction
Examples:
| comment |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa |
+39
View File
@@ -0,0 +1,39 @@
# Scenarios: Poll Read - 1, Poll Read - 2, Poll Read - 3
#
# The psf-memo-db REST API exposes the read side of Memo polls:
# - GET /polls/:txid returns the poll with its question, options, and votes
# - GET /polls/:txid/options returns the poll's options
# - GET /polls/:txid/votes returns the poll's votes
Feature: Poll Read
Background:
Given the psf-memo-db API serves a poll with the txid aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa with the question "which is better?"
Given the psf-memo-db API serves the option "yes" for the poll aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Given the psf-memo-db API serves the option "no" for the poll aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Given the psf-memo-db API serves a vote with the comment "yes" for the poll aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
Scenario Outline: Poll Read - 1 the poll endpoint returns the poll with its question, options, and votes
When I request the poll with txid <txid>
Then the response shows the question "<question>"
Then the response shows the options "<option1>" and "<option2>"
Then the response shows <vote_count> vote
Examples:
| txid | question | option1 | option2 | vote_count |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | which is better? | yes | no | 1 |
Scenario Outline: Poll Read - 2 the options endpoint returns the poll's options
When I request the options for the poll with txid <txid>
Then the response shows the options "<option1>" and "<option2>"
Examples:
| txid | option1 | option2 |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes | no |
Scenario Outline: Poll Read - 3 the votes endpoint returns the poll's votes
When I request the votes for the poll with txid <txid>
Then the response shows <vote_count> vote with the comment "<comment>"
Examples:
| txid | comment | vote_count |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes | 1 |
@@ -0,0 +1,64 @@
# Scenarios: Poll Indexer - 1, Poll Indexer - 2, Poll Indexer - 3, Poll Indexer - 4, Poll Indexer - 5, Poll Indexer - 6
#
# The indexer parses Memo poll actions and stores structured records:
# - 0x6d10 create poll: poll_type byte + option_count byte + question
# - 0x6d13 add poll option: poll txid (32 bytes) + option text
# - 0x6d14 poll vote: poll txid (32 bytes) + comment text
# The poll txid is a 32-byte binary hash reversed to hex, like other Memo
# txid payloads.
Feature: Poll Indexer
Background:
Given a psf-memo-db instance that records poll records
Given a psf-memo-indexer configured to write to that database
Scenario Outline: Poll Indexer - 1 a create-poll transaction stores the poll
When the indexer processes a create-poll transaction with the question "<question>" and <option_count> options
Then the psf-memo-db stores a poll with the question "<question>" and <option_count> options
Examples:
| question | option_count |
| which is better? | 2 |
| what should we build next? | 3 |
Scenario Outline: Poll Indexer - 2 an add-option transaction stores the option for the poll
When the indexer processes an add-option transaction for the poll <txid> with the option "<option>"
Then the psf-memo-db stores the option "<option>" for the poll <txid>
Examples:
| txid | option |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | definitely |
Scenario Outline: Poll Indexer - 3 a vote transaction stores the vote for the poll
When the indexer processes a vote transaction for the poll <txid> with the comment "<comment>"
Then the psf-memo-db stores the vote "<comment>" for the poll <txid>
Examples:
| txid | comment |
| aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa | yes |
| bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb | I choose this one |
Scenario Outline: Poll Indexer - 4 a create-poll transaction with a missing question is rejected
When the indexer processes a create-poll transaction with the question "<question>" and 2 options
Then the indexer records a process error and stores no poll
Examples:
| question |
| |
Scenario Outline: Poll Indexer - 5 an add-option transaction with a missing option is rejected
When the indexer processes an add-option transaction for the poll aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa with the option "<option>"
Then the indexer records a process error and stores no option
Examples:
| option |
| |
Scenario Outline: Poll Indexer - 6 a vote transaction with a missing comment is rejected
When the indexer processes a vote transaction for the poll aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa with the comment "<comment>"
Then the indexer records a process error and stores no vote
Examples:
| comment |
| |