banksi 0.1.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 +84 -0
- package/dist/chunk-7MKH6B3K.mjs +62 -0
- package/dist/chunk-QHCD73JW.mjs +49 -0
- package/dist/client-jLNKFIPq.d.mts +50 -0
- package/dist/client-jLNKFIPq.d.ts +50 -0
- package/dist/express.d.mts +27 -0
- package/dist/express.d.ts +27 -0
- package/dist/express.js +129 -0
- package/dist/express.mjs +46 -0
- package/dist/index.d.mts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +132 -0
- package/dist/index.mjs +10 -0
- package/dist/next.d.mts +25 -0
- package/dist/next.d.ts +25 -0
- package/dist/next.js +132 -0
- package/dist/next.mjs +10 -0
- package/dist/react.d.mts +16 -0
- package/dist/react.d.ts +16 -0
- package/dist/react.js +213 -0
- package/dist/react.mjs +130 -0
- package/package.json +49 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# banksi
|
|
2
|
+
|
|
3
|
+
Crypto payment module for vibe coders. Add USDT/USDC payments to any app in one prompt.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install banksi
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Environment Variables
|
|
12
|
+
|
|
13
|
+
```env
|
|
14
|
+
BANKSI_API_KEY=bks_your_key_here # from banksi.io/merchant/settings
|
|
15
|
+
BANKSI_URL=https://banksi.io # optional, defaults to https://banksi.io
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
## Next.js — Paywall Middleware
|
|
19
|
+
|
|
20
|
+
```typescript
|
|
21
|
+
// app/api/premium/route.ts
|
|
22
|
+
import { createBanksiPaywall } from 'banksi/next';
|
|
23
|
+
|
|
24
|
+
const paywall = createBanksiPaywall({ amount: 0.10 });
|
|
25
|
+
|
|
26
|
+
export async function GET(request: Request) {
|
|
27
|
+
const blocked = await paywall(request);
|
|
28
|
+
if (blocked) return blocked; // 402 + payment instructions
|
|
29
|
+
return Response.json({ data: 'premium content' });
|
|
30
|
+
}
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Express — Paywall Middleware
|
|
34
|
+
|
|
35
|
+
```typescript
|
|
36
|
+
import { createBanksiPaywall } from 'banksi/express';
|
|
37
|
+
|
|
38
|
+
app.use('/api/premium', createBanksiPaywall({ amount: 0.10 }));
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## React — Pay Button
|
|
42
|
+
|
|
43
|
+
```tsx
|
|
44
|
+
import { BanksiPayButton } from 'banksi/react';
|
|
45
|
+
|
|
46
|
+
<BanksiPayButton
|
|
47
|
+
amount={4.50}
|
|
48
|
+
onPaymentConfirmed={(id) => console.log('Paid!', id)}
|
|
49
|
+
/>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## Client API
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
import { BanksiClient } from 'banksi';
|
|
56
|
+
|
|
57
|
+
const client = new BanksiClient();
|
|
58
|
+
|
|
59
|
+
const chains = await client.listChains();
|
|
60
|
+
const payment = await client.createPayment({ chainId: 'arbitrum', tokenId: '...', amount: 4.50 });
|
|
61
|
+
const status = await client.verifyPayment(payment.paymentId);
|
|
62
|
+
const confirmed = await client.isPaymentConfirmed(payment.paymentId);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## MCP Server
|
|
66
|
+
|
|
67
|
+
AI agents can integrate Banksi using the MCP server:
|
|
68
|
+
|
|
69
|
+
```json
|
|
70
|
+
{
|
|
71
|
+
"mcpServers": {
|
|
72
|
+
"banksi": {
|
|
73
|
+
"command": "npx",
|
|
74
|
+
"args": ["banksi-mcp"]
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
## Links
|
|
81
|
+
|
|
82
|
+
- [Docs](https://banksi.io/docs)
|
|
83
|
+
- [Dashboard](https://banksi.io/merchant)
|
|
84
|
+
- [Demo](https://banksi.io/examples/cafe)
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
// src/client.ts
|
|
2
|
+
function getConfig(override) {
|
|
3
|
+
return {
|
|
4
|
+
baseUrl: override?.baseUrl || process.env.BANKSI_URL || "https://banksi.io",
|
|
5
|
+
merchantSlug: override?.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || void 0,
|
|
6
|
+
apiKey: override?.apiKey || process.env.BANKSI_API_KEY || void 0
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
var BanksiClient = class {
|
|
10
|
+
constructor(config) {
|
|
11
|
+
const c = getConfig(config);
|
|
12
|
+
this.baseUrl = c.baseUrl.replace(/\/$/, "");
|
|
13
|
+
this.merchantSlug = c.merchantSlug;
|
|
14
|
+
this.apiKey = c.apiKey;
|
|
15
|
+
}
|
|
16
|
+
headers() {
|
|
17
|
+
const h = { "Content-Type": "application/json" };
|
|
18
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
19
|
+
return h;
|
|
20
|
+
}
|
|
21
|
+
async listChains() {
|
|
22
|
+
const res = await fetch(`${this.baseUrl}/api/chains`);
|
|
23
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
24
|
+
const data = await res.json();
|
|
25
|
+
return data.chains;
|
|
26
|
+
}
|
|
27
|
+
async createPayment(opts) {
|
|
28
|
+
const body = {
|
|
29
|
+
chainId: opts.chainId,
|
|
30
|
+
tokenId: opts.tokenId,
|
|
31
|
+
amount: opts.amount
|
|
32
|
+
};
|
|
33
|
+
if (!this.apiKey) {
|
|
34
|
+
body.merchantSlug = opts.merchantSlug || this.merchantSlug;
|
|
35
|
+
}
|
|
36
|
+
const res = await fetch(`${this.baseUrl}/api/x402/pay`, {
|
|
37
|
+
method: "POST",
|
|
38
|
+
headers: this.headers(),
|
|
39
|
+
body: JSON.stringify(body)
|
|
40
|
+
});
|
|
41
|
+
if (!res.ok) {
|
|
42
|
+
const data = await res.json().catch(() => ({}));
|
|
43
|
+
throw new Error(data.error || `Banksi API error: ${res.status}`);
|
|
44
|
+
}
|
|
45
|
+
return res.json();
|
|
46
|
+
}
|
|
47
|
+
async verifyPayment(paymentId) {
|
|
48
|
+
const res = await fetch(`${this.baseUrl}/api/payments/${paymentId}/status`, {
|
|
49
|
+
headers: this.headers()
|
|
50
|
+
});
|
|
51
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
52
|
+
return res.json();
|
|
53
|
+
}
|
|
54
|
+
async isPaymentConfirmed(paymentId) {
|
|
55
|
+
const status = await this.verifyPayment(paymentId);
|
|
56
|
+
return ["CONFIRMED", "SWEPT"].includes(status.status);
|
|
57
|
+
}
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export {
|
|
61
|
+
BanksiClient
|
|
62
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BanksiClient
|
|
3
|
+
} from "./chunk-7MKH6B3K.mjs";
|
|
4
|
+
|
|
5
|
+
// src/next.ts
|
|
6
|
+
function createBanksiPaywall(config) {
|
|
7
|
+
const client = new BanksiClient(config);
|
|
8
|
+
return async function paywall(request) {
|
|
9
|
+
const paymentId = request.headers.get("X-Payment");
|
|
10
|
+
if (paymentId) {
|
|
11
|
+
try {
|
|
12
|
+
const confirmed = await client.isPaymentConfirmed(paymentId);
|
|
13
|
+
if (confirmed) return null;
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const chains = await client.listChains();
|
|
18
|
+
const banksiUrl = config.baseUrl || process.env.BANKSI_URL || "http://localhost:3001";
|
|
19
|
+
const merchantSlug = config.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || "";
|
|
20
|
+
return Response.json(
|
|
21
|
+
{
|
|
22
|
+
status: 402,
|
|
23
|
+
paymentRequired: {
|
|
24
|
+
scheme: "x402",
|
|
25
|
+
description: config.description || "Payment required.",
|
|
26
|
+
merchant: merchantSlug,
|
|
27
|
+
amount: config.amount,
|
|
28
|
+
currency: "USD",
|
|
29
|
+
chains: chains.map((c) => ({
|
|
30
|
+
id: c.id,
|
|
31
|
+
name: c.name,
|
|
32
|
+
tokens: c.tokens.map((t) => ({ id: t.id, symbol: t.symbol }))
|
|
33
|
+
})),
|
|
34
|
+
payUrl: `${banksiUrl}/api/x402/pay`,
|
|
35
|
+
howToPay: [
|
|
36
|
+
`POST ${banksiUrl}/api/x402/pay with { "merchantSlug": "${merchantSlug}", "chainId": "<chain>", "tokenId": "<token>", "amount": ${config.amount} }`,
|
|
37
|
+
"Send the stablecoin to the returned address.",
|
|
38
|
+
"Retry with header: X-Payment: <paymentId>"
|
|
39
|
+
]
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
{ status: 402 }
|
|
43
|
+
);
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export {
|
|
48
|
+
createBanksiPaywall
|
|
49
|
+
};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
interface BanksiConfig {
|
|
2
|
+
/** Banksi instance URL */
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
/** Merchant store slug (optional if apiKey is set) */
|
|
5
|
+
merchantSlug?: string;
|
|
6
|
+
/** API key from banksi.io dashboard (bks_xxx) */
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
interface PaymentResult {
|
|
10
|
+
paymentId: string;
|
|
11
|
+
address: string;
|
|
12
|
+
amountExpected: string;
|
|
13
|
+
tokenSymbol: string;
|
|
14
|
+
chainName: string;
|
|
15
|
+
expiresAt: string;
|
|
16
|
+
}
|
|
17
|
+
interface PaymentStatus {
|
|
18
|
+
id: string;
|
|
19
|
+
status: 'PENDING' | 'CONFIRMING' | 'CONFIRMED' | 'SWEPT' | 'EXPIRED' | 'FAILED';
|
|
20
|
+
txHash: string | null;
|
|
21
|
+
amountReceived: string | null;
|
|
22
|
+
paidAt: string | null;
|
|
23
|
+
}
|
|
24
|
+
interface Chain {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
tokens: {
|
|
28
|
+
id: string;
|
|
29
|
+
symbol: string;
|
|
30
|
+
name: string;
|
|
31
|
+
}[];
|
|
32
|
+
}
|
|
33
|
+
declare class BanksiClient {
|
|
34
|
+
private baseUrl;
|
|
35
|
+
private merchantSlug?;
|
|
36
|
+
private apiKey?;
|
|
37
|
+
constructor(config?: Partial<BanksiConfig>);
|
|
38
|
+
private headers;
|
|
39
|
+
listChains(): Promise<Chain[]>;
|
|
40
|
+
createPayment(opts: {
|
|
41
|
+
chainId: string;
|
|
42
|
+
tokenId: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
merchantSlug?: string;
|
|
45
|
+
}): Promise<PaymentResult>;
|
|
46
|
+
verifyPayment(paymentId: string): Promise<PaymentStatus>;
|
|
47
|
+
isPaymentConfirmed(paymentId: string): Promise<boolean>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { type BanksiConfig as B, type Chain as C, type PaymentResult as P, BanksiClient as a, type PaymentStatus as b };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
interface BanksiConfig {
|
|
2
|
+
/** Banksi instance URL */
|
|
3
|
+
baseUrl: string;
|
|
4
|
+
/** Merchant store slug (optional if apiKey is set) */
|
|
5
|
+
merchantSlug?: string;
|
|
6
|
+
/** API key from banksi.io dashboard (bks_xxx) */
|
|
7
|
+
apiKey?: string;
|
|
8
|
+
}
|
|
9
|
+
interface PaymentResult {
|
|
10
|
+
paymentId: string;
|
|
11
|
+
address: string;
|
|
12
|
+
amountExpected: string;
|
|
13
|
+
tokenSymbol: string;
|
|
14
|
+
chainName: string;
|
|
15
|
+
expiresAt: string;
|
|
16
|
+
}
|
|
17
|
+
interface PaymentStatus {
|
|
18
|
+
id: string;
|
|
19
|
+
status: 'PENDING' | 'CONFIRMING' | 'CONFIRMED' | 'SWEPT' | 'EXPIRED' | 'FAILED';
|
|
20
|
+
txHash: string | null;
|
|
21
|
+
amountReceived: string | null;
|
|
22
|
+
paidAt: string | null;
|
|
23
|
+
}
|
|
24
|
+
interface Chain {
|
|
25
|
+
id: string;
|
|
26
|
+
name: string;
|
|
27
|
+
tokens: {
|
|
28
|
+
id: string;
|
|
29
|
+
symbol: string;
|
|
30
|
+
name: string;
|
|
31
|
+
}[];
|
|
32
|
+
}
|
|
33
|
+
declare class BanksiClient {
|
|
34
|
+
private baseUrl;
|
|
35
|
+
private merchantSlug?;
|
|
36
|
+
private apiKey?;
|
|
37
|
+
constructor(config?: Partial<BanksiConfig>);
|
|
38
|
+
private headers;
|
|
39
|
+
listChains(): Promise<Chain[]>;
|
|
40
|
+
createPayment(opts: {
|
|
41
|
+
chainId: string;
|
|
42
|
+
tokenId: string;
|
|
43
|
+
amount: number;
|
|
44
|
+
merchantSlug?: string;
|
|
45
|
+
}): Promise<PaymentResult>;
|
|
46
|
+
verifyPayment(paymentId: string): Promise<PaymentStatus>;
|
|
47
|
+
isPaymentConfirmed(paymentId: string): Promise<boolean>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { type BanksiConfig as B, type Chain as C, type PaymentResult as P, BanksiClient as a, type PaymentStatus as b };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { B as BanksiConfig } from './client-jLNKFIPq.mjs';
|
|
2
|
+
export { a as BanksiClient } from './client-jLNKFIPq.mjs';
|
|
3
|
+
|
|
4
|
+
type Request = {
|
|
5
|
+
headers: Record<string, string | string[] | undefined>;
|
|
6
|
+
};
|
|
7
|
+
type Response = {
|
|
8
|
+
status(code: number): Response;
|
|
9
|
+
json(body: unknown): void;
|
|
10
|
+
};
|
|
11
|
+
type NextFunction = () => void;
|
|
12
|
+
interface PaywallConfig extends Partial<BanksiConfig> {
|
|
13
|
+
amount: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Express paywall middleware.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { createBanksiPaywall } from 'banksi/express';
|
|
22
|
+
* app.use('/api/premium', createBanksiPaywall({ amount: 0.10 }));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function createBanksiPaywall(config: PaywallConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
26
|
+
|
|
27
|
+
export { createBanksiPaywall };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { B as BanksiConfig } from './client-jLNKFIPq.js';
|
|
2
|
+
export { a as BanksiClient } from './client-jLNKFIPq.js';
|
|
3
|
+
|
|
4
|
+
type Request = {
|
|
5
|
+
headers: Record<string, string | string[] | undefined>;
|
|
6
|
+
};
|
|
7
|
+
type Response = {
|
|
8
|
+
status(code: number): Response;
|
|
9
|
+
json(body: unknown): void;
|
|
10
|
+
};
|
|
11
|
+
type NextFunction = () => void;
|
|
12
|
+
interface PaywallConfig extends Partial<BanksiConfig> {
|
|
13
|
+
amount: number;
|
|
14
|
+
description?: string;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Express paywall middleware.
|
|
18
|
+
*
|
|
19
|
+
* Usage:
|
|
20
|
+
* ```ts
|
|
21
|
+
* import { createBanksiPaywall } from 'banksi/express';
|
|
22
|
+
* app.use('/api/premium', createBanksiPaywall({ amount: 0.10 }));
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
declare function createBanksiPaywall(config: PaywallConfig): (req: Request, res: Response, next: NextFunction) => Promise<void>;
|
|
26
|
+
|
|
27
|
+
export { createBanksiPaywall };
|
package/dist/express.js
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/express.ts
|
|
21
|
+
var express_exports = {};
|
|
22
|
+
__export(express_exports, {
|
|
23
|
+
BanksiClient: () => BanksiClient,
|
|
24
|
+
createBanksiPaywall: () => createBanksiPaywall
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(express_exports);
|
|
27
|
+
|
|
28
|
+
// src/client.ts
|
|
29
|
+
function getConfig(override) {
|
|
30
|
+
return {
|
|
31
|
+
baseUrl: override?.baseUrl || process.env.BANKSI_URL || "https://banksi.io",
|
|
32
|
+
merchantSlug: override?.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || void 0,
|
|
33
|
+
apiKey: override?.apiKey || process.env.BANKSI_API_KEY || void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var BanksiClient = class {
|
|
37
|
+
constructor(config) {
|
|
38
|
+
const c = getConfig(config);
|
|
39
|
+
this.baseUrl = c.baseUrl.replace(/\/$/, "");
|
|
40
|
+
this.merchantSlug = c.merchantSlug;
|
|
41
|
+
this.apiKey = c.apiKey;
|
|
42
|
+
}
|
|
43
|
+
headers() {
|
|
44
|
+
const h = { "Content-Type": "application/json" };
|
|
45
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
46
|
+
return h;
|
|
47
|
+
}
|
|
48
|
+
async listChains() {
|
|
49
|
+
const res = await fetch(`${this.baseUrl}/api/chains`);
|
|
50
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
return data.chains;
|
|
53
|
+
}
|
|
54
|
+
async createPayment(opts) {
|
|
55
|
+
const body = {
|
|
56
|
+
chainId: opts.chainId,
|
|
57
|
+
tokenId: opts.tokenId,
|
|
58
|
+
amount: opts.amount
|
|
59
|
+
};
|
|
60
|
+
if (!this.apiKey) {
|
|
61
|
+
body.merchantSlug = opts.merchantSlug || this.merchantSlug;
|
|
62
|
+
}
|
|
63
|
+
const res = await fetch(`${this.baseUrl}/api/x402/pay`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: this.headers(),
|
|
66
|
+
body: JSON.stringify(body)
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
const data = await res.json().catch(() => ({}));
|
|
70
|
+
throw new Error(data.error || `Banksi API error: ${res.status}`);
|
|
71
|
+
}
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
async verifyPayment(paymentId) {
|
|
75
|
+
const res = await fetch(`${this.baseUrl}/api/payments/${paymentId}/status`, {
|
|
76
|
+
headers: this.headers()
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
79
|
+
return res.json();
|
|
80
|
+
}
|
|
81
|
+
async isPaymentConfirmed(paymentId) {
|
|
82
|
+
const status = await this.verifyPayment(paymentId);
|
|
83
|
+
return ["CONFIRMED", "SWEPT"].includes(status.status);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/express.ts
|
|
88
|
+
function createBanksiPaywall(config) {
|
|
89
|
+
const client = new BanksiClient(config);
|
|
90
|
+
return async function paywall(req, res, next) {
|
|
91
|
+
const paymentId = req.headers["x-payment"];
|
|
92
|
+
if (paymentId) {
|
|
93
|
+
try {
|
|
94
|
+
const confirmed = await client.isPaymentConfirmed(paymentId);
|
|
95
|
+
if (confirmed) return next();
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const chains = await client.listChains();
|
|
100
|
+
const banksiUrl = config.baseUrl || process.env.BANKSI_URL || "http://localhost:3001";
|
|
101
|
+
const merchantSlug = config.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || "";
|
|
102
|
+
res.status(402).json({
|
|
103
|
+
status: 402,
|
|
104
|
+
paymentRequired: {
|
|
105
|
+
scheme: "x402",
|
|
106
|
+
description: config.description || "Payment required.",
|
|
107
|
+
merchant: merchantSlug,
|
|
108
|
+
amount: config.amount,
|
|
109
|
+
currency: "USD",
|
|
110
|
+
chains: chains.map((c) => ({
|
|
111
|
+
id: c.id,
|
|
112
|
+
name: c.name,
|
|
113
|
+
tokens: c.tokens.map((t) => ({ id: t.id, symbol: t.symbol }))
|
|
114
|
+
})),
|
|
115
|
+
payUrl: `${banksiUrl}/api/x402/pay`,
|
|
116
|
+
howToPay: [
|
|
117
|
+
`POST ${banksiUrl}/api/x402/pay with { "merchantSlug": "${merchantSlug}", "chainId": "<chain>", "tokenId": "<token>", "amount": ${config.amount} }`,
|
|
118
|
+
"Send the stablecoin to the returned address.",
|
|
119
|
+
"Retry with header: X-Payment: <paymentId>"
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
126
|
+
0 && (module.exports = {
|
|
127
|
+
BanksiClient,
|
|
128
|
+
createBanksiPaywall
|
|
129
|
+
});
|
package/dist/express.mjs
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import {
|
|
2
|
+
BanksiClient
|
|
3
|
+
} from "./chunk-7MKH6B3K.mjs";
|
|
4
|
+
|
|
5
|
+
// src/express.ts
|
|
6
|
+
function createBanksiPaywall(config) {
|
|
7
|
+
const client = new BanksiClient(config);
|
|
8
|
+
return async function paywall(req, res, next) {
|
|
9
|
+
const paymentId = req.headers["x-payment"];
|
|
10
|
+
if (paymentId) {
|
|
11
|
+
try {
|
|
12
|
+
const confirmed = await client.isPaymentConfirmed(paymentId);
|
|
13
|
+
if (confirmed) return next();
|
|
14
|
+
} catch {
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
const chains = await client.listChains();
|
|
18
|
+
const banksiUrl = config.baseUrl || process.env.BANKSI_URL || "http://localhost:3001";
|
|
19
|
+
const merchantSlug = config.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || "";
|
|
20
|
+
res.status(402).json({
|
|
21
|
+
status: 402,
|
|
22
|
+
paymentRequired: {
|
|
23
|
+
scheme: "x402",
|
|
24
|
+
description: config.description || "Payment required.",
|
|
25
|
+
merchant: merchantSlug,
|
|
26
|
+
amount: config.amount,
|
|
27
|
+
currency: "USD",
|
|
28
|
+
chains: chains.map((c) => ({
|
|
29
|
+
id: c.id,
|
|
30
|
+
name: c.name,
|
|
31
|
+
tokens: c.tokens.map((t) => ({ id: t.id, symbol: t.symbol }))
|
|
32
|
+
})),
|
|
33
|
+
payUrl: `${banksiUrl}/api/x402/pay`,
|
|
34
|
+
howToPay: [
|
|
35
|
+
`POST ${banksiUrl}/api/x402/pay with { "merchantSlug": "${merchantSlug}", "chainId": "<chain>", "tokenId": "<token>", "amount": ${config.amount} }`,
|
|
36
|
+
"Send the stablecoin to the returned address.",
|
|
37
|
+
"Retry with header: X-Payment: <paymentId>"
|
|
38
|
+
]
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
BanksiClient,
|
|
45
|
+
createBanksiPaywall
|
|
46
|
+
};
|
package/dist/index.d.mts
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
BanksiClient: () => BanksiClient,
|
|
24
|
+
createBanksiPaywall: () => createBanksiPaywall
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(src_exports);
|
|
27
|
+
|
|
28
|
+
// src/client.ts
|
|
29
|
+
function getConfig(override) {
|
|
30
|
+
return {
|
|
31
|
+
baseUrl: override?.baseUrl || process.env.BANKSI_URL || "https://banksi.io",
|
|
32
|
+
merchantSlug: override?.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || void 0,
|
|
33
|
+
apiKey: override?.apiKey || process.env.BANKSI_API_KEY || void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var BanksiClient = class {
|
|
37
|
+
constructor(config) {
|
|
38
|
+
const c = getConfig(config);
|
|
39
|
+
this.baseUrl = c.baseUrl.replace(/\/$/, "");
|
|
40
|
+
this.merchantSlug = c.merchantSlug;
|
|
41
|
+
this.apiKey = c.apiKey;
|
|
42
|
+
}
|
|
43
|
+
headers() {
|
|
44
|
+
const h = { "Content-Type": "application/json" };
|
|
45
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
46
|
+
return h;
|
|
47
|
+
}
|
|
48
|
+
async listChains() {
|
|
49
|
+
const res = await fetch(`${this.baseUrl}/api/chains`);
|
|
50
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
return data.chains;
|
|
53
|
+
}
|
|
54
|
+
async createPayment(opts) {
|
|
55
|
+
const body = {
|
|
56
|
+
chainId: opts.chainId,
|
|
57
|
+
tokenId: opts.tokenId,
|
|
58
|
+
amount: opts.amount
|
|
59
|
+
};
|
|
60
|
+
if (!this.apiKey) {
|
|
61
|
+
body.merchantSlug = opts.merchantSlug || this.merchantSlug;
|
|
62
|
+
}
|
|
63
|
+
const res = await fetch(`${this.baseUrl}/api/x402/pay`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: this.headers(),
|
|
66
|
+
body: JSON.stringify(body)
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
const data = await res.json().catch(() => ({}));
|
|
70
|
+
throw new Error(data.error || `Banksi API error: ${res.status}`);
|
|
71
|
+
}
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
async verifyPayment(paymentId) {
|
|
75
|
+
const res = await fetch(`${this.baseUrl}/api/payments/${paymentId}/status`, {
|
|
76
|
+
headers: this.headers()
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
79
|
+
return res.json();
|
|
80
|
+
}
|
|
81
|
+
async isPaymentConfirmed(paymentId) {
|
|
82
|
+
const status = await this.verifyPayment(paymentId);
|
|
83
|
+
return ["CONFIRMED", "SWEPT"].includes(status.status);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/next.ts
|
|
88
|
+
function createBanksiPaywall(config) {
|
|
89
|
+
const client = new BanksiClient(config);
|
|
90
|
+
return async function paywall(request) {
|
|
91
|
+
const paymentId = request.headers.get("X-Payment");
|
|
92
|
+
if (paymentId) {
|
|
93
|
+
try {
|
|
94
|
+
const confirmed = await client.isPaymentConfirmed(paymentId);
|
|
95
|
+
if (confirmed) return null;
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const chains = await client.listChains();
|
|
100
|
+
const banksiUrl = config.baseUrl || process.env.BANKSI_URL || "http://localhost:3001";
|
|
101
|
+
const merchantSlug = config.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || "";
|
|
102
|
+
return Response.json(
|
|
103
|
+
{
|
|
104
|
+
status: 402,
|
|
105
|
+
paymentRequired: {
|
|
106
|
+
scheme: "x402",
|
|
107
|
+
description: config.description || "Payment required.",
|
|
108
|
+
merchant: merchantSlug,
|
|
109
|
+
amount: config.amount,
|
|
110
|
+
currency: "USD",
|
|
111
|
+
chains: chains.map((c) => ({
|
|
112
|
+
id: c.id,
|
|
113
|
+
name: c.name,
|
|
114
|
+
tokens: c.tokens.map((t) => ({ id: t.id, symbol: t.symbol }))
|
|
115
|
+
})),
|
|
116
|
+
payUrl: `${banksiUrl}/api/x402/pay`,
|
|
117
|
+
howToPay: [
|
|
118
|
+
`POST ${banksiUrl}/api/x402/pay with { "merchantSlug": "${merchantSlug}", "chainId": "<chain>", "tokenId": "<token>", "amount": ${config.amount} }`,
|
|
119
|
+
"Send the stablecoin to the returned address.",
|
|
120
|
+
"Retry with header: X-Payment: <paymentId>"
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{ status: 402 }
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
129
|
+
0 && (module.exports = {
|
|
130
|
+
BanksiClient,
|
|
131
|
+
createBanksiPaywall
|
|
132
|
+
});
|
package/dist/index.mjs
ADDED
package/dist/next.d.mts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { B as BanksiConfig } from './client-jLNKFIPq.mjs';
|
|
2
|
+
export { a as BanksiClient } from './client-jLNKFIPq.mjs';
|
|
3
|
+
|
|
4
|
+
interface PaywallConfig extends Partial<BanksiConfig> {
|
|
5
|
+
amount: number;
|
|
6
|
+
description?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Next.js App Router paywall middleware.
|
|
10
|
+
*
|
|
11
|
+
* Usage in a route handler:
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { createBanksiPaywall } from 'banksi/next';
|
|
14
|
+
* const paywall = createBanksiPaywall({ amount: 0.10, description: 'Premium API' });
|
|
15
|
+
*
|
|
16
|
+
* export async function GET(request: NextRequest) {
|
|
17
|
+
* const blocked = await paywall(request);
|
|
18
|
+
* if (blocked) return blocked;
|
|
19
|
+
* return NextResponse.json({ data: 'premium content' });
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function createBanksiPaywall(config: PaywallConfig): (request: Request) => Promise<Response | null>;
|
|
24
|
+
|
|
25
|
+
export { createBanksiPaywall };
|
package/dist/next.d.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { B as BanksiConfig } from './client-jLNKFIPq.js';
|
|
2
|
+
export { a as BanksiClient } from './client-jLNKFIPq.js';
|
|
3
|
+
|
|
4
|
+
interface PaywallConfig extends Partial<BanksiConfig> {
|
|
5
|
+
amount: number;
|
|
6
|
+
description?: string;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Next.js App Router paywall middleware.
|
|
10
|
+
*
|
|
11
|
+
* Usage in a route handler:
|
|
12
|
+
* ```ts
|
|
13
|
+
* import { createBanksiPaywall } from 'banksi/next';
|
|
14
|
+
* const paywall = createBanksiPaywall({ amount: 0.10, description: 'Premium API' });
|
|
15
|
+
*
|
|
16
|
+
* export async function GET(request: NextRequest) {
|
|
17
|
+
* const blocked = await paywall(request);
|
|
18
|
+
* if (blocked) return blocked;
|
|
19
|
+
* return NextResponse.json({ data: 'premium content' });
|
|
20
|
+
* }
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
declare function createBanksiPaywall(config: PaywallConfig): (request: Request) => Promise<Response | null>;
|
|
24
|
+
|
|
25
|
+
export { createBanksiPaywall };
|
package/dist/next.js
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/next.ts
|
|
21
|
+
var next_exports = {};
|
|
22
|
+
__export(next_exports, {
|
|
23
|
+
BanksiClient: () => BanksiClient,
|
|
24
|
+
createBanksiPaywall: () => createBanksiPaywall
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(next_exports);
|
|
27
|
+
|
|
28
|
+
// src/client.ts
|
|
29
|
+
function getConfig(override) {
|
|
30
|
+
return {
|
|
31
|
+
baseUrl: override?.baseUrl || process.env.BANKSI_URL || "https://banksi.io",
|
|
32
|
+
merchantSlug: override?.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || void 0,
|
|
33
|
+
apiKey: override?.apiKey || process.env.BANKSI_API_KEY || void 0
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
var BanksiClient = class {
|
|
37
|
+
constructor(config) {
|
|
38
|
+
const c = getConfig(config);
|
|
39
|
+
this.baseUrl = c.baseUrl.replace(/\/$/, "");
|
|
40
|
+
this.merchantSlug = c.merchantSlug;
|
|
41
|
+
this.apiKey = c.apiKey;
|
|
42
|
+
}
|
|
43
|
+
headers() {
|
|
44
|
+
const h = { "Content-Type": "application/json" };
|
|
45
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
46
|
+
return h;
|
|
47
|
+
}
|
|
48
|
+
async listChains() {
|
|
49
|
+
const res = await fetch(`${this.baseUrl}/api/chains`);
|
|
50
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
51
|
+
const data = await res.json();
|
|
52
|
+
return data.chains;
|
|
53
|
+
}
|
|
54
|
+
async createPayment(opts) {
|
|
55
|
+
const body = {
|
|
56
|
+
chainId: opts.chainId,
|
|
57
|
+
tokenId: opts.tokenId,
|
|
58
|
+
amount: opts.amount
|
|
59
|
+
};
|
|
60
|
+
if (!this.apiKey) {
|
|
61
|
+
body.merchantSlug = opts.merchantSlug || this.merchantSlug;
|
|
62
|
+
}
|
|
63
|
+
const res = await fetch(`${this.baseUrl}/api/x402/pay`, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: this.headers(),
|
|
66
|
+
body: JSON.stringify(body)
|
|
67
|
+
});
|
|
68
|
+
if (!res.ok) {
|
|
69
|
+
const data = await res.json().catch(() => ({}));
|
|
70
|
+
throw new Error(data.error || `Banksi API error: ${res.status}`);
|
|
71
|
+
}
|
|
72
|
+
return res.json();
|
|
73
|
+
}
|
|
74
|
+
async verifyPayment(paymentId) {
|
|
75
|
+
const res = await fetch(`${this.baseUrl}/api/payments/${paymentId}/status`, {
|
|
76
|
+
headers: this.headers()
|
|
77
|
+
});
|
|
78
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
79
|
+
return res.json();
|
|
80
|
+
}
|
|
81
|
+
async isPaymentConfirmed(paymentId) {
|
|
82
|
+
const status = await this.verifyPayment(paymentId);
|
|
83
|
+
return ["CONFIRMED", "SWEPT"].includes(status.status);
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// src/next.ts
|
|
88
|
+
function createBanksiPaywall(config) {
|
|
89
|
+
const client = new BanksiClient(config);
|
|
90
|
+
return async function paywall(request) {
|
|
91
|
+
const paymentId = request.headers.get("X-Payment");
|
|
92
|
+
if (paymentId) {
|
|
93
|
+
try {
|
|
94
|
+
const confirmed = await client.isPaymentConfirmed(paymentId);
|
|
95
|
+
if (confirmed) return null;
|
|
96
|
+
} catch {
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const chains = await client.listChains();
|
|
100
|
+
const banksiUrl = config.baseUrl || process.env.BANKSI_URL || "http://localhost:3001";
|
|
101
|
+
const merchantSlug = config.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || "";
|
|
102
|
+
return Response.json(
|
|
103
|
+
{
|
|
104
|
+
status: 402,
|
|
105
|
+
paymentRequired: {
|
|
106
|
+
scheme: "x402",
|
|
107
|
+
description: config.description || "Payment required.",
|
|
108
|
+
merchant: merchantSlug,
|
|
109
|
+
amount: config.amount,
|
|
110
|
+
currency: "USD",
|
|
111
|
+
chains: chains.map((c) => ({
|
|
112
|
+
id: c.id,
|
|
113
|
+
name: c.name,
|
|
114
|
+
tokens: c.tokens.map((t) => ({ id: t.id, symbol: t.symbol }))
|
|
115
|
+
})),
|
|
116
|
+
payUrl: `${banksiUrl}/api/x402/pay`,
|
|
117
|
+
howToPay: [
|
|
118
|
+
`POST ${banksiUrl}/api/x402/pay with { "merchantSlug": "${merchantSlug}", "chainId": "<chain>", "tokenId": "<token>", "amount": ${config.amount} }`,
|
|
119
|
+
"Send the stablecoin to the returned address.",
|
|
120
|
+
"Retry with header: X-Payment: <paymentId>"
|
|
121
|
+
]
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
{ status: 402 }
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
129
|
+
0 && (module.exports = {
|
|
130
|
+
BanksiClient,
|
|
131
|
+
createBanksiPaywall
|
|
132
|
+
});
|
package/dist/next.mjs
ADDED
package/dist/react.d.mts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { B as BanksiConfig, P as PaymentResult } from './client-jLNKFIPq.mjs';
|
|
3
|
+
export { a as BanksiClient } from './client-jLNKFIPq.mjs';
|
|
4
|
+
|
|
5
|
+
interface BanksiPayButtonProps extends Partial<BanksiConfig> {
|
|
6
|
+
amount: number;
|
|
7
|
+
chainId?: string;
|
|
8
|
+
tokenId?: string;
|
|
9
|
+
onPaymentCreated?: (payment: PaymentResult) => void;
|
|
10
|
+
onPaymentConfirmed?: (paymentId: string) => void;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function BanksiPayButton({ amount, chainId, tokenId, onPaymentCreated, onPaymentConfirmed, children, className, ...config }: BanksiPayButtonProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
|
|
16
|
+
export { BanksiPayButton };
|
package/dist/react.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
2
|
+
import { B as BanksiConfig, P as PaymentResult } from './client-jLNKFIPq.js';
|
|
3
|
+
export { a as BanksiClient } from './client-jLNKFIPq.js';
|
|
4
|
+
|
|
5
|
+
interface BanksiPayButtonProps extends Partial<BanksiConfig> {
|
|
6
|
+
amount: number;
|
|
7
|
+
chainId?: string;
|
|
8
|
+
tokenId?: string;
|
|
9
|
+
onPaymentCreated?: (payment: PaymentResult) => void;
|
|
10
|
+
onPaymentConfirmed?: (paymentId: string) => void;
|
|
11
|
+
children?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
}
|
|
14
|
+
declare function BanksiPayButton({ amount, chainId, tokenId, onPaymentCreated, onPaymentConfirmed, children, className, ...config }: BanksiPayButtonProps): react_jsx_runtime.JSX.Element;
|
|
15
|
+
|
|
16
|
+
export { BanksiPayButton };
|
package/dist/react.js
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
20
|
+
|
|
21
|
+
// src/react.tsx
|
|
22
|
+
var react_exports = {};
|
|
23
|
+
__export(react_exports, {
|
|
24
|
+
BanksiClient: () => BanksiClient,
|
|
25
|
+
BanksiPayButton: () => BanksiPayButton
|
|
26
|
+
});
|
|
27
|
+
module.exports = __toCommonJS(react_exports);
|
|
28
|
+
var import_react = require("react");
|
|
29
|
+
|
|
30
|
+
// src/client.ts
|
|
31
|
+
function getConfig(override) {
|
|
32
|
+
return {
|
|
33
|
+
baseUrl: override?.baseUrl || process.env.BANKSI_URL || "https://banksi.io",
|
|
34
|
+
merchantSlug: override?.merchantSlug || process.env.BANKSI_MERCHANT_SLUG || void 0,
|
|
35
|
+
apiKey: override?.apiKey || process.env.BANKSI_API_KEY || void 0
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
var BanksiClient = class {
|
|
39
|
+
constructor(config) {
|
|
40
|
+
const c = getConfig(config);
|
|
41
|
+
this.baseUrl = c.baseUrl.replace(/\/$/, "");
|
|
42
|
+
this.merchantSlug = c.merchantSlug;
|
|
43
|
+
this.apiKey = c.apiKey;
|
|
44
|
+
}
|
|
45
|
+
headers() {
|
|
46
|
+
const h = { "Content-Type": "application/json" };
|
|
47
|
+
if (this.apiKey) h["Authorization"] = `Bearer ${this.apiKey}`;
|
|
48
|
+
return h;
|
|
49
|
+
}
|
|
50
|
+
async listChains() {
|
|
51
|
+
const res = await fetch(`${this.baseUrl}/api/chains`);
|
|
52
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
53
|
+
const data = await res.json();
|
|
54
|
+
return data.chains;
|
|
55
|
+
}
|
|
56
|
+
async createPayment(opts) {
|
|
57
|
+
const body = {
|
|
58
|
+
chainId: opts.chainId,
|
|
59
|
+
tokenId: opts.tokenId,
|
|
60
|
+
amount: opts.amount
|
|
61
|
+
};
|
|
62
|
+
if (!this.apiKey) {
|
|
63
|
+
body.merchantSlug = opts.merchantSlug || this.merchantSlug;
|
|
64
|
+
}
|
|
65
|
+
const res = await fetch(`${this.baseUrl}/api/x402/pay`, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: this.headers(),
|
|
68
|
+
body: JSON.stringify(body)
|
|
69
|
+
});
|
|
70
|
+
if (!res.ok) {
|
|
71
|
+
const data = await res.json().catch(() => ({}));
|
|
72
|
+
throw new Error(data.error || `Banksi API error: ${res.status}`);
|
|
73
|
+
}
|
|
74
|
+
return res.json();
|
|
75
|
+
}
|
|
76
|
+
async verifyPayment(paymentId) {
|
|
77
|
+
const res = await fetch(`${this.baseUrl}/api/payments/${paymentId}/status`, {
|
|
78
|
+
headers: this.headers()
|
|
79
|
+
});
|
|
80
|
+
if (!res.ok) throw new Error(`Banksi API error: ${res.status}`);
|
|
81
|
+
return res.json();
|
|
82
|
+
}
|
|
83
|
+
async isPaymentConfirmed(paymentId) {
|
|
84
|
+
const status = await this.verifyPayment(paymentId);
|
|
85
|
+
return ["CONFIRMED", "SWEPT"].includes(status.status);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
// src/react.tsx
|
|
90
|
+
var import_jsx_runtime = require("react/jsx-runtime");
|
|
91
|
+
function BanksiPayButton({
|
|
92
|
+
amount,
|
|
93
|
+
chainId,
|
|
94
|
+
tokenId,
|
|
95
|
+
onPaymentCreated,
|
|
96
|
+
onPaymentConfirmed,
|
|
97
|
+
children,
|
|
98
|
+
className,
|
|
99
|
+
...config
|
|
100
|
+
}) {
|
|
101
|
+
const [client] = (0, import_react.useState)(() => new BanksiClient(config));
|
|
102
|
+
const [chains, setChains] = (0, import_react.useState)([]);
|
|
103
|
+
const [step, setStep] = (0, import_react.useState)("idle");
|
|
104
|
+
const [selectedChain, setSelectedChain] = (0, import_react.useState)(chainId || "");
|
|
105
|
+
const [selectedToken, setSelectedToken] = (0, import_react.useState)(tokenId || "");
|
|
106
|
+
const [payment, setPayment] = (0, import_react.useState)(null);
|
|
107
|
+
const [error, setError] = (0, import_react.useState)("");
|
|
108
|
+
const [copied, setCopied] = (0, import_react.useState)(false);
|
|
109
|
+
(0, import_react.useEffect)(() => {
|
|
110
|
+
if (step === "select" && chains.length === 0) {
|
|
111
|
+
client.listChains().then(setChains).catch(() => setError("Failed to load chains"));
|
|
112
|
+
}
|
|
113
|
+
}, [step, chains.length, client]);
|
|
114
|
+
(0, import_react.useEffect)(() => {
|
|
115
|
+
if (!payment || step !== "paying") return;
|
|
116
|
+
const iv = setInterval(async () => {
|
|
117
|
+
try {
|
|
118
|
+
const confirmed = await client.isPaymentConfirmed(payment.paymentId);
|
|
119
|
+
if (confirmed) {
|
|
120
|
+
setStep("done");
|
|
121
|
+
onPaymentConfirmed?.(payment.paymentId);
|
|
122
|
+
clearInterval(iv);
|
|
123
|
+
}
|
|
124
|
+
} catch {
|
|
125
|
+
}
|
|
126
|
+
}, 5e3);
|
|
127
|
+
return () => clearInterval(iv);
|
|
128
|
+
}, [payment, step, client, onPaymentConfirmed]);
|
|
129
|
+
const handlePay = (0, import_react.useCallback)(async () => {
|
|
130
|
+
if (!selectedChain || !selectedToken) return;
|
|
131
|
+
setError("");
|
|
132
|
+
try {
|
|
133
|
+
const result = await client.createPayment({ chainId: selectedChain, tokenId: selectedToken, amount });
|
|
134
|
+
setPayment(result);
|
|
135
|
+
setStep("paying");
|
|
136
|
+
onPaymentCreated?.(result);
|
|
137
|
+
} catch (err) {
|
|
138
|
+
setError(err instanceof Error ? err.message : "Payment failed");
|
|
139
|
+
}
|
|
140
|
+
}, [client, selectedChain, selectedToken, amount, onPaymentCreated]);
|
|
141
|
+
const handleCopy = (0, import_react.useCallback)(async () => {
|
|
142
|
+
if (!payment) return;
|
|
143
|
+
await navigator.clipboard.writeText(payment.address);
|
|
144
|
+
setCopied(true);
|
|
145
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
146
|
+
}, [payment]);
|
|
147
|
+
if (step === "idle") {
|
|
148
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => chainId && tokenId ? handlePay() : setStep("select"), className: className || "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700", children: children || `Pay $${amount.toFixed(2)}` });
|
|
149
|
+
}
|
|
150
|
+
const selectedChainData = chains.find((c) => c.id === selectedChain);
|
|
151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "w-full max-w-sm rounded-xl border border-gray-200 bg-white p-5 shadow-lg space-y-4", children: [
|
|
152
|
+
error && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-red-600", children: error }),
|
|
153
|
+
step === "select" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
154
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-medium text-gray-700", children: "Select network & token" }),
|
|
155
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex flex-wrap gap-2", children: chains.map((c) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
156
|
+
"button",
|
|
157
|
+
{
|
|
158
|
+
onClick: () => {
|
|
159
|
+
setSelectedChain(c.id);
|
|
160
|
+
setSelectedToken("");
|
|
161
|
+
},
|
|
162
|
+
className: `rounded-lg border px-3 py-1.5 text-xs font-medium ${selectedChain === c.id ? "border-indigo-500 bg-indigo-50 text-indigo-700" : "border-gray-200 text-gray-600"}`,
|
|
163
|
+
children: c.name
|
|
164
|
+
},
|
|
165
|
+
c.id
|
|
166
|
+
)) }),
|
|
167
|
+
selectedChainData && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "flex gap-2", children: selectedChainData.tokens.map((tk) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
|
|
168
|
+
"button",
|
|
169
|
+
{
|
|
170
|
+
onClick: () => setSelectedToken(tk.id),
|
|
171
|
+
className: `rounded-lg border px-3 py-1.5 text-xs font-medium ${selectedToken === tk.id ? "border-indigo-500 bg-indigo-50 text-indigo-700" : "border-gray-200 text-gray-600"}`,
|
|
172
|
+
children: tk.symbol
|
|
173
|
+
},
|
|
174
|
+
tk.id
|
|
175
|
+
)) }),
|
|
176
|
+
selectedToken && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("button", { onClick: handlePay, className: "w-full rounded-lg bg-indigo-600 py-2 text-sm font-medium text-white hover:bg-indigo-700", children: [
|
|
177
|
+
"Pay $",
|
|
178
|
+
amount.toFixed(2)
|
|
179
|
+
] }),
|
|
180
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: () => setStep("idle"), className: "text-xs text-gray-400 hover:text-gray-600", children: "Cancel" })
|
|
181
|
+
] }),
|
|
182
|
+
step === "paying" && payment && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
|
|
183
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm text-gray-500", children: "Send exactly" }),
|
|
184
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-lg font-bold text-gray-900", children: [
|
|
185
|
+
payment.amountExpected,
|
|
186
|
+
" ",
|
|
187
|
+
payment.tokenSymbol
|
|
188
|
+
] }),
|
|
189
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("p", { className: "text-xs text-gray-500", children: [
|
|
190
|
+
"on ",
|
|
191
|
+
payment.chainName
|
|
192
|
+
] }),
|
|
193
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { onClick: handleCopy, className: "w-full rounded-lg bg-gray-50 border border-gray-200 px-3 py-2.5 font-mono text-xs text-gray-800 break-all text-left hover:bg-gray-100", children: payment.address }),
|
|
194
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-xs text-center text-gray-400", children: copied ? "Copied!" : "Tap to copy" }),
|
|
195
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [
|
|
196
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: "relative flex h-2 w-2", children: [
|
|
197
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "absolute h-full w-full animate-ping rounded-full bg-amber-400 opacity-75" }),
|
|
198
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("span", { className: "relative h-2 w-2 rounded-full bg-amber-400" })
|
|
199
|
+
] }),
|
|
200
|
+
"Waiting for payment..."
|
|
201
|
+
] })
|
|
202
|
+
] }),
|
|
203
|
+
step === "done" && /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "text-center py-2", children: [
|
|
204
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("svg", { className: "h-6 w-6 text-green-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }) }),
|
|
205
|
+
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "text-sm font-semibold text-green-700", children: "Payment Confirmed" })
|
|
206
|
+
] })
|
|
207
|
+
] });
|
|
208
|
+
}
|
|
209
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
210
|
+
0 && (module.exports = {
|
|
211
|
+
BanksiClient,
|
|
212
|
+
BanksiPayButton
|
|
213
|
+
});
|
package/dist/react.mjs
ADDED
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
BanksiClient
|
|
4
|
+
} from "./chunk-7MKH6B3K.mjs";
|
|
5
|
+
|
|
6
|
+
// src/react.tsx
|
|
7
|
+
import { useState, useEffect, useCallback } from "react";
|
|
8
|
+
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
9
|
+
function BanksiPayButton({
|
|
10
|
+
amount,
|
|
11
|
+
chainId,
|
|
12
|
+
tokenId,
|
|
13
|
+
onPaymentCreated,
|
|
14
|
+
onPaymentConfirmed,
|
|
15
|
+
children,
|
|
16
|
+
className,
|
|
17
|
+
...config
|
|
18
|
+
}) {
|
|
19
|
+
const [client] = useState(() => new BanksiClient(config));
|
|
20
|
+
const [chains, setChains] = useState([]);
|
|
21
|
+
const [step, setStep] = useState("idle");
|
|
22
|
+
const [selectedChain, setSelectedChain] = useState(chainId || "");
|
|
23
|
+
const [selectedToken, setSelectedToken] = useState(tokenId || "");
|
|
24
|
+
const [payment, setPayment] = useState(null);
|
|
25
|
+
const [error, setError] = useState("");
|
|
26
|
+
const [copied, setCopied] = useState(false);
|
|
27
|
+
useEffect(() => {
|
|
28
|
+
if (step === "select" && chains.length === 0) {
|
|
29
|
+
client.listChains().then(setChains).catch(() => setError("Failed to load chains"));
|
|
30
|
+
}
|
|
31
|
+
}, [step, chains.length, client]);
|
|
32
|
+
useEffect(() => {
|
|
33
|
+
if (!payment || step !== "paying") return;
|
|
34
|
+
const iv = setInterval(async () => {
|
|
35
|
+
try {
|
|
36
|
+
const confirmed = await client.isPaymentConfirmed(payment.paymentId);
|
|
37
|
+
if (confirmed) {
|
|
38
|
+
setStep("done");
|
|
39
|
+
onPaymentConfirmed?.(payment.paymentId);
|
|
40
|
+
clearInterval(iv);
|
|
41
|
+
}
|
|
42
|
+
} catch {
|
|
43
|
+
}
|
|
44
|
+
}, 5e3);
|
|
45
|
+
return () => clearInterval(iv);
|
|
46
|
+
}, [payment, step, client, onPaymentConfirmed]);
|
|
47
|
+
const handlePay = useCallback(async () => {
|
|
48
|
+
if (!selectedChain || !selectedToken) return;
|
|
49
|
+
setError("");
|
|
50
|
+
try {
|
|
51
|
+
const result = await client.createPayment({ chainId: selectedChain, tokenId: selectedToken, amount });
|
|
52
|
+
setPayment(result);
|
|
53
|
+
setStep("paying");
|
|
54
|
+
onPaymentCreated?.(result);
|
|
55
|
+
} catch (err) {
|
|
56
|
+
setError(err instanceof Error ? err.message : "Payment failed");
|
|
57
|
+
}
|
|
58
|
+
}, [client, selectedChain, selectedToken, amount, onPaymentCreated]);
|
|
59
|
+
const handleCopy = useCallback(async () => {
|
|
60
|
+
if (!payment) return;
|
|
61
|
+
await navigator.clipboard.writeText(payment.address);
|
|
62
|
+
setCopied(true);
|
|
63
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
64
|
+
}, [payment]);
|
|
65
|
+
if (step === "idle") {
|
|
66
|
+
return /* @__PURE__ */ jsx("button", { onClick: () => chainId && tokenId ? handlePay() : setStep("select"), className: className || "rounded-lg bg-indigo-600 px-4 py-2 text-sm font-medium text-white hover:bg-indigo-700", children: children || `Pay $${amount.toFixed(2)}` });
|
|
67
|
+
}
|
|
68
|
+
const selectedChainData = chains.find((c) => c.id === selectedChain);
|
|
69
|
+
return /* @__PURE__ */ jsxs("div", { className: "w-full max-w-sm rounded-xl border border-gray-200 bg-white p-5 shadow-lg space-y-4", children: [
|
|
70
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-red-600", children: error }),
|
|
71
|
+
step === "select" && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
72
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-gray-700", children: "Select network & token" }),
|
|
73
|
+
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-2", children: chains.map((c) => /* @__PURE__ */ jsx(
|
|
74
|
+
"button",
|
|
75
|
+
{
|
|
76
|
+
onClick: () => {
|
|
77
|
+
setSelectedChain(c.id);
|
|
78
|
+
setSelectedToken("");
|
|
79
|
+
},
|
|
80
|
+
className: `rounded-lg border px-3 py-1.5 text-xs font-medium ${selectedChain === c.id ? "border-indigo-500 bg-indigo-50 text-indigo-700" : "border-gray-200 text-gray-600"}`,
|
|
81
|
+
children: c.name
|
|
82
|
+
},
|
|
83
|
+
c.id
|
|
84
|
+
)) }),
|
|
85
|
+
selectedChainData && /* @__PURE__ */ jsx("div", { className: "flex gap-2", children: selectedChainData.tokens.map((tk) => /* @__PURE__ */ jsx(
|
|
86
|
+
"button",
|
|
87
|
+
{
|
|
88
|
+
onClick: () => setSelectedToken(tk.id),
|
|
89
|
+
className: `rounded-lg border px-3 py-1.5 text-xs font-medium ${selectedToken === tk.id ? "border-indigo-500 bg-indigo-50 text-indigo-700" : "border-gray-200 text-gray-600"}`,
|
|
90
|
+
children: tk.symbol
|
|
91
|
+
},
|
|
92
|
+
tk.id
|
|
93
|
+
)) }),
|
|
94
|
+
selectedToken && /* @__PURE__ */ jsxs("button", { onClick: handlePay, className: "w-full rounded-lg bg-indigo-600 py-2 text-sm font-medium text-white hover:bg-indigo-700", children: [
|
|
95
|
+
"Pay $",
|
|
96
|
+
amount.toFixed(2)
|
|
97
|
+
] }),
|
|
98
|
+
/* @__PURE__ */ jsx("button", { onClick: () => setStep("idle"), className: "text-xs text-gray-400 hover:text-gray-600", children: "Cancel" })
|
|
99
|
+
] }),
|
|
100
|
+
step === "paying" && payment && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
101
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-gray-500", children: "Send exactly" }),
|
|
102
|
+
/* @__PURE__ */ jsxs("p", { className: "text-lg font-bold text-gray-900", children: [
|
|
103
|
+
payment.amountExpected,
|
|
104
|
+
" ",
|
|
105
|
+
payment.tokenSymbol
|
|
106
|
+
] }),
|
|
107
|
+
/* @__PURE__ */ jsxs("p", { className: "text-xs text-gray-500", children: [
|
|
108
|
+
"on ",
|
|
109
|
+
payment.chainName
|
|
110
|
+
] }),
|
|
111
|
+
/* @__PURE__ */ jsx("button", { onClick: handleCopy, className: "w-full rounded-lg bg-gray-50 border border-gray-200 px-3 py-2.5 font-mono text-xs text-gray-800 break-all text-left hover:bg-gray-100", children: payment.address }),
|
|
112
|
+
/* @__PURE__ */ jsx("p", { className: "text-xs text-center text-gray-400", children: copied ? "Copied!" : "Tap to copy" }),
|
|
113
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-gray-500", children: [
|
|
114
|
+
/* @__PURE__ */ jsxs("span", { className: "relative flex h-2 w-2", children: [
|
|
115
|
+
/* @__PURE__ */ jsx("span", { className: "absolute h-full w-full animate-ping rounded-full bg-amber-400 opacity-75" }),
|
|
116
|
+
/* @__PURE__ */ jsx("span", { className: "relative h-2 w-2 rounded-full bg-amber-400" })
|
|
117
|
+
] }),
|
|
118
|
+
"Waiting for payment..."
|
|
119
|
+
] })
|
|
120
|
+
] }),
|
|
121
|
+
step === "done" && /* @__PURE__ */ jsxs("div", { className: "text-center py-2", children: [
|
|
122
|
+
/* @__PURE__ */ jsx("div", { className: "mx-auto flex h-12 w-12 items-center justify-center rounded-full bg-green-100 mb-3", children: /* @__PURE__ */ jsx("svg", { className: "h-6 w-6 text-green-600", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) }) }),
|
|
123
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-green-700", children: "Payment Confirmed" })
|
|
124
|
+
] })
|
|
125
|
+
] });
|
|
126
|
+
}
|
|
127
|
+
export {
|
|
128
|
+
BanksiClient,
|
|
129
|
+
BanksiPayButton
|
|
130
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "banksi",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Crypto payment module for vibe coders. Add USDT/USDC payments to any app in one prompt.",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./dist/index.d.ts",
|
|
10
|
+
"import": "./dist/index.mjs",
|
|
11
|
+
"require": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./next": {
|
|
14
|
+
"types": "./dist/next.d.ts",
|
|
15
|
+
"import": "./dist/next.mjs",
|
|
16
|
+
"require": "./dist/next.js"
|
|
17
|
+
},
|
|
18
|
+
"./express": {
|
|
19
|
+
"types": "./dist/express.d.ts",
|
|
20
|
+
"import": "./dist/express.mjs",
|
|
21
|
+
"require": "./dist/express.js"
|
|
22
|
+
},
|
|
23
|
+
"./react": {
|
|
24
|
+
"types": "./dist/react.d.ts",
|
|
25
|
+
"import": "./dist/react.mjs",
|
|
26
|
+
"require": "./dist/react.js"
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
"files": ["dist", "README.md"],
|
|
30
|
+
"scripts": {
|
|
31
|
+
"build": "tsup",
|
|
32
|
+
"prepublishOnly": "npm run build"
|
|
33
|
+
},
|
|
34
|
+
"keywords": ["crypto", "payments", "usdt", "usdc", "x402", "stablecoin", "mcp", "vibe-coding"],
|
|
35
|
+
"license": "MIT",
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": ">=18",
|
|
38
|
+
"react-dom": ">=18"
|
|
39
|
+
},
|
|
40
|
+
"peerDependenciesMeta": {
|
|
41
|
+
"react": { "optional": true },
|
|
42
|
+
"react-dom": { "optional": true }
|
|
43
|
+
},
|
|
44
|
+
"devDependencies": {
|
|
45
|
+
"tsup": "^8.0.0",
|
|
46
|
+
"typescript": "^5.0.0",
|
|
47
|
+
"@types/react": "^19.0.0"
|
|
48
|
+
}
|
|
49
|
+
}
|