@pybara/pybara-js 0.9.1 → 0.11.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 +1 -1
- package/README.md +61 -31
- package/checkout.schema.json +15 -5
- package/dist/checkout.d.ts.map +1 -1
- package/dist/gate.d.ts +5 -5
- package/dist/gate.d.ts.map +1 -1
- package/dist/modal/modal.d.ts +7 -6
- package/dist/modal/modal.d.ts.map +1 -1
- package/dist/pybara-js.iife.js +1 -1
- package/dist/pybara-js.js +43 -38
- package/dist/types.d.ts +7 -5
- package/dist/types.d.ts.map +1 -1
- package/package.json +6 -6
package/LICENSE
CHANGED
package/README.md
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
# @pybara/pybara-js
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Take crypto donations with **Pybara** on any page — a callable checkout, in the same convention as `@stripe/stripe-js` and `@paypal/paypal-js`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
> **Donations only, for now.** `checkout()` runs the donation flow: the `siteUrl` resolves a registered recipient, and the checkout collects the donor's details, optional anonymity and tax-receipt flag. It is not for selling goods or services yet — for a store, use [Pybara for WooCommerce](https://docs.pybara.com/woocommerce/overview/). Merchant payments will ride the same surface when they land: the site's registry record decides the flow, and the API won't change. Want the whole donation *form* instead — presets, amount selector, frequency picker, styled button? That's [`@pybara/donate-widget`](https://docs.pybara.com/donate-widget/overview/), built on the same machinery.
|
|
6
|
+
|
|
7
|
+
You keep your own donation form — its payment methods, amount selector, fields. `Pybara.checkout()` binds your site once; `checkout.buttons()` draws a "Pybara" button beside your other payment methods, or `checkout.open()` opens Pybara's checkout from your own Donate button. The checkout itself (wallet, token choice, settlement, success screen) is Pybara's.
|
|
6
8
|
|
|
7
9
|
## Install
|
|
8
10
|
|
|
@@ -13,7 +15,7 @@ npm install @pybara/pybara-js
|
|
|
13
15
|
No bundler? The IIFE build exposes `window.Pybara` — the same calls as the module:
|
|
14
16
|
|
|
15
17
|
```html
|
|
16
|
-
<script src="https://cdn.jsdelivr.net/npm/@pybara/pybara-js@0.
|
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/@pybara/pybara-js@0.11/dist/pybara-js.iife.js"></script>
|
|
17
19
|
<script>
|
|
18
20
|
const pybara = Pybara.checkout({ siteUrl, siteName, recipientPrincipal, currency: 'EUR' });
|
|
19
21
|
pybara.buttons({ createPayment: () => ({ amount: '25' }) }).render('#pybara-button');
|
|
@@ -22,7 +24,7 @@ No bundler? The IIFE build exposes `window.Pybara` — the same calls as the mod
|
|
|
22
24
|
|
|
23
25
|
## Add Pybara next to PayPal
|
|
24
26
|
|
|
25
|
-
A
|
|
27
|
+
A donation form with PayPal Buttons gets a Pybara button beside them in a few lines. Pass the PayPal button's `style` as it is (`color`, `shape`, `height`, `borderRadius`) and the two match:
|
|
26
28
|
|
|
27
29
|
```html
|
|
28
30
|
<div id="paypal-button-container"></div>
|
|
@@ -42,7 +44,7 @@ const pybara = Pybara.checkout({
|
|
|
42
44
|
pybara.buttons({
|
|
43
45
|
style: { color: 'black', shape: 'rect', height: 45 }, // the same style as the PayPal button
|
|
44
46
|
createPayment: () => ({ amount: amountInput.value }), // read on the click; add frequency: 'monthly' for a subscription
|
|
45
|
-
onStateChange: ({ message }) => (hint.textContent = message ?? ''), // e.g. "Minimum €0.70", in the
|
|
47
|
+
onStateChange: ({ message }) => (hint.textContent = message ?? ''), // e.g. "Minimum €0.70", in the donor's language
|
|
46
48
|
onSuccess: (result) => showThanks(result),
|
|
47
49
|
}).render('#pybara-button');
|
|
48
50
|
|
|
@@ -51,7 +53,9 @@ amountInput.addEventListener('input', () => pybara.precheck({ amount: amountInpu
|
|
|
51
53
|
|
|
52
54
|
- **The button follows availability by itself:** disabled below the minimum, and its slot left empty when Pybara can't be used on this page yet. It holds no text but "Pybara"; the page around it says what it's for.
|
|
53
55
|
- **One-time and monthly side by side:** call `buttons()` twice on the same checkout, one with `frequency: 'monthly'`.
|
|
54
|
-
- **Everything the
|
|
56
|
+
- **Everything the donor sees is served by Pybara,** so the button stays current without updating this package.
|
|
57
|
+
|
|
58
|
+
Full recipe: <https://docs.pybara.com/pybara-js/next-to-paypal/>
|
|
55
59
|
|
|
56
60
|
## Before it works: the site owner's steps
|
|
57
61
|
|
|
@@ -59,13 +63,13 @@ Code can't do these; whoever adds Pybara to the site relays them to the site own
|
|
|
59
63
|
|
|
60
64
|
> 1. Create a Pybara Wallet at <https://pybara.io>, then open **Manage › Sites › Add a site without a plugin** and enter this site's address.
|
|
61
65
|
> 2. Publish the DNS `TXT` record the wallet shows (`_pybara-payto`, holding the wallet's principal) with the domain's DNS provider, until the wallet shows **Verified**.
|
|
62
|
-
> 3. Accept the
|
|
66
|
+
> 3. Accept the Pybara Terms of Service for the site there, and copy the wallet's principal into `recipientPrincipal`.
|
|
63
67
|
>
|
|
64
68
|
> Until then the Pybara button stays hidden, and the browser console says which step is missing. It works on the site's registered domain, not on a preview URL.
|
|
65
69
|
|
|
66
70
|
Full guide: <https://docs.pybara.com/pybara-js/setup/>
|
|
67
71
|
|
|
68
|
-
## Or your own button: `open()`
|
|
72
|
+
## Or your own Donate button: `open()`
|
|
69
73
|
|
|
70
74
|
```ts
|
|
71
75
|
import { Pybara } from '@pybara/pybara-js';
|
|
@@ -88,15 +92,39 @@ await pybara.open({
|
|
|
88
92
|
|
|
89
93
|
That's the whole integration. `open()` resolves once the checkout is up; the result arrives on `onSuccess`.
|
|
90
94
|
|
|
91
|
-
**Amounts** are decimal strings in the currency's major units — `'12.34'` for €12.34, `'1000'` for ¥1,000 — as PayPal's API takes them; a number is accepted too (`12.34`). The checkout reads them with the currency's ISO 4217 minor units, so your page never needs to know how many decimals a currency has, and it refuses an amount the currency can't hold (`'12.345'` EUR, `'1000.5'` JPY). It converts to USD itself, with Pybara's own rates, and shows the minimum in the
|
|
95
|
+
**Amounts** are decimal strings in the currency's major units — `'12.34'` for €12.34, `'1000'` for ¥1,000 — as PayPal's API takes them; a number is accepted too (`12.34`). The checkout reads them with the currency's ISO 4217 minor units, so your page never needs to know how many decimals a currency has, and it refuses an amount the currency can't hold (`'12.345'` EUR, `'1000.5'` JPY). It converts to USD itself, with Pybara's own rates, and shows the minimum in the donor's currency if the amount is below it.
|
|
92
96
|
|
|
93
|
-
**
|
|
97
|
+
**Monthly giving** — same call, two extra params:
|
|
94
98
|
|
|
95
99
|
```ts
|
|
96
100
|
await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
|
|
97
101
|
// omit durationMonths for an open-ended subscription
|
|
98
102
|
```
|
|
99
103
|
|
|
104
|
+
### No amount: the checkout asks
|
|
105
|
+
|
|
106
|
+
A tip jar, or a "Donate" button with no amount next to it: open the checkout without one, and it asks the donor how much, before the wallet.
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const pybara = Pybara.checkout({ siteUrl, siteName, recipientPrincipal, currency: 'USD' });
|
|
110
|
+
donateButton.addEventListener('click', () => pybara.open({}));
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
With suggested amounts, shown as buttons beside the amount field:
|
|
114
|
+
|
|
115
|
+
```ts
|
|
116
|
+
donateButton.addEventListener('click', () => pybara.open({ suggestedAmounts: ['5', '10', '25'] }));
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
**Built with AI? Ask the site owner first,** rather than guessing:
|
|
120
|
+
- **Which amounts to suggest, if any:** up to four, in the site's currency. Without them, the donor types the amount; the checkout has no presets of its own.
|
|
121
|
+
- **Which currency the donations are in,** if the site doesn't say: it is required, set once in `Pybara.checkout()`, or on each `open()` on a multi-currency site. Never guess it from the visitor.
|
|
122
|
+
- **Whether to offer monthly giving,** and how: a second "Give monthly" button calling `open({ frequency: 'monthly' })`, or `frequency` on the existing one. Without `frequency`, donations are one-time.
|
|
123
|
+
|
|
124
|
+
Below the minimum, the checkout shows it in the donor's currency.
|
|
125
|
+
|
|
126
|
+
Full recipe: <https://docs.pybara.com/pybara-js/donate-button/>
|
|
127
|
+
|
|
100
128
|
## Reference
|
|
101
129
|
|
|
102
130
|
### `Pybara.checkout(config)` → `PybaraCheckout`
|
|
@@ -108,21 +136,22 @@ await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
|
|
|
108
136
|
| `siteName` | `string` | ✓ | Display name — shown in the checkout and stored on subscriptions |
|
|
109
137
|
| `currency` | `string` | | Default currency for `open()`, ISO 4217 uppercase (`'EUR'`) — no default of its own |
|
|
110
138
|
| `thankYouMessage` | `string` | | Success-screen title override |
|
|
111
|
-
| `locale` | `string` | | The checkout's language, a BCP 47 tag (`'fr'`, `'de-DE'`), usually your site's; otherwise the
|
|
112
|
-
| `thankYouRedirectUrl` | `string` | | Redirect after the
|
|
139
|
+
| `locale` | `string` | | The checkout's language, a BCP 47 tag (`'fr'`, `'de-DE'`), usually your site's; otherwise the donor's own |
|
|
140
|
+
| `thankYouRedirectUrl` | `string` | | Redirect after the donor closes the success screen |
|
|
113
141
|
| `siteCountry` | `string` | | ISO 3166-1 alpha-2 |
|
|
114
|
-
| `notifyEmail` | `string` | | Operator email — terms warnings,
|
|
115
|
-
| `notifyDonations` | `boolean` | | `false` silences per-
|
|
142
|
+
| `notifyEmail` | `string` | | Operator email — terms warnings, donation notifications |
|
|
143
|
+
| `notifyDonations` | `boolean` | | `false` silences per-donation emails (default `true`) |
|
|
116
144
|
| `platform` | `string` | | Your integration's slug in the payment log, `a-z 0-9 -` (default `'pybara-js'`) |
|
|
117
145
|
| `pluginVersion` | `string` | | Set by plugins — skips the autonomous-embed terms gate |
|
|
118
146
|
| `staging` / `debug` | `boolean` | | Staging canisters + wallet / console logging |
|
|
119
|
-
| `onAvailability(availability)` | `function` | | Whether a
|
|
147
|
+
| `onAvailability(availability)` | `function` | | Whether a donation would go through right now, before any click — see [Availability](#availability) |
|
|
120
148
|
|
|
121
149
|
### `checkout.open(payment)` → `Promise<void>`
|
|
122
150
|
|
|
123
151
|
| Field | Type | Description |
|
|
124
152
|
|---|---|---|
|
|
125
|
-
| `amount` | `string` \| `number` | Decimal string in the currency's major units: `'12.34'`, `'1000'` (JPY) |
|
|
153
|
+
| `amount` | `string` \| `number` | Decimal string in the currency's major units: `'12.34'`, `'1000'` (JPY). Omit it and the donor chooses ([No amount: the checkout asks](#no-amount-the-checkout-asks)) |
|
|
154
|
+
| `suggestedAmounts` | `(string \| number)[]` | Without `amount`: up to four amounts offered as buttons beside the amount field |
|
|
126
155
|
| `currency` | `string` | ISO 4217 — required here unless set in `Pybara.checkout()`; a multi-currency site passes it on every call |
|
|
127
156
|
| `frequency` | `'weekly' \| 'monthly' \| 'yearly'` | Omit for one-time |
|
|
128
157
|
| `durationMonths` | `3 \| 6 \| 12 \| 24` | Omit for unlimited |
|
|
@@ -130,14 +159,14 @@ await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
|
|
|
130
159
|
| `donorIsAnonymous` | `boolean` | Hide identity on the public record |
|
|
131
160
|
| `donorMessage` | `string` | Stored with the payment log |
|
|
132
161
|
| `wantsTaxReceipt` | `boolean` | Prefills the receipt checkbox (eligible sites only) |
|
|
133
|
-
| `onSuccess(result)` | `function` |
|
|
162
|
+
| `onSuccess(result)` | `function` | Donation confirmed — `result` carries block height, token, principals |
|
|
134
163
|
| `onError(err)` `onClose()` | `function` | Checkout refusals (`EmbeddedError`, `err.code`) / modal closed |
|
|
135
164
|
|
|
136
165
|
### `checkout.buttons(options)` → `{ render(el), destroy() }`
|
|
137
166
|
|
|
138
167
|
| Field | Type | Description |
|
|
139
168
|
|---|---|---|
|
|
140
|
-
| `createPayment()` | `function` | **Required.** Called on the click: the
|
|
169
|
+
| `createPayment()` | `function` | **Required.** Called on the click: the donation from the form, as `open()` takes it (`amount`, `currency`, `frequency`, donor fields), without callbacks. May return a promise |
|
|
141
170
|
| `style` | `{ color, shape, height, borderRadius }` | `color` `'brand'` \| `'black'` \| `'white'` (PayPal's names; its `'gold'`, `'blue'`, `'silver'` read as `'brand'`), `shape` `'pill'` \| `'rect'` \| `'sharp'`, `height` 25–55 px (default 45), `borderRadius` in px, overriding `shape` as PayPal's does. Passed to the button as given |
|
|
142
171
|
| `hideWhenUnavailable` | `boolean` | Collapse the button instead of leaving its slot empty when Pybara is unavailable |
|
|
143
172
|
| `onStateChange(availability)` | `function` | The checkout's availability answer, once per answer — see [Availability](#availability) |
|
|
@@ -147,14 +176,14 @@ await pybara.open({ amount: '25', frequency: 'monthly', durationMonths: 12 });
|
|
|
147
176
|
|
|
148
177
|
### Availability
|
|
149
178
|
|
|
150
|
-
With `onAvailability` set, Pybara tells the page — before any click — whether a
|
|
179
|
+
With `onAvailability` set, Pybara tells the page — before any click — whether a donation would go through, so you show the option only when it works:
|
|
151
180
|
|
|
152
181
|
```js
|
|
153
182
|
const pybara = Pybara.checkout({
|
|
154
183
|
recipientPrincipal, siteUrl, siteName, currency: 'EUR',
|
|
155
184
|
onAvailability: ({ status, message }) => {
|
|
156
185
|
payButton.hidden = status === 'unavailable'; // the site isn't set up, or the currency isn't served
|
|
157
|
-
payButton.disabled = status === 'below-minimum'; // message: "Minimum €0.70", in the
|
|
186
|
+
payButton.disabled = status === 'below-minimum'; // message: "Minimum €0.70", in the donor's language
|
|
158
187
|
hint.textContent = status === 'below-minimum' ? message : '';
|
|
159
188
|
},
|
|
160
189
|
});
|
|
@@ -163,7 +192,7 @@ amountInput.addEventListener('input', () => pybara.precheck({ amount: amountInpu
|
|
|
163
192
|
|
|
164
193
|
- **Called once on its own** when the checkout is ready (the site and its currency), then after each `checkout.precheck({ amount, currency })`. Call `precheck()` whenever the amount or currency changes; only the latest is answered.
|
|
165
194
|
- **Act on `status`:** `available`; `unavailable` (hide Pybara: nothing on the page can fix it); `below-minimum` (keep it, disable the button, show `message`; `minimum` is `{ amount, currency }`); `retry-later` (keep it: the click tries again).
|
|
166
|
-
- **`message`** is in the
|
|
195
|
+
- **`message`** is in the donor's language, ready to show. **`detail`**, in English, says what's missing and who fixes it — e.g. the site owner's DNS record or terms — and is printed to the console. **`reason`** is for debugging only: never branch on it.
|
|
167
196
|
- Without `onAvailability`, nothing changes: `open()` checks everything at the click, as always.
|
|
168
197
|
|
|
169
198
|
### Errors
|
|
@@ -172,20 +201,14 @@ amountInput.addEventListener('input', () => pybara.precheck({ amount: amountInpu
|
|
|
172
201
|
|
|
173
202
|
| Code | Meaning |
|
|
174
203
|
|---|---|
|
|
175
|
-
| `GATE_REFUSED` | Site hasn't accepted the
|
|
176
|
-
| `RECIPIENT_SUSPENDED` | Recipient can't accept
|
|
204
|
+
| `GATE_REFUSED` | Site hasn't accepted the Pybara Terms of Service, or a kill switch is on — `err.message` says which |
|
|
205
|
+
| `RECIPIENT_SUSPENDED` | Recipient can't accept donations right now |
|
|
177
206
|
| `INVALID_CONFIG` | Missing or malformed config or params — `err.message` names the field, e.g. `open(): "currency" is required` |
|
|
178
207
|
| `CHECKOUT_FAILED` | The checkout modal couldn't initialise |
|
|
179
208
|
|
|
180
|
-
Once open, the checkout reports a refusal to `onError` as an `EmbeddedError`, also with `err.code`. The ones an integration can cause: `INVALID_CHECKOUT` (the message names the field and what it must be, e.g. `checkout.amount "12.345" has more decimals than EUR has (2)`) and `RATE_UNAVAILABLE` (Pybara's rate for the currency couldn't be loaded — let the
|
|
181
|
-
|
|
182
|
-
If pybara.io can't be reached, the checkout doesn't spin forever: after 15 seconds without its first screen it says it couldn't load, with **Try again** and **Close**, and closing reports `FRAME_UNAVAILABLE` to `onError`, so the page can offer another way to pay. A `buttons()` button that doesn't load in that time leaves its slot empty and reports `unavailable` to `onStateChange`.
|
|
209
|
+
Once open, the checkout reports a refusal to `onError` as an `EmbeddedError`, also with `err.code`. The ones an integration can cause: `INVALID_CHECKOUT` (the message names the field and what it must be, e.g. `checkout.amount "12.345" has more decimals than EUR has (2)`) and `RATE_UNAVAILABLE` (Pybara's rate for the currency couldn't be loaded — let the donor try again). An amount below the minimum isn't an error: the checkout shows the minimum itself.
|
|
183
210
|
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
Today `checkout()` runs the **donation** flow (the `siteUrl` resolves a registered recipient; the frame collects donor details, optional anonymity, tax-receipt flag). Merchant payments ride the same surface when they land — the site's registry record decides the flow, the API doesn't change.
|
|
187
|
-
|
|
188
|
-
If you want the whole donation *form* — presets, amount selector, frequency picker, styled button — that's [`@pybara/donate-widget`](https://docs.pybara.com/donate-widget/overview/), a product built on the same machinery.
|
|
211
|
+
If pybara.io can't be reached, the checkout doesn't spin forever: after 15 seconds without its first screen it says it couldn't load, with **Try again** and **Close**, and closing reports `FRAME_UNAVAILABLE` to `onError`, so the page can offer another way to give. A `buttons()` button that doesn't load in that time leaves its slot empty and reports `unavailable` to `onStateChange`.
|
|
189
212
|
|
|
190
213
|
## Internal entry points
|
|
191
214
|
|
|
@@ -195,3 +218,10 @@ If you want the whole donation *form* — presets, amount selector, frequency pi
|
|
|
195
218
|
|
|
196
219
|
- Docs — <https://docs.pybara.com>
|
|
197
220
|
- Wallet — <https://pybara.io>
|
|
221
|
+
|
|
222
|
+
## License
|
|
223
|
+
|
|
224
|
+
MIT. See [LICENSE](LICENSE).
|
|
225
|
+
|
|
226
|
+
"Pybara" is a trademark of Pybara OÜ and is not licensed under the MIT License.
|
|
227
|
+
Forks must remove Pybara branding.
|
package/checkout.schema.json
CHANGED
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"recipientPrincipal": {
|
|
11
11
|
"type": "string",
|
|
12
12
|
"minLength": 1,
|
|
13
|
-
"
|
|
13
|
+
"not": { "enum": ["2vxsx-fae", "aaaaa-aa"] },
|
|
14
|
+
"description": "Recipient's wallet principal — the same one the site's _pybara-payto DNS record lists. The registry does not serve it; the integrator passes it. Never the anonymous principal (2vxsx-fae) or the management canister (aaaaa-aa): both are refused."
|
|
14
15
|
},
|
|
15
16
|
"siteUrl": {
|
|
16
17
|
"type": "string",
|
|
@@ -93,7 +94,6 @@
|
|
|
93
94
|
"description": "One payment attempt — the params of a single open() call.",
|
|
94
95
|
"type": "object",
|
|
95
96
|
"additionalProperties": false,
|
|
96
|
-
"required": ["amount"],
|
|
97
97
|
"properties": {
|
|
98
98
|
"amount": {
|
|
99
99
|
"oneOf": [
|
|
@@ -101,7 +101,19 @@
|
|
|
101
101
|
{ "type": "number", "exclusiveMinimum": 0 }
|
|
102
102
|
],
|
|
103
103
|
"examples": ["12.34", "1000", "5"],
|
|
104
|
-
"description": "The amount in the currency's major units, as a decimal string ('12.34' for €12.34, '1000' for ¥1,000); a number is accepted and turned into its decimal text. The checkout reads it with the currency's ISO 4217 minor units and refuses more decimals than the currency holds ('12.345' EUR, '1000.5' JPY), so the page never needs to know them. No minimum is checked here: the checkout shows its own, in the payer's currency."
|
|
104
|
+
"description": "The amount in the currency's major units, as a decimal string ('12.34' for €12.34, '1000' for ¥1,000); a number is accepted and turned into its decimal text. The checkout reads it with the currency's ISO 4217 minor units and refuses more decimals than the currency holds ('12.345' EUR, '1000.5' JPY), so the page never needs to know them. No minimum is checked here: the checkout shows its own, in the payer's currency. Omit it for a 'Donate' button with no amount: the checkout then asks the donor how much."
|
|
105
|
+
},
|
|
106
|
+
"suggestedAmounts": {
|
|
107
|
+
"type": "array",
|
|
108
|
+
"maxItems": 4,
|
|
109
|
+
"items": {
|
|
110
|
+
"oneOf": [
|
|
111
|
+
{ "type": "string", "pattern": "^(0|[1-9][0-9]*)(\\.[0-9]+)?$" },
|
|
112
|
+
{ "type": "number", "exclusiveMinimum": 0 }
|
|
113
|
+
]
|
|
114
|
+
},
|
|
115
|
+
"examples": [["5", "10", "25"]],
|
|
116
|
+
"description": "Without amount: up to four amounts the checkout offers the donor as buttons beside an amount field, in the currency's major units. Without them, the donor types the amount. Ask the site owner which amounts to suggest, if any, rather than inventing them."
|
|
105
117
|
},
|
|
106
118
|
"currency": {
|
|
107
119
|
"type": "string",
|
|
@@ -139,8 +151,6 @@
|
|
|
139
151
|
"donorAddressState": { "type": "string" },
|
|
140
152
|
"donorAddressPostalCode": { "type": "string" },
|
|
141
153
|
"donorAddressCountry": { "type": "string" },
|
|
142
|
-
"donorTosVersion": { "type": "string", "description": "Terms version the payer accepted, if the host collected one." },
|
|
143
|
-
"donorTosAcceptedAt": { "type": "string", "format": "date-time" },
|
|
144
154
|
"onSuccess": { "description": "function (CheckoutResult) => void — called once the payment is confirmed on-chain; not expressible in JSON." },
|
|
145
155
|
"onError": { "description": "function (Error) => void — called on frame-level errors; not expressible in JSON." },
|
|
146
156
|
"onClose": { "description": "function () => void — called when the payer closes the checkout; not expressible in JSON." }
|
package/dist/checkout.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE1D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAcjB;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,gIAAgI;IAChI,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAA8B;IACnD,uGAAuG;IACvG,SAAgB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,8FAA8F;IAC9F,OAAO,CAAC,YAAY,CAA8C;IAClE,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAmD;IACzF,gEAAgE;IAChE,OAAO,CAAC,kBAAkB,CAA6B;gBAE3C,UAAU,EAAE,cAAc;IAQtC;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa;IAqB/C,OAAO,CAAC,gBAAgB;IAKxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAM9D,YAAY;IAkB1B,2IAA2I;IAC3I,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAE5B;IAED;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"checkout.d.ts","sourceRoot":"","sources":["../src/checkout.ts"],"names":[],"mappings":"AAMA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,QAAQ,CAAC;AAE1D,OAAO,EACL,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,aAAa,EAElB,KAAK,aAAa,EACnB,MAAM,SAAS,CAAC;AAcjB;;;;;;GAMG;AACH,qBAAa,cAAc;IACzB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAyB;IAChD,OAAO,CAAC,WAAW,CAAkC;IACrD,OAAO,CAAC,KAAK,CAA8B;IAC3C,OAAO,CAAC,WAAW,CAA2B;IAC9C,OAAO,CAAC,MAAM,CAAS;IACvB,gIAAgI;IAChI,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,aAAa,CAA8B;IACnD,uGAAuG;IACvG,SAAgB,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,8FAA8F;IAC9F,OAAO,CAAC,YAAY,CAA8C;IAClE,sGAAsG;IACtG,OAAO,CAAC,QAAQ,CAAC,qBAAqB,CAAmD;IACzF,gEAAgE;IAChE,OAAO,CAAC,kBAAkB,CAA6B;gBAE3C,UAAU,EAAE,cAAc;IAQtC;;;;OAIG;IACH,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,aAAa;IAqB/C,OAAO,CAAC,gBAAgB;IAKxB;;;;OAIG;IACH,QAAQ,CAAC,MAAM,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAO,GAAG,IAAI;YAM9D,YAAY;IAkB1B,2IAA2I;IAC3I,IAAI,IAAI,IAAI,UAAU,GAAG,IAAI,CAE5B;IAED;;;;;OAKG;IACG,IAAI,CAAC,OAAO,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAuFjD,4EAA4E;IAC5E,KAAK,IAAI,IAAI;YAIC,IAAI;IA8ClB,OAAO,CAAC,iBAAiB;IAyDzB;;;;OAIG;IACH,OAAO,CAAC,WAAW;IAoCnB,6FAA6F;IAC7F,OAAO,CAAC,gBAAgB;CAOzB"}
|
package/dist/gate.d.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Gate for autonomous embeds (no plugin): the
|
|
2
|
+
* Gate for autonomous embeds (no plugin): the services terms + the donate kill switches.
|
|
3
3
|
*
|
|
4
|
-
* A custom form built on Pybara.checkout() is the same product surface as the donate widget — a site embeds it under the
|
|
4
|
+
* A custom form built on Pybara.checkout() is the same product surface as the donate widget — a site embeds it under the same services terms.
|
|
5
5
|
* The two packages share no code, so the gate is duplicated on each side: keep the response shape and the semantics in sync with widget-core/src/gate.ts.
|
|
6
6
|
*/
|
|
7
|
-
/** The
|
|
8
|
-
export declare const
|
|
7
|
+
/** The services terms version this release requires: raised only by a release that needs new terms, so most updates keep showing on sites that accepted older ones. */
|
|
8
|
+
export declare const REQUIRED_SITE_TERMS_VERSION = "1-0";
|
|
9
9
|
/** A refusal's `cause`: the configuration could not be read (transient), Pybara switched embeds off, or the site's terms are missing or outdated (the owner fixes it in Pybara Wallet). */
|
|
10
10
|
export type WidgetGate = {
|
|
11
11
|
show: false;
|
|
@@ -17,6 +17,6 @@ export type WidgetGate = {
|
|
|
17
17
|
};
|
|
18
18
|
/** Whether `accepted` is at least `required`, both `major-minor`, compared as numbers. */
|
|
19
19
|
export declare function versionAtLeast(accepted: string, required: string): boolean;
|
|
20
|
-
/** Reads core's /
|
|
20
|
+
/** Reads core's /kill-switch-config and regs' /site-terms in parallel, and says whether the checkout may open, and with recurring. */
|
|
21
21
|
export declare function checkWidgetGate(env: 'prod' | 'staging', siteUrl: string, recipientPrincipal: string): Promise<WidgetGate>;
|
|
22
22
|
//# sourceMappingURL=gate.d.ts.map
|
package/dist/gate.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,
|
|
1
|
+
{"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../src/gate.ts"],"names":[],"mappings":"AAEA;;;;;GAKG;AAEH,uKAAuK;AACvK,eAAO,MAAM,2BAA2B,QAAQ,CAAC;AAKjD,2LAA2L;AAC3L,MAAM,MAAM,UAAU,GAAG;IAAE,IAAI,EAAE,KAAK,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,YAAY,GAAG,cAAc,GAAG,OAAO,CAAA;CAAE,GAAG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,SAAS,EAAE,OAAO,CAAA;CAAE,CAAC;AAW9I,0FAA0F;AAC1F,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAS1E;AAQD,sIAAsI;AACtI,wBAAsB,eAAe,CACnC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,OAAO,EAAE,MAAM,EACf,kBAAkB,EAAE,MAAM,GACzB,OAAO,CAAC,UAAU,CAAC,CAqCrB"}
|
package/dist/modal/modal.d.ts
CHANGED
|
@@ -82,8 +82,11 @@ export interface PaymentData {
|
|
|
82
82
|
*/
|
|
83
83
|
export interface Checkout {
|
|
84
84
|
v: 1;
|
|
85
|
-
/**
|
|
86
|
-
|
|
85
|
+
/**
|
|
86
|
+
* A decimal string in the currency's major units: "12.34" is €12.34, "1000" is ¥1,000. The frame reads it with the currency's ISO 4217 minor units.
|
|
87
|
+
* A donation may omit it: the checkout then asks the donor how much, with `donation.suggestedAmounts` as its buttons. An order never may.
|
|
88
|
+
*/
|
|
89
|
+
amount?: string;
|
|
87
90
|
/** ISO 4217, uppercase. */
|
|
88
91
|
currency: string;
|
|
89
92
|
site: {
|
|
@@ -117,14 +120,12 @@ export interface Checkout {
|
|
|
117
120
|
postalCode?: string;
|
|
118
121
|
country?: string;
|
|
119
122
|
};
|
|
120
|
-
tos?: {
|
|
121
|
-
version?: string;
|
|
122
|
-
acceptedAt?: string;
|
|
123
|
-
};
|
|
124
123
|
};
|
|
125
124
|
message?: string;
|
|
126
125
|
isAnonymous?: boolean;
|
|
127
126
|
wantsTaxReceipt?: boolean;
|
|
127
|
+
/** Without `amount`: up to four amounts the checkout's amount step offers as buttons, decimal strings in the checkout's currency. */
|
|
128
|
+
suggestedAmounts?: string[];
|
|
128
129
|
};
|
|
129
130
|
/** A merchant payment's part (context 'payment'): the order. Informational amounts are decimal text or numbers, any decimals; only `id` and each item's `name` and `quantity` are required. */
|
|
130
131
|
order?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../src/modal/modal.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AASH,MAAM,WAAW,SAAS;IACtB,sJAAsJ;IACtJ,WAAW,EAAE,MAAM,CAAC;IACpB,0FAA0F;IAC1F,IAAI,EAAE,MAAM,CAAC;IACb,+JAA+J;IAC/J,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAChC,yFAAyF;IACzF,SAAS,EAAE,MAAM,CAAC;IAClB,6HAA6H;IAC7H,OAAO,EAAE,SAAS,GAAG,UAAU,CAAC;IAChC,2JAA2J;IAC3J,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,kJAAkJ;IAClJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,qLAAqL;IACrL,SAAS,CAAC,EAAE,CAAC,IAAI,EAAE;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,cAAc,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,CAAC;IAC7G,sEAAsE;IACtE,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IACjC,oHAAoH;IACpH,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mIAAmI;IACnI,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,CAAC;CACzD;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,MAAM,EAAE,WAAW,GAAG,aAAa,GAAG,eAAe,GAAG,aAAa,CAAC;IACtE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;CAClD;AAED,yGAAyG;AACzG,MAAM,WAAW,QAAQ;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yHAAyH;IACzH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8EAA8E;IAC9E,QAAQ,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,8HAA8H;AAC9H,MAAM,WAAW,WAAW;IACxB,SAAS,EAAE,SAAS,CAAC;IACrB,4HAA4H;IAC5H,SAAS,CAAC,EAAE;QACR,SAAS,EAAE,MAAM,CAAC;QAClB,wGAAwG;QACxG,cAAc,CAAC,EAAE,MAAM,CAAC;KAC3B,CAAC;IACF,mGAAmG;IACnG,QAAQ,EAAE,QAAQ,CAAC;CACtB;AAED;;;GAGG;AACH,MAAM,WAAW,QAAQ;IACrB,CAAC,EAAE,CAAC,CAAC;IACL
|
|
1
|
+
{"version":3,"file":"modal.d.ts","sourceRoot":"","sources":["../../src/modal/modal.ts"],"names":[],"mappings":"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"}
|
package/dist/pybara-js.iife.js
CHANGED
|
@@ -65,4 +65,4 @@ ic-request`);var ei=new TextEncoder().encode(`\vic-response`);new TextEncoder().
|
|
|
65
65
|
text-align: center;
|
|
66
66
|
font-family: system-ui, sans-serif;
|
|
67
67
|
user-select: text;
|
|
68
|
-
`,n.textContent=e,t.appendChild(n),t.addEventListener(`click`,e=>{e.target===t&&(t.remove(),Qu(),this.config.onClose?.())}),document.body.appendChild(t),this.overlay=t}close(){this.handleMessage&&=(window.removeEventListener(`message`,this.handleMessage),null),this.handleEscapeKey&&=(document.removeEventListener(`keydown`,this.handleEscapeKey),null),Qu();let e=this.overlay,t=this.iframe;this.overlay=null,this.iframe=null,this.spinner=null,this.iframeLoaded=!1,this.pendingPaymentData=null,this.lastPaymentData=null,this.pendingPrecheck=null,this.closable=!0,this.clearLoadTimer(),this.unavailableBox=null,e&&(e.style.display===`none`||$u()?e.remove():(e.style.pointerEvents=`none`,t?.animate([{transform:`scale(1)`,opacity:1},{transform:`scale(0.95)`,opacity:0}],{duration:Hu.PANEL_CLOSE_MS,easing:`ease-out`,fill:`forwards`}),e.animate([{opacity:1},{opacity:0}],{duration:Hu.OVERLAY_FADE_OUT_MS,delay:Hu.OVERLAY_FADE_OUT_DELAY_MS,easing:`ease-out`,fill:`forwards`}).finished.then(()=>e.remove(),()=>e.remove())))}},ad={widget:`donate-widget`,recurring:`donate-widget-recurring`};function od(e,t){let n=e=>{let t=/^(\d+)-(\d+)$/.exec(e);return t?[Number(t[1]),Number(t[2])]:null},r=n(e),i=n(t);return!r||!i?!1:r[0]>i[0]||r[0]===i[0]&&r[1]>=i[1]}async function sd(e){let t=await fetch(e);if(!t.ok)throw Error(`HTTP ${t.status} from ${e}`);return await t.json()}async function cd(e,t,n){let r=i[e],a=`https://${r.admin_core}.raw.icp0.io/widget-config`,o=`https://${r.admin_regs}.raw.icp0.io/widget-terms?site_url=${encodeURIComponent(t)}&principal=${encodeURIComponent(n)}`,s,c;try{[s,c]=await Promise.all([sd(a),sd(o)])}catch(e){return{show:!1,cause:`unreadable`,reason:`could not read the widget's configuration (${e instanceof Error?e.message:String(e)})`}}let l=s.kill_switch?.plugins??{};return l[ad.widget]?.enabled===!0?!c.signed||!c.version?{show:!1,cause:`terms`,reason:`${t} has not accepted the widget's terms in Pybara Wallet (Manage › Sites › Add a site without a plugin)`}:od(c.version,`1-0`)?{show:!0,recurring:l[ad.recurring]?.enabled===!0}:{show:!1,cause:`terms`,reason:`this widget version requires terms 1-0, and ${t} accepted ${c.version}: accept the new terms in Pybara Wallet (Manage › Sites)`}:{show:!1,cause:`switched-off`,reason:`the widget is switched off by Pybara for now`}}var $=class extends Error{constructor(e,t){super(t),this.name=`PybaraError`,this.code=e}};function ld(e){let t=typeof e?.height==`number`&&Number.isFinite(e.height)?Math.round(e.height):45;return Math.min(55,Math.max(25,t))}function ud(e,t){return typeof e?.borderRadius==`number`&&Number.isFinite(e.borderRadius)&&e.borderRadius>=0?`${e.borderRadius}px`:e?.shape===`sharp`?`0`:e?.shape===`rect`?`4px`:`${t/2}px`}function dd(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw new $(`INVALID_CONFIG`,`render(): no element matches ${JSON.stringify(e)}`);return t}function fd(e,t){let n=dd(e),r=new URL(t.walletUrl).origin,i=ld(t.style),a=document.createElement(`div`);a.style.cssText=`position:relative;width:100%;height:${i}px;`;let o=document.createElement(`div`);o.setAttribute(`aria-hidden`,`true`),o.style.cssText=`position:absolute;inset:0;border-radius:${ud(t.style,i)};background:rgba(128,128,128,0.16);`;let s=document.createElement(`iframe`);s.src=`${r}/button`,s.title=`Pybara`,s.style.cssText=`position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;`,a.append(o,s),n.appendChild(a);let c=!1,l=null,u=e=>{s.contentWindow?.postMessage(e,r)},d=()=>u({type:`pybara_button_idle`,v:1}),f=e=>{l=e,c&&u({type:`pybara_button_availability`,v:1,status:e.status}),t.onStateChange?.(e)},p=setTimeout(()=>{if(c)return;o.remove(),t.hideWhenUnavailable===!0&&(a.style.height=`0px`);let e=`Pybara: the button (${r}/button) did not load within ${Uu/1e3} seconds; pybara.io may be unreachable from this browser.`;console.warn(e),t.onStateChange?.({status:`unavailable`,reason:`BUTTON_UNAVAILABLE`,detail:e})},Uu);s.addEventListener(`load`,()=>{u({type:`pybara_button_init`,v:1,style:t.style??{},hideWhenUnavailable:t.hideWhenUnavailable===!0,locale:t.locale,busy:!0})},{once:!0});let m=e=>{if(e.origin!==r||e.source!==s.contentWindow)return;let n=e.data;n?.type===`pybara_button_ready`||n?.type===`pybara_button_resize`?(typeof n.height==`number`&&(a.style.height=`${n.height}px`),c||(c=!0,clearTimeout(p),s.style.opacity=`1`,o.remove(),l&&u({type:`pybara_button_availability`,v:1,status:l.status}))):n?.type===`pybara_button_click`&&(async()=>{try{await t.onClick()}catch{d()}})()};window.addEventListener(`message`,m);let h=t.subscribeAvailability(f);return{idle:d,destroy(){clearTimeout(p),window.removeEventListener(`message`,m),h(),a.remove()}}}function pd(e,t){if(typeof t?.createPayment!=`function`)throw new $(`INVALID_CONFIG`,`buttons(): "createPayment" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: "EUR" })`);let n=[],r=()=>{for(let e of n)e.idle()};async function i(){try{let n=await t.createPayment();await e.open({...n,onSuccess:t.onSuccess,onError:e=>{r(),t.onError?.(e)},onClose:()=>{r(),t.onClose?.()}})||r()}catch(e){r(),t.onError?.(e instanceof Error?e:Error(String(e)))}}function a(r){let a=n.length===0;n.push(fd(r,{walletUrl:e.walletUrl,style:t.style,hideWhenUnavailable:t.hideWhenUnavailable,locale:e.locale,subscribeAvailability:e.subscribeAvailability,onClick:i,onStateChange:a?t.onStateChange:void 0}))}return{render:a,destroy(){for(let e of n.splice(0))e.destroy()}}}var md=/^(0|[1-9]\d*)(\.\d+)?$/,hd=/^[a-z0-9-]{1,64}$/,gd=class{constructor(e){this.adminClient=null,this.modal=null,this.gateOutcome=null,this.isOpen=!1,this.completedPayment=!1,this.activePayment=null,this.lastPrecheck={},this.availabilityListeners=new Set,this.latestAvailability=null,this.config=yd(e),this.config.onAvailability&&this.availabilityListeners.add(this.config.onAvailability),this.ready=this.init(),this.config.onAvailability&&this.precheck()}buttons(e){return pd({walletUrl:r[this.config.staging?`staging`:`prod`],locale:this.config.locale,open:async e=>(await this.open(e),this.activePayment===e),subscribeAvailability:e=>(this.availabilityListeners.add(e),this.latestAvailability?e(this.latestAvailability):!this.config.onAvailability&&this.availabilityListeners.size===1&&this.precheck(this.lastPrecheck),()=>{this.availabilityListeners.delete(e)})},e)}emitAvailability(e){this.latestAvailability=e;for(let t of this.availabilityListeners)t(e)}precheck(e={}){let t=typeof e.amount==`number`&&Number.isFinite(e.amount)?String(e.amount):e.amount;this.lastPrecheck={amount:typeof t==`string`?t:void 0,currency:e.currency??this.config.currency},this.sendPrecheck()}async sendPrecheck(){if(this.availabilityListeners.size===0)return;await this.ready;let e=this.gateOutcome;if(e&&!e.show){let t=e.cause===`unreadable`?{status:`retry-later`,reason:`GATE_UNREADABLE`,detail:`Pybara: ${e.reason}; the checkout tries again at the click.`}:e.cause===`switched-off`?{status:`unavailable`,reason:`SWITCHED_OFF`,detail:`Pybara: ${e.reason}.`}:{status:`unavailable`,reason:`SITE_NOT_READY`,detail:`Pybara: ${e.reason}; the site owner does this, not the page. https://docs.pybara.com/pybara-js/setup/`};t.detail&&console.warn(t.detail),this.emitAvailability(t)}else this.modal?.precheck({beneficiary:this.config.recipientPrincipal,siteUrl:this.config.siteUrl,...this.lastPrecheck})}get gate(){return this.gateOutcome}async open(e){if(await this.ready,this.gateOutcome&&!this.gateOutcome.show)throw new $(`GATE_REFUSED`,this.gateOutcome.reason??`This site cannot accept Pybara payments yet.`);let t=_d(e.amount);if(t===null)throw new $(`INVALID_CONFIG`,`open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);let n=e.currency??this.config.currency;if(!n)throw new $(`INVALID_CONFIG`,`open(): "currency" is required — pass it to open(), or set it once in Pybara.checkout()`);if(!/^[A-Z]{3}$/.test(n))throw new $(`INVALID_CONFIG`,`open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(n)}`);if(e.durationMonths!=null&&!e.frequency)throw new $(`INVALID_CONFIG`,`open(): "durationMonths" needs a "frequency"`);let r=e.frequency?{frequency:e.frequency,...e.durationMonths==null?{}:{durationMonths:e.durationMonths}}:void 0;if(r&&this.gateOutcome&&this.gateOutcome.show&&!this.gateOutcome.recurring)throw new $(`GATE_REFUSED`,`Recurring payments are temporarily unavailable.`);if(this.isOpen)return;this.isOpen=!0;let i=!1;try{await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl)}catch(e){this.config.debug&&console.warn(`🧩 pybara-js: recipient access validation failed:`,e),i=!0}this.modal||this.initCheckoutModal();let a=this.modal;if(!a)throw this.isOpen=!1,new $(`CHECKOUT_FAILED`,`The checkout modal could not be initialised.`);if(i)this.isOpen=!1,a.renderTerminalState(`This recipient is currently unable to accept donations.`),this.initCheckoutModal();else{this.activePayment=e;try{a.show({modalData:{beneficiary:this.config.recipientPrincipal,salt:bd(),reference:this.config.siteName},recurring:r,checkout:this.checkoutFor(e,t,n)})}catch(e){throw this.isOpen=!1,this.activePayment=null,xd(e)}}}close(){this.modal?.close()}async init(){let e=this.config.staging?`staging`:`prod`,t=this.config.debug;t&&console.log(`🧩 pybara-js: initializing checkout…`),this.preconnectWallet(e),this.initCheckoutModal();let n=new Bu({adminCoreCanisterId:i[e].admin_core,debug:t});this.adminClient=n;let r=(async()=>{try{await n.init(),await n.getPybaraAdminConfig(),t&&console.log(`🧩 pybara-js: admin client ready`),n.getRecipientDataWithCache(this.config.siteUrl).catch(e=>{t&&console.warn(`🧩 pybara-js: recipient prewarm failed:`,e)})}catch(e){t&&console.error(`🧩 pybara-js: admin client init failed:`,e)}})(),a=(async()=>{this.config.pluginVersion||(this.gateOutcome=await cd(e,this.config.siteUrl,this.config.recipientPrincipal),!this.gateOutcome.show&&t&&console.warn(`🧩 pybara-js: gate refused —`,this.gateOutcome.reason))})();await Promise.all([r,a])}initCheckoutModal(){let e=this.config.staging?`staging`:`prod`,t=this.config,n=this;this.modal=new id({walletUrl:r[e],context:`donation`,thankYouMessage:t.thankYouMessage,locale:t.locale,onAvailability:e=>n.emitAvailability(e),onSuccess:e=>{n.completedPayment=!0;let r=n.activePayment,i=r?.frequency!=null,a={blockIndex:e.blockIndex,reference:e.reference,token:e.token,recurring:i,frequency:r?.frequency,durationMonths:i?r?.durationMonths??void 0:void 0,isUnlimited:i&&r?.durationMonths==null,payerPrincipal:e.payerPrincipal,recipientPrincipal:t.recipientPrincipal};r?.onSuccess?.(a)},onError:e=>{n.isOpen=!1;let t=n.activePayment;n.activePayment=null,t?.onError?.(xd(e)),n.modal=null,n.initCheckoutModal()},onClose:()=>{n.isOpen=!1;let e=n.activePayment;n.activePayment=null,e?.onClose?.(),n.completedPayment&&t.thankYouRedirectUrl?window.location.href=t.thankYouRedirectUrl:(n.completedPayment=!1,n.modal=null,n.initCheckoutModal())}}),this.availabilityListeners.size>0&&this.modal&&Object.keys(this.lastPrecheck).length>0&&this.sendPrecheck()}checkoutFor(e,t,n){let r=this.config;return{v:1,amount:t,currency:n,site:{url:r.siteUrl,name:r.siteName,country:r.siteCountry},platform:r.platform??`pybara-js`,pluginVersion:r.pluginVersion,siteTerms:{version:r.recipientTosVersion,acceptedAt:r.recipientTosAcceptedAt},notify:{email:r.notifyEmail,enabled:r.notifyDonations},donation:{donor:{email:e.donorEmail,firstName:e.donorFirstName,lastName:e.donorLastName,company:e.donorCompany,country:e.donorCountry,address:{line1:e.donorAddressLine1,line2:e.donorAddressLine2,city:e.donorAddressCity,state:e.donorAddressState,postalCode:e.donorAddressPostalCode,country:e.donorAddressCountry},tos:{version:e.donorTosVersion,acceptedAt:e.donorTosAcceptedAt}},message:e.donorMessage,isAnonymous:e.donorIsAnonymous,wantsTaxReceipt:e.wantsTaxReceipt}}}preconnectWallet(e){let t=document.createElement(`link`);t.rel=`preconnect`,t.href=new URL(r[e]).origin,t.crossOrigin=`anonymous`,document.head.appendChild(t)}};function _d(e){let t=typeof e==`number`&&Number.isFinite(e)?String(e):e;return typeof t!=`string`||!md.test(t)||!/[1-9]/.test(t)?null:t}function vd(e){let t=e.trim();if(!t)return null;let n;try{n=new URL(t.includes(`://`)?t:`https://${t}`)}catch{return null}return n.protocol!==`https:`&&n.protocol!==`http:`?null:n.origin+n.pathname.replace(/\/+$/,``)}function yd(e){if(!e.recipientPrincipal)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "recipientPrincipal" is required`);if(!e.siteUrl)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is required`);let t=vd(e.siteUrl);if(!t)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);if(!e.siteName)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteName" is required`);if(e.currency!=null&&!/^[A-Z]{3}$/.test(e.currency))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);if(e.platform!=null&&!hd.test(e.platform))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "platform" must be a lowercase slug (a-z, 0-9, -), at most 64 characters`);return{...e,siteUrl:t,staging:e.staging??!1,debug:e.debug??!1}}function bd(){let e=crypto.getRandomValues(new Uint8Array(16));return btoa(String.fromCharCode(...e))}function xd(e){return e instanceof Error?e:Error(String(e))}function Sd(e){return new gd(e)}return e.Pybara={checkout:Sd},e.PybaraCheckout=gd,e.PybaraError=$,e.checkout=Sd,e})({});
|
|
68
|
+
`,n.textContent=e,t.appendChild(n),t.addEventListener(`click`,e=>{e.target===t&&(t.remove(),Qu(),this.config.onClose?.())}),document.body.appendChild(t),this.overlay=t}close(){this.handleMessage&&=(window.removeEventListener(`message`,this.handleMessage),null),this.handleEscapeKey&&=(document.removeEventListener(`keydown`,this.handleEscapeKey),null),Qu();let e=this.overlay,t=this.iframe;this.overlay=null,this.iframe=null,this.spinner=null,this.iframeLoaded=!1,this.pendingPaymentData=null,this.lastPaymentData=null,this.pendingPrecheck=null,this.closable=!0,this.clearLoadTimer(),this.unavailableBox=null,e&&(e.style.display===`none`||$u()?e.remove():(e.style.pointerEvents=`none`,t?.animate([{transform:`scale(1)`,opacity:1},{transform:`scale(0.95)`,opacity:0}],{duration:Hu.PANEL_CLOSE_MS,easing:`ease-out`,fill:`forwards`}),e.animate([{opacity:1},{opacity:0}],{duration:Hu.OVERLAY_FADE_OUT_MS,delay:Hu.OVERLAY_FADE_OUT_DELAY_MS,easing:`ease-out`,fill:`forwards`}).finished.then(()=>e.remove(),()=>e.remove())))}},ad={widget:`donate-widget`,recurring:`donate-widget-recurring`};function od(e,t){let n=e=>{let t=/^(\d+)-(\d+)$/.exec(e);return t?[Number(t[1]),Number(t[2])]:null},r=n(e),i=n(t);return!r||!i?!1:r[0]>i[0]||r[0]===i[0]&&r[1]>=i[1]}async function sd(e){let t=await fetch(e);if(!t.ok)throw Error(`HTTP ${t.status} from ${e}`);return await t.json()}async function cd(e,t,n){let r=i[e],a=`https://${r.admin_core}.raw.icp0.io/kill-switch-config`,o=`https://${r.admin_regs}.raw.icp0.io/site-terms?site_url=${encodeURIComponent(t)}&principal=${encodeURIComponent(n)}`,s,c;try{[s,c]=await Promise.all([sd(a),sd(o)])}catch(e){return{show:!1,cause:`unreadable`,reason:`could not read the widget's configuration (${e instanceof Error?e.message:String(e)})`}}let l=s.plugins??{};return l[ad.widget]?.enabled===!0?!c.signed||!c.version?{show:!1,cause:`terms`,reason:`${t} has not accepted the Pybara Terms of Service in Pybara Wallet (Manage › Sites › Add a site without a plugin)`}:od(c.version,`1-0`)?{show:!0,recurring:l[ad.recurring]?.enabled===!0}:{show:!1,cause:`terms`,reason:`this version requires the Pybara Terms of Service 1-0, and ${t} accepted ${c.version}: accept the new terms in Pybara Wallet (Manage › Sites)`}:{show:!1,cause:`switched-off`,reason:`the widget is switched off by Pybara for now`}}var $=class extends Error{constructor(e,t){super(t),this.name=`PybaraError`,this.code=e}};function ld(e){let t=typeof e?.height==`number`&&Number.isFinite(e.height)?Math.round(e.height):45;return Math.min(55,Math.max(25,t))}function ud(e,t){return typeof e?.borderRadius==`number`&&Number.isFinite(e.borderRadius)&&e.borderRadius>=0?`${e.borderRadius}px`:e?.shape===`sharp`?`0`:e?.shape===`rect`?`4px`:`${t/2}px`}function dd(e){let t=typeof e==`string`?document.querySelector(e):e;if(!t)throw new $(`INVALID_CONFIG`,`render(): no element matches ${JSON.stringify(e)}`);return t}function fd(e,t){let n=dd(e),r=new URL(t.walletUrl).origin,i=ld(t.style),a=document.createElement(`div`);a.style.cssText=`position:relative;width:100%;height:${i}px;`;let o=document.createElement(`div`);o.setAttribute(`aria-hidden`,`true`),o.style.cssText=`position:absolute;inset:0;border-radius:${ud(t.style,i)};background:rgba(128,128,128,0.16);`;let s=document.createElement(`iframe`);s.src=`${r}/button`,s.title=`Pybara`,s.style.cssText=`position:absolute;inset:0;width:100%;height:100%;border:0;opacity:0;color-scheme:normal;background:transparent;`,a.append(o,s),n.appendChild(a);let c=!1,l=null,u=e=>{s.contentWindow?.postMessage(e,r)},d=()=>u({type:`pybara_button_idle`,v:1}),f=e=>{l=e,c&&u({type:`pybara_button_availability`,v:1,status:e.status}),t.onStateChange?.(e)},p=setTimeout(()=>{if(c)return;o.remove(),t.hideWhenUnavailable===!0&&(a.style.height=`0px`);let e=`Pybara: the button (${r}/button) did not load within ${Uu/1e3} seconds; pybara.io may be unreachable from this browser.`;console.warn(e),t.onStateChange?.({status:`unavailable`,reason:`BUTTON_UNAVAILABLE`,detail:e})},Uu);s.addEventListener(`load`,()=>{u({type:`pybara_button_init`,v:1,style:t.style??{},hideWhenUnavailable:t.hideWhenUnavailable===!0,locale:t.locale,busy:!0})},{once:!0});let m=e=>{if(e.origin!==r||e.source!==s.contentWindow)return;let n=e.data;n?.type===`pybara_button_ready`||n?.type===`pybara_button_resize`?(typeof n.height==`number`&&(a.style.height=`${n.height}px`),c||(c=!0,clearTimeout(p),s.style.opacity=`1`,o.remove(),l&&u({type:`pybara_button_availability`,v:1,status:l.status}))):n?.type===`pybara_button_click`&&(async()=>{try{await t.onClick()}catch{d()}})()};window.addEventListener(`message`,m);let h=t.subscribeAvailability(f);return{idle:d,destroy(){clearTimeout(p),window.removeEventListener(`message`,m),h(),a.remove()}}}function pd(e,t){if(typeof t?.createPayment!=`function`)throw new $(`INVALID_CONFIG`,`buttons(): "createPayment" is required, a function returning the payment from the form, e.g. () => ({ amount: form.amount.value, currency: "EUR" })`);let n=[],r=()=>{for(let e of n)e.idle()};async function i(){try{let n=await t.createPayment();await e.open({...n,onSuccess:t.onSuccess,onError:e=>{r(),t.onError?.(e)},onClose:()=>{r(),t.onClose?.()}})||r()}catch(e){r(),t.onError?.(e instanceof Error?e:Error(String(e)))}}function a(r){let a=n.length===0;n.push(fd(r,{walletUrl:e.walletUrl,style:t.style,hideWhenUnavailable:t.hideWhenUnavailable,locale:e.locale,subscribeAvailability:e.subscribeAvailability,onClick:i,onStateChange:a?t.onStateChange:void 0}))}return{render:a,destroy(){for(let e of n.splice(0))e.destroy()}}}var md=/^(0|[1-9]\d*)(\.\d+)?$/,hd=/^[a-z0-9-]{1,64}$/,gd=class{constructor(e){this.adminClient=null,this.modal=null,this.gateOutcome=null,this.isOpen=!1,this.completedPayment=!1,this.activePayment=null,this.lastPrecheck={},this.availabilityListeners=new Set,this.latestAvailability=null,this.config=yd(e),this.config.onAvailability&&this.availabilityListeners.add(this.config.onAvailability),this.ready=this.init(),this.config.onAvailability&&this.precheck()}buttons(e){return pd({walletUrl:r[this.config.staging?`staging`:`prod`],locale:this.config.locale,open:async e=>(await this.open(e),this.activePayment===e),subscribeAvailability:e=>(this.availabilityListeners.add(e),this.latestAvailability?e(this.latestAvailability):!this.config.onAvailability&&this.availabilityListeners.size===1&&this.precheck(this.lastPrecheck),()=>{this.availabilityListeners.delete(e)})},e)}emitAvailability(e){this.latestAvailability=e;for(let t of this.availabilityListeners)t(e)}precheck(e={}){let t=typeof e.amount==`number`&&Number.isFinite(e.amount)?String(e.amount):e.amount;this.lastPrecheck={amount:typeof t==`string`?t:void 0,currency:e.currency??this.config.currency},this.sendPrecheck()}async sendPrecheck(){if(this.availabilityListeners.size===0)return;await this.ready;let e=this.gateOutcome;if(e&&!e.show){let t=e.cause===`unreadable`?{status:`retry-later`,reason:`GATE_UNREADABLE`,detail:`Pybara: ${e.reason}; the checkout tries again at the click.`}:e.cause===`switched-off`?{status:`unavailable`,reason:`SWITCHED_OFF`,detail:`Pybara: ${e.reason}.`}:{status:`unavailable`,reason:`SITE_NOT_READY`,detail:`Pybara: ${e.reason}; the site owner does this, not the page. https://docs.pybara.com/pybara-js/setup/`};t.detail&&console.warn(t.detail),this.emitAvailability(t)}else this.modal?.precheck({beneficiary:this.config.recipientPrincipal,siteUrl:this.config.siteUrl,...this.lastPrecheck})}get gate(){return this.gateOutcome}async open(e){if(await this.ready,this.gateOutcome&&!this.gateOutcome.show)throw new $(`GATE_REFUSED`,this.gateOutcome.reason??`This site cannot accept Pybara payments yet.`);let t=e.amount==null||e.amount===``?void 0:_d(e.amount);if(t===null)throw new $(`INVALID_CONFIG`,`open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}; omit it to let the donor choose`);let n=e.suggestedAmounts?.map(e=>{let t=_d(e);if(t===null)throw new $(`INVALID_CONFIG`,`open(): every "suggestedAmounts" entry must be a decimal string in the currency's major units, e.g. "10", or a positive number — got ${JSON.stringify(e)}`);return t});if(n&&n.length>4)throw new $(`INVALID_CONFIG`,`open(): "suggestedAmounts" holds at most 4 amounts — got ${n.length}`);let r=e.currency??this.config.currency;if(!r)throw new $(`INVALID_CONFIG`,`open(): "currency" is required — pass it to open(), or set it once in Pybara.checkout()`);if(!/^[A-Z]{3}$/.test(r))throw new $(`INVALID_CONFIG`,`open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(r)}`);if(e.durationMonths!=null&&!e.frequency)throw new $(`INVALID_CONFIG`,`open(): "durationMonths" needs a "frequency"`);let i=e.frequency?{frequency:e.frequency,...e.durationMonths==null?{}:{durationMonths:e.durationMonths}}:void 0;if(i&&this.gateOutcome&&this.gateOutcome.show&&!this.gateOutcome.recurring)throw new $(`GATE_REFUSED`,`Recurring payments are temporarily unavailable.`);if(this.isOpen)return;this.isOpen=!0;let a=!1;try{await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl)}catch(e){this.config.debug&&console.warn(`🧩 pybara-js: recipient access validation failed:`,e),a=!0}this.modal||this.initCheckoutModal();let o=this.modal;if(!o)throw this.isOpen=!1,new $(`CHECKOUT_FAILED`,`The checkout modal could not be initialised.`);if(a)this.isOpen=!1,o.renderTerminalState(`This recipient is currently unable to accept donations.`),this.initCheckoutModal();else{this.activePayment=e;try{o.show({modalData:{beneficiary:this.config.recipientPrincipal,salt:bd(),reference:this.config.siteName},recurring:i,checkout:this.checkoutFor(e,t,r,n)})}catch(e){throw this.isOpen=!1,this.activePayment=null,xd(e)}}}close(){this.modal?.close()}async init(){let e=this.config.staging?`staging`:`prod`,t=this.config.debug;t&&console.log(`🧩 pybara-js: initializing checkout…`),this.preconnectWallet(e),this.initCheckoutModal();let n=new Bu({adminCoreCanisterId:i[e].admin_core,debug:t});this.adminClient=n;let r=(async()=>{try{await n.init(),await n.getPybaraAdminConfig(),t&&console.log(`🧩 pybara-js: admin client ready`),n.getRecipientDataWithCache(this.config.siteUrl).catch(e=>{t&&console.warn(`🧩 pybara-js: recipient prewarm failed:`,e)})}catch(e){t&&console.error(`🧩 pybara-js: admin client init failed:`,e)}})(),a=(async()=>{this.config.pluginVersion||(this.gateOutcome=await cd(e,this.config.siteUrl,this.config.recipientPrincipal),!this.gateOutcome.show&&t&&console.warn(`🧩 pybara-js: gate refused —`,this.gateOutcome.reason))})();await Promise.all([r,a])}initCheckoutModal(){let e=this.config.staging?`staging`:`prod`,t=this.config,n=this;this.modal=new id({walletUrl:r[e],context:`donation`,thankYouMessage:t.thankYouMessage,locale:t.locale,onAvailability:e=>n.emitAvailability(e),onSuccess:e=>{n.completedPayment=!0;let r=n.activePayment,i=r?.frequency!=null,a={blockIndex:e.blockIndex,reference:e.reference,token:e.token,recurring:i,frequency:r?.frequency,durationMonths:i?r?.durationMonths??void 0:void 0,isUnlimited:i&&r?.durationMonths==null,payerPrincipal:e.payerPrincipal,recipientPrincipal:t.recipientPrincipal};r?.onSuccess?.(a)},onError:e=>{n.isOpen=!1;let t=n.activePayment;n.activePayment=null,t?.onError?.(xd(e)),n.modal=null,n.initCheckoutModal()},onClose:()=>{n.isOpen=!1;let e=n.activePayment;n.activePayment=null,e?.onClose?.(),n.completedPayment&&t.thankYouRedirectUrl?window.location.href=t.thankYouRedirectUrl:(n.completedPayment=!1,n.modal=null,n.initCheckoutModal())}}),this.availabilityListeners.size>0&&this.modal&&Object.keys(this.lastPrecheck).length>0&&this.sendPrecheck()}checkoutFor(e,t,n,r){let i=this.config;return{v:1,amount:t,currency:n,site:{url:i.siteUrl,name:i.siteName,country:i.siteCountry},platform:i.platform??`pybara-js`,pluginVersion:i.pluginVersion,siteTerms:{version:i.recipientTosVersion,acceptedAt:i.recipientTosAcceptedAt},notify:{email:i.notifyEmail,enabled:i.notifyDonations},donation:{donor:{email:e.donorEmail,firstName:e.donorFirstName,lastName:e.donorLastName,company:e.donorCompany,country:e.donorCountry,address:{line1:e.donorAddressLine1,line2:e.donorAddressLine2,city:e.donorAddressCity,state:e.donorAddressState,postalCode:e.donorAddressPostalCode,country:e.donorAddressCountry}},message:e.donorMessage,isAnonymous:e.donorIsAnonymous,wantsTaxReceipt:e.wantsTaxReceipt,...t===void 0&&r?.length?{suggestedAmounts:r}:{}}}}preconnectWallet(e){let t=document.createElement(`link`);t.rel=`preconnect`,t.href=new URL(r[e]).origin,t.crossOrigin=`anonymous`,document.head.appendChild(t)}};function _d(e){let t=typeof e==`number`&&Number.isFinite(e)?String(e):e;return typeof t!=`string`||!md.test(t)||!/[1-9]/.test(t)?null:t}function vd(e){let t=e.trim();if(!t)return null;let n;try{n=new URL(t.includes(`://`)?t:`https://${t}`)}catch{return null}return n.protocol!==`https:`&&n.protocol!==`http:`?null:n.origin+n.pathname.replace(/\/+$/,``)}function yd(e){if(!e.recipientPrincipal)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "recipientPrincipal" is required`);let t=e.recipientPrincipal.trim().toLowerCase();if(t===`2vxsx-fae`||t===`aaaaa-aa`)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "recipientPrincipal" ${t} cannot receive payments (${t===`2vxsx-fae`?`the anonymous principal: anyone can move what it holds`:`the management canister`}); use the wallet principal the site's _pybara-payto DNS record lists`);if(!e.siteUrl)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is required`);let n=vd(e.siteUrl);if(!n)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);if(!e.siteName)throw new $(`INVALID_CONFIG`,`Pybara.checkout: "siteName" is required`);if(e.currency!=null&&!/^[A-Z]{3}$/.test(e.currency))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);if(e.platform!=null&&!hd.test(e.platform))throw new $(`INVALID_CONFIG`,`Pybara.checkout: "platform" must be a lowercase slug (a-z, 0-9, -), at most 64 characters`);return{...e,siteUrl:n,staging:e.staging??!1,debug:e.debug??!1}}function bd(){let e=crypto.getRandomValues(new Uint8Array(16));return btoa(String.fromCharCode(...e))}function xd(e){return e instanceof Error?e:Error(String(e))}function Sd(e){return new gd(e)}return e.Pybara={checkout:Sd},e.PybaraCheckout=gd,e.PybaraError=$,e.checkout=Sd,e})({});
|
package/dist/pybara-js.js
CHANGED
|
@@ -19,7 +19,7 @@ async function c(e) {
|
|
|
19
19
|
return await t.json();
|
|
20
20
|
}
|
|
21
21
|
async function l(t, n, r) {
|
|
22
|
-
let i = e[t], a = `https://${i.admin_core}.raw.icp0.io/
|
|
22
|
+
let i = e[t], a = `https://${i.admin_core}.raw.icp0.io/kill-switch-config`, l = `https://${i.admin_regs}.raw.icp0.io/site-terms?site_url=${encodeURIComponent(n)}&principal=${encodeURIComponent(r)}`, u, d;
|
|
23
23
|
try {
|
|
24
24
|
[u, d] = await Promise.all([c(a), c(l)]);
|
|
25
25
|
} catch (e) {
|
|
@@ -29,18 +29,18 @@ async function l(t, n, r) {
|
|
|
29
29
|
reason: `could not read the widget's configuration (${e instanceof Error ? e.message : String(e)})`
|
|
30
30
|
};
|
|
31
31
|
}
|
|
32
|
-
let f = u.
|
|
32
|
+
let f = u.plugins ?? {};
|
|
33
33
|
return f[o.widget]?.enabled === !0 ? !d.signed || !d.version ? {
|
|
34
34
|
show: !1,
|
|
35
35
|
cause: "terms",
|
|
36
|
-
reason: `${n} has not accepted the
|
|
36
|
+
reason: `${n} has not accepted the Pybara Terms of Service in Pybara Wallet (Manage › Sites › Add a site without a plugin)`
|
|
37
37
|
} : s(d.version, "1-0") ? {
|
|
38
38
|
show: !0,
|
|
39
39
|
recurring: f[o.recurring]?.enabled === !0
|
|
40
40
|
} : {
|
|
41
41
|
show: !1,
|
|
42
42
|
cause: "terms",
|
|
43
|
-
reason: `this
|
|
43
|
+
reason: `this version requires the Pybara Terms of Service 1-0, and ${n} accepted ${d.version}: accept the new terms in Pybara Wallet (Manage › Sites)`
|
|
44
44
|
} : {
|
|
45
45
|
show: !1,
|
|
46
46
|
cause: "switched-off",
|
|
@@ -104,40 +104,46 @@ var u = /^(0|[1-9]\d*)(\.\d+)?$/, d = /^[a-z0-9-]{1,64}$/, f = class {
|
|
|
104
104
|
}
|
|
105
105
|
async open(e) {
|
|
106
106
|
if (await this.ready, this.gateOutcome && !this.gateOutcome.show) throw new i("GATE_REFUSED", this.gateOutcome.reason ?? "This site cannot accept Pybara payments yet.");
|
|
107
|
-
let t = p(e.amount);
|
|
108
|
-
if (t === null) throw new i("INVALID_CONFIG", `open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}`);
|
|
109
|
-
let n = e.
|
|
110
|
-
|
|
111
|
-
|
|
107
|
+
let t = e.amount == null || e.amount === "" ? void 0 : p(e.amount);
|
|
108
|
+
if (t === null) throw new i("INVALID_CONFIG", `open(): "amount" must be a decimal string in the currency's major units, e.g. "12.34", or a positive number — got ${JSON.stringify(e.amount)}; omit it to let the donor choose`);
|
|
109
|
+
let n = e.suggestedAmounts?.map((e) => {
|
|
110
|
+
let t = p(e);
|
|
111
|
+
if (t === null) throw new i("INVALID_CONFIG", `open(): every "suggestedAmounts" entry must be a decimal string in the currency's major units, e.g. "10", or a positive number — got ${JSON.stringify(e)}`);
|
|
112
|
+
return t;
|
|
113
|
+
});
|
|
114
|
+
if (n && n.length > 4) throw new i("INVALID_CONFIG", `open(): "suggestedAmounts" holds at most 4 amounts — got ${n.length}`);
|
|
115
|
+
let r = e.currency ?? this.config.currency;
|
|
116
|
+
if (!r) throw new i("INVALID_CONFIG", "open(): \"currency\" is required — pass it to open(), or set it once in Pybara.checkout()");
|
|
117
|
+
if (!/^[A-Z]{3}$/.test(r)) throw new i("INVALID_CONFIG", `open(): "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(r)}`);
|
|
112
118
|
if (e.durationMonths != null && !e.frequency) throw new i("INVALID_CONFIG", "open(): \"durationMonths\" needs a \"frequency\"");
|
|
113
|
-
let
|
|
119
|
+
let a = e.frequency ? {
|
|
114
120
|
frequency: e.frequency,
|
|
115
121
|
...e.durationMonths == null ? {} : { durationMonths: e.durationMonths }
|
|
116
122
|
} : void 0;
|
|
117
|
-
if (
|
|
123
|
+
if (a && this.gateOutcome && this.gateOutcome.show && !this.gateOutcome.recurring) throw new i("GATE_REFUSED", "Recurring payments are temporarily unavailable.");
|
|
118
124
|
if (this.isOpen) return;
|
|
119
125
|
this.isOpen = !0;
|
|
120
|
-
let
|
|
126
|
+
let o = !1;
|
|
121
127
|
try {
|
|
122
128
|
await this.adminClient?.getRecipientDataWithCache(this.config.siteUrl);
|
|
123
129
|
} catch (e) {
|
|
124
|
-
this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e),
|
|
130
|
+
this.config.debug && console.warn("🧩 pybara-js: recipient access validation failed:", e), o = !0;
|
|
125
131
|
}
|
|
126
132
|
this.modal || this.initCheckoutModal();
|
|
127
|
-
let
|
|
128
|
-
if (!
|
|
129
|
-
if (
|
|
133
|
+
let s = this.modal;
|
|
134
|
+
if (!s) throw this.isOpen = !1, new i("CHECKOUT_FAILED", "The checkout modal could not be initialised.");
|
|
135
|
+
if (o) this.isOpen = !1, s.renderTerminalState("This recipient is currently unable to accept donations."), this.initCheckoutModal();
|
|
130
136
|
else {
|
|
131
137
|
this.activePayment = e;
|
|
132
138
|
try {
|
|
133
|
-
|
|
139
|
+
s.show({
|
|
134
140
|
modalData: {
|
|
135
141
|
beneficiary: this.config.recipientPrincipal,
|
|
136
142
|
salt: g(),
|
|
137
143
|
reference: this.config.siteName
|
|
138
144
|
},
|
|
139
|
-
recurring:
|
|
140
|
-
checkout: this.checkoutFor(e, t, n)
|
|
145
|
+
recurring: a,
|
|
146
|
+
checkout: this.checkoutFor(e, t, r, n)
|
|
141
147
|
});
|
|
142
148
|
} catch (e) {
|
|
143
149
|
throw this.isOpen = !1, this.activePayment = null, _(e);
|
|
@@ -203,26 +209,26 @@ var u = /^(0|[1-9]\d*)(\.\d+)?$/, d = /^[a-z0-9-]{1,64}$/, f = class {
|
|
|
203
209
|
}
|
|
204
210
|
}), this.availabilityListeners.size > 0 && this.modal && Object.keys(this.lastPrecheck).length > 0 && this.sendPrecheck();
|
|
205
211
|
}
|
|
206
|
-
checkoutFor(e, t, n) {
|
|
207
|
-
let
|
|
212
|
+
checkoutFor(e, t, n, r) {
|
|
213
|
+
let i = this.config;
|
|
208
214
|
return {
|
|
209
215
|
v: 1,
|
|
210
216
|
amount: t,
|
|
211
217
|
currency: n,
|
|
212
218
|
site: {
|
|
213
|
-
url:
|
|
214
|
-
name:
|
|
215
|
-
country:
|
|
219
|
+
url: i.siteUrl,
|
|
220
|
+
name: i.siteName,
|
|
221
|
+
country: i.siteCountry
|
|
216
222
|
},
|
|
217
|
-
platform:
|
|
218
|
-
pluginVersion:
|
|
223
|
+
platform: i.platform ?? "pybara-js",
|
|
224
|
+
pluginVersion: i.pluginVersion,
|
|
219
225
|
siteTerms: {
|
|
220
|
-
version:
|
|
221
|
-
acceptedAt:
|
|
226
|
+
version: i.recipientTosVersion,
|
|
227
|
+
acceptedAt: i.recipientTosAcceptedAt
|
|
222
228
|
},
|
|
223
229
|
notify: {
|
|
224
|
-
email:
|
|
225
|
-
enabled:
|
|
230
|
+
email: i.notifyEmail,
|
|
231
|
+
enabled: i.notifyDonations
|
|
226
232
|
},
|
|
227
233
|
donation: {
|
|
228
234
|
donor: {
|
|
@@ -238,15 +244,12 @@ var u = /^(0|[1-9]\d*)(\.\d+)?$/, d = /^[a-z0-9-]{1,64}$/, f = class {
|
|
|
238
244
|
state: e.donorAddressState,
|
|
239
245
|
postalCode: e.donorAddressPostalCode,
|
|
240
246
|
country: e.donorAddressCountry
|
|
241
|
-
},
|
|
242
|
-
tos: {
|
|
243
|
-
version: e.donorTosVersion,
|
|
244
|
-
acceptedAt: e.donorTosAcceptedAt
|
|
245
247
|
}
|
|
246
248
|
},
|
|
247
249
|
message: e.donorMessage,
|
|
248
250
|
isAnonymous: e.donorIsAnonymous,
|
|
249
|
-
wantsTaxReceipt: e.wantsTaxReceipt
|
|
251
|
+
wantsTaxReceipt: e.wantsTaxReceipt,
|
|
252
|
+
...t === void 0 && r?.length ? { suggestedAmounts: r } : {}
|
|
250
253
|
}
|
|
251
254
|
};
|
|
252
255
|
}
|
|
@@ -272,15 +275,17 @@ function m(e) {
|
|
|
272
275
|
}
|
|
273
276
|
function h(e) {
|
|
274
277
|
if (!e.recipientPrincipal) throw new i("INVALID_CONFIG", "Pybara.checkout: \"recipientPrincipal\" is required");
|
|
278
|
+
let t = e.recipientPrincipal.trim().toLowerCase();
|
|
279
|
+
if (t === "2vxsx-fae" || t === "aaaaa-aa") throw new i("INVALID_CONFIG", `Pybara.checkout: "recipientPrincipal" ${t} cannot receive payments (${t === "2vxsx-fae" ? "the anonymous principal: anyone can move what it holds" : "the management canister"}); use the wallet principal the site's _pybara-payto DNS record lists`);
|
|
275
280
|
if (!e.siteUrl) throw new i("INVALID_CONFIG", "Pybara.checkout: \"siteUrl\" is required");
|
|
276
|
-
let
|
|
277
|
-
if (!
|
|
281
|
+
let n = m(e.siteUrl);
|
|
282
|
+
if (!n) throw new i("INVALID_CONFIG", `Pybara.checkout: "siteUrl" is not a valid http(s) URL: ${e.siteUrl}`);
|
|
278
283
|
if (!e.siteName) throw new i("INVALID_CONFIG", "Pybara.checkout: \"siteName\" is required");
|
|
279
284
|
if (e.currency != null && !/^[A-Z]{3}$/.test(e.currency)) throw new i("INVALID_CONFIG", `Pybara.checkout: "currency" must be an uppercase ISO 4217 code, e.g. "EUR" — got ${JSON.stringify(e.currency)}`);
|
|
280
285
|
if (e.platform != null && !d.test(e.platform)) throw new i("INVALID_CONFIG", "Pybara.checkout: \"platform\" must be a lowercase slug (a-z, 0-9, -), at most 64 characters");
|
|
281
286
|
return {
|
|
282
287
|
...e,
|
|
283
|
-
siteUrl:
|
|
288
|
+
siteUrl: n,
|
|
284
289
|
staging: e.staging ?? !1,
|
|
285
290
|
debug: e.debug ?? !1
|
|
286
291
|
};
|
package/dist/types.d.ts
CHANGED
|
@@ -49,8 +49,14 @@ export interface PaymentParams {
|
|
|
49
49
|
* The amount in the currency's major units, as a decimal string — "12.34" for €12.34, "1000" for ¥1,000 — as PayPal's API takes it.
|
|
50
50
|
* A number is accepted and turned into its decimal text (12.34 → "12.34").
|
|
51
51
|
* The checkout reads it with the currency's ISO 4217 minor units, and refuses more decimals than the currency holds ("12.345" EUR, "1000.5" JPY), so the page never needs to know them.
|
|
52
|
+
* Omit it for a "Donate" button with no amount: the checkout then asks the donor how much, with `suggestedAmounts` as its buttons.
|
|
52
53
|
*/
|
|
53
|
-
amount
|
|
54
|
+
amount?: string | number;
|
|
55
|
+
/**
|
|
56
|
+
* Without `amount`: up to four amounts the checkout offers the donor as buttons, beside an amount field, in the currency's major units (decimal strings or numbers, as `amount`).
|
|
57
|
+
* Without them, the donor types the amount. Ask the site owner which amounts to suggest, if any, rather than inventing them.
|
|
58
|
+
*/
|
|
59
|
+
suggestedAmounts?: (string | number)[];
|
|
54
60
|
/** The currency charged (ISO 4217, e.g. 'EUR') — the checkout config's when absent; one of the two is required. A multi-currency site passes it on every call. */
|
|
55
61
|
currency?: string;
|
|
56
62
|
/** Recurring frequency — omit for a one-time payment. */
|
|
@@ -75,10 +81,6 @@ export interface PaymentParams {
|
|
|
75
81
|
donorAddressState?: string;
|
|
76
82
|
donorAddressPostalCode?: string;
|
|
77
83
|
donorAddressCountry?: string;
|
|
78
|
-
/** ToS version the donor accepted — pass it if the host collected acceptance. */
|
|
79
|
-
donorTosVersion?: string;
|
|
80
|
-
/** Donor ToS acceptance timestamp — same forwarding role as donorTosVersion. */
|
|
81
|
-
donorTosAcceptedAt?: string;
|
|
82
84
|
/** Called once the payment is confirmed on-chain. */
|
|
83
85
|
onSuccess?: (result: CheckoutResult) => void;
|
|
84
86
|
/** Called on frame-level errors — the modal closes itself first. */
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAElD,8IAA8I;AAC9I,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,SAAS,GAAG,QAAQ,GAAG,WAAW,CAAC;AAEtE,iEAAiE;AACjE,MAAM,WAAW,cAAc;IAC7B,uKAAuK;IACvK,kBAAkB,EAAE,MAAM,CAAC;IAC3B,gIAAgI;IAChI,OAAO,EAAE,MAAM,CAAC;IAChB,iHAAiH;IACjH,QAAQ,EAAE,MAAM,CAAC;IACjB,uLAAuL;IACvL,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mDAAmD;IACnD,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,yJAAyJ;IACzJ,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,2FAA2F;IAC3F,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2PAA2P;IAC3P,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uFAAuF;IACvF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sFAAsF;IACtF,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,6KAA6K;IAC7K,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,mHAAmH;IACnH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,wFAAwF;IACxF,sBAAsB,CAAC,EAAE,MAAM,CAAC;IAChC,iFAAiF;IACjF,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,oCAAoC;IACpC,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,CAAC,YAAY,EAAE,YAAY,KAAK,IAAI,CAAC;CACvD;AAED,gEAAgE;AAChE,MAAM,WAAW,aAAa;IAC5B
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pybara/pybara-js",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.11.0",
|
|
4
|
+
"description": "Take crypto donations with Pybara on any page — a callable checkout for your own donation form or Donate button, in the stripe-js / paypal-js convention.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pybara",
|
|
7
|
-
"
|
|
8
|
-
"
|
|
7
|
+
"donations",
|
|
8
|
+
"donate",
|
|
9
|
+
"donate-button",
|
|
9
10
|
"crypto",
|
|
10
|
-
"crypto-
|
|
11
|
+
"crypto-donations",
|
|
11
12
|
"checkout",
|
|
12
|
-
"donations",
|
|
13
13
|
"icp",
|
|
14
14
|
"internet-computer"
|
|
15
15
|
],
|