stablecoin-games-renpy 0.1.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (64) hide show
  1. stablecoin_games_renpy-0.1.4/.gitignore +54 -0
  2. stablecoin_games_renpy-0.1.4/LICENSE +21 -0
  3. stablecoin_games_renpy-0.1.4/PKG-INFO +90 -0
  4. stablecoin_games_renpy-0.1.4/README.md +141 -0
  5. stablecoin_games_renpy-0.1.4/docs/developers/README.md +14 -0
  6. stablecoin_games_renpy-0.1.4/docs/developers/configure/README.md +139 -0
  7. stablecoin_games_renpy-0.1.4/docs/developers/security/README.md +24 -0
  8. stablecoin_games_renpy-0.1.4/docs/developers/use/README.md +45 -0
  9. stablecoin_games_renpy-0.1.4/installer/README.md +62 -0
  10. stablecoin_games_renpy-0.1.4/installer/scfg_renpy/__init__.py +4 -0
  11. stablecoin_games_renpy-0.1.4/installer/scfg_renpy/__main__.py +5 -0
  12. stablecoin_games_renpy-0.1.4/installer/scfg_renpy/cli.py +145 -0
  13. stablecoin_games_renpy-0.1.4/npm/README.md +61 -0
  14. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/__init__.py +7 -0
  15. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/_qrcodegen.py +907 -0
  16. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/_xkcp.py +90 -0
  17. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/amounts.py +84 -0
  18. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/backends/__init__.py +42 -0
  19. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/backends/base.py +36 -0
  20. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/backends/evm.py +40 -0
  21. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/backends/solana.py +359 -0
  22. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/chains.py +228 -0
  23. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/checkout.py +516 -0
  24. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/coio.py +118 -0
  25. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/config.py +384 -0
  26. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/engine.py +243 -0
  27. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/errors.py +9 -0
  28. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/evm.py +98 -0
  29. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/keccak.py +17 -0
  30. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/local_server.py +203 -0
  31. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/models.py +46 -0
  32. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/overlay.py +110 -0
  33. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/page_messages.py +42 -0
  34. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/paylinks.py +41 -0
  35. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/payments.py +57 -0
  36. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/pump_worker.py +168 -0
  37. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/receipts.py +68 -0
  38. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/restore.py +132 -0
  39. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/restore_flow.py +100 -0
  40. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/reverify.py +99 -0
  41. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/rpc.py +263 -0
  42. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/sessions.py +97 -0
  43. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/__init__.py +2 -0
  44. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/base58.py +48 -0
  45. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/ed25519.py +24 -0
  46. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/paylinks.py +16 -0
  47. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/pda.py +36 -0
  48. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/rpc.py +143 -0
  49. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/solana/tx.py +104 -0
  50. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/transfers.py +20 -0
  51. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/watcher.py +184 -0
  52. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/web_page.py +98 -0
  53. stablecoin_games_renpy-0.1.4/plugin/game/python-packages/scfg_core/worker.py +100 -0
  54. stablecoin_games_renpy-0.1.4/plugin/game/scfg/scfg_api.rpy +769 -0
  55. stablecoin_games_renpy-0.1.4/plugin/game/scfg/scfg_screens.rpy +848 -0
  56. stablecoin_games_renpy-0.1.4/plugin/game/scfg/ui/dot.png +0 -0
  57. stablecoin_games_renpy-0.1.4/plugin/game/scfg/ui/fill.png +0 -0
  58. stablecoin_games_renpy-0.1.4/plugin/game/scfg/ui/line.png +0 -0
  59. stablecoin_games_renpy-0.1.4/plugin/game/scfg/web/app.js +224 -0
  60. stablecoin_games_renpy-0.1.4/plugin/game/scfg/web/bridge.js +284 -0
  61. stablecoin_games_renpy-0.1.4/plugin/game/scfg/web/evm.js +195 -0
  62. stablecoin_games_renpy-0.1.4/plugin/game/scfg/web/index.html +71 -0
  63. stablecoin_games_renpy-0.1.4/plugin/game/scfg/web/solana.js +182 -0
  64. stablecoin_games_renpy-0.1.4/pyproject.toml +99 -0
