Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
55 changes: 28 additions & 27 deletions payment-widget/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# RustChain Payment Widget (rustchain-pay.js)
# RustChain Payment Widget (rustchain-pay.js)

<p align="center">
<img src="https://img.shields.io/badge/version-1.0.0-orange" alt="Version">
Expand All @@ -8,18 +8,16 @@

A lightweight, embeddable JavaScript widget for accepting **RTC (RustChain Token)** payments on any website. Similar to Stripe's checkout button, but for RustChain's Proof-of-Antiquity cryptocurrency.

## ✨ Features

- **🔒 Client-Side Signing** - Private keys never leave the browser
- **📦 Zero Dependencies** - Self-contained with bundled TweetNaCl.js
- **🎨 Beautiful UI** - Modern, responsive modal design
- **⚡ Easy Integration** - Single script tag, auto-initializes
- **🔑 Multiple Auth Methods** - Supports seed phrases and encrypted keystores
- **📱 Responsive** - Works on desktop and mobile
- **🔗 Callback Support** - Webhook notifications for payment confirmation

## 🚀 Quick Start
## Features
- Client-side signing (private keys never leave the browser)
- Zero dependencies (bundled TweetNaCl.js)
- Modal checkout UI
- Data-attribute integration or JS API
- Seed phrase and keystore support
- Responsive (desktop and mobile)
- Callback/webhook notification (restricted by default)

## Quick Start
### Method 1: Data Attributes (Easiest)

```html
Expand Down Expand Up @@ -68,8 +66,7 @@ document.getElementById('pay-btn').onclick = () => {
</script>
```

## 📖 API Reference

## API Reference
### `RustChainPay` Class

#### Constructor Options
Expand Down Expand Up @@ -128,6 +125,9 @@ console.log(balance.amount_rtc); // e.g., 150.5
| `data-memo` | No | Payment memo/description |
| `data-label` | No | Custom button text |
| `data-callback` | No | Webhook URL for payment notification |
| `data-allow-iframe` | No | Set to `true` to allow running inside an iframe (default: blocked) |
| `data-allowed-origins` | No | Comma-separated origin allowlist (defense-in-depth) |
| `data-allow-callback-any-origin` | No | Set to `true` to allow cross-origin callback URLs (default: same-origin only) |

### Success Callback Payload

Expand All @@ -142,7 +142,14 @@ console.log(balance.amount_rtc); // e.g., 150.5
}
```

## 🔐 Security
## Security

### Embed Hardening (Defense-in-Depth)

- DOM injection hardening: widget renders user-provided fields via `textContent`/text nodes, not `innerHTML`.
- Iframe default-deny: widget refuses to run in iframes unless `data-allow-iframe="true"` is set.
- Optional origin allowlist: `data-allowed-origins` can restrict which `window.location.origin` values are allowed.
- Callback restriction: `data-callback` is same-origin only by default; set `data-allow-callback-any-origin="true"` to override.

### Client-Side Signing

Expand Down Expand Up @@ -177,8 +184,7 @@ Supports RustChain's encrypted keystore format:
}
```

## 🎨 Customization

## Customization
### CSS Variables

Override the default styles:
Expand Down Expand Up @@ -216,8 +222,7 @@ document.getElementById('pay').onclick = () => {
</script>
```

## 🌐 Webhook Integration

## Webhook Integration
Set `data-callback` or pass `callback` in options to receive POST notifications:

```javascript
Expand Down Expand Up @@ -246,8 +251,7 @@ app.post('/payment-webhook', (req, res) => {
});
```

## 🔧 Development

## Development
### Building from Source

The widget is self-contained. To modify:
Expand All @@ -264,17 +268,15 @@ python3 -m http.server 8000
# Open http://localhost:8000/demo.html
```

## 📋 Browser Support

## Browser Support
- Chrome 60+
- Firefox 55+
- Safari 11+
- Edge 79+

Requires Web Crypto API support.

## 🔗 Resources

## Resources
- **RustChain Repo**: [github.com/Scottcjn/Rustchain](https://github.com/Scottcjn/Rustchain)
- **Network Explorer**: [50.28.86.131/explorer](https://50.28.86.131/explorer/)
- **Bounties**: [github.com/Scottcjn/rustchain-bounties](https://github.com/Scottcjn/rustchain-bounties)
Expand All @@ -284,8 +286,7 @@ Requires Web Crypto API support.
- `GET /wallet/balance?miner_id=ADDRESS` - Check balance
- `POST /wallet/transfer/signed` - Submit signed transfer

## 📜 License

## License
MIT License - Free for commercial and non-commercial use.

---
Expand Down
30 changes: 30 additions & 0 deletions payment-widget/poc/iframe-block.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PoC: Iframe Block (Payment Widget)</title>
</head>
<body>
<h1>PoC: Iframe Block</h1>
<p>
The hardened widget blocks execution in iframes by default (anti-clickjacking).
To allow, set <code>data-allow-iframe="true"</code>.
</p>

<iframe
title="Widget iframe"
style="width: 100%; height: 220px; border: 1px solid #ccc"
srcdoc='
<!doctype html>
<html>
<body>
<div id="rtc-pay" data-to="RTC0123456789abcdef0123456789abcdef01234567" data-amount="1"></div>
<script src="../rustchain-pay.js"></script>
</body>
</html>
'
></iframe>
</body>
</html>

26 changes: 26 additions & 0 deletions payment-widget/poc/xss-label.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PoC: XSS via data-label (Payment Widget)</title>
</head>
<body>
<h1>PoC: XSS via <code>data-label</code></h1>
<p>
This page demonstrates the injection vector that existed when the widget rendered
<code>data-label</code> via <code>innerHTML</code>. In the hardened version, the label is rendered
via a text node and should not execute HTML/JS.
</p>

<div
id="rtc-pay"
data-to="RTC0123456789abcdef0123456789abcdef01234567"
data-amount="1"
data-label="Pay 1 RTC &lt;img src=x onerror=alert('xss-label')&gt;"
></div>

<script src="../rustchain-pay.js"></script>
</body>
</html>

26 changes: 26 additions & 0 deletions payment-widget/poc/xss-memo.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>PoC: XSS via data-memo (Payment Widget)</title>
</head>
<body>
<h1>PoC: XSS via <code>data-memo</code></h1>
<p>
This page demonstrates the injection vector that existed when the widget interpolated
<code>data-memo</code> into <code>innerHTML</code>. In the hardened version, memo is rendered via
<code>textContent</code> and should not execute HTML/JS.
</p>

<div
id="rtc-pay"
data-to="RTC0123456789abcdef0123456789abcdef01234567"
data-amount="1"
data-memo="&lt;img src=x onerror=alert('xss-memo')&gt;"
></div>

<script src="../rustchain-pay.js"></script>
</body>
</html>

130 changes: 112 additions & 18 deletions payment-widget/rustchain-pay.js

Large diffs are not rendered by default.