Skip to content

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

1 Commit
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

U.CASH Pay for Safe

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.

What it does

  • 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).

U.CASH Pay API contract

The app uses exactly these two endpoints.

Client-side hosted pay link (publishable, browser-safe)

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

Server-side tracked checkout (idempotent per external_reference)

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.

Usage

  1. Start the dev server:

    npm install
    npm run dev
  2. 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 like ngrok or cloudflared, then point the Safe{Wallet} at that URL. Browsers block framed http:// origins inside the Safe{Wallet}, so HTTPS is required even for local dev.

  3. 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.php directly 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 at src/exampleServer/checkout.mjs (run node src/exampleServer/checkout.mjs, then POST /create-checkout).

Set up your pay.u.cash account

  1. Sign up at pay.u.cash, then click the verification link in the email.
  2. Set receive addresses under Settings -> Addresses (raw address, ENS, Unstoppable Domains, or FIO).
  3. Create a store under Account -> Stores and copy its Store Cloud Token (use the store-level token, not the account-wide one).
  4. For fiat cards, connect your own Stripe under Settings -> Payment processors.

Local development

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 build

Project 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 model and limitations

  • 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.

Deploy

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.

Publish

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.0

License

MIT. See LICENSE.

About

A Gnosis Safe app letting a Safe treasury create U.CASH checkouts to pay vendors (crypto + cards). Non-custodial.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages