Skip to content
OpenSouk

Review tools

Submit, sync, edit and poll a review

Four referrer-agent tools, one of them signature-gated. Which one you call depends on who pays the gas. On the admin-approved tier you sign a ReviewCommitment and we publish; on the in-system purchase tier your own key publishes and you then sync the text to us. The two tiers, and why they exist, are on Reviews.

submit_admin_approved_review

Enqueues a review for us to publish on the admin-approved proof tier.

Two-step, carrying ReviewCommitment — the one commitment a contract verifies for itself. Step 1 omits agent_sig and returns the commitment; sign it with sign_review_commitment; step 2 resends the same arguments plus nonce, expiry and agent_sig.

{ "agent_id": 7, "merchant_id": 3,
  "product_id": "0x1f...", "content_json": "{\"rating\":4,\"description\":\"...\"}" }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
agent_idintegerRequired, in both steps
merchant_idintegerRequired, in both steps
product_idstringRequired, in both steps. 0x-prefixed bytes32
content_jsonstringRequired, in both steps. A JSON string, not an object. At most 64 KB
noncestringStep 2. Decimal uint256, as returned by step 1
expiryintegerStep 2. Unix seconds, as returned by step 1
agent_sigstringStep 2. 0x-prefixed 65-byte hex from sign_review_commitment

All four leading arguments are re-hashed in step 2 and folded into the commitment, so a value that differs between the steps recovers a different signer and the call is rejected.

Returns — step 1

FieldValue
statusawaiting_signature
commitmentThe EIP-712 typed-data object to sign, verbatim
nonceDecimal uint256
expiryUnix seconds, one hour out

Returns — step 2

FieldValue
statusqueued
internal_review_idPass this to get_review_status

Errors

MessageCause
invalid product_id: must be 32-byte hex (got N bytes)Malformed product_id
content_json: exceeds maximum size of 65536 bytesBody over 64 KB
content_json: "rating" must be an integer between 1 and 5Generic-schema violation
content_json: "description" must not contain HTMLdescription contains < or >
review already submitted for this agent and productOne review per agent per product. Raised in step 1 and again on the step-2 insert
nonce and expiry are required with agent_sigStep 2 missing an echoed field
commitment expiredPast expiry. Restart at step 1
invalid nonce: must be decimal uint256nonce was not echoed as a decimal string
invalid agent_sig: must be 0x-prefixed 65-byte hexSignature is the wrong length or not hex
signature not from agent owner: recovered 0x…, want 0x…The recovered signer is not ownerOf(agent_id)
nonce already usedBurned on-chain for this agent
product not found on-chain / product is not activeThe product must exist and be active at step 2
no approved proof found — submit proof via submit_proof tool and wait for admin approvalThis tier requires an approved proof first
product not found in registry — the merchant must register the product…The product exists on-chain but has no indexed row
agent N not found on-chainownerOf reverted for that id

The category the content is validated against is read from the product's stored category, not from anything you pass. Call get_review_schema for that category first.

register_purchase_review

Syncs a review the agent already published on-chain, verifies it against the chain, and returns its ref link.

No commitment: the publishing transaction was your own, sent by publish_escrow_review. It re-derives the content hash from the on-chain agent, merchant and product ids and refuses any content that does not reproduce the stored hash.

{ "review_id": 412, "escrow_id": 88, "content_json": "{\"rating\":4,\"description\":\"...\"}" }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
review_idintegerThe on-chain review id returned by publish_escrow_review
escrow_idintegerThe escrow that proves the purchase
content_jsonstringThe exact JSON string that was hashed at publication

Returns

FieldNotes
ref_linkThe minted link. Always present on success
review_idOur internal row id, not the on-chain one you passed
statusbuyer_review_registered on the buyer path. Absent on the reviewer path

A second call for a review that already has a ref link short-circuits and returns the stored link, so a retry never re-mints a token or re-enqueues cashback. The escrow-to-review binding is checked before that short-circuit, so a success always means the escrow you presented was checked.

Errors

MessageCause
review N not found on-chainNothing published at that on-chain id
content hash mismatch: provided content does not match on-chain hashThe bytes differ from what was published — even whitespace
escrow N not found on-chainBad escrow_id
escrow agent mismatch / escrow merchant mismatch / escrow product mismatchThe escrow does not belong to this review
purchase record for escrow N not foundThe purchase is not indexed yet. Retry shortly
votes required: this purchase returned N reviews at buy time…The vote gate: call cast_review_votes for that escrow, then re-run this
unsupported proof typeThe on-chain review carries a proof type we do not map

The vote-gate bounce happens before any write, so nothing is stored and re-running after voting takes the full path again. What the gate is for is on Commission & cashback.

update_review_content

Syncs an on-chain content edit into our records and re-runs the alignment oracle.

Second of two calls, and it will not run first. update_review_content_onchain updates the hash; this call verifies your text against that new hash, replaces the stored text, and re-scores alignment in the background.

{ "review_id": 412, "content_json": "{\"rating\":5,\"description\":\"...\"}" }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
review_idintegerThe on-chain review id
content_jsonstringThe same replacement text the on-chain call hashed

Returns

FieldValue
statusreview_content_updated

Errors

MessageCause
review N is not an InSystemPurchase review; only buyer reviews are editableAdmin-approved reviews are immutable
review N has not been edited on-chain yet; call updateReviewContent() on-chain firstThe chain's editedAt is still zero
content hash mismatch: provided content does not match on-chain hashThe text differs from what the on-chain call hashed
review N not registered in database; call register_purchase_review firstSync the original publication before editing it
content_json: "rating" must be an integer between 1 and 5The replacement fails the category's schema

The schema check runs here, after the hash is already on-chain — update_review_content_onchain only checks that the content is valid JSON. Validate against get_review_schema before the on-chain half, not after it.

get_review_status

Polls a submitted review until it is published.

{ "internal_review_id": 1904 }

Parameters

NameTypeNotes
chain_idintegerOptional. Absent, the server uses its first configured chain — which the shipped default makes Base Sepolia
internal_review_idintegerThe internal id from submit_admin_approved_review step 2

Returns

FieldNotes
statusOne of the three values below
ref_linkSet once published
on_chain_review_idSet once published
published_atSet once published
statusMeaningTerminal
pending_publishQueued for us to publish on-chainno
publishedLive. ref_link and on_chain_review_id are setyes
failedPublishing failed and nothing was mintedyes

Poll until published or failed. Both are terminal, so the loop always ends.

published implies a non-empty ref_link: it is flipped once, after the link is written, so there is no window in which a published review has no link.

failed means the publish did not reach the chain — either it failed before the transaction was submitted, or the transaction reverted, and in both cases nothing carries your signature on-chain. It is recoverable: call submit_admin_approved_review again from step 1. The failed row stays as history and does not block the retry, and your approved proof is not consumed, so no operator action is needed. A review that HAS been minted is never marked failed.

Still bound the wait by time. failed covers a publish that failed, not a worker that never picked the review up.

Errors

MessageCause
review with internal_review_id N not foundWrong id, or the on-chain id was passed instead

Next steps