@t402/paywall 2.3.0 → 2.4.0
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.
- package/README.md +8 -6
- package/dist/cjs/index.cjs +231 -1
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/cjs/index.d.cts +23 -1
- package/dist/cjs/ton/index.cjs +1 -1
- package/dist/cjs/ton/index.cjs.map +1 -1
- package/dist/esm/{chunk-EOOBF4SM.js → chunk-HJJ35L3R.js} +3 -3
- package/dist/esm/{chunk-EOOBF4SM.js.map → chunk-HJJ35L3R.js.map} +1 -1
- package/dist/esm/index.d.ts +23 -1
- package/dist/esm/index.js +232 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/ton/index.js +1 -1
- package/package.json +9 -8
package/dist/esm/index.d.ts
CHANGED
|
@@ -43,6 +43,28 @@ declare class PaywallBuilder {
|
|
|
43
43
|
*/
|
|
44
44
|
declare function createPaywall(): PaywallBuilder;
|
|
45
45
|
|
|
46
|
+
/**
|
|
47
|
+
* Gasless ERC-4337 paywall handler for EVM networks.
|
|
48
|
+
*
|
|
49
|
+
* Renders a paywall page that indicates the payment will be gasless
|
|
50
|
+
* (sponsored by a paymaster). Use this handler instead of `evmPaywall`
|
|
51
|
+
* when your application supports gasless payments.
|
|
52
|
+
*
|
|
53
|
+
* The handler checks for `eip155:` network prefix AND
|
|
54
|
+
* the `extra.gasless` field in payment requirements.
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* ```typescript
|
|
58
|
+
* import { createPaywall, gaslessPaywall, evmPaywall } from '@t402/paywall';
|
|
59
|
+
*
|
|
60
|
+
* const paywall = createPaywall()
|
|
61
|
+
* .withNetwork(gaslessPaywall) // gasless first (checked before evm)
|
|
62
|
+
* .withNetwork(evmPaywall) // fallback to regular EVM
|
|
63
|
+
* .build();
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
declare const gaslessPaywall: PaywallNetworkHandler;
|
|
67
|
+
|
|
46
68
|
/**
|
|
47
69
|
* Transaction status states
|
|
48
70
|
*/
|
|
@@ -85,4 +107,4 @@ declare function useTransactionStatus(): {
|
|
|
85
107
|
hasTransaction: boolean;
|
|
86
108
|
};
|
|
87
109
|
|
|
88
|
-
export { PaywallBuilder, PaywallConfig, PaywallNetworkHandler, PaywallProvider, TransactionStatus, type TransactionStatusProps, type TxStatus, createPaywall, useTransactionStatus };
|
|
110
|
+
export { PaywallBuilder, PaywallConfig, PaywallNetworkHandler, PaywallProvider, TransactionStatus, type TransactionStatusProps, type TxStatus, createPaywall, gaslessPaywall, useTransactionStatus };
|
package/dist/esm/index.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
export { evmPaywall } from './chunk-SRHRRBJI.js';
|
|
2
2
|
export { svmPaywall } from './chunk-24EMPU4L.js';
|
|
3
|
-
export { tonPaywall } from './chunk-
|
|
3
|
+
export { tonPaywall } from './chunk-HJJ35L3R.js';
|
|
4
4
|
export { tronPaywall } from './chunk-TOBWEW2X.js';
|
|
5
5
|
export { stacksPaywall } from './chunk-BPRW35TS.js';
|
|
6
6
|
export { cosmosPaywall } from './chunk-MRACIFIK.js';
|
|
7
7
|
export { nearPaywall } from './chunk-5C2Z62JY.js';
|
|
8
|
-
import './chunk-JGRSCQJO.js';
|
|
8
|
+
import { generateThemeScript } from './chunk-JGRSCQJO.js';
|
|
9
9
|
import { useState, useCallback, useEffect } from 'react';
|
|
10
10
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
11
11
|
|
|
@@ -66,6 +66,235 @@ var PaywallBuilder = class {
|
|
|
66
66
|
function createPaywall() {
|
|
67
67
|
return new PaywallBuilder();
|
|
68
68
|
}
|
|
69
|
+
|
|
70
|
+
// src/gasless/paywall.ts
|
|
71
|
+
function escapeString(str) {
|
|
72
|
+
return str.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/'/g, "\\'").replace(/\n/g, "\\n").replace(/\r/g, "\\r").replace(/\t/g, "\\t");
|
|
73
|
+
}
|
|
74
|
+
function getGaslessPaywallHtml(options) {
|
|
75
|
+
const { amount, testnet, paymentRequired, currentUrl, appName, appLogo, theme } = options;
|
|
76
|
+
const themeScript = generateThemeScript(theme);
|
|
77
|
+
const configScript = `
|
|
78
|
+
<script>
|
|
79
|
+
window.t402 = {
|
|
80
|
+
amount: ${amount},
|
|
81
|
+
paymentRequired: ${JSON.stringify(paymentRequired)},
|
|
82
|
+
testnet: ${testnet},
|
|
83
|
+
currentUrl: "${escapeString(currentUrl)}",
|
|
84
|
+
appName: "${escapeString(appName || "")}",
|
|
85
|
+
appLogo: "${escapeString(appLogo || "")}",
|
|
86
|
+
gasless: true,
|
|
87
|
+
};
|
|
88
|
+
</script>`;
|
|
89
|
+
return `<!DOCTYPE html>
|
|
90
|
+
<html lang="en">
|
|
91
|
+
<head>
|
|
92
|
+
<meta charset="UTF-8">
|
|
93
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
94
|
+
<title>Payment Required - ${escapeString(appName || "t402")}</title>
|
|
95
|
+
${themeScript}
|
|
96
|
+
${configScript}
|
|
97
|
+
<style>
|
|
98
|
+
:root {
|
|
99
|
+
--primary: #00d4aa;
|
|
100
|
+
--bg: #0a0a0a;
|
|
101
|
+
--container-bg: #141414;
|
|
102
|
+
--text: #ffffff;
|
|
103
|
+
--secondary-text: #888888;
|
|
104
|
+
--border: #2a2a2a;
|
|
105
|
+
--radius: 0.75rem;
|
|
106
|
+
--font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
107
|
+
}
|
|
108
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
109
|
+
body {
|
|
110
|
+
font-family: var(--font);
|
|
111
|
+
background: var(--bg);
|
|
112
|
+
color: var(--text);
|
|
113
|
+
min-height: 100vh;
|
|
114
|
+
display: flex;
|
|
115
|
+
align-items: center;
|
|
116
|
+
justify-content: center;
|
|
117
|
+
padding: 1rem;
|
|
118
|
+
}
|
|
119
|
+
.container {
|
|
120
|
+
background: var(--container-bg);
|
|
121
|
+
border: 1px solid var(--border);
|
|
122
|
+
border-radius: var(--radius);
|
|
123
|
+
padding: 2rem;
|
|
124
|
+
max-width: 420px;
|
|
125
|
+
width: 100%;
|
|
126
|
+
text-align: center;
|
|
127
|
+
}
|
|
128
|
+
.logo { width: 48px; height: 48px; margin-bottom: 1rem; border-radius: 50%; }
|
|
129
|
+
h1 { font-size: 1.25rem; margin-bottom: 0.5rem; }
|
|
130
|
+
.amount { font-size: 2rem; font-weight: 700; color: var(--primary); margin: 1rem 0; }
|
|
131
|
+
.badge {
|
|
132
|
+
display: inline-flex;
|
|
133
|
+
align-items: center;
|
|
134
|
+
gap: 0.375rem;
|
|
135
|
+
background: rgba(0, 212, 170, 0.1);
|
|
136
|
+
color: var(--primary);
|
|
137
|
+
border: 1px solid rgba(0, 212, 170, 0.3);
|
|
138
|
+
border-radius: 2rem;
|
|
139
|
+
padding: 0.375rem 0.875rem;
|
|
140
|
+
font-size: 0.8125rem;
|
|
141
|
+
font-weight: 500;
|
|
142
|
+
margin-bottom: 1.5rem;
|
|
143
|
+
}
|
|
144
|
+
.badge svg { width: 14px; height: 14px; }
|
|
145
|
+
.info {
|
|
146
|
+
background: rgba(255, 255, 255, 0.03);
|
|
147
|
+
border: 1px solid var(--border);
|
|
148
|
+
border-radius: calc(var(--radius) - 2px);
|
|
149
|
+
padding: 1rem;
|
|
150
|
+
margin-bottom: 1.5rem;
|
|
151
|
+
text-align: left;
|
|
152
|
+
font-size: 0.875rem;
|
|
153
|
+
}
|
|
154
|
+
.info-row { display: flex; justify-content: space-between; padding: 0.375rem 0; }
|
|
155
|
+
.info-row .label { color: var(--secondary-text); }
|
|
156
|
+
.info-row .value { font-weight: 500; }
|
|
157
|
+
.divider { height: 1px; background: var(--border); margin: 0.5rem 0; }
|
|
158
|
+
.btn {
|
|
159
|
+
width: 100%;
|
|
160
|
+
padding: 0.875rem;
|
|
161
|
+
background: var(--primary);
|
|
162
|
+
color: #000;
|
|
163
|
+
border: none;
|
|
164
|
+
border-radius: var(--radius);
|
|
165
|
+
font-size: 1rem;
|
|
166
|
+
font-weight: 600;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
transition: opacity 0.15s;
|
|
169
|
+
}
|
|
170
|
+
.btn:hover { opacity: 0.9; }
|
|
171
|
+
.btn:disabled { opacity: 0.5; cursor: not-allowed; }
|
|
172
|
+
.btn.loading { position: relative; color: transparent; }
|
|
173
|
+
.btn.loading::after {
|
|
174
|
+
content: '';
|
|
175
|
+
position: absolute;
|
|
176
|
+
width: 1.25rem;
|
|
177
|
+
height: 1.25rem;
|
|
178
|
+
top: 50%;
|
|
179
|
+
left: 50%;
|
|
180
|
+
margin: -0.625rem 0 0 -0.625rem;
|
|
181
|
+
border: 2px solid rgba(0,0,0,0.2);
|
|
182
|
+
border-top-color: #000;
|
|
183
|
+
border-radius: 50%;
|
|
184
|
+
animation: spin 0.6s linear infinite;
|
|
185
|
+
}
|
|
186
|
+
@keyframes spin { to { transform: rotate(360deg); } }
|
|
187
|
+
.status {
|
|
188
|
+
margin-top: 1rem;
|
|
189
|
+
padding: 0.75rem;
|
|
190
|
+
border-radius: calc(var(--radius) - 2px);
|
|
191
|
+
font-size: 0.875rem;
|
|
192
|
+
}
|
|
193
|
+
.status.success { background: rgba(0, 212, 170, 0.1); color: var(--primary); }
|
|
194
|
+
.status.error { background: rgba(255, 59, 48, 0.1); color: #ff3b30; }
|
|
195
|
+
.footer { margin-top: 1.5rem; font-size: 0.75rem; color: var(--secondary-text); }
|
|
196
|
+
</style>
|
|
197
|
+
</head>
|
|
198
|
+
<body>
|
|
199
|
+
<div class="container">
|
|
200
|
+
${appLogo ? `<img class="logo" src="${escapeString(appLogo)}" alt="" />` : ""}
|
|
201
|
+
<h1>Payment Required</h1>
|
|
202
|
+
<div class="amount">$${amount.toFixed(2)}</div>
|
|
203
|
+
<div class="badge">
|
|
204
|
+
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
|
|
205
|
+
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z"/>
|
|
206
|
+
</svg>
|
|
207
|
+
Gasless Payment
|
|
208
|
+
</div>
|
|
209
|
+
<div class="info">
|
|
210
|
+
<div class="info-row">
|
|
211
|
+
<span class="label">Token</span>
|
|
212
|
+
<span class="value">USDT0</span>
|
|
213
|
+
</div>
|
|
214
|
+
<div class="divider"></div>
|
|
215
|
+
<div class="info-row">
|
|
216
|
+
<span class="label">Gas Fee</span>
|
|
217
|
+
<span class="value" style="color: var(--primary)">Sponsored (Free)</span>
|
|
218
|
+
</div>
|
|
219
|
+
<div class="divider"></div>
|
|
220
|
+
<div class="info-row">
|
|
221
|
+
<span class="label">Method</span>
|
|
222
|
+
<span class="value">Smart Account (ERC-4337)</span>
|
|
223
|
+
</div>
|
|
224
|
+
</div>
|
|
225
|
+
<button class="btn" id="payBtn" onclick="handlePay()">
|
|
226
|
+
Pay $${amount.toFixed(2)} \u2014 No Gas Required
|
|
227
|
+
</button>
|
|
228
|
+
<div id="status"></div>
|
|
229
|
+
<div class="footer">
|
|
230
|
+
Powered by t402 Protocol${testnet ? " (Testnet)" : ""}
|
|
231
|
+
</div>
|
|
232
|
+
</div>
|
|
233
|
+
<script>
|
|
234
|
+
async function handlePay() {
|
|
235
|
+
var btn = document.getElementById('payBtn');
|
|
236
|
+
var statusEl = document.getElementById('status');
|
|
237
|
+
btn.classList.add('loading');
|
|
238
|
+
btn.disabled = true;
|
|
239
|
+
statusEl.innerHTML = '';
|
|
240
|
+
try {
|
|
241
|
+
var response = await fetch(window.t402.currentUrl, {
|
|
242
|
+
method: 'POST',
|
|
243
|
+
headers: { 'Content-Type': 'application/json', 'X-T402-Gasless': 'true' },
|
|
244
|
+
body: JSON.stringify({ paymentRequired: window.t402.paymentRequired }),
|
|
245
|
+
});
|
|
246
|
+
if (response.ok) {
|
|
247
|
+
statusEl.innerHTML = '<div class="status success">Payment confirmed! Redirecting...</div>';
|
|
248
|
+
setTimeout(function() { window.location.reload(); }, 1500);
|
|
249
|
+
} else {
|
|
250
|
+
var data = await response.json().catch(function() { return {}; });
|
|
251
|
+
throw new Error(data.error || 'Payment failed');
|
|
252
|
+
}
|
|
253
|
+
} catch (err) {
|
|
254
|
+
statusEl.innerHTML = '<div class="status error">' + (err.message || 'Payment failed') + '</div>';
|
|
255
|
+
btn.classList.remove('loading');
|
|
256
|
+
btn.disabled = false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
</script>
|
|
260
|
+
</body>
|
|
261
|
+
</html>`;
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// src/gasless/index.ts
|
|
265
|
+
var gaslessPaywall = {
|
|
266
|
+
/**
|
|
267
|
+
* Check if this handler supports the given payment requirement.
|
|
268
|
+
* Matches EVM networks with gasless support indicated.
|
|
269
|
+
*/
|
|
270
|
+
supports(requirement) {
|
|
271
|
+
if (!requirement.network.startsWith("eip155:")) {
|
|
272
|
+
return false;
|
|
273
|
+
}
|
|
274
|
+
if (requirement.extra?.gasless === true) {
|
|
275
|
+
return true;
|
|
276
|
+
}
|
|
277
|
+
if (requirement.scheme === "erc4337" || requirement.scheme === "gasless") {
|
|
278
|
+
return true;
|
|
279
|
+
}
|
|
280
|
+
return false;
|
|
281
|
+
},
|
|
282
|
+
/**
|
|
283
|
+
* Generate gasless paywall HTML
|
|
284
|
+
*/
|
|
285
|
+
generateHtml(requirement, paymentRequired, config) {
|
|
286
|
+
const amount = requirement.amount ? parseFloat(requirement.amount) / 1e6 : requirement.maxAmountRequired ? parseFloat(requirement.maxAmountRequired) / 1e6 : 0;
|
|
287
|
+
return getGaslessPaywallHtml({
|
|
288
|
+
amount,
|
|
289
|
+
paymentRequired,
|
|
290
|
+
currentUrl: paymentRequired.resource?.url || config.currentUrl || "",
|
|
291
|
+
testnet: config.testnet ?? true,
|
|
292
|
+
appName: config.appName,
|
|
293
|
+
appLogo: config.appLogo,
|
|
294
|
+
theme: config.theme
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
};
|
|
69
298
|
function getExplorerUrl(txHash, network) {
|
|
70
299
|
if (network.startsWith("eip155:")) {
|
|
71
300
|
const chainId = parseInt(network.split(":")[1]);
|
|
@@ -328,6 +557,6 @@ function useTransactionStatus() {
|
|
|
328
557
|
};
|
|
329
558
|
}
|
|
330
559
|
|
|
331
|
-
export { PaywallBuilder, TransactionStatus, createPaywall, useTransactionStatus };
|
|
560
|
+
export { PaywallBuilder, TransactionStatus, createPaywall, gaslessPaywall, useTransactionStatus };
|
|
332
561
|
//# sourceMappingURL=index.js.map
|
|
333
562
|
//# sourceMappingURL=index.js.map
|
package/dist/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/builder.ts","../../src/components/TransactionStatus.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n PaywallConfig,\n PaywallProvider,\n PaymentRequired,\n PaywallNetworkHandler,\n} from \"./types\";\n\n/**\n * Builder for creating configured paywall providers\n */\nexport class PaywallBuilder {\n private config: PaywallConfig = {};\n private handlers: PaywallNetworkHandler[] = [];\n\n /**\n * Register a network-specific paywall handler\n *\n * @param handler - Network handler to register\n * @returns This builder instance for chaining\n */\n withNetwork(handler: PaywallNetworkHandler): this {\n this.handlers.push(handler);\n return this;\n }\n\n /**\n * Set configuration options for the paywall\n *\n * @param config - Paywall configuration options\n * @returns This builder instance for chaining\n */\n withConfig(config: PaywallConfig): this {\n this.config = { ...this.config, ...config };\n return this;\n }\n\n /**\n * Build the paywall provider\n *\n * @returns A configured PaywallProvider instance\n */\n build(): PaywallProvider {\n const builderConfig = this.config;\n const handlers = this.handlers;\n\n return {\n generateHtml: (paymentRequired: PaymentRequired, runtimeConfig?: PaywallConfig): string => {\n // Merge builder config with runtime config (runtime takes precedence)\n const finalConfig = { ...builderConfig, ...runtimeConfig };\n\n if (handlers.length === 0) {\n throw new Error(\n \"No paywall handlers registered. Use .withNetwork(evmPaywall) or .withNetwork(svmPaywall)\",\n );\n }\n\n for (const requirement of paymentRequired.accepts) {\n const handler = handlers.find(h => h.supports(requirement));\n if (handler) {\n return handler.generateHtml(requirement, paymentRequired, finalConfig);\n }\n }\n\n const networks = paymentRequired.accepts.map(r => r.network).join(\", \");\n throw new Error(\n `No paywall handler supports networks: ${networks}. Register appropriate handlers with .withNetwork()`,\n );\n },\n };\n }\n}\n\n/**\n * Create a new paywall builder\n *\n * @returns A new PaywallBuilder instance\n */\nexport function createPaywall(): PaywallBuilder {\n return new PaywallBuilder();\n}\n","import { useState, useEffect, useCallback } from \"react\";\n\n/**\n * Transaction status states\n */\nexport type TxStatus = \"pending\" | \"confirming\" | \"confirmed\" | \"failed\";\n\nexport interface TransactionStatusProps {\n /**\n * Transaction hash\n */\n txHash: string;\n /**\n * Network identifier (CAIP-2 format)\n */\n network: string;\n /**\n * Number of confirmations required (default: 1)\n */\n requiredConfirmations?: number;\n /**\n * Callback when transaction is confirmed\n */\n onConfirmed?: () => void;\n /**\n * Callback when transaction fails\n */\n onFailed?: (error: string) => void;\n}\n\n/**\n * Get block explorer URL for a transaction\n */\nfunction getExplorerUrl(txHash: string, network: string): string | null {\n // EVM chains\n if (network.startsWith(\"eip155:\")) {\n const chainId = parseInt(network.split(\":\")[1]);\n const explorers: Record<number, string> = {\n 1: \"https://etherscan.io/tx/\",\n 8453: \"https://basescan.org/tx/\",\n 84532: \"https://sepolia.basescan.org/tx/\",\n 42161: \"https://arbiscan.io/tx/\",\n 421614: \"https://sepolia.arbiscan.io/tx/\",\n 10: \"https://optimistic.etherscan.io/tx/\",\n 11155420: \"https://sepolia-optimism.etherscan.io/tx/\",\n 137: \"https://polygonscan.com/tx/\",\n };\n const baseUrl = explorers[chainId];\n return baseUrl ? `${baseUrl}${txHash}` : null;\n }\n\n // Solana\n if (network.startsWith(\"solana:\")) {\n const ref = network.split(\":\")[1];\n const isDevnet = ref === \"EtWTRABZaYq6iMfeYKouRu166VU2xqa1\";\n const cluster = isDevnet ? \"?cluster=devnet\" : \"\";\n return `https://solscan.io/tx/${txHash}${cluster}`;\n }\n\n // TON\n if (network.startsWith(\"ton:\")) {\n const ref = network.split(\":\")[1];\n const isTestnet = ref === \"testnet\";\n return isTestnet\n ? `https://testnet.tonscan.org/tx/${txHash}`\n : `https://tonscan.org/tx/${txHash}`;\n }\n\n // TRON\n if (network.startsWith(\"tron:\")) {\n const ref = network.split(\":\")[1];\n if (ref === \"nile\") return `https://nile.tronscan.org/#/transaction/${txHash}`;\n if (ref === \"shasta\") return `https://shasta.tronscan.org/#/transaction/${txHash}`;\n return `https://tronscan.org/#/transaction/${txHash}`;\n }\n\n // Stacks\n if (network.startsWith(\"stacks:\")) {\n const chainId = network.split(\":\")[1];\n const isTestnet = chainId === \"2147483648\";\n return isTestnet\n ? `https://explorer.hiro.so/txid/${txHash}?chain=testnet`\n : `https://explorer.hiro.so/txid/${txHash}`;\n }\n\n // Cosmos/Noble\n if (network.startsWith(\"cosmos:\")) {\n const chainId = network.split(\":\")[1];\n if (chainId === \"noble-1\") return `https://www.mintscan.io/noble/tx/${txHash}`;\n if (chainId === \"grand-1\") return `https://testnet.mintscan.io/noble-testnet/tx/${txHash}`;\n return null;\n }\n\n // NEAR\n if (network.startsWith(\"near:\")) {\n const ref = network.split(\":\")[1];\n const isTestnet = ref === \"testnet\";\n return isTestnet\n ? `https://testnet.nearblocks.io/txns/${txHash}`\n : `https://nearblocks.io/txns/${txHash}`;\n }\n\n return null;\n}\n\n/**\n * Truncate transaction hash for display\n */\nfunction truncateHash(hash: string): string {\n if (hash.length <= 16) return hash;\n return `${hash.slice(0, 8)}...${hash.slice(-6)}`;\n}\n\n/**\n * Copy icon SVG\n */\nfunction CopyIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M2 10V3a1 1 0 011-1h7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * Check icon SVG\n */\nfunction CheckIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M11.5 4L5.5 10L2.5 7\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * External link icon SVG\n */\nfunction ExternalLinkIcon() {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M9 6.5v3a1 1 0 01-1 1H2.5a1 1 0 01-1-1V4a1 1 0 011-1H6M8 1.5h2.5m0 0V4m0-2.5L6 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * Spinner for pending state\n */\nfunction StatusSpinner() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className=\"tx-status-spinner\"\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeDasharray=\"24\"\n strokeDashoffset=\"12\"\n />\n </svg>\n );\n}\n\n/**\n * Transaction status display component.\n * Shows transaction hash, explorer link, and confirmation status.\n */\nexport function TransactionStatus({\n txHash,\n network,\n requiredConfirmations = 1,\n onConfirmed,\n onFailed,\n}: TransactionStatusProps) {\n const [status, setStatus] = useState<TxStatus>(\"pending\");\n const [confirmations, setConfirmations] = useState(0);\n const [copied, setCopied] = useState(false);\n\n const explorerUrl = getExplorerUrl(txHash, network);\n\n const copyToClipboard = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(txHash);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement(\"textarea\");\n textArea.value = txHash;\n document.body.appendChild(textArea);\n textArea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(textArea);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n }, [txHash]);\n\n // Simulate confirmation polling (in a real implementation, this would poll the blockchain)\n useEffect(() => {\n if (status === \"confirmed\" || status === \"failed\") return;\n\n // For demo purposes, simulate confirmation after a delay\n // In production, this would poll the blockchain for actual confirmation status\n const timer = setTimeout(() => {\n if (confirmations < requiredConfirmations) {\n setConfirmations(prev => prev + 1);\n setStatus(\"confirming\");\n }\n }, 2000);\n\n return () => clearTimeout(timer);\n }, [confirmations, requiredConfirmations, status]);\n\n // Check if confirmed or failed\n useEffect(() => {\n if (confirmations >= requiredConfirmations && status !== \"confirmed\") {\n setStatus(\"confirmed\");\n onConfirmed?.();\n }\n if (status === \"failed\") {\n onFailed?.(\"Transaction failed\");\n }\n }, [confirmations, requiredConfirmations, status, onConfirmed, onFailed]);\n\n const getStatusText = () => {\n switch (status) {\n case \"pending\":\n return \"Waiting for confirmation...\";\n case \"confirming\":\n return `${confirmations}/${requiredConfirmations} confirmation${confirmations !== 1 ? \"s\" : \"\"}`;\n case \"confirmed\":\n return \"Transaction confirmed\";\n case \"failed\":\n return \"Transaction failed\";\n default:\n return \"\";\n }\n };\n\n const getStatusClass = () => {\n switch (status) {\n case \"confirmed\":\n return \"tx-status-success\";\n case \"failed\":\n return \"tx-status-error\";\n default:\n return \"tx-status-pending\";\n }\n };\n\n return (\n <div className=\"tx-status-container\" role=\"status\" aria-live=\"polite\">\n <div className=\"tx-status-header\">\n <span className=\"tx-status-label\">Transaction</span>\n <div className={`tx-status-badge ${getStatusClass()}`}>\n {status === \"pending\" || status === \"confirming\" ? (\n <StatusSpinner />\n ) : status === \"confirmed\" ? (\n <CheckIcon />\n ) : null}\n <span>{getStatusText()}</span>\n </div>\n </div>\n\n <div className=\"tx-hash-row\">\n <code className=\"tx-hash\">{truncateHash(txHash)}</code>\n <div className=\"tx-hash-actions\">\n <button\n className=\"tx-action-button\"\n onClick={copyToClipboard}\n title={copied ? \"Copied!\" : \"Copy transaction hash\"}\n aria-label={copied ? \"Copied to clipboard\" : \"Copy transaction hash\"}\n >\n {copied ? <CheckIcon /> : <CopyIcon />}\n </button>\n {explorerUrl && (\n <a\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"tx-action-button\"\n title=\"View on explorer\"\n aria-label=\"View transaction on block explorer\"\n >\n <ExternalLinkIcon />\n </a>\n )}\n </div>\n </div>\n\n {status === \"confirming\" && (\n <div\n className=\"tx-confirmations-bar\"\n role=\"progressbar\"\n aria-valuenow={confirmations}\n aria-valuemax={requiredConfirmations}\n >\n <div\n className=\"tx-confirmations-progress\"\n style={{ width: `${(confirmations / requiredConfirmations) * 100}%` }}\n />\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Hook to manage transaction status\n */\nexport function useTransactionStatus() {\n const [txHash, setTxHash] = useState<string | null>(null);\n const [txNetwork, setTxNetwork] = useState<string | null>(null);\n\n const setTransaction = useCallback((hash: string, network: string) => {\n setTxHash(hash);\n setTxNetwork(network);\n }, []);\n\n const clearTransaction = useCallback(() => {\n setTxHash(null);\n setTxNetwork(null);\n }, []);\n\n return {\n txHash,\n txNetwork,\n setTransaction,\n clearTransaction,\n hasTransaction: txHash !== null,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/builder.ts","../../src/gasless/paywall.ts","../../src/gasless/index.ts","../../src/components/TransactionStatus.tsx"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type {\n PaywallConfig,\n PaywallProvider,\n PaymentRequired,\n PaywallNetworkHandler,\n} from \"./types\";\n\n/**\n * Builder for creating configured paywall providers\n */\nexport class PaywallBuilder {\n private config: PaywallConfig = {};\n private handlers: PaywallNetworkHandler[] = [];\n\n /**\n * Register a network-specific paywall handler\n *\n * @param handler - Network handler to register\n * @returns This builder instance for chaining\n */\n withNetwork(handler: PaywallNetworkHandler): this {\n this.handlers.push(handler);\n return this;\n }\n\n /**\n * Set configuration options for the paywall\n *\n * @param config - Paywall configuration options\n * @returns This builder instance for chaining\n */\n withConfig(config: PaywallConfig): this {\n this.config = { ...this.config, ...config };\n return this;\n }\n\n /**\n * Build the paywall provider\n *\n * @returns A configured PaywallProvider instance\n */\n build(): PaywallProvider {\n const builderConfig = this.config;\n const handlers = this.handlers;\n\n return {\n generateHtml: (paymentRequired: PaymentRequired, runtimeConfig?: PaywallConfig): string => {\n // Merge builder config with runtime config (runtime takes precedence)\n const finalConfig = { ...builderConfig, ...runtimeConfig };\n\n if (handlers.length === 0) {\n throw new Error(\n \"No paywall handlers registered. Use .withNetwork(evmPaywall) or .withNetwork(svmPaywall)\",\n );\n }\n\n for (const requirement of paymentRequired.accepts) {\n const handler = handlers.find(h => h.supports(requirement));\n if (handler) {\n return handler.generateHtml(requirement, paymentRequired, finalConfig);\n }\n }\n\n const networks = paymentRequired.accepts.map(r => r.network).join(\", \");\n throw new Error(\n `No paywall handler supports networks: ${networks}. Register appropriate handlers with .withNetwork()`,\n );\n },\n };\n }\n}\n\n/**\n * Create a new paywall builder\n *\n * @returns A new PaywallBuilder instance\n */\nexport function createPaywall(): PaywallBuilder {\n return new PaywallBuilder();\n}\n","import type { PaymentRequired, PaywallTheme } from \"../types\";\nimport { generateThemeScript } from \"../themeUtils\";\n\nfunction escapeString(str: string): string {\n return str\n .replace(/\\\\/g, \"\\\\\\\\\")\n .replace(/\"/g, '\\\\\"')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, \"\\\\n\")\n .replace(/\\r/g, \"\\\\r\")\n .replace(/\\t/g, \"\\\\t\");\n}\n\ninterface GaslessPaywallOptions {\n amount: number;\n paymentRequired: PaymentRequired;\n currentUrl: string;\n testnet: boolean;\n appName?: string;\n appLogo?: string;\n theme?: PaywallTheme;\n}\n\n/**\n * Generates gasless ERC-4337 paywall HTML\n *\n * Unlike the regular EVM paywall, this doesn't require wallet connection.\n * The payment is processed via a smart account with gas sponsorship.\n */\nexport function getGaslessPaywallHtml(options: GaslessPaywallOptions): string {\n const { amount, testnet, paymentRequired, currentUrl, appName, appLogo, theme } = options;\n const themeScript = generateThemeScript(theme);\n\n const configScript = `\n <script>\n window.t402 = {\n amount: ${amount},\n paymentRequired: ${JSON.stringify(paymentRequired)},\n testnet: ${testnet},\n currentUrl: \"${escapeString(currentUrl)}\",\n appName: \"${escapeString(appName || \"\")}\",\n appLogo: \"${escapeString(appLogo || \"\")}\",\n gasless: true,\n };\n </script>`;\n\n return `<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Payment Required - ${escapeString(appName || \"t402\")}</title>\n ${themeScript}\n ${configScript}\n <style>\n :root {\n --primary: #00d4aa;\n --bg: #0a0a0a;\n --container-bg: #141414;\n --text: #ffffff;\n --secondary-text: #888888;\n --border: #2a2a2a;\n --radius: 0.75rem;\n --font: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;\n }\n * { box-sizing: border-box; margin: 0; padding: 0; }\n body {\n font-family: var(--font);\n background: var(--bg);\n color: var(--text);\n min-height: 100vh;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 1rem;\n }\n .container {\n background: var(--container-bg);\n border: 1px solid var(--border);\n border-radius: var(--radius);\n padding: 2rem;\n max-width: 420px;\n width: 100%;\n text-align: center;\n }\n .logo { width: 48px; height: 48px; margin-bottom: 1rem; border-radius: 50%; }\n h1 { font-size: 1.25rem; margin-bottom: 0.5rem; }\n .amount { font-size: 2rem; font-weight: 700; color: var(--primary); margin: 1rem 0; }\n .badge {\n display: inline-flex;\n align-items: center;\n gap: 0.375rem;\n background: rgba(0, 212, 170, 0.1);\n color: var(--primary);\n border: 1px solid rgba(0, 212, 170, 0.3);\n border-radius: 2rem;\n padding: 0.375rem 0.875rem;\n font-size: 0.8125rem;\n font-weight: 500;\n margin-bottom: 1.5rem;\n }\n .badge svg { width: 14px; height: 14px; }\n .info {\n background: rgba(255, 255, 255, 0.03);\n border: 1px solid var(--border);\n border-radius: calc(var(--radius) - 2px);\n padding: 1rem;\n margin-bottom: 1.5rem;\n text-align: left;\n font-size: 0.875rem;\n }\n .info-row { display: flex; justify-content: space-between; padding: 0.375rem 0; }\n .info-row .label { color: var(--secondary-text); }\n .info-row .value { font-weight: 500; }\n .divider { height: 1px; background: var(--border); margin: 0.5rem 0; }\n .btn {\n width: 100%;\n padding: 0.875rem;\n background: var(--primary);\n color: #000;\n border: none;\n border-radius: var(--radius);\n font-size: 1rem;\n font-weight: 600;\n cursor: pointer;\n transition: opacity 0.15s;\n }\n .btn:hover { opacity: 0.9; }\n .btn:disabled { opacity: 0.5; cursor: not-allowed; }\n .btn.loading { position: relative; color: transparent; }\n .btn.loading::after {\n content: '';\n position: absolute;\n width: 1.25rem;\n height: 1.25rem;\n top: 50%;\n left: 50%;\n margin: -0.625rem 0 0 -0.625rem;\n border: 2px solid rgba(0,0,0,0.2);\n border-top-color: #000;\n border-radius: 50%;\n animation: spin 0.6s linear infinite;\n }\n @keyframes spin { to { transform: rotate(360deg); } }\n .status {\n margin-top: 1rem;\n padding: 0.75rem;\n border-radius: calc(var(--radius) - 2px);\n font-size: 0.875rem;\n }\n .status.success { background: rgba(0, 212, 170, 0.1); color: var(--primary); }\n .status.error { background: rgba(255, 59, 48, 0.1); color: #ff3b30; }\n .footer { margin-top: 1.5rem; font-size: 0.75rem; color: var(--secondary-text); }\n </style>\n</head>\n<body>\n <div class=\"container\">\n ${appLogo ? `<img class=\"logo\" src=\"${escapeString(appLogo)}\" alt=\"\" />` : \"\"}\n <h1>Payment Required</h1>\n <div class=\"amount\">$${amount.toFixed(2)}</div>\n <div class=\"badge\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\"/>\n </svg>\n Gasless Payment\n </div>\n <div class=\"info\">\n <div class=\"info-row\">\n <span class=\"label\">Token</span>\n <span class=\"value\">USDT0</span>\n </div>\n <div class=\"divider\"></div>\n <div class=\"info-row\">\n <span class=\"label\">Gas Fee</span>\n <span class=\"value\" style=\"color: var(--primary)\">Sponsored (Free)</span>\n </div>\n <div class=\"divider\"></div>\n <div class=\"info-row\">\n <span class=\"label\">Method</span>\n <span class=\"value\">Smart Account (ERC-4337)</span>\n </div>\n </div>\n <button class=\"btn\" id=\"payBtn\" onclick=\"handlePay()\">\n Pay $${amount.toFixed(2)} — No Gas Required\n </button>\n <div id=\"status\"></div>\n <div class=\"footer\">\n Powered by t402 Protocol${testnet ? \" (Testnet)\" : \"\"}\n </div>\n </div>\n <script>\n async function handlePay() {\n var btn = document.getElementById('payBtn');\n var statusEl = document.getElementById('status');\n btn.classList.add('loading');\n btn.disabled = true;\n statusEl.innerHTML = '';\n try {\n var response = await fetch(window.t402.currentUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json', 'X-T402-Gasless': 'true' },\n body: JSON.stringify({ paymentRequired: window.t402.paymentRequired }),\n });\n if (response.ok) {\n statusEl.innerHTML = '<div class=\"status success\">Payment confirmed! Redirecting...</div>';\n setTimeout(function() { window.location.reload(); }, 1500);\n } else {\n var data = await response.json().catch(function() { return {}; });\n throw new Error(data.error || 'Payment failed');\n }\n } catch (err) {\n statusEl.innerHTML = '<div class=\"status error\">' + (err.message || 'Payment failed') + '</div>';\n btn.classList.remove('loading');\n btn.disabled = false;\n }\n }\n </script>\n</body>\n</html>`;\n}\n","import type {\n PaywallNetworkHandler,\n PaymentRequirements,\n PaymentRequired,\n PaywallConfig,\n} from \"../types\";\nimport { getGaslessPaywallHtml } from \"./paywall\";\n\n/**\n * Gasless ERC-4337 paywall handler for EVM networks.\n *\n * Renders a paywall page that indicates the payment will be gasless\n * (sponsored by a paymaster). Use this handler instead of `evmPaywall`\n * when your application supports gasless payments.\n *\n * The handler checks for `eip155:` network prefix AND\n * the `extra.gasless` field in payment requirements.\n *\n * @example\n * ```typescript\n * import { createPaywall, gaslessPaywall, evmPaywall } from '@t402/paywall';\n *\n * const paywall = createPaywall()\n * .withNetwork(gaslessPaywall) // gasless first (checked before evm)\n * .withNetwork(evmPaywall) // fallback to regular EVM\n * .build();\n * ```\n */\nexport const gaslessPaywall: PaywallNetworkHandler = {\n /**\n * Check if this handler supports the given payment requirement.\n * Matches EVM networks with gasless support indicated.\n */\n supports(requirement: PaymentRequirements): boolean {\n if (!requirement.network.startsWith(\"eip155:\")) {\n return false;\n }\n\n // Check for gasless flag in extra metadata\n if (requirement.extra?.gasless === true) {\n return true;\n }\n\n // Check for ERC-4337 scheme\n if (requirement.scheme === \"erc4337\" || requirement.scheme === \"gasless\") {\n return true;\n }\n\n return false;\n },\n\n /**\n * Generate gasless paywall HTML\n */\n generateHtml(\n requirement: PaymentRequirements,\n paymentRequired: PaymentRequired,\n config: PaywallConfig,\n ): string {\n const amount = requirement.amount\n ? parseFloat(requirement.amount) / 1000000\n : requirement.maxAmountRequired\n ? parseFloat(requirement.maxAmountRequired) / 1000000\n : 0;\n\n return getGaslessPaywallHtml({\n amount,\n paymentRequired,\n currentUrl: paymentRequired.resource?.url || config.currentUrl || \"\",\n testnet: config.testnet ?? true,\n appName: config.appName,\n appLogo: config.appLogo,\n theme: config.theme,\n });\n },\n};\n","import { useState, useEffect, useCallback } from \"react\";\n\n/**\n * Transaction status states\n */\nexport type TxStatus = \"pending\" | \"confirming\" | \"confirmed\" | \"failed\";\n\nexport interface TransactionStatusProps {\n /**\n * Transaction hash\n */\n txHash: string;\n /**\n * Network identifier (CAIP-2 format)\n */\n network: string;\n /**\n * Number of confirmations required (default: 1)\n */\n requiredConfirmations?: number;\n /**\n * Callback when transaction is confirmed\n */\n onConfirmed?: () => void;\n /**\n * Callback when transaction fails\n */\n onFailed?: (error: string) => void;\n}\n\n/**\n * Get block explorer URL for a transaction\n */\nfunction getExplorerUrl(txHash: string, network: string): string | null {\n // EVM chains\n if (network.startsWith(\"eip155:\")) {\n const chainId = parseInt(network.split(\":\")[1]);\n const explorers: Record<number, string> = {\n 1: \"https://etherscan.io/tx/\",\n 8453: \"https://basescan.org/tx/\",\n 84532: \"https://sepolia.basescan.org/tx/\",\n 42161: \"https://arbiscan.io/tx/\",\n 421614: \"https://sepolia.arbiscan.io/tx/\",\n 10: \"https://optimistic.etherscan.io/tx/\",\n 11155420: \"https://sepolia-optimism.etherscan.io/tx/\",\n 137: \"https://polygonscan.com/tx/\",\n };\n const baseUrl = explorers[chainId];\n return baseUrl ? `${baseUrl}${txHash}` : null;\n }\n\n // Solana\n if (network.startsWith(\"solana:\")) {\n const ref = network.split(\":\")[1];\n const isDevnet = ref === \"EtWTRABZaYq6iMfeYKouRu166VU2xqa1\";\n const cluster = isDevnet ? \"?cluster=devnet\" : \"\";\n return `https://solscan.io/tx/${txHash}${cluster}`;\n }\n\n // TON\n if (network.startsWith(\"ton:\")) {\n const ref = network.split(\":\")[1];\n const isTestnet = ref === \"testnet\";\n return isTestnet\n ? `https://testnet.tonscan.org/tx/${txHash}`\n : `https://tonscan.org/tx/${txHash}`;\n }\n\n // TRON\n if (network.startsWith(\"tron:\")) {\n const ref = network.split(\":\")[1];\n if (ref === \"nile\") return `https://nile.tronscan.org/#/transaction/${txHash}`;\n if (ref === \"shasta\") return `https://shasta.tronscan.org/#/transaction/${txHash}`;\n return `https://tronscan.org/#/transaction/${txHash}`;\n }\n\n // Stacks\n if (network.startsWith(\"stacks:\")) {\n const chainId = network.split(\":\")[1];\n const isTestnet = chainId === \"2147483648\";\n return isTestnet\n ? `https://explorer.hiro.so/txid/${txHash}?chain=testnet`\n : `https://explorer.hiro.so/txid/${txHash}`;\n }\n\n // Cosmos/Noble\n if (network.startsWith(\"cosmos:\")) {\n const chainId = network.split(\":\")[1];\n if (chainId === \"noble-1\") return `https://www.mintscan.io/noble/tx/${txHash}`;\n if (chainId === \"grand-1\") return `https://testnet.mintscan.io/noble-testnet/tx/${txHash}`;\n return null;\n }\n\n // NEAR\n if (network.startsWith(\"near:\")) {\n const ref = network.split(\":\")[1];\n const isTestnet = ref === \"testnet\";\n return isTestnet\n ? `https://testnet.nearblocks.io/txns/${txHash}`\n : `https://nearblocks.io/txns/${txHash}`;\n }\n\n return null;\n}\n\n/**\n * Truncate transaction hash for display\n */\nfunction truncateHash(hash: string): string {\n if (hash.length <= 16) return hash;\n return `${hash.slice(0, 8)}...${hash.slice(-6)}`;\n}\n\n/**\n * Copy icon SVG\n */\nfunction CopyIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <rect x=\"4\" y=\"4\" width=\"8\" height=\"8\" rx=\"1\" stroke=\"currentColor\" strokeWidth=\"1.5\" />\n <path\n d=\"M2 10V3a1 1 0 011-1h7\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * Check icon SVG\n */\nfunction CheckIcon() {\n return (\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 14 14\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M11.5 4L5.5 10L2.5 7\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * External link icon SVG\n */\nfunction ExternalLinkIcon() {\n return (\n <svg width=\"12\" height=\"12\" viewBox=\"0 0 12 12\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M9 6.5v3a1 1 0 01-1 1H2.5a1 1 0 01-1-1V4a1 1 0 011-1H6M8 1.5h2.5m0 0V4m0-2.5L6 6\"\n stroke=\"currentColor\"\n strokeWidth=\"1.5\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n />\n </svg>\n );\n}\n\n/**\n * Spinner for pending state\n */\nfunction StatusSpinner() {\n return (\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n className=\"tx-status-spinner\"\n aria-hidden=\"true\"\n >\n <circle\n cx=\"8\"\n cy=\"8\"\n r=\"6\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeDasharray=\"24\"\n strokeDashoffset=\"12\"\n />\n </svg>\n );\n}\n\n/**\n * Transaction status display component.\n * Shows transaction hash, explorer link, and confirmation status.\n */\nexport function TransactionStatus({\n txHash,\n network,\n requiredConfirmations = 1,\n onConfirmed,\n onFailed,\n}: TransactionStatusProps) {\n const [status, setStatus] = useState<TxStatus>(\"pending\");\n const [confirmations, setConfirmations] = useState(0);\n const [copied, setCopied] = useState(false);\n\n const explorerUrl = getExplorerUrl(txHash, network);\n\n const copyToClipboard = useCallback(async () => {\n try {\n await navigator.clipboard.writeText(txHash);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n } catch {\n // Fallback for older browsers\n const textArea = document.createElement(\"textarea\");\n textArea.value = txHash;\n document.body.appendChild(textArea);\n textArea.select();\n document.execCommand(\"copy\");\n document.body.removeChild(textArea);\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n }\n }, [txHash]);\n\n // Simulate confirmation polling (in a real implementation, this would poll the blockchain)\n useEffect(() => {\n if (status === \"confirmed\" || status === \"failed\") return;\n\n // For demo purposes, simulate confirmation after a delay\n // In production, this would poll the blockchain for actual confirmation status\n const timer = setTimeout(() => {\n if (confirmations < requiredConfirmations) {\n setConfirmations(prev => prev + 1);\n setStatus(\"confirming\");\n }\n }, 2000);\n\n return () => clearTimeout(timer);\n }, [confirmations, requiredConfirmations, status]);\n\n // Check if confirmed or failed\n useEffect(() => {\n if (confirmations >= requiredConfirmations && status !== \"confirmed\") {\n setStatus(\"confirmed\");\n onConfirmed?.();\n }\n if (status === \"failed\") {\n onFailed?.(\"Transaction failed\");\n }\n }, [confirmations, requiredConfirmations, status, onConfirmed, onFailed]);\n\n const getStatusText = () => {\n switch (status) {\n case \"pending\":\n return \"Waiting for confirmation...\";\n case \"confirming\":\n return `${confirmations}/${requiredConfirmations} confirmation${confirmations !== 1 ? \"s\" : \"\"}`;\n case \"confirmed\":\n return \"Transaction confirmed\";\n case \"failed\":\n return \"Transaction failed\";\n default:\n return \"\";\n }\n };\n\n const getStatusClass = () => {\n switch (status) {\n case \"confirmed\":\n return \"tx-status-success\";\n case \"failed\":\n return \"tx-status-error\";\n default:\n return \"tx-status-pending\";\n }\n };\n\n return (\n <div className=\"tx-status-container\" role=\"status\" aria-live=\"polite\">\n <div className=\"tx-status-header\">\n <span className=\"tx-status-label\">Transaction</span>\n <div className={`tx-status-badge ${getStatusClass()}`}>\n {status === \"pending\" || status === \"confirming\" ? (\n <StatusSpinner />\n ) : status === \"confirmed\" ? (\n <CheckIcon />\n ) : null}\n <span>{getStatusText()}</span>\n </div>\n </div>\n\n <div className=\"tx-hash-row\">\n <code className=\"tx-hash\">{truncateHash(txHash)}</code>\n <div className=\"tx-hash-actions\">\n <button\n className=\"tx-action-button\"\n onClick={copyToClipboard}\n title={copied ? \"Copied!\" : \"Copy transaction hash\"}\n aria-label={copied ? \"Copied to clipboard\" : \"Copy transaction hash\"}\n >\n {copied ? <CheckIcon /> : <CopyIcon />}\n </button>\n {explorerUrl && (\n <a\n href={explorerUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"tx-action-button\"\n title=\"View on explorer\"\n aria-label=\"View transaction on block explorer\"\n >\n <ExternalLinkIcon />\n </a>\n )}\n </div>\n </div>\n\n {status === \"confirming\" && (\n <div\n className=\"tx-confirmations-bar\"\n role=\"progressbar\"\n aria-valuenow={confirmations}\n aria-valuemax={requiredConfirmations}\n >\n <div\n className=\"tx-confirmations-progress\"\n style={{ width: `${(confirmations / requiredConfirmations) * 100}%` }}\n />\n </div>\n )}\n </div>\n );\n}\n\n/**\n * Hook to manage transaction status\n */\nexport function useTransactionStatus() {\n const [txHash, setTxHash] = useState<string | null>(null);\n const [txNetwork, setTxNetwork] = useState<string | null>(null);\n\n const setTransaction = useCallback((hash: string, network: string) => {\n setTxHash(hash);\n setTxNetwork(network);\n }, []);\n\n const clearTransaction = useCallback(() => {\n setTxHash(null);\n setTxNetwork(null);\n }, []);\n\n return {\n txHash,\n txNetwork,\n setTransaction,\n clearTransaction,\n hasTransaction: txHash !== null,\n };\n}\n"]}
|
package/dist/esm/ton/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t402/paywall",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.4.0",
|
|
4
4
|
"main": "./dist/cjs/index.js",
|
|
5
5
|
"module": "./dist/esm/index.js",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"devDependencies": {
|
|
19
19
|
"@craftamap/esbuild-plugin-html": "^0.9.0",
|
|
20
20
|
"@eslint/js": "^9.24.0",
|
|
21
|
-
"@types/node": "^
|
|
21
|
+
"@types/node": "^25.2.0",
|
|
22
22
|
"@types/react": "^19",
|
|
23
23
|
"@types/react-dom": "^19",
|
|
24
24
|
"@typescript-eslint/eslint-plugin": "^8.29.1",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"esbuild": "^0.25.4",
|
|
28
28
|
"eslint": "^9.24.0",
|
|
29
29
|
"eslint-plugin-import": "^2.31.0",
|
|
30
|
-
"eslint-plugin-jsdoc": "^
|
|
30
|
+
"eslint-plugin-jsdoc": "^62.5.0",
|
|
31
31
|
"eslint-plugin-prettier": "^5.2.6",
|
|
32
32
|
"glob": "^13.0.0",
|
|
33
33
|
"prettier": "3.5.2",
|
|
@@ -39,10 +39,10 @@
|
|
|
39
39
|
"vite": "^7.3.1",
|
|
40
40
|
"vite-tsconfig-paths": "^5.1.4",
|
|
41
41
|
"vitest": "^3.2.4",
|
|
42
|
-
"@t402/
|
|
43
|
-
"@t402/
|
|
44
|
-
"@t402/
|
|
45
|
-
"@t402/
|
|
42
|
+
"@t402/svm": "2.4.0",
|
|
43
|
+
"@t402/tron": "2.4.0",
|
|
44
|
+
"@t402/evm": "2.4.0",
|
|
45
|
+
"@t402/ton": "2.4.0"
|
|
46
46
|
},
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@scure/base": "^1.2.6",
|
|
@@ -64,7 +64,8 @@
|
|
|
64
64
|
"viem": "^2.44.2",
|
|
65
65
|
"wagmi": "^2.17.1",
|
|
66
66
|
"zod": "^3.24.2",
|
|
67
|
-
"@t402/core": "2.
|
|
67
|
+
"@t402/core": "2.4.0",
|
|
68
|
+
"@t402/stacks": "2.4.0"
|
|
68
69
|
},
|
|
69
70
|
"peerDependencies": {
|
|
70
71
|
"react": "^19.0.0",
|