@@ -0,0 +1,54 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ .venv/
5
+ .pytest_cache/
6
+ .hypothesis/
7
+ .ruff_cache/
8
+ .coverage
9
+ htmlcov/
10
+
11
+ # Ren'Py build artefacts and runtime files
12
+ *.rpyc
13
+ *.rpymc
14
+ *.rpyb
15
+ cache/
16
+ saves/
17
+ log.txt
18
+ traceback.txt
19
+ errors.txt
20
+ files.txt
21
+ *-dists/
22
+
23
+ # Foundry (integration tests)
24
+ contracts/out/
25
+ contracts/cache/
26
+
27
+ # OS / editors
28
+ .DS_Store
29
+ Thumbs.db
30
+ .idea/
31
+ .vscode/
32
+
33
+ # Plugin copies made by tools/sync_demo.py
34
+ examples/demo_game/game/scfg/
35
+ examples/demo_game/game/python-packages/
36
+ tests/renpy_e2e/game/scfg/
37
+ tests/renpy_e2e/game/python-packages/
38
+ tests/renpy_e2e/*.txt
39
+ dist/
40
+ tests/renpy_e2e/game/e2e_testcase.rpy
41
+ tests/renpy_web_e2e/game/scfg/
42
+ tests/renpy_web_e2e/game/python-packages/
43
+ tests/renpy_web_e2e/game/e2e_web_config.json
44
+ tests/renpy_web_e2e/progressive_download.txt
45
+
46
+ # Docusaurus (website/)
47
+ website/node_modules/
48
+ website/build/
49
+ website/.docusaurus/
50
+
51
+ # npm installer: filled in by npm/scripts/bundle.js at pack time
52
+ npm/plugin/
53
+ npm/LICENSE
54
+ npm/*.tgz
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Repulse Game Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,90 @@
1
+ Metadata-Version: 2.4
2
+ Name: stablecoin-games-renpy
3
+ Version: 0.1.4
4
+ Summary: Stablecoin for Games (SCFG): USDC/USDT tips and unlocks for Ren'Py games, paid straight to your wallet. No server, no tokens, no NFTs. Installs the plugin into your project.
5
+ Project-URL: Homepage, https://jrpg.com/stablecoinforgames/
6
+ Project-URL: Documentation, https://jrpg.com/stablecoinforgames/docs/
7
+ Project-URL: Source, https://github.com/Repulse-Game-Studio/jrpg-stablecoin-games
8
+ Project-URL: Changelog, https://github.com/Repulse-Game-Studio/jrpg-stablecoin-games/releases
9
+ License-Expression: MIT
10
+ License-File: LICENSE
11
+ Keywords: arbitrum,arc,base,crypto,donations,ethereum,game-monetization,monetization,payments,polygon,ren'py,renpy,scfg,solana,stablecoin,stablecoin-for-games,stablecoin-games,stablecoinforgames,tips,usdc,usdt,visual-novel,wallet,web3
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: Console
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3 :: Only
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Programming Language :: Python :: 3.13
23
+ Classifier: Topic :: Games/Entertainment
24
+ Classifier: Topic :: Office/Business :: Financial
25
+ Classifier: Topic :: Software Development :: Libraries
26
+ Requires-Python: >=3.9
27
+ Description-Content-Type: text/markdown
28
+
29
+ # Stablecoin for Games
30
+
31
+ Take tips and sell unlocks in **USDC** and **USDT** inside your Ren'Py game, on Ethereum,
32
+ Arbitrum, Polygon, Base, Arc or Solana. The player's wallet pays yours directly. There is no
33
+ store, account or server in between: the game watches the blockchain itself. Prices are in
34
+ dollars. There are no tokens to buy and no NFTs.
35
+
36
+ ![A player tips 3 USDC on Arc in Ruby Dreams: pick an amount, pick a network, scan the QR code, payment confirmed](https://raw.githubusercontent.com/Repulse-Game-Studio/jrpg-stablecoin-games/main/.github/media/tip-arc.gif)
37
+
38
+ This package installs the plugin into your Ren'Py project. Ren'Py only loads code from a
39
+ game's own `game/` folder, so the plugin is copied there rather than installed into Python.
40
+
41
+ ## Install
42
+
43
+ From your Ren'Py project folder (the one that contains `game/`):
44
+
45
+ ```bash
46
+ uvx stablecoin-games-renpy install .
47
+ ```
48
+
49
+ or, with pipx: `pipx run stablecoin-games-renpy install .`, or with Node: `npx stablecoin-games-renpy install .`
50
+
51
+ That adds:
52
+
53
+ ```
54
+ game/scfg/ (screens, API, browser checkout page)
55
+ game/python-packages/scfg_core/ (the engine; plain Python)
56
+ ```
57
+
58
+ ## Update
59
+
60
+ ```bash
61
+ uvx stablecoin-games-renpy update .
62
+ ```
63
+
64
+ It replaces those two folders with the latest version. Your own files, your configuration
65
+ and your players' purchases are not touched.
66
+
67
+ ## Use it
68
+
69
+ ```renpy
70
+ init python:
71
+ scfg.configure(wallet="0xYourWallet", testnet=True)
72
+ scfg.add_item("chapter2", code=1, price="4.99", token="USDC", title="Chapter 2")
73
+
74
+ label end_of_chapter1:
75
+ $ result = scfg.pay("unlock", item="chapter2")
76
+ if scfg.owns("chapter2"):
77
+ jump chapter2
78
+ ```
79
+
80
+ Requires Ren'Py 8.2 or newer. Read the
81
+ [developer guide](https://jrpg.com/stablecoinforgames/docs/developers/install) and the
82
+ [security notes](https://jrpg.com/stablecoinforgames/docs/developers/security) before you
83
+ sell anything: without a server, unlocks are honour-grade.
84
+
85
+ - Website: https://jrpg.com/stablecoinforgames/
86
+ - Docs: https://jrpg.com/stablecoinforgames/docs/
87
+ - Source and release zips: https://github.com/Repulse-Game-Studio/jrpg-stablecoin-games
88
+ - itch.io: https://repulse-games.itch.io/stablecoin-for-games
89
+ - npm: https://www.npmjs.com/package/stablecoin-games-renpy
90
+ - License: MIT
@@ -0,0 +1,141 @@
1
+ # Stablecoin for Games
2
+
3
+ **[Website](https://jrpg.com/stablecoinforgames/)** ·
4
+ [Docs](https://jrpg.com/stablecoinforgames/docs/) ·
5
+ [itch.io](https://repulse-games.itch.io/stablecoin-for-games) ·
6
+ [npm](https://www.npmjs.com/package/stablecoin-games-renpy) ·
7
+ [PyPI](https://pypi.org/project/stablecoin-games-renpy/)
8
+
9
+ Accept **USDC/USDT tips and unlock purchases** in Ren'Py games, paid straight to the
10
+ developer's wallet, on Ethereum, Arbitrum, Polygon, Base, **Arc** and **Solana**. No server, no
11
+ accounts, no middleman: the game watches the blockchain itself. Works in desktop builds and
12
+ in Ren'Py's web (HTML5) build.
13
+
14
+ ![A player tips 3 USDC on Arc in Ruby Dreams: pick an amount, pick a network, scan the QR code, payment confirmed](.github/media/tip-arc.gif)
15
+
16
+ ```renpy
17
+ init python:
18
+ scfg.configure(wallet="0xYourWallet", testnet=True)
19
+ scfg.add_item("chapter2", code=1, price="4.99", token="USDC", title="Chapter 2")
20
+
21
+ label end_of_chapter1:
22
+ $ result = scfg.pay("unlock", item="chapter2")
23
+ if scfg.owns("chapter2"):
24
+ jump chapter2
25
+ ```
26
+
27
+ ## Using it in your game
28
+
29
+ 1. From your Ren'Py project folder, run `uvx stablecoin-games-renpy install .` (or `pipx run stablecoin-games-renpy install .`, or `npx stablecoin-games-renpy install .`),
30
+ and `uvx stablecoin-games-renpy update .` later for new versions. Or download `scfg-renpy-<version>.zip`
31
+ from the [latest release](https://github.com/Repulse-Game-Studio/jrpg-stablecoin-games/releases/latest)
32
+ or [itch.io](https://repulse-games.itch.io/stablecoin-for-games).
33
+ To build it yourself instead, clone the repo and run `python tools/package.py` (Python 3.9+,
34
+ no dependencies), which writes the same zip to `dist/`. Don't copy the repo itself into your
35
+ game: only `plugin/game/` ships, and the zip holds exactly that.
36
+ 2. Unzip it into your Ren'Py project folder, the one that contains `game/`. You get `game/scfg/` and
37
+ `game/python-packages/scfg_core/`. See [Install](docs/developers/install.md) for the layout and for updating.
38
+ 3. Follow the [developer guide](docs/developers/README.md). It covers configuration, the
39
+ API, testing on testnets, customizing the look, web builds and the security model.
40
+
41
+ **Updating an existing game:** Arc is now built in and offered by default. Read the
42
+ guide's [upgrade notes](docs/developers/configure/arc.md#upgrading-to-the-version-with-arc-built-in)
43
+ first, especially if your payout wallet is a smart-contract wallet or your game added Arc
44
+ itself with `add_chain()`.
45
+
46
+ Requires Ren'Py 8.2 or newer. Read [Security and limitations](docs/developers/security/README.md)
47
+ before selling anything: without a server, unlocks are honour-grade.
48
+
49
+ The docs are published at https://jrpg.com/stablecoinforgames/docs/.
50
+ Players can read how paying works, which wallets work and how to restore a purchase in
51
+ [docs/players/](docs/players/paying.md).
52
+
53
+ ## Repository layout
54
+
55
+ | Path | Contents |
56
+ |---|---|
57
+ | `plugin/game/scfg/` | Ren'Py glue: API (`scfg_api.rpy`), screens, UI images (`ui/`), browser checkout page and web-build bridge (`web/`) |
58
+ | `plugin/game/python-packages/scfg_core/` | Engine-independent core (Python 3.9, stdlib only) |
59
+ | `examples/demo_game/` | Demo game (run `tools/sync_demo.py` first) |
60
+ | `docs/` | The docs: `players/` for players, `developers/` for the developer guide (joined into one `scfg-README.md` in the zip) |
61
+ | `website/` | Docusaurus site built from `docs/`, sidebar in `sidebars.json`. `.github/workflows/docs.yml` checks that it builds |
62
+ | `tests/unit/` | Fast unit tests |
63
+ | `tests/integration/` | Local Anvil chain (also dressed as Arc), local Solana validator and headless Chrome tests (`-m integration`) |
64
+ | `tests/live/` | Read-only checks of pinned real Arc mainnet payments (`-m live`, needs internet) |
65
+ | `tests/renpy_e2e/`, `tests/renpy_web_e2e/` | Real Ren'Py runs (desktop and web build) driving a payment through the screens |
66
+ | `tools/` | `package.py` (release zip), `sync_demo.py`, `check_rpcs.py`, `run_renpy_e2e.py`, `run_renpy_web_e2e.py`, `make_ui_assets.py` (screen corner images) |
67
+ | `contracts/` | `MockToken.sol` (6-decimal mock token) and the Arc stand-ins `ArcMockUsdc.sol` / `ArcSystemEmitter.sol`, used by integration tests |
68
+
69
+ ## Development
70
+
71
+ ```bash
72
+ uv sync # Python 3.9 venv + dev tools
73
+ uv run pytest # unit tests
74
+ uv run ruff check . # lint
75
+
76
+ # needs Foundry's `anvil` (https://getfoundry.sh) and Agave's `solana-test-validator`
77
+ # (https://github.com/anza-xyz/agave/releases) on PATH; browser tests need Chrome/Chromium
78
+ uv run pytest -m integration
79
+
80
+ # real Ren'Py run (opens a small window; needs a Ren'Py SDK, anvil and, for Solana, the validator)
81
+ uv run python tools/run_renpy_e2e.py --sdk /path/to/renpy-8.5.3-sdk
82
+ uv run python tools/run_renpy_e2e.py --sdk /path/to/renpy-8.5.3-sdk --family solana
83
+ uv run python tools/run_renpy_e2e.py --sdk /path/to/renpy-8.5.3-sdk --family arc
84
+
85
+ # real web build in headless Chrome (needs an SDK with web support, anvil and Playwright's Chromium)
86
+ uv run python tools/run_renpy_web_e2e.py --sdk /path/to/renpy-8.5.3-sdk [--family arc]
87
+
88
+ uv run pytest -m live # pinned real Arc payments, read-only
89
+
90
+ uv run python tools/check_rpcs.py # are the built-in public RPCs alive?
91
+ uv run python tools/package.py # build dist/scfg-renpy-<version>.zip
92
+
93
+ # docs site (Node 20+)
94
+ cd website && npm ci && npm start # live preview at http://localhost:3000/stablecoinforgames/docs/
95
+ ```
96
+
97
+ ### Testing Arc
98
+
99
+ Arc (USDC as the gas coin) is tested without its network at three levels:
100
+
101
+ - **Anvil dressed as Arc.** `anvil_setCode` places `contracts/ArcSystemEmitter.sol` at Arc's
102
+ system emitter (`0xffff…fffe`) and `contracts/ArcMockUsdc.sol` at its USDC address
103
+ (`0x3600…0000`). They log in the same order as Arc: a native send logs only at the
104
+ emitter (18 decimals), an ERC-20 `transfer()` logs at the emitter and then at `0x3600`.
105
+ The integration tests (`tests/integration/test_arc_anvil.py`) and both Ren'Py e2e runs
106
+ with `--family arc` use them. The compiled bytecode lives in
107
+ `tests/integration/mock_token.py`, whose docstring has the `forge build` command to
108
+ regenerate it after editing the contracts.
109
+ - **Real Arc mainnet, read-only.** `uv run pytest -m live` reads two pinned real payments
110
+ (one native send, one `transfer()`) through the plugin's restore, re-verify and scan code.
111
+ No key or funds are needed; the tests skip when Arc's RPC can't be reached. In CI they
112
+ run with the scheduled RPC check, not on every push.
113
+ - **A real wallet, by hand.** Before a release, pay on Arc Testnet once with a wallet's
114
+ Send button and once through the browser checkout (see the guide's
115
+ [Arc page](docs/developers/configure/arc.md)).
116
+
117
+ The desktop e2e defaults to SDL's offscreen video driver. Where that isn't available, set
118
+ `SCFG_E2E_VIDEODRIVER=x11` (or another SDL driver).
119
+
120
+ ## Releasing
121
+
122
+ 1. Set the new version in `plugin/game/python-packages/scfg_core/__init__.py` (`__version__`) and
123
+ merge it to `main`.
124
+ 2. Tag that commit and push the tag:
125
+ ```bash
126
+ git tag v0.2.0 && git push origin v0.2.0
127
+ ```
128
+
129
+ `.github/workflows/release.yml` then runs the lint and unit tests, checks that the tag matches
130
+ `__version__`, builds the zip with `tools/package.py` and publishes it as a GitHub release with
131
+ generated notes. A second job builds the `stablecoin-games-renpy` package (`uv build`: the installer in
132
+ `installer/` with the plugin files inside it) and uploads it to PyPI through trusted publishing,
133
+ from the `pypi` environment. A version with letters in it, such as `0.2.0rc1`, is published as a
134
+ prerelease and does not become "latest".
135
+
136
+ ## License
137
+
138
+ MIT, see [`LICENSE`](LICENSE).
139
+
140
+ Third-party code vendored unmodified: `scfg_core/_xkcp.py` (Keccak team, CC0) and
141
+ `scfg_core/_qrcodegen.py` (Project Nayuki, MIT).
@@ -0,0 +1,14 @@
1
+ # Developer guide
2
+
3
+ Accept **USDC** and **USDT** tips and unlock purchases in your Ren'Py game, paid
4
+ **directly to your own wallet**. There is no server, no account, and no middleman:
5
+ the plugin watches the blockchain itself.
6
+
7
+ - Chains: Ethereum, Arbitrum, Polygon (USDC + USDT), Base (USDC), **Arc (USDC, also its gas coin)**, **Solana (USDC + USDT; devnet USDC)**, plus any EVM chain you add yourself (see [Your own RPC endpoints and chains](configure/README.md#your-own-rpc-endpoints-and-chains), [Arc](configure/arc.md) and [Solana](configure/solana.md))
8
+ - Platforms: Windows, macOS, Linux, Android and the web (HTML5) build, on your own site or on itch.io
9
+ - Requires Ren'Py 8.2 or newer (tested on 8.3.7 and 8.5.3)
10
+
11
+ Start with [Install](install.md).
12
+
13
+ > **Read [Security and limitations](security/README.md) before you sell anything.** Without a server,
14
+ > unlocks are honour-grade: a determined player can bypass them.
@@ -0,0 +1,139 @@
1
+ # Configure
2
+
3
+ ```renpy
4
+ init python:
5
+ scfg.configure(
6
+ wallet="0xYourWalletAddressHere", # where payments go (EIP-55 checked)
7
+ testnet=True, # remove (or False) for real money
8
+ )
9
+
10
+ # Paid items. `code` (1-99) is written into players' payments forever:
11
+ # NEVER change an item's code after release.
12
+ scfg.add_item("chapter2", code=1, price="4.99", token="USDC", title="Chapter 2: The Fall")
13
+ scfg.add_item("ost", code=2, price="2.00", token="USDT", title="Original Soundtrack")
14
+ ```
15
+
16
+ ## All `configure()` options
17
+
18
+ | Option | Default | Meaning |
19
+ |---|---|---|
20
+ | `wallet` | required unless `solana_wallet` is given | Your EVM payout address. A wrong-case checksum raises an error, which catches typos |
21
+ | `solana_wallet` | none | Your Solana payout address (base58) to accept USDC/USDT on Solana. See [Solana](solana.md) |
22
+ | `testnet` | `False` | `True` uses Sepolia, Arbitrum Sepolia, Polygon Amoy, Base Sepolia, Arc Testnet and Solana Devnet (USDC only) |
23
+ | `chains` | all built-ins + yours | Which networks players may pay on, in display order: `["arbitrum", "base", "arc", "polygon", "ethereum", "solana"]`. Chains you added with `add_chain()` can be listed too. By default the EVM chains (built-in, then yours) are offered if `wallet` is set, followed by `"solana"` if `solana_wallet` is set |
24
+ | `tokens` | both | `["USDC"]`, `["USDT"]` or both |
25
+ | `methods` | all on | Per-method options, see below |
26
+ | `rpc_urls` | none | Your own RPC endpoints per chain, tried before the built-in public ones, e.g. `{"arbitrum": ["https://arb-mainnet.g.alchemy.com/v2/KEY"]}`. See below |
27
+ | `confirmations` | per chain | Override blocks to wait on EVM chains, e.g. `{"ethereum": 12}`. Arc's default is 1: its blocks are final. Refused for `"solana"`, which has no block count (see [Solana](solana.md)) |
28
+ | `previous_wallets` | none | Wallets used by earlier versions of your game, EVM (`0x…`) and Solana addresses can be mixed. Keeps old purchases valid after you change wallets |
29
+ | `logo` | none | An image in your game folder, e.g. `"images/logo.png"` (`.png`, `.jpg` or `.webp`). Shown at the top of the payment screens and the browser checkout page, fitted into 240 × 64 (at 1280 × 720). A wide wordmark works best |
30
+ | `accent` | `"#0e7c74"` | Color of selected options and the main browser button, e.g. `accent=gui.accent_color`. Text on it switches between white and dark automatically |
31
+
32
+ ## Payment methods
33
+
34
+ | Method | Options | What the player does |
35
+ |---|---|---|
36
+ | `browser` | `enabled`, `timeout_min` (30) | Desktop: clicks "Open checkout in browser"; a page served by the game on `127.0.0.1` connects MetaMask, Rabby, Coinbase Wallet or another extension (on Solana: Phantom, Solflare or Backpack), and sends the payment. Web build: clicks "Open wallet"; the same checkout opens over the game (offered only when the page has a wallet for the network; see [Web builds](../security/web-builds.md)) |
37
+ | `qr` | `enabled`, `wallet_button` (Android "Open wallet app"), `chains` (restrict) | Scans a QR code with a phone wallet (EIP-681 payment link; on Solana, a Solana Pay link) |
38
+ | `manual` | `enabled`, `allow_tx_paste` | Sends the exact amount from any wallet or exchange; can paste the transaction hash |
39
+
40
+ ```renpy
41
+ scfg.configure(wallet="0x...", methods={"browser": {"enabled": False},
42
+ "qr": {"chains": ["base", "polygon"]}})
43
+ ```
44
+
45
+ ## Your own RPC endpoints and chains
46
+
47
+ **Your own RPC endpoint for a built-in chain.** The plugin talks to each chain through
48
+ free public RPC endpoints. They work, but they rate-limit and sometimes go down. If you
49
+ have an endpoint from Alchemy, Infura, QuickNode, Ankr, or your own node, pass it in
50
+ `rpc_urls`. Your endpoints are tried first, and the built-in public ones remain as a fallback:
51
+
52
+ ```renpy
53
+ init python:
54
+ scfg.configure(
55
+ wallet="0xYourWallet",
56
+ rpc_urls={
57
+ "arbitrum": "https://arb-mainnet.g.alchemy.com/v2/YOUR_KEY",
58
+ "base": ["https://base-mainnet.g.alchemy.com/v2/YOUR_KEY",
59
+ "https://my-backup-node.example.com"],
60
+ },
61
+ )
62
+ ```
63
+
64
+ **Your own chain.** For an EVM chain that isn't built in (Avalanche, Optimism, Linea,
65
+ your own appchain…), describe it with `scfg.add_chain()` **before** `configure()`.
66
+ Its key then works everywhere a built-in key does: `chains=`, `rpc_urls=`, `confirmations=`
67
+ and `methods={"qr": {"chains": [...]}}`.
68
+
69
+ ```renpy
70
+ init python:
71
+ # Avalanche C-Chain, real money (used when testnet=False).
72
+ scfg.add_chain(
73
+ "avalanche",
74
+ name="Avalanche", # shown on the network button
75
+ chain_id=43114,
76
+ rpc=["https://api.avax.network/ext/bc/C/rpc"],
77
+ tokens={"USDC": "0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E"},
78
+ confirmations=3,
79
+ explorer_tx="https://snowtrace.io/tx/{}",
80
+ native_symbol="AVAX",
81
+ fee_hint="low",
82
+ )
83
+ # The same key for testing (used when testnet=True): Avalanche Fuji.
84
+ scfg.add_chain(
85
+ "avalanche", testnet=True,
86
+ name="Avalanche Fuji", chain_id=43113,
87
+ rpc=["https://api.avax-test.network/ext/bc/C/rpc"],
88
+ tokens={"USDC": "0x5425890298aed601595a70AB815c96711a31Bc65"},
89
+ confirmations=3,
90
+ explorer_tx="https://testnet.snowtrace.io/tx/{}",
91
+ native_symbol="AVAX",
92
+ )
93
+
94
+ scfg.configure(
95
+ wallet="0xYourWallet",
96
+ testnet=True,
97
+ chains=["base", "avalanche"], # leave out to offer all built-ins + yours
98
+ )
99
+ ```
100
+
101
+ | `add_chain()` argument | Meaning |
102
+ |---|---|
103
+ | `key` | Your name for the chain: lowercase letters, digits, `_`, `-`. It is stored in players' receipts, so **never change it after release**. It can't reuse a built-in key (`"arc"` is built in now: if your game added Arc itself, delete that `add_chain()` call; purchases it recorded stay valid, see [Arc](arc.md#upgrading-to-the-version-with-arc-built-in)) |
104
+ | `name` | Shown to players on the network button (at most 32 characters) |
105
+ | `chain_id` | The EVM chain id (see [chainlist.org](https://chainlist.org)). Wallets use it to switch networks, and QR codes carry it |
106
+ | `rpc` | One URL or a list, tried in order. `https://` only, except `http://127.0.0.1` / `http://localhost` for a local test node. The **last** one is also handed to the player's browser wallet if it needs to add the network, so put a public endpoint last |
107
+ | `tokens` | `{"USDC": "0x…"}` and/or `"USDT"`. Copy addresses from Circle's / Tether's official lists, never from a block explorer search |
108
+ | `confirmations` | Blocks to wait before a payment counts. Use the chain's finality: a few for fast-finality chains, more for chains that reorg |
109
+ | `explorer_tx` | Transaction page with `{}` where the hash goes |
110
+ | `native_symbol` | The gas token (`"AVAX"`, `"ETH"`, …), named in "you need gas" warnings. Default `"ETH"` |
111
+ | `fee_hint` | `"lowest"`, `"low"` (default) or `"high"`, shown under the network name |
112
+ | `testnet` | `False` (default) adds the chain for real-money games; `True` for `configure(testnet=True)` games. Add it twice with the same key to have both |
113
+ | `max_log_range` | Blocks per `eth_getLogs` call to start with (default 1000). The plugin shrinks it by itself when an endpoint complains |
114
+
115
+ Rules your chain must follow (checked when the game starts where possible):
116
+
117
+ - **EVM only.** The plugin finds payments through ERC-20 `Transfer` events over Ethereum
118
+ JSON-RPC (`eth_getLogs`, `eth_getTransactionReceipt`, …). Tron, Bitcoin and other non-EVM
119
+ chains can't be added this way. Solana is built in: see [Solana](solana.md).
120
+ - **The token must not be the chain's gas coin.** On chains like Arc, where USDC *is* the
121
+ gas coin, a plain wallet send logs no ERC-20 event at the token contract, so `add_chain()`
122
+ would miss it. Arc is built in for that reason (see [Arc](arc.md)).
123
+ - **6-decimal tokens only.** The item code lives in the last four of six decimals. This
124
+ rules out BNB Chain's USDC/USDT (18 decimals). The plugin can't check this offline, so
125
+ confirm `decimals()` on the explorer before you ship.
126
+ - **The endpoint must serve `eth_getLogs`** for recent blocks. Most do; check it with a test
127
+ payment on the chain's testnet.
128
+ - **Test it first.** Make one payment on the testnet version of your chain, then one small
129
+ real payment, before you release.
130
+
131
+ ## Item options
132
+
133
+ `scfg.add_item(item_id, code, price, token, title, min_price=None)`
134
+
135
+ - `item_id`: lowercase letters, digits, `_` and `-`.
136
+ - `price`: a **string** like `"4.99"` (at most 2 decimals). Floats are refused.
137
+ - `min_price`: the lowest amount that still unlocks the item (defaults to `price`).
138
+ - **Sales:** you can pass a lower `amount` to `pay()` as long as it's at least `min_price`.
139
+ - **Raising a price later:** keep `min_price` at the old price, so earlier buyers stay unlocked.
@@ -0,0 +1,24 @@
1
+ # Security and limitations
2
+
3
+ What the plugin protects against:
4
+ - **Typing a fake purchase into the save data:** every receipt is re-checked on the blockchain at each launch, and invented ones are removed.
5
+ - **Look-alike "USDC" tokens:** only the official contract addresses count.
6
+ - **Fake transaction hashes sent to the browser page:** every hash is verified on-chain.
7
+
8
+ What it **cannot** prevent (no server means nobody holds a secret):
9
+ - A player reusing **someone else's real transaction hash**, or copying a `persistent` file.
10
+ - **Patched game code**, or a player-controlled fake RPC endpoint.
11
+ - A pirate re-releasing your game with their own wallet address.
12
+ - **Rare amount collisions:** two players buying the same item within minutes of each other, paying by QR or manual transfer without pasting the hash (about 1 % chance per overlapping pair).
13
+
14
+ So treat unlocks as **honour-grade**: right for supporter rewards and tips, weak for valuable content.
15
+
16
+ ## Debug menus and cheats
17
+ If your game has a hidden debug mode or a level select, gate it with `owns()`. Otherwise it is an easy way around the paywall.
18
+
19
+ ## Platform rules
20
+ - **Steam** forbids games that use cryptocurrencies.
21
+ - **Google Play and the App Store** require their own billing for digital unlocks.
22
+ - **itch.io and direct distribution** are the natural home for this plugin.
23
+
24
+ Check each store's current terms yourself.
@@ -0,0 +1,45 @@
1
+ # Use it
2
+
3
+ ```renpy
4
+ label end_of_chapter1:
5
+ if not scfg.owns("chapter2"):
6
+ "Chapter 2 is available for 4.99 USDC."
7
+ $ result = scfg.pay("unlock", item="chapter2")
8
+
9
+ if scfg.owns("chapter2"):
10
+ jump chapter2
11
+ "Maybe later, then."
12
+ ```
13
+
14
+ Tips (the player can change the suggested amount on the payment screen):
15
+
16
+ ```renpy
17
+ $ result = scfg.pay("tip", amount="3.00", token="USDC")
18
+ ```
19
+
20
+ Buttons in screens use non-blocking actions:
21
+
22
+ ```renpy
23
+ textbutton "Support the developer" action ScfgPay("tip", amount="3", token="USDC")
24
+ textbutton "Restore purchases" action CryptoRestore()
25
+ ```
26
+
27
+ Every call and the `PaymentResult` fields are listed in the [API reference](api-reference.md).
28
+
29
+ ## Callbacks
30
+
31
+ ```renpy
32
+ init python:
33
+ def on_payment(result):
34
+ if result.status == "paid":
35
+ achievement.grant("supporter")
36
+ scfg.on_result = on_payment # also catches payments finished after a restart
37
+
38
+ # per call:
39
+ # $ scfg.pay("unlock", item="chapter2", callback=on_payment)
40
+ ```
41
+
42
+ Rules:
43
+ - Callbacks run on the main thread, for **side effects only**. Never call `jump`, `call` or `renpy.call_screen` inside one; change the story using `pay()`'s return value or `owns()`.
44
+ - The receipt is saved **before** your callback runs. Ownership never depends on the callback.
45
+ - A session can report `"cancelled"` or `"expired"` and **later** `"paid"` (the player paid late). Always treat `"paid"` as final.
@@ -0,0 +1,62 @@
1
+ # Stablecoin for Games
2
+
3
+ Take tips and sell unlocks in **USDC** and **USDT** inside your Ren'Py game, on Ethereum,
4
+ Arbitrum, Polygon, Base, Arc or Solana. The player's wallet pays yours directly. There is no
5
+ store, account or server in between: the game watches the blockchain itself. Prices are in
6
+ dollars. There are no tokens to buy and no NFTs.
7
+
8
+ ![A player tips 3 USDC on Arc in Ruby Dreams: pick an amount, pick a network, scan the QR code, payment confirmed](https://raw.githubusercontent.com/Repulse-Game-Studio/jrpg-stablecoin-games/main/.github/media/tip-arc.gif)
9
+
10
+ This package installs the plugin into your Ren'Py project. Ren'Py only loads code from a
11
+ game's own `game/` folder, so the plugin is copied there rather than installed into Python.
12
+
13
+ ## Install
14
+
15
+ From your Ren'Py project folder (the one that contains `game/`):
16
+
17
+ ```bash
18
+ uvx stablecoin-games-renpy install .
19
+ ```
20
+
21
+ or, with pipx: `pipx run stablecoin-games-renpy install .`, or with Node: `npx stablecoin-games-renpy install .`
22
+
23
+ That adds:
24
+
25
+ ```
26
+ game/scfg/ (screens, API, browser checkout page)
27
+ game/python-packages/scfg_core/ (the engine; plain Python)
28
+ ```
29
+
30
+ ## Update
31
+
32
+ ```bash
33
+ uvx stablecoin-games-renpy update .
34
+ ```
35
+
36
+ It replaces those two folders with the latest version. Your own files, your configuration
37
+ and your players' purchases are not touched.
38
+
39
+ ## Use it
40
+
41
+ ```renpy
42
+ init python:
43
+ scfg.configure(wallet="0xYourWallet", testnet=True)
44
+ scfg.add_item("chapter2", code=1, price="4.99", token="USDC", title="Chapter 2")
45
+
46
+ label end_of_chapter1:
47
+ $ result = scfg.pay("unlock", item="chapter2")
48
+ if scfg.owns("chapter2"):
49
+ jump chapter2
50
+ ```
51
+
52
+ Requires Ren'Py 8.2 or newer. Read the
53
+ [developer guide](https://jrpg.com/stablecoinforgames/docs/developers/install) and the
54
+ [security notes](https://jrpg.com/stablecoinforgames/docs/developers/security) before you
55
+ sell anything: without a server, unlocks are honour-grade.
56
+
57
+ - Website: https://jrpg.com/stablecoinforgames/
58
+ - Docs: https://jrpg.com/stablecoinforgames/docs/
59
+ - Source and release zips: https://github.com/Repulse-Game-Studio/jrpg-stablecoin-games
60
+ - itch.io: https://repulse-games.itch.io/stablecoin-for-games
61
+ - npm: https://www.npmjs.com/package/stablecoin-games-renpy
62
+ - License: MIT
@@ -0,0 +1,4 @@
1
+ """Installer for the Stablecoin for Games Ren'Py plugin.
2
+
3
+ Usage: `stablecoin-games-renpy install <project>`.
4
+ """
@@ -0,0 +1,5 @@
1
+ import sys
2
+
3
+ from .cli import main
4
+
5
+ sys.exit(main())