@relai-fi/subscriptions-react 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/LICENSE +21 -0
- package/README.md +171 -0
- package/dist/index.cjs +456 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +208 -0
- package/dist/index.d.ts +208 -0
- package/dist/index.js +438 -0
- package/dist/index.js.map +1 -0
- package/dist/styles.css +214 -0
- package/dist/types-CTW_egjj.d.cts +19 -0
- package/dist/types-CTW_egjj.d.ts +19 -0
- package/dist/wallet.cjs +44 -0
- package/dist/wallet.cjs.map +1 -0
- package/dist/wallet.d.cts +16 -0
- package/dist/wallet.d.ts +16 -0
- package/dist/wallet.js +41 -0
- package/dist/wallet.js.map +1 -0
- package/package.json +79 -0
package/dist/styles.css
ADDED
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/* @relai-fi/subscriptions-react — drop-in styles.
|
|
2
|
+
Theme by overriding the --relai-* variables (or pass the `theme` prop). */
|
|
3
|
+
|
|
4
|
+
.relai-root {
|
|
5
|
+
/* Brand palette (electric violet) — override via the `theme` prop. */
|
|
6
|
+
--relai-primary: #7c3aed;
|
|
7
|
+
--relai-primary-hover: #6d28d9;
|
|
8
|
+
--relai-primary-fg: #ffffff;
|
|
9
|
+
--relai-bg: transparent;
|
|
10
|
+
--relai-card: #ffffff;
|
|
11
|
+
--relai-fg: #0c0e16;
|
|
12
|
+
--relai-muted-fg: #6b7280;
|
|
13
|
+
--relai-border: #e7e8ee;
|
|
14
|
+
--relai-success: #10b981;
|
|
15
|
+
--relai-danger: #ef4444;
|
|
16
|
+
--relai-radius: 16px;
|
|
17
|
+
|
|
18
|
+
font-family:
|
|
19
|
+
"Inter", ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial,
|
|
20
|
+
sans-serif;
|
|
21
|
+
color: var(--relai-fg);
|
|
22
|
+
background: var(--relai-bg);
|
|
23
|
+
-webkit-font-smoothing: antialiased;
|
|
24
|
+
}
|
|
25
|
+
.relai-root *,
|
|
26
|
+
.relai-root *::before,
|
|
27
|
+
.relai-root *::after {
|
|
28
|
+
box-sizing: border-box;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/* ── Table grid ─────────────────────────────────────────────────────────── */
|
|
32
|
+
.relai-table {
|
|
33
|
+
display: grid;
|
|
34
|
+
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
|
35
|
+
gap: 20px;
|
|
36
|
+
align-items: stretch;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/* ── Card ───────────────────────────────────────────────────────────────── */
|
|
40
|
+
.relai-card {
|
|
41
|
+
position: relative;
|
|
42
|
+
display: flex;
|
|
43
|
+
flex-direction: column;
|
|
44
|
+
background: var(--relai-card);
|
|
45
|
+
border: 1px solid var(--relai-border);
|
|
46
|
+
border-radius: var(--relai-radius);
|
|
47
|
+
padding: 28px 24px;
|
|
48
|
+
box-shadow: 0 1px 2px rgba(12, 14, 22, 0.04);
|
|
49
|
+
transition: box-shadow 0.2s ease, transform 0.2s ease, border-color 0.2s ease;
|
|
50
|
+
}
|
|
51
|
+
.relai-card--highlight {
|
|
52
|
+
border-color: color-mix(in srgb, var(--relai-primary) 55%, var(--relai-border));
|
|
53
|
+
box-shadow:
|
|
54
|
+
0 0 0 1px color-mix(in srgb, var(--relai-primary) 35%, transparent),
|
|
55
|
+
0 12px 32px color-mix(in srgb, var(--relai-primary) 16%, transparent);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
.relai-badge {
|
|
59
|
+
position: absolute;
|
|
60
|
+
top: -11px;
|
|
61
|
+
left: 24px;
|
|
62
|
+
font-size: 12px;
|
|
63
|
+
font-weight: 600;
|
|
64
|
+
letter-spacing: 0.02em;
|
|
65
|
+
text-transform: uppercase;
|
|
66
|
+
color: var(--relai-primary-fg);
|
|
67
|
+
background: var(--relai-primary);
|
|
68
|
+
padding: 4px 10px;
|
|
69
|
+
border-radius: 999px;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.relai-card__head {
|
|
73
|
+
margin-bottom: 18px;
|
|
74
|
+
}
|
|
75
|
+
.relai-card__name {
|
|
76
|
+
margin: 0;
|
|
77
|
+
font-size: 19px;
|
|
78
|
+
font-weight: 600;
|
|
79
|
+
letter-spacing: -0.01em;
|
|
80
|
+
}
|
|
81
|
+
.relai-card__desc {
|
|
82
|
+
margin: 6px 0 0;
|
|
83
|
+
font-size: 14px;
|
|
84
|
+
line-height: 1.45;
|
|
85
|
+
color: var(--relai-muted-fg);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/* ── Price ──────────────────────────────────────────────────────────────── */
|
|
89
|
+
.relai-price {
|
|
90
|
+
display: flex;
|
|
91
|
+
align-items: baseline;
|
|
92
|
+
gap: 8px;
|
|
93
|
+
}
|
|
94
|
+
.relai-price__amount {
|
|
95
|
+
font-size: 44px;
|
|
96
|
+
font-weight: 800;
|
|
97
|
+
letter-spacing: -0.03em;
|
|
98
|
+
line-height: 1;
|
|
99
|
+
font-variant-numeric: tabular-nums;
|
|
100
|
+
}
|
|
101
|
+
.relai-price__unit {
|
|
102
|
+
display: flex;
|
|
103
|
+
flex-direction: column;
|
|
104
|
+
line-height: 1.1;
|
|
105
|
+
}
|
|
106
|
+
.relai-price__ticker {
|
|
107
|
+
font-size: 13px;
|
|
108
|
+
font-weight: 600;
|
|
109
|
+
color: var(--relai-muted-fg);
|
|
110
|
+
}
|
|
111
|
+
.relai-price__period {
|
|
112
|
+
font-size: 13px;
|
|
113
|
+
color: var(--relai-muted-fg);
|
|
114
|
+
}
|
|
115
|
+
.relai-price__caption {
|
|
116
|
+
margin: 8px 0 20px;
|
|
117
|
+
font-size: 13px;
|
|
118
|
+
color: var(--relai-muted-fg);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/* ── Button ─────────────────────────────────────────────────────────────── */
|
|
122
|
+
.relai-btn {
|
|
123
|
+
display: inline-flex;
|
|
124
|
+
align-items: center;
|
|
125
|
+
justify-content: center;
|
|
126
|
+
gap: 9px;
|
|
127
|
+
width: 100%;
|
|
128
|
+
padding: 12px 16px;
|
|
129
|
+
font: inherit;
|
|
130
|
+
font-size: 15px;
|
|
131
|
+
font-weight: 600;
|
|
132
|
+
color: var(--relai-primary-fg);
|
|
133
|
+
background: var(--relai-primary);
|
|
134
|
+
border: 1px solid transparent;
|
|
135
|
+
border-radius: calc(var(--relai-radius) - 4px);
|
|
136
|
+
cursor: pointer;
|
|
137
|
+
transition: background 0.15s ease, opacity 0.15s ease, color 0.15s ease;
|
|
138
|
+
}
|
|
139
|
+
.relai-btn:hover:not(:disabled) {
|
|
140
|
+
background: var(--relai-primary-hover);
|
|
141
|
+
}
|
|
142
|
+
.relai-btn:focus-visible {
|
|
143
|
+
outline: none;
|
|
144
|
+
box-shadow: 0 0 0 3px color-mix(in srgb, var(--relai-primary) 35%, transparent);
|
|
145
|
+
}
|
|
146
|
+
.relai-btn:disabled {
|
|
147
|
+
cursor: default;
|
|
148
|
+
opacity: 0.6;
|
|
149
|
+
}
|
|
150
|
+
.relai-btn[data-state="done"]:disabled {
|
|
151
|
+
opacity: 1;
|
|
152
|
+
color: var(--relai-success);
|
|
153
|
+
background: color-mix(in srgb, var(--relai-success) 12%, transparent);
|
|
154
|
+
border-color: color-mix(in srgb, var(--relai-success) 35%, transparent);
|
|
155
|
+
}
|
|
156
|
+
.relai-btn[data-state="error"] {
|
|
157
|
+
background: var(--relai-danger);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
.relai-spinner {
|
|
161
|
+
width: 15px;
|
|
162
|
+
height: 15px;
|
|
163
|
+
border-radius: 50%;
|
|
164
|
+
border: 2px solid color-mix(in srgb, var(--relai-primary-fg) 40%, transparent);
|
|
165
|
+
border-top-color: var(--relai-primary-fg);
|
|
166
|
+
animation: relai-spin 0.6s linear infinite;
|
|
167
|
+
}
|
|
168
|
+
@keyframes relai-spin {
|
|
169
|
+
to {
|
|
170
|
+
transform: rotate(360deg);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
@media (prefers-reduced-motion: reduce) {
|
|
174
|
+
.relai-spinner {
|
|
175
|
+
animation-duration: 1.4s;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/* ── Features ───────────────────────────────────────────────────────────── */
|
|
180
|
+
.relai-features {
|
|
181
|
+
list-style: none;
|
|
182
|
+
margin: 22px 0 0;
|
|
183
|
+
padding: 18px 0 0;
|
|
184
|
+
border-top: 1px solid var(--relai-border);
|
|
185
|
+
display: flex;
|
|
186
|
+
flex-direction: column;
|
|
187
|
+
gap: 11px;
|
|
188
|
+
}
|
|
189
|
+
.relai-features__item {
|
|
190
|
+
display: flex;
|
|
191
|
+
align-items: flex-start;
|
|
192
|
+
gap: 10px;
|
|
193
|
+
font-size: 14px;
|
|
194
|
+
line-height: 1.4;
|
|
195
|
+
}
|
|
196
|
+
.relai-check {
|
|
197
|
+
flex: none;
|
|
198
|
+
margin-top: 1px;
|
|
199
|
+
color: var(--relai-success);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
/* ── States ─────────────────────────────────────────────────────────────── */
|
|
203
|
+
.relai-state {
|
|
204
|
+
padding: 28px 24px;
|
|
205
|
+
border: 1px dashed var(--relai-border);
|
|
206
|
+
border-radius: var(--relai-radius);
|
|
207
|
+
font-size: 14px;
|
|
208
|
+
color: var(--relai-muted-fg);
|
|
209
|
+
text-align: center;
|
|
210
|
+
}
|
|
211
|
+
.relai-state--error {
|
|
212
|
+
color: var(--relai-danger);
|
|
213
|
+
border-color: color-mix(in srgb, var(--relai-danger) 40%, var(--relai-border));
|
|
214
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs and broadcasts a base64 wire transaction, resolving to the tx signature.
|
|
3
|
+
* Wallet-agnostic: wire it to @solana/wallet-adapter (see `@relai-fi/subscriptions-react/wallet`),
|
|
4
|
+
* Privy, Crossmint, a raw Keypair — anything that can sign + send a Solana tx.
|
|
5
|
+
*/
|
|
6
|
+
type SignAndSend = (wireTransactionBase64: string) => Promise<string>;
|
|
7
|
+
/** Theme overrides — mapped to CSS variables on the component root. */
|
|
8
|
+
interface RelaiTheme {
|
|
9
|
+
primary?: string;
|
|
10
|
+
primaryForeground?: string;
|
|
11
|
+
background?: string;
|
|
12
|
+
card?: string;
|
|
13
|
+
foreground?: string;
|
|
14
|
+
mutedForeground?: string;
|
|
15
|
+
border?: string;
|
|
16
|
+
radius?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { RelaiTheme as R, SignAndSend as S };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signs and broadcasts a base64 wire transaction, resolving to the tx signature.
|
|
3
|
+
* Wallet-agnostic: wire it to @solana/wallet-adapter (see `@relai-fi/subscriptions-react/wallet`),
|
|
4
|
+
* Privy, Crossmint, a raw Keypair — anything that can sign + send a Solana tx.
|
|
5
|
+
*/
|
|
6
|
+
type SignAndSend = (wireTransactionBase64: string) => Promise<string>;
|
|
7
|
+
/** Theme overrides — mapped to CSS variables on the component root. */
|
|
8
|
+
interface RelaiTheme {
|
|
9
|
+
primary?: string;
|
|
10
|
+
primaryForeground?: string;
|
|
11
|
+
background?: string;
|
|
12
|
+
card?: string;
|
|
13
|
+
foreground?: string;
|
|
14
|
+
mutedForeground?: string;
|
|
15
|
+
border?: string;
|
|
16
|
+
radius?: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export type { RelaiTheme as R, SignAndSend as S };
|
package/dist/wallet.cjs
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var react = require('react');
|
|
4
|
+
var walletAdapterReact = require('@solana/wallet-adapter-react');
|
|
5
|
+
var web3_js = require('@solana/web3.js');
|
|
6
|
+
|
|
7
|
+
// src/wallet.ts
|
|
8
|
+
function base64ToBytes(b64) {
|
|
9
|
+
if (typeof atob !== "function") {
|
|
10
|
+
throw new Error("atob is unavailable \u2014 the wallet adapter helper is browser-only.");
|
|
11
|
+
}
|
|
12
|
+
const bin = atob(b64);
|
|
13
|
+
const out = new Uint8Array(bin.length);
|
|
14
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
function useRelaiSignAndSend() {
|
|
18
|
+
const { connection } = walletAdapterReact.useConnection();
|
|
19
|
+
const { sendTransaction } = walletAdapterReact.useWallet();
|
|
20
|
+
return react.useCallback(
|
|
21
|
+
async (wireTransactionBase64) => {
|
|
22
|
+
const bytes = base64ToBytes(wireTransactionBase64);
|
|
23
|
+
let tx;
|
|
24
|
+
try {
|
|
25
|
+
tx = web3_js.VersionedTransaction.deserialize(bytes);
|
|
26
|
+
} catch {
|
|
27
|
+
tx = web3_js.Transaction.from(bytes);
|
|
28
|
+
}
|
|
29
|
+
const signature = await sendTransaction(tx, connection);
|
|
30
|
+
await connection.confirmTransaction(signature, "confirmed");
|
|
31
|
+
return signature;
|
|
32
|
+
},
|
|
33
|
+
[connection, sendTransaction]
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
function useRelaiWallet() {
|
|
37
|
+
const { publicKey } = walletAdapterReact.useWallet();
|
|
38
|
+
return publicKey?.toBase58();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
exports.useRelaiSignAndSend = useRelaiSignAndSend;
|
|
42
|
+
exports.useRelaiWallet = useRelaiWallet;
|
|
43
|
+
//# sourceMappingURL=wallet.cjs.map
|
|
44
|
+
//# sourceMappingURL=wallet.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wallet.ts"],"names":["useConnection","useWallet","useCallback","VersionedTransaction","Transaction"],"mappings":";;;;;;;AAOA,SAAS,cAAc,GAAA,EAAyB;AAC9C,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,IAAA,MAAM,IAAI,MAAM,uEAAkE,CAAA;AAAA,EACpF;AACA,EAAA,MAAM,GAAA,GAAM,KAAK,GAAG,CAAA;AACpB,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACrC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC9D,EAAA,OAAO,GAAA;AACT;AAWO,SAAS,mBAAA,GAAmC;AACjD,EAAA,MAAM,EAAE,UAAA,EAAW,GAAIA,gCAAA,EAAc;AACrC,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAIC,4BAAA,EAAU;AACtC,EAAA,OAAOC,iBAAA;AAAA,IACL,OAAO,qBAAA,KAA0B;AAC/B,MAAA,MAAM,KAAA,GAAQ,cAAc,qBAAqB,CAAA;AACjD,MAAA,IAAI,EAAA;AACJ,MAAA,IAAI;AACF,QAAA,EAAA,GAAKC,4BAAA,CAAqB,YAAY,KAAK,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AACN,QAAA,EAAA,GAAKC,mBAAA,CAAY,KAAK,KAAK,CAAA;AAAA,MAC7B;AACA,MAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAgB,EAAA,EAAI,UAAU,CAAA;AACtD,MAAA,MAAM,UAAA,CAAW,kBAAA,CAAmB,SAAA,EAAW,WAAW,CAAA;AAC1D,MAAA,OAAO,SAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,YAAY,eAAe;AAAA,GAC9B;AACF;AAGO,SAAS,cAAA,GAAqC;AACnD,EAAA,MAAM,EAAE,SAAA,EAAU,GAAIH,4BAAA,EAAU;AAChC,EAAA,OAAO,WAAW,QAAA,EAAS;AAC7B","file":"wallet.cjs","sourcesContent":["// Optional adapter for @solana/wallet-adapter-react.\n// Import from \"@relai-fi/subscriptions-react/wallet\" so the core stays wallet-agnostic.\nimport { useCallback } from \"react\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { Transaction, VersionedTransaction } from \"@solana/web3.js\";\nimport type { SignAndSend } from \"./types.js\";\n\nfunction base64ToBytes(b64: string): Uint8Array {\n if (typeof atob !== \"function\") {\n throw new Error(\"atob is unavailable — the wallet adapter helper is browser-only.\");\n }\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/**\n * Returns a `signAndSend` wired to the connected wallet-adapter wallet —\n * deserialize the base64 tx, sign + send it, wait for confirmation, return the signature.\n *\n * import { useRelaiSignAndSend, useRelaiWallet } from \"@relai-fi/subscriptions-react/wallet\";\n * const signAndSend = useRelaiSignAndSend();\n * const wallet = useRelaiWallet();\n * <PricingTable planId=\"pl_x\" wallet={wallet} signAndSend={signAndSend} />\n */\nexport function useRelaiSignAndSend(): SignAndSend {\n const { connection } = useConnection();\n const { sendTransaction } = useWallet();\n return useCallback<SignAndSend>(\n async (wireTransactionBase64) => {\n const bytes = base64ToBytes(wireTransactionBase64);\n let tx: Transaction | VersionedTransaction;\n try {\n tx = VersionedTransaction.deserialize(bytes);\n } catch {\n tx = Transaction.from(bytes);\n }\n const signature = await sendTransaction(tx, connection);\n await connection.confirmTransaction(signature, \"confirmed\");\n return signature;\n },\n [connection, sendTransaction],\n );\n}\n\n/** The connected wallet's base58 address (or undefined). */\nexport function useRelaiWallet(): string | undefined {\n const { publicKey } = useWallet();\n return publicKey?.toBase58();\n}\n"]}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { S as SignAndSend } from './types-CTW_egjj.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns a `signAndSend` wired to the connected wallet-adapter wallet —
|
|
5
|
+
* deserialize the base64 tx, sign + send it, wait for confirmation, return the signature.
|
|
6
|
+
*
|
|
7
|
+
* import { useRelaiSignAndSend, useRelaiWallet } from "@relai-fi/subscriptions-react/wallet";
|
|
8
|
+
* const signAndSend = useRelaiSignAndSend();
|
|
9
|
+
* const wallet = useRelaiWallet();
|
|
10
|
+
* <PricingTable planId="pl_x" wallet={wallet} signAndSend={signAndSend} />
|
|
11
|
+
*/
|
|
12
|
+
declare function useRelaiSignAndSend(): SignAndSend;
|
|
13
|
+
/** The connected wallet's base58 address (or undefined). */
|
|
14
|
+
declare function useRelaiWallet(): string | undefined;
|
|
15
|
+
|
|
16
|
+
export { useRelaiSignAndSend, useRelaiWallet };
|
package/dist/wallet.d.ts
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { S as SignAndSend } from './types-CTW_egjj.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Returns a `signAndSend` wired to the connected wallet-adapter wallet —
|
|
5
|
+
* deserialize the base64 tx, sign + send it, wait for confirmation, return the signature.
|
|
6
|
+
*
|
|
7
|
+
* import { useRelaiSignAndSend, useRelaiWallet } from "@relai-fi/subscriptions-react/wallet";
|
|
8
|
+
* const signAndSend = useRelaiSignAndSend();
|
|
9
|
+
* const wallet = useRelaiWallet();
|
|
10
|
+
* <PricingTable planId="pl_x" wallet={wallet} signAndSend={signAndSend} />
|
|
11
|
+
*/
|
|
12
|
+
declare function useRelaiSignAndSend(): SignAndSend;
|
|
13
|
+
/** The connected wallet's base58 address (or undefined). */
|
|
14
|
+
declare function useRelaiWallet(): string | undefined;
|
|
15
|
+
|
|
16
|
+
export { useRelaiSignAndSend, useRelaiWallet };
|
package/dist/wallet.js
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { useCallback } from 'react';
|
|
2
|
+
import { useConnection, useWallet } from '@solana/wallet-adapter-react';
|
|
3
|
+
import { VersionedTransaction, Transaction } from '@solana/web3.js';
|
|
4
|
+
|
|
5
|
+
// src/wallet.ts
|
|
6
|
+
function base64ToBytes(b64) {
|
|
7
|
+
if (typeof atob !== "function") {
|
|
8
|
+
throw new Error("atob is unavailable \u2014 the wallet adapter helper is browser-only.");
|
|
9
|
+
}
|
|
10
|
+
const bin = atob(b64);
|
|
11
|
+
const out = new Uint8Array(bin.length);
|
|
12
|
+
for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);
|
|
13
|
+
return out;
|
|
14
|
+
}
|
|
15
|
+
function useRelaiSignAndSend() {
|
|
16
|
+
const { connection } = useConnection();
|
|
17
|
+
const { sendTransaction } = useWallet();
|
|
18
|
+
return useCallback(
|
|
19
|
+
async (wireTransactionBase64) => {
|
|
20
|
+
const bytes = base64ToBytes(wireTransactionBase64);
|
|
21
|
+
let tx;
|
|
22
|
+
try {
|
|
23
|
+
tx = VersionedTransaction.deserialize(bytes);
|
|
24
|
+
} catch {
|
|
25
|
+
tx = Transaction.from(bytes);
|
|
26
|
+
}
|
|
27
|
+
const signature = await sendTransaction(tx, connection);
|
|
28
|
+
await connection.confirmTransaction(signature, "confirmed");
|
|
29
|
+
return signature;
|
|
30
|
+
},
|
|
31
|
+
[connection, sendTransaction]
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
function useRelaiWallet() {
|
|
35
|
+
const { publicKey } = useWallet();
|
|
36
|
+
return publicKey?.toBase58();
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export { useRelaiSignAndSend, useRelaiWallet };
|
|
40
|
+
//# sourceMappingURL=wallet.js.map
|
|
41
|
+
//# sourceMappingURL=wallet.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/wallet.ts"],"names":[],"mappings":";;;;;AAOA,SAAS,cAAc,GAAA,EAAyB;AAC9C,EAAA,IAAI,OAAO,SAAS,UAAA,EAAY;AAC9B,IAAA,MAAM,IAAI,MAAM,uEAAkE,CAAA;AAAA,EACpF;AACA,EAAA,MAAM,GAAA,GAAM,KAAK,GAAG,CAAA;AACpB,EAAA,MAAM,GAAA,GAAM,IAAI,UAAA,CAAW,GAAA,CAAI,MAAM,CAAA;AACrC,EAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,GAAA,CAAI,MAAA,EAAQ,CAAA,EAAA,EAAK,GAAA,CAAI,CAAC,CAAA,GAAI,GAAA,CAAI,UAAA,CAAW,CAAC,CAAA;AAC9D,EAAA,OAAO,GAAA;AACT;AAWO,SAAS,mBAAA,GAAmC;AACjD,EAAA,MAAM,EAAE,UAAA,EAAW,GAAI,aAAA,EAAc;AACrC,EAAA,MAAM,EAAE,eAAA,EAAgB,GAAI,SAAA,EAAU;AACtC,EAAA,OAAO,WAAA;AAAA,IACL,OAAO,qBAAA,KAA0B;AAC/B,MAAA,MAAM,KAAA,GAAQ,cAAc,qBAAqB,CAAA;AACjD,MAAA,IAAI,EAAA;AACJ,MAAA,IAAI;AACF,QAAA,EAAA,GAAK,oBAAA,CAAqB,YAAY,KAAK,CAAA;AAAA,MAC7C,CAAA,CAAA,MAAQ;AACN,QAAA,EAAA,GAAK,WAAA,CAAY,KAAK,KAAK,CAAA;AAAA,MAC7B;AACA,MAAA,MAAM,SAAA,GAAY,MAAM,eAAA,CAAgB,EAAA,EAAI,UAAU,CAAA;AACtD,MAAA,MAAM,UAAA,CAAW,kBAAA,CAAmB,SAAA,EAAW,WAAW,CAAA;AAC1D,MAAA,OAAO,SAAA;AAAA,IACT,CAAA;AAAA,IACA,CAAC,YAAY,eAAe;AAAA,GAC9B;AACF;AAGO,SAAS,cAAA,GAAqC;AACnD,EAAA,MAAM,EAAE,SAAA,EAAU,GAAI,SAAA,EAAU;AAChC,EAAA,OAAO,WAAW,QAAA,EAAS;AAC7B","file":"wallet.js","sourcesContent":["// Optional adapter for @solana/wallet-adapter-react.\n// Import from \"@relai-fi/subscriptions-react/wallet\" so the core stays wallet-agnostic.\nimport { useCallback } from \"react\";\nimport { useConnection, useWallet } from \"@solana/wallet-adapter-react\";\nimport { Transaction, VersionedTransaction } from \"@solana/web3.js\";\nimport type { SignAndSend } from \"./types.js\";\n\nfunction base64ToBytes(b64: string): Uint8Array {\n if (typeof atob !== \"function\") {\n throw new Error(\"atob is unavailable — the wallet adapter helper is browser-only.\");\n }\n const bin = atob(b64);\n const out = new Uint8Array(bin.length);\n for (let i = 0; i < bin.length; i++) out[i] = bin.charCodeAt(i);\n return out;\n}\n\n/**\n * Returns a `signAndSend` wired to the connected wallet-adapter wallet —\n * deserialize the base64 tx, sign + send it, wait for confirmation, return the signature.\n *\n * import { useRelaiSignAndSend, useRelaiWallet } from \"@relai-fi/subscriptions-react/wallet\";\n * const signAndSend = useRelaiSignAndSend();\n * const wallet = useRelaiWallet();\n * <PricingTable planId=\"pl_x\" wallet={wallet} signAndSend={signAndSend} />\n */\nexport function useRelaiSignAndSend(): SignAndSend {\n const { connection } = useConnection();\n const { sendTransaction } = useWallet();\n return useCallback<SignAndSend>(\n async (wireTransactionBase64) => {\n const bytes = base64ToBytes(wireTransactionBase64);\n let tx: Transaction | VersionedTransaction;\n try {\n tx = VersionedTransaction.deserialize(bytes);\n } catch {\n tx = Transaction.from(bytes);\n }\n const signature = await sendTransaction(tx, connection);\n await connection.confirmTransaction(signature, \"confirmed\");\n return signature;\n },\n [connection, sendTransaction],\n );\n}\n\n/** The connected wallet's base58 address (or undefined). */\nexport function useRelaiWallet(): string | undefined {\n const { publicKey } = useWallet();\n return publicKey?.toBase58();\n}\n"]}
|
package/package.json
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@relai-fi/subscriptions-react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Drop-in React UI for RelAI subscriptions — a Stripe-style pricing table and subscribe button for recurring USDC billing on Solana. Wallet-agnostic, themeable, no API key in the browser.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.cjs",
|
|
7
|
+
"module": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"sideEffects": ["*.css"],
|
|
10
|
+
"exports": {
|
|
11
|
+
".": {
|
|
12
|
+
"types": "./dist/index.d.ts",
|
|
13
|
+
"import": "./dist/index.js",
|
|
14
|
+
"require": "./dist/index.cjs"
|
|
15
|
+
},
|
|
16
|
+
"./wallet": {
|
|
17
|
+
"types": "./dist/wallet.d.ts",
|
|
18
|
+
"import": "./dist/wallet.js",
|
|
19
|
+
"require": "./dist/wallet.cjs"
|
|
20
|
+
},
|
|
21
|
+
"./styles.css": "./dist/styles.css"
|
|
22
|
+
},
|
|
23
|
+
"files": ["dist", "README.md", "LICENSE"],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"build": "tsup",
|
|
26
|
+
"dev": "tsup --watch",
|
|
27
|
+
"typecheck": "tsc --noEmit",
|
|
28
|
+
"test": "vitest run",
|
|
29
|
+
"test:watch": "vitest",
|
|
30
|
+
"test:coverage": "vitest run --coverage",
|
|
31
|
+
"prepublishOnly": "npm run build && npm test"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"relai",
|
|
35
|
+
"solana",
|
|
36
|
+
"subscriptions",
|
|
37
|
+
"recurring",
|
|
38
|
+
"usdc",
|
|
39
|
+
"stablecoin",
|
|
40
|
+
"payments",
|
|
41
|
+
"react",
|
|
42
|
+
"pricing-table",
|
|
43
|
+
"pricing",
|
|
44
|
+
"ui",
|
|
45
|
+
"drop-in"
|
|
46
|
+
],
|
|
47
|
+
"homepage": "https://relai.fi/documentation/subscriptions",
|
|
48
|
+
"publishConfig": { "access": "public" },
|
|
49
|
+
"license": "MIT",
|
|
50
|
+
"engines": { "node": ">=18" },
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@relai-fi/subscriptions": "^0.1.0"
|
|
53
|
+
},
|
|
54
|
+
"peerDependencies": {
|
|
55
|
+
"react": ">=18",
|
|
56
|
+
"react-dom": ">=18",
|
|
57
|
+
"@solana/wallet-adapter-react": ">=0.15",
|
|
58
|
+
"@solana/web3.js": "^1.91.0"
|
|
59
|
+
},
|
|
60
|
+
"peerDependenciesMeta": {
|
|
61
|
+
"@solana/wallet-adapter-react": { "optional": true },
|
|
62
|
+
"@solana/web3.js": { "optional": true }
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@solana/wallet-adapter-react": "^0.15.35",
|
|
66
|
+
"@solana/web3.js": "^1.95.3",
|
|
67
|
+
"@testing-library/dom": "^10.4.0",
|
|
68
|
+
"@testing-library/react": "^16.0.1",
|
|
69
|
+
"@types/react": "^18.3.3",
|
|
70
|
+
"@types/react-dom": "^18.3.0",
|
|
71
|
+
"@vitest/coverage-v8": "^1.6.0",
|
|
72
|
+
"jsdom": "^24.1.3",
|
|
73
|
+
"react": "^18.3.1",
|
|
74
|
+
"react-dom": "^18.3.1",
|
|
75
|
+
"tsup": "^8.0.2",
|
|
76
|
+
"typescript": "^5.4.0",
|
|
77
|
+
"vitest": "^1.6.0"
|
|
78
|
+
}
|
|
79
|
+
}
|