A Gnosis Safe app that lets a Safe treasury create U.CASH checkouts to pay vendors in crypto and cards. Non-custodial.
The Safe never holds funds for U.CASH and never sends a transaction from this app. Funds settle directly to your store's configured receive addresses. The app only reads the connected Safe's address and chain, then mints a hosted U.CASH pay link (or a server-tracked checkout) that you share with a vendor.
- Reads the connected Safe context (address + chain) via
@safe-global/safe-apps-react-sdk. - Lets a treasury operator enter an amount, currency, vendor memo, and optional redirect URL.
- Generates a client-side hosted pay link (
https://pay.u.cash/embed.php) using your publishable Store Cloud Token. - Optionally creates a server-side tracked checkout (idempotent per
external_reference) that returns a tracked payment URL + transaction ID.
Both flows are non-custodial. The Cloud Token is a publishable credential, safe to use straight from the browser/app (like a Stripe publishable key).
The app uses exactly these two endpoints.
GET https://pay.u.cash/embed.php
Query params:
| Param | Required | Notes |
|---|---|---|
cloud |
yes | the store Cloud Token |
amount |
yes | numeric |
currency |
no | default USD |
title |
no | vendor / memo |
external_reference |
no | your idempotency / reconciliation key |
redirect |
no | URL to return to after payment |
POST https://pay.u.cash/payment/ajax.php
Content-Type: application/x-www-form-urlencoded
Body fields:
function=create-transaction
amount
currency_code
cryptocurrency_code= (empty string)
external_reference
title
redirect
cloud
idempotent=1
Response JSON:
{ "success": true, "response": ["<paymentUrl>", "<transactionId>", ...] }The payment URL is the array element that starts with http(s)://. idempotent=1 means re-submitting the same external_reference returns the same checkout instead of creating a duplicate.
-
Start the dev server:
npm install npm run dev
-
Open the Safe{Wallet} (app.safe.global), go to Apps -> My custom apps, and add
https://<your-hosted-url>/manifest.json. For local development, tunnel the Vite dev server (port 5173) over HTTPS with a tool likengrokorcloudflared, then point the Safe{Wallet} at that URL. Browsers block framedhttp://origins inside the Safe{Wallet}, so HTTPS is required even for local dev. -
In the app, paste your Store Cloud Token, enter an amount and vendor, and click Generate pay link (hosted/embed) or Create tracked checkout (server-tracked). The generated URL is what you send to the vendor.
Server-side CORS note: the Create tracked checkout button calls
pay.u.cash/payment/ajax.phpdirectly from the browser. If your store/server blocks cross-origin requests, run that call from your own server route instead. A dependency-free example server is included atsrc/exampleServer/checkout.mjs(runnode src/exampleServer/checkout.mjs, thenPOST /create-checkout).
- Sign up at pay.u.cash, then click the verification link in the email.
- Set receive addresses under Settings -> Addresses (raw address, ENS, Unstoppable Domains, or FIO).
- Create a store under Account -> Stores and copy its Store Cloud Token (use the store-level token, not the account-wide one).
- For fiat cards, connect your own Stripe under Settings -> Payment processors.
npm install
npm run dev # Vite dev server on http://localhost:5173
npm run build # production build to dist/
npm run preview # preview the production buildProject layout:
.
├── index.html
├── package.json
├── vite.config.js
├── public/
│ ├── manifest.json # Safe app manifest
│ └── icon.svg
├── src/
│ ├── main.jsx
│ ├── App.jsx
│ ├── styles.css
│ └── exampleServer/
│ └── checkout.mjs # optional server-side checkout route
└── README.md
- Non-custodial. This app never sends a transaction from your Safe and never holds funds. The Safe only reads its own address and chain. Settlement goes straight to your store's configured receive addresses.
- Cards require your own Stripe. Fiat card acceptance uses your own Stripe account connected under pay.u.cash; U.CASH is not the merchant of record.
- No automatic recurring billing. U.CASH checkouts are one-off payment links. There is no automatic crypto recurring billing. For scheduled payouts, generate a fresh checkout on your own schedule (a cron job calling
create-transaction). - Cloud Token is publishable. It is safe to embed in the app, like a Stripe publishable key. It can mint checkouts but cannot move funds or read balances.
Build and host the static dist/ output over HTTPS (Vercel, Netlify, Cloudflare Pages, GitHub Pages, or any static host). Add your hosted manifest.json URL in the Safe{Wallet} under Apps -> My custom apps.
This is a static Safe app, not a published package. No registry publish is needed. If you want to version releases, tag the repo:
git tag v0.1.0
git push origin v0.1.0MIT. See LICENSE.