From b1fb4706a8344b34e78628b1f6a981e1240c213d Mon Sep 17 00:00:00 2001 From: Joshua Date: Wed, 18 Feb 2026 13:14:09 -0800 Subject: [PATCH] Add marketplace checkout harness controls to launcher --- README.md | 7 ++-- app/app.js | 67 ++++++++++++++++++++++++++++++++++++ app/index.html | 40 +++++++++++++++++++++ docs/integration-contract.md | 12 ++++--- 4 files changed, 119 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index b80ecfb..5d3980d 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,10 @@ Advanced integration controls (collapsible): 1. API/chain connection settings 2. Wallet intent + verify primitives 3. Membership quote + confirm primitives -4. Member channel register/poll primitives -5. Governance install + lease primitives -6. Raw response log for deterministic troubleshooting +4. Marketplace offer list + checkout quote/confirm primitives +5. Member channel register/poll primitives +6. Governance install + lease primitives +7. Raw response log for deterministic troubleshooting Wallet automation helpers remain available in advanced controls: diff --git a/app/app.js b/app/app.js index 7e34f05..b17a296 100644 --- a/app/app.js +++ b/app/app.js @@ -6,6 +6,7 @@ const state = { eventMap: new Map(), lastIntent: null, lastQuote: null, + lastCheckoutQuote: null, channelReady: false, }; @@ -584,6 +585,68 @@ async function onInstallStatus() { return out; } +async function onListOffers() { + const out = await request("GET", "/marketplace/offers"); + logLine("marketplace offers", out); + return out; +} + +async function onCheckoutQuote() { + const payload = { + wallet: requireWallet(), + offer_id: $("checkoutOfferId").value.trim(), + org_root_id: orgRootID(), + principal_id: principalID(), + principal_role: principalRole(), + include_membership_if_missing: true, + }; + const payerWallet = $("payerWallet").value.trim(); + const payerProof = $("payerProof").value.trim(); + if (payerWallet) { + payload.payer_wallet = payerWallet; + } + if (payerProof) { + payload.ownership_proof = payerProof; + } + const out = await request("POST", "/marketplace/checkout/quote", payload); + state.lastCheckoutQuote = out; + $("checkoutQuoteId").value = out.quote_id || ""; + $("checkoutTotal").value = out.total_amount || ""; + logLine("marketplace checkout quote", out); + return out; +} + +async function onCheckoutConfirm() { + const quoteID = $("checkoutQuoteId").value.trim(); + if (!quoteID) { + throw new Error("checkout quote id is required"); + } + const txHash = $("checkoutTxHash").value.trim(); + if (!txHash) { + throw new Error("checkout tx hash is required"); + } + const offerID = state.lastCheckoutQuote?.offer_id || $("checkoutOfferId").value.trim(); + const out = await request("POST", "/marketplace/checkout/confirm", { + quote_id: quoteID, + wallet: requireWallet(), + offer_id: offerID, + org_root_id: orgRootID(), + principal_id: principalID(), + principal_role: principalRole(), + tx_hash: txHash, + chain_id: chainID(), + }); + $("checkoutEntitlementId").value = out.entitlement_id || ""; + logLine("marketplace checkout confirm", out); + return out; +} + +async function onListEntitlements() { + const out = await request("GET", `/marketplace/entitlements?wallet=${encodeURIComponent(requireWallet())}`); + logLine("marketplace entitlements", out); + return out; +} + async function ensureChannelBinding() { if (state.channelReady) { return; @@ -690,6 +753,10 @@ bind("btnInstallConfirm", onInstallConfirm); bind("btnInstallStatus", onInstallStatus); bind("btnLeaseHeartbeat", onLeaseHeartbeat); bind("btnOfflineRenew", onOfflineRenew); +bind("btnListOffers", onListOffers); +bind("btnCheckoutQuote", onCheckoutQuote); +bind("btnCheckoutConfirm", onCheckoutConfirm); +bind("btnListEntitlements", onListEntitlements); logLine("launcher shell ready", { api_base: baseURL(), diff --git a/app/index.html b/app/index.html index 891cb01..6c6a88d 100644 --- a/app/index.html +++ b/app/index.html @@ -167,6 +167,46 @@ +
+

Marketplace Checkout

+
+ + + + +
+
+ + + +
+
+ + +
+
+

Member Channel

diff --git a/docs/integration-contract.md b/docs/integration-contract.md index f4c3c75..a6c9bcf 100644 --- a/docs/integration-contract.md +++ b/docs/integration-contract.md @@ -9,10 +9,14 @@ Launcher integrates with EDUT web/backend contracts as follows: 3. `POST /secret/membership/quote` 4. `POST /secret/membership/confirm` 5. `GET /secret/membership/status` -6. `POST /governance/install/token` -7. `POST /governance/install/confirm` -8. `GET /governance/install/status` -9. `GET /member/channel/events` +6. `GET /marketplace/offers` +7. `POST /marketplace/checkout/quote` +8. `POST /marketplace/checkout/confirm` +9. `GET /marketplace/entitlements` +10. `POST /governance/install/token` +11. `POST /governance/install/confirm` +12. `GET /governance/install/status` +13. `GET /member/channel/events` ## Deterministic Requirements