import tempfile import unittest from coffer.ledger import GrantedCreditNotForGoods from pathlib import Path from coffer.product import CofferProduct from coffer.units import ( ACCOUNT_COFFER, ACCOUNT_LEORA, ACCOUNT_NEW_INTERNET, agent_account, cut_subunits, to_subunits, ) class ProductTests(unittest.TestCase): def setUp(self): self.tmp = tempfile.TemporaryDirectory() self.db_path = Path(self.tmp.name) / "coffer.db" self.product = CofferProduct(self.db_path) def tearDown(self): self.product.close() self.tmp.cleanup() def test_first_tx_is_200c_contract(self): boot = self.product.bootstrap_opening_books() self.assertFalse(boot["already"]) self.assertEqual(boot["coffer"]["spendable"], 500.0) self.assertEqual(boot["leora"]["spendable"], 400.0) self.assertEqual(self.product.history(), []) result = self.product.record_build_contract() self.assertFalse(result["already"]) tx = result["tx"] self.assertEqual(tx["seq"], 1) self.assertEqual(tx["kind"], "contract_payment") self.assertEqual(tx["amount_centicredits"], to_subunits(200)) self.assertEqual(tx["debit_account"], ACCOUNT_COFFER) self.assertEqual(tx["credit_account"], ACCOUNT_LEORA) self.assertEqual(result["payer"]["spendable"], 300.0) self.assertEqual(result["payee"]["spendable"], 600.0) # Idempotent again = self.product.record_build_contract() self.assertTrue(again["already"]) self.assertEqual(len(self.product.history()), 1) # Durable across reopen self.product.close() self.product = CofferProduct(self.db_path) hist = self.product.history() self.assertEqual(len(hist), 1) self.assertEqual(hist[0]["kind"], "contract_payment") self.assertEqual(self.product.balance(ACCOUNT_COFFER)["spendable"], 300.0) self.assertEqual(self.product.balance(ACCOUNT_LEORA)["spendable"], 600.0) def test_signup_grant_40c(self): self.product.bootstrap_opening_books() self.product.record_build_contract() out = self.product.grant_signup("explorer1") self.assertFalse(out["already"]) self.assertEqual(out["granted_credits"], 40) self.assertEqual(out["balance"]["promotional"], 40.0) self.assertEqual(out["balance"]["spendable"], 40.0) again = self.product.grant_signup("explorer1") self.assertTrue(again["already"]) self.assertEqual(self.product.balance("explorer1")["spendable"], 40.0) def test_subscription_through_coffer_with_one_percent_cut(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.grant_signup("explorer2") coffer_before = self.product.balance(ACCOUNT_COFFER)["spendable_centicredits"] nic_before = self.product.balance(ACCOUNT_NEW_INTERNET)["spendable_centicredits"] sub = self.product.charge_subscription("explorer2") self.assertEqual(sub["gross_credits"], 20) self.assertEqual(sub["coffer_cut_centicredits"], 20) # 0.20c self.assertEqual(sub["leora_net_centicredits"], 1980) # 19.80c self.assertEqual(sub["coffer_cut_credits"], "0.20") self.assertEqual(sub["leora_net_credits"], "19.80") # Agent: 40 - 20 = 20 left self.assertEqual(self.product.balance("explorer2")["spendable"], 20.0) # Coffer kept 0.20 self.assertEqual( self.product.balance(ACCOUNT_COFFER)["spendable_centicredits"], coffer_before + 20, ) # New Internet Co received 19.80 self.assertEqual( self.product.balance(ACCOUNT_NEW_INTERNET)["spendable_centicredits"], nic_before + 1980, ) def test_signup_flow_wallet_grant_and_sub(self): self.product.bootstrap_opening_books() self.product.record_build_contract() flow = self.product.signup_flow("newbie") self.assertEqual(flow["grant"]["granted_credits"], 40) self.assertEqual(flow["subscription"]["gross_credits"], 20) self.assertEqual(self.product.balance("newbie")["spendable"], 20.0) def test_shirt_purchase_20c(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.signup_flow("shopper") # left with 20c of granted credit with self.assertRaises(GrantedCreditNotForGoods): self.product.buy_shirt("shopper") # free grant credit never buys physical goods self.assertEqual(self.product.balance("shopper")["spendable"], 20.0) self.product.top_up("shopper", 20) # funded credit can out = self.product.buy_shirt("shopper") self.assertEqual(out["order"]["credits_charged"], 20) self.assertEqual(out["order"]["sku"], "coffer-shirt") self.assertEqual((out["balance"]["spendable"], out["balance"]["granted"], out["balance"]["funded"]), (20.0, 20.0, 0.0)) self.assertEqual(len(out["txs"]), 1) self.assertEqual(out["txs"][0]["kind"], "purchase") def test_full_history_and_company_vs_agent_books(self): self.product.bootstrap_opening_books() self.product.record_build_contract() self.product.signup_flow("hist-agent") self.product.top_up("hist-agent", 20) self.product.buy_shirt("hist-agent") hist = self.product.history() kinds = [t["kind"] for t in hist] self.assertEqual(kinds[0], "contract_payment") self.assertIn("grant", kinds) self.assertIn("subscription_charge", kinds) self.assertIn("subscription_forward", kinds) self.assertIn("purchase", kinds) # Company books separate from founder agent self.assertNotEqual(ACCOUNT_COFFER, agent_account("cursorman")) self.assertTrue(ACCOUNT_COFFER.startswith("company:")) self.assertTrue(ACCOUNT_LEORA.startswith("agent:")) def test_cut_math(self): self.assertEqual(cut_subunits(to_subunits(20), 100), 20) self.assertEqual(cut_subunits(to_subunits(20), 0), 0) if __name__ == "__main__": unittest.main()