{"id":46666901,"url":"https://github.com/digitalscyther/cryo-pay","last_synced_at":"2026-03-08T19:08:04.018Z","repository":{"id":257923138,"uuid":"864882989","full_name":"digitalscyther/cryo-pay","owner":"digitalscyther","description":null,"archived":false,"fork":false,"pushed_at":"2026-03-08T17:45:57.000Z","size":1340,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2026-03-08T17:55:51.048Z","etag":null,"topics":["arbitrum","axum","blockchain","ethereum","optimism","payment-gateway","react","rust","self-hosted","solidity","usdt","web3"],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/digitalscyther.png","metadata":{"files":{"readme":"readme.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":"docs/roadmap-synthesized.md","authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-09-29T12:25:45.000Z","updated_at":"2026-03-08T17:46:01.000Z","dependencies_parsed_at":"2024-11-07T09:27:45.470Z","dependency_job_id":"3d2d31bd-ff82-49f7-b80a-97a0862f3153","html_url":"https://github.com/digitalscyther/cryo-pay","commit_stats":null,"previous_names":["digitalscyther/cryo-pay"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/digitalscyther/cryo-pay","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalscyther%2Fcryo-pay","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalscyther%2Fcryo-pay/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalscyther%2Fcryo-pay/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalscyther%2Fcryo-pay/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/digitalscyther","download_url":"https://codeload.github.com/digitalscyther/cryo-pay/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/digitalscyther%2Fcryo-pay/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30269509,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-08T17:53:40.517Z","status":"ssl_error","status_checked_at":"2026-03-08T17:53:40.101Z","response_time":56,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arbitrum","axum","blockchain","ethereum","optimism","payment-gateway","react","rust","self-hosted","solidity","usdt","web3"],"created_at":"2026-03-08T19:07:58.192Z","updated_at":"2026-03-08T19:08:04.007Z","avatar_url":"https://github.com/digitalscyther.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Cryo Pay\n\n[![Rust](https://img.shields.io/badge/Rust-1.92+-orange?logo=rust)](https://www.rust-lang.org/)\n[![React](https://img.shields.io/badge/React-18-blue?logo=react)](https://reactjs.org/)\n[![Docker](https://img.shields.io/badge/Docker-Compose-2496ED?logo=docker)](https://docs.docker.com/compose/)\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)\n\nSelf-hosted crypto payment gateway for USDT (ERC-20) invoices on Optimism and Arbitrum.\nSellers create invoices, share a payment link, and the payer completes the transaction via\nMetaMask. The blockchain daemon detects on-chain confirmation and fires webhooks,\nemail, and Telegram notifications automatically.\n\n## Tech Stack\n\nRust (Axum) · React 18 · PostgreSQL · Redis · Nginx · Docker Compose · Solidity (EVM)\n\n## Payment Flow\n\n```mermaid\nsequenceDiagram\n    participant Buyer\n    participant Frontend\n    participant API\n    participant Contract as Smart Contract (EVM)\n    participant Daemon\n\n    Buyer-\u003e\u003eFrontend: Open invoice URL\n    Frontend-\u003e\u003eAPI: GET /payment/invoice/:id\n    API--\u003e\u003eFrontend: Invoice (amount, networks, seller)\n    Frontend-\u003e\u003eBuyer: Payment UI (MetaMask + QR)\n    Buyer-\u003e\u003eContract: Send USDT\n    Contract--\u003e\u003eDaemon: Emit Transfer event (on-chain)\n    loop Block scanning (per network)\n        Daemon-\u003e\u003eContract: eth_getLogs (seller filter)\n        Daemon-\u003e\u003eAPI: Mark invoice paid (internal)\n        API-\u003e\u003eAPI: Verify amount \u003e= invoice.amount\n    end\n    API-\u003e\u003eBuyer: Webhook notification → status Paid\n```\n\n## Quickstart\n\n1. **Clone the repo**\n   ```bash\n   git clone https://github.com/digitalscyther/cryo-pay \u0026\u0026 cd cryo-pay\n   ```\n\n2. **Add Firebase credentials**\n   - `api/data/firebaseConfig.json` — service account private key\n   - `web/src/firebaseConfig.json` — web app config\n\n3. **Configure the backend**\n   ```bash\n   # Create api/.env — see the api/.env reference section below\n   # Required: NETWORKS, INFURA_TOKEN, APP_SECRET, TGBOT_TOKEN, BREVO_API_KEY\n   ```\n\n4. **Start the stack**\n   ```bash\n   docker compose build\n   NGINX_PORT=80 POSTGRES_PORT=6432 REDIS_PORT=6381 \\\n     docker compose -f docker-compose.yml -f docker-compose.dev.yml up -d\n   ```\n\n5. **Open the app** at `http://localhost`, sign in, and create your first invoice.\n\n## Documentation\n\n- [Architecture](docs/architecture.md) — module map, DB schema, auth/payment flows\n- [Roadmap](docs/roadmap.md) — feature backlog and known gaps\n- [Changelog](CHANGELOG.md) — what has been implemented\n\n## Development\n\n```bash\n# Backend\ncd api \u0026\u0026 cargo build\nSQLX_OFFLINE=true cargo build   # without live DB\n\n# Frontend\ncd web \u0026\u0026 npm install \u0026\u0026 npm start\n\n# Add a DB migration\nDATABASE_URL=postgres://cryo:example@localhost:6432/cryo sqlx migrate add -r \u003cname\u003e\n```\n\nLocal frontend with custom API URL:\n```bash\nREACT_APP_BASE_API_URL=http://127.0.0.1:3001 REACT_APP_PROJECT_NAME=LOCALTest REACT_APP_CONTACTS='{\"email\":\"foo@bar.baz\",\"telegram\":\"foo\",\"linkedin\":\"foo\"}' npm start\n```\n\n## api/.env reference\n\n```dotenv\nRUST_LOG=info,tower_http=trace\n\nHOST=0.0.0.0\nPORT=8080\n\nPOSTGRES_URL=postgres://cryo:example@postgres/cryo\nREDIS_URL=redis://:redis123@redis\n\nAPP_SECRET=your_secret\nGOOGLE_APPLICATION_CREDENTIALS=/opt/data/firebaseConfig.json\nINFRA_RPM=1\nERC20_ABI_PATH=/opt/data/erc20_abi.json\nCONTRACT_ABI_PATH=/opt/data/invoice_abi.json\nEVENT_SIGNATURE=PayInvoiceEvent(string,address,address,uint128,uint128)\nNETWORKS=[{\"name\":\"optimism-sepolia\",\"id\":11155420,\"link\":\"https://optimism-sepolia.infura.io/v3/foo\",\"addresses\":{\"erc20\":\"0x9A211fD6C60BdC4Cc1dB22cBe2f882ae527B1D87\",\"contract\":\"...\"}},{\"name\":\"optimism\",\"id\":10,\"link\":\"https://optimism-mainnet.infura.io/v3/foo\",\"addresses\":{\"erc20\":\"0x94b008aa00579c1307b0ef2c499ad98a8ce58e58\",\"contract\":\"...\"}},{\"name\":\"arbitrum\",\"id\":42161,\"link\":\"https://arbitrum-mainnet.infura.io/v3/foo\",\"addresses\":{\"erc20\":\"0xfd086bc7cd5c481dcc9c85ebe478a1c0b69fcbb9\",\"contract\":\"...\"}}]\nTGBOT_TOKEN=foobarbaz\nBREVO_API_KEY=foobarbaz\nEMAIL_SENDER=noreply@example.com\nINFURA_TOKEN=\u003cinfura_token\u003e\nWEB_BASE_URL=https://example.com:3000\nAPI_GLOBAL_URL=http://127.0.0.1/api\nCRYO_PAY_API_KEY=\u003cself_api_key\u003e\nCRYO_PAY_SELF_ADDRESS=\u003cwallet_address\u003e\nCRYO_PAY_RECIEVE_FROM_NETWORKS=[\"optimism-sepolia\",\"optimism\",\"arbitrum\"]\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalscyther%2Fcryo-pay","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdigitalscyther%2Fcryo-pay","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdigitalscyther%2Fcryo-pay/lists"}