@invonetwork/web-sdk 0.4.2 → 0.6.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/CHANGELOG.md +167 -141
- package/README.md +35 -12
- package/dist/{chunk-JOVATUDY.js → chunk-D3XBTH4C.js} +10 -2
- package/dist/index.cjs +87 -1
- package/dist/index.d.cts +22 -3
- package/dist/index.d.ts +22 -3
- package/dist/index.js +81 -3
- package/dist/server.cjs +9 -0
- package/dist/server.d.cts +4 -2
- package/dist/server.d.ts +4 -2
- package/dist/server.js +3 -2
- package/dist/{types-CBMLNwbe.d.cts → types-v8bDu2_p.d.cts} +56 -1
- package/dist/{types-CBMLNwbe.d.ts → types-v8bDu2_p.d.ts} +56 -1
- package/package.json +76 -76
package/CHANGELOG.md
CHANGED
|
@@ -1,141 +1,167 @@
|
|
|
1
|
-
# Changelog
|
|
2
|
-
|
|
3
|
-
All notable changes to `@invonetwork/web-sdk` are documented here. This project follows
|
|
4
|
-
[Semantic Versioning](https://semver.org/). Releases are managed with
|
|
5
|
-
[changesets](https://github.com/changesets/changesets).
|
|
6
|
-
|
|
7
|
-
## [0.
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
- **`
|
|
12
|
-
`
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
`
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
`
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
- **
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
- **
|
|
72
|
-
`
|
|
73
|
-
- **
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
-
|
|
82
|
-
|
|
83
|
-
purchase
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
- `
|
|
112
|
-
`
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
-
|
|
138
|
-
|
|
139
|
-
-
|
|
140
|
-
|
|
141
|
-
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@invonetwork/web-sdk` are documented here. This project follows
|
|
4
|
+
[Semantic Versioning](https://semver.org/). Releases are managed with
|
|
5
|
+
[changesets](https://github.com/changesets/changesets).
|
|
6
|
+
|
|
7
|
+
## [0.6.0] — 2026-07-01
|
|
8
|
+
|
|
9
|
+
Three additive browser flows the dashboard needed, built to the live backend contracts.
|
|
10
|
+
|
|
11
|
+
- **`InvoClient.getPendingCollect()`** — the player's own pending-to-collect list
|
|
12
|
+
(player-token `GET /api/sdk/transfers/pending`), PII-free. Each row's `kind`
|
|
13
|
+
(`identity_gate` → `approve*`, `receiving_confirm` → `confirmReceipt*`) tells you the
|
|
14
|
+
action; typed fields incl. `held` / `holdReason` / `stepUpRequired`.
|
|
15
|
+
- **First-enrollment OTP grant** — `enrollmentBegin()` / `enrollmentVerify(code)` for
|
|
16
|
+
`ENROLLMENT_REQUIRES_AUTHORIZATION` (send OTP to phone+email, verify, then retry the
|
|
17
|
+
same `enrollPasskey()` — the server grant is auto-consumed). New `InvoError` helpers
|
|
18
|
+
`isEnrollmentAuthorizationRequired` / `isEnrollmentProofRequired`.
|
|
19
|
+
- **Typed approve/confirm holds** — `approve*`/`confirmReceipt*` now surface a typed
|
|
20
|
+
`holdReason` (from `error_code ?? code`) on HTTP 202 holds, plus `risk` /
|
|
21
|
+
`guardianApproval` / `pollEndpoint` on approve. `RECIPIENT_IDENTITY_PENDING` correctly
|
|
22
|
+
surfaces on confirm-receipt. Success carries no `holdReason`.
|
|
23
|
+
|
|
24
|
+
## [0.5.0] — 2026-07-01
|
|
25
|
+
|
|
26
|
+
Support partner `metadata` end-to-end on the purchase flow (additive, backward-compatible).
|
|
27
|
+
|
|
28
|
+
- **`PurchaseCompletedData.metadata?`** — the `purchase.completed` webhook now echoes your
|
|
29
|
+
metadata back (all rails); `event.data.metadata` is typed.
|
|
30
|
+
- **`purchaseCurrency`** now accepts and forwards `metadata` (the direct `/purchase-currency`
|
|
31
|
+
endpoint accepts it too, matching `createCheckout`).
|
|
32
|
+
|
|
33
|
+
## [0.4.2] — 2026-06-30
|
|
34
|
+
|
|
35
|
+
Fixes from an independent line-by-line audit against the live backend.
|
|
36
|
+
|
|
37
|
+
- **`linkDevice` now works.** `device/link/webauthn/begin` returns a wrapped
|
|
38
|
+
`{ link_id, options }` body (challenge nested under `options`) and binds the
|
|
39
|
+
challenge to a server-generated `link_id`. The client now unwraps `options` and
|
|
40
|
+
echoes the server's `link_id` to `/complete` (it previously threw on an undefined
|
|
41
|
+
challenge and sent the wrong id).
|
|
42
|
+
- **`InvoError.code` is now populated for the direct purchase rail + guardian flows.**
|
|
43
|
+
`errorFromResponse` reads `error_code` (SecureErrorHandler + `/purchase-currency`)
|
|
44
|
+
in addition to `code`, and promotes known no-code tokens (`flow_paused`,
|
|
45
|
+
`spending_limit_exceeded`, `receiver_not_enrolled_use_claim_code`) to `.code`. Fixes
|
|
46
|
+
`isDuplicateRequest` on the direct rail.
|
|
47
|
+
- **Guardian/minor routing.** The 202 guardian body also carries
|
|
48
|
+
`verification_method:"sms"`; the SDK now suppresses it (reports
|
|
49
|
+
`verificationMethod: undefined`) so a guardian-pending minor isn't routed into the
|
|
50
|
+
SMS-PIN UI. README example reordered to branch on `guardianApproval` first.
|
|
51
|
+
|
|
52
|
+
## [0.4.1] — 2026-06-30
|
|
53
|
+
|
|
54
|
+
Docs only — replaced the README's internal-leaking "Deployment prerequisites"
|
|
55
|
+
(backend flag names, DB columns, gating mechanics) with a partner-facing
|
|
56
|
+
"Before you go live"; republished so the npm page README is current.
|
|
57
|
+
|
|
58
|
+
## [0.4.0] — 2026-06-30
|
|
59
|
+
|
|
60
|
+
Additive release — more server reads, edge-ready webhooks, cancellation, and tooling.
|
|
61
|
+
|
|
62
|
+
- **`getInboundPending({ playerEmail | playerPhone })`** — live, unclaimed inbound
|
|
63
|
+
sends/transfers for a player (the source of truth behind the "you have X to collect"
|
|
64
|
+
badge; pairs with `transfer.claim_pending`).
|
|
65
|
+
- **`verifyWebhookAsync`** — Web Crypto variant of `verifyWebhook` that runs on
|
|
66
|
+
Cloudflare Workers / Deno / Vercel+Netlify Edge / Bun / browsers; and
|
|
67
|
+
**`createWebhookHandler`** — a zero-dep Fetch-API `(Request) => Promise<Response>`
|
|
68
|
+
webhook route handler (Next.js App Router, Workers, Deno, Hono, Bun).
|
|
69
|
+
- **`iterateItemPurchaseHistory`** — async iterator that pages through a player's
|
|
70
|
+
full item-purchase history.
|
|
71
|
+
- **Per-call `AbortSignal`** — every method accepts an optional `{ signal }`; an
|
|
72
|
+
aborted call throws `InvoError` code `ABORTED` and is never retried.
|
|
73
|
+
- **Tooling**: ESLint (+ lint in CI), changesets release automation, `SECURITY.md`,
|
|
74
|
+
and `CODEOWNERS`.
|
|
75
|
+
|
|
76
|
+
## [0.3.0] — 2026-06-30
|
|
77
|
+
|
|
78
|
+
Additive release — new server capabilities plus transport resilience/observability.
|
|
79
|
+
|
|
80
|
+
- **Webhook verification** (`/server`): `verifyWebhook(rawBody, signatureHeader, secret | secrets, opts?)`
|
|
81
|
+
— constant-time HMAC-SHA256 over `${t}.${rawBody}`, 5-minute replay window,
|
|
82
|
+
multi-secret rotation; returns a typed `InvoWebhookEvent` discriminated union
|
|
83
|
+
(`purchase.*`, `item.purchased`, `transfer.*`, `payout.status_changed`, `webhook.test`).
|
|
84
|
+
Throws `InvoError` (`WEBHOOK_SIGNATURE_INVALID` / `WEBHOOK_TIMESTAMP_EXPIRED` /
|
|
85
|
+
`WEBHOOK_MALFORMED` / `WEBHOOK_SECRET_MISSING`). Server-only; the browser bundle
|
|
86
|
+
stays crypto-free. Independently security-audited.
|
|
87
|
+
- **`getPlayerBalance({ playerEmail | playerId })`** (`/server`): typed `player` / `balances` / `summary`.
|
|
88
|
+
- **Automatic retries**: network errors/timeouts, `429` (honoring `retry_after`), and
|
|
89
|
+
`5xx` are retried with exponential backoff + jitter. New config `maxRetries`
|
|
90
|
+
(default 2, `0` disables) and `retryBaseDelayMs` (default 250).
|
|
91
|
+
- **Observability hooks**: optional `onRequest` / `onResponse` / `onError` on both
|
|
92
|
+
entries (best-effort/non-throwing); `InvoError.requestId` carries the backend
|
|
93
|
+
request id for support/tracing.
|
|
94
|
+
- **Typed reads**: `confirmPayment` → `ConfirmPaymentResult`; `getOrderDetails` /
|
|
95
|
+
`getItemOrderDetails` → `OrderDetailsResult`; `getItemPurchaseHistory` →
|
|
96
|
+
`ItemHistoryResult` (previously untyped `Record`). All keep `raw`.
|
|
97
|
+
- **Light validation**: `mintPlayerToken` and `createCheckout` require a non-blank
|
|
98
|
+
`playerEmail` (throws `INVALID_INPUT` before the network call).
|
|
99
|
+
- **License**: `package.json` `license` is now `SEE LICENSE IN LICENSE` (was
|
|
100
|
+
`UNLICENSED`); `LICENSE` rewritten as an explicit install-and-use grant for
|
|
101
|
+
building INVO integrations.
|
|
102
|
+
|
|
103
|
+
## [0.2.1] — 2026-06-30
|
|
104
|
+
|
|
105
|
+
Docs only — no code change (republished so the npm page README is current).
|
|
106
|
+
|
|
107
|
+
- Rewrote the README into a complete integration/deployment guide: capability
|
|
108
|
+
overview, architecture, deployment prerequisites, per-flow sections (currency
|
|
109
|
+
purchase, item purchase, sends, transfers, passkeys), webhooks, errors, and a
|
|
110
|
+
full API reference for both entries.
|
|
111
|
+
- Added INVO console onboarding: `https://console.invo.network` (production) and
|
|
112
|
+
`https://dev.console.invo.network` (testing/sandbox), mapped to their API base URLs.
|
|
113
|
+
|
|
114
|
+
## [0.2.0] — 2026-06-30
|
|
115
|
+
|
|
116
|
+
Adds **item purchase** (spend existing game currency on an in-game item, §4.8) — an
|
|
117
|
+
additive, server-only surface.
|
|
118
|
+
|
|
119
|
+
- `InvoServer` (`/server`): `purchaseItem`, `getItemPurchaseHistory`, `getItemOrderDetails`.
|
|
120
|
+
- Server-side, game-secret auth — no passkey, no real money, no payment rail (it's a
|
|
121
|
+
balance debit). Grant the item off the `item.purchased` webhook.
|
|
122
|
+
- Client-side guards: required fields (trim-checked), `itemQuantity` integer `1..1000`,
|
|
123
|
+
prices `> 0` and `<= 999999.99` (magnitude-safe 2-decimal check), and
|
|
124
|
+
`totalPrice == unitPrice × itemQuantity (±0.01)` compared in integer cents.
|
|
125
|
+
- Load-bearing response fields (`transaction_id`, `order_id`) throw `INVALID_RESPONSE`
|
|
126
|
+
if missing on a 200.
|
|
127
|
+
- `InvoError` helpers: `isInsufficientBalance` (gated to 400; not the `429` throttle),
|
|
128
|
+
`isDuplicateRequest` (409), `retryAfter` (numeric or string `retry_after`); all
|
|
129
|
+
null-safe against non-JSON error bodies.
|
|
130
|
+
- Independently audited (2 agents) against handoff doc §4.8/§6/§8; contract verified,
|
|
131
|
+
error-classification edge cases fixed.
|
|
132
|
+
|
|
133
|
+
## [0.1.0] — 2026-06-30
|
|
134
|
+
|
|
135
|
+
Initial scaffold.
|
|
136
|
+
|
|
137
|
+
- `InvoServer` (`/server`): `mintPlayerToken`, `initiateSend`, `initiateTransfer`,
|
|
138
|
+
`createCheckout`, `purchaseCurrency`, `confirmPayment`, `getOrderDetails`.
|
|
139
|
+
- Client-side purchase guards (§4.7): USD amount `0 < x ≤ 999.99`, required
|
|
140
|
+
`purchaseReference`, and `rail:"steam"` rejected before the network call
|
|
141
|
+
(`INVALID_INPUT` / `MISSING_PURCHASE_REFERENCE` / `WRONG_RAIL_ENDPOINT`).
|
|
142
|
+
- `InvoClient` (browser): `enrollPasskey`, `approveSend`/`approveTransfer`,
|
|
143
|
+
`confirmReceiptSend`/`confirmReceiptTransfer`, and `linkDevice` for the
|
|
144
|
+
interchangeable-methods flow (§4.6).
|
|
145
|
+
- Optional `refreshToken` hook: transparently re-mints and retries once on
|
|
146
|
+
`SDK_TOKEN_EXPIRED` (§11.2).
|
|
147
|
+
- Shared: typed `InvoError`, isomorphic HTTP client, WebAuthn JSON⇄binary helpers.
|
|
148
|
+
- Tests: HTTP layer, server request mapping + purchase guards, browser client
|
|
149
|
+
flows (enroll/approve/link/token-refresh), and WebAuthn serialization.
|
|
150
|
+
- Contracts extracted + auditor-verified against the INVO backend.
|
|
151
|
+
|
|
152
|
+
### Hardening (independent red-team pass)
|
|
153
|
+
|
|
154
|
+
- **Guardian/minor `202` path no longer mismapped to `verificationMethod:"sms"`** —
|
|
155
|
+
`initiateSend`/`initiateTransfer` now return `verificationMethod: undefined` and a
|
|
156
|
+
`guardianApproval` block on the guardian path, so callers don't route into the
|
|
157
|
+
PIN UI by mistake (§4.3).
|
|
158
|
+
- `usdAmount` validation tightened: rejects non-plain-decimal strings
|
|
159
|
+
(`"0x10"`, `"1e2"`, whitespace) and >2 decimal places before any network call.
|
|
160
|
+
- Load-bearing response fields (`token`, `checkout_url`) now throw `INVALID_RESPONSE`
|
|
161
|
+
instead of silently surfacing as empty strings.
|
|
162
|
+
- `getOrderDetails` requires at least one of `orderId`/`transactionId`.
|
|
163
|
+
- Token refresh now re-runs the **whole** passkey ceremony on `SDK_TOKEN_EXPIRED`
|
|
164
|
+
(never replays a single-use assertion) and single-flights concurrent refreshes.
|
|
165
|
+
- `baseUrl` must be `https://` (localhost exempt) so the token/secret can't travel
|
|
166
|
+
in cleartext.
|
|
167
|
+
- Published tarball excludes sourcemaps (no proprietary source shipped).
|
package/README.md
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
First-party TypeScript SDK for integrating **INVO** into partner **web** platforms (storefronts, web games, dashboards). It wraps INVO's web money flows behind a typed, versioned API — the web analog of the Unity/Unreal plugins.
|
|
4
4
|
|
|
5
|
-
> **Status:** `v0.
|
|
5
|
+
> **Status:** `v0.6.0`, published on npm. The backend it wraps is **live** on sandbox + production, so you can build and test against sandbox today.
|
|
6
6
|
> Canonical partner reference: **https://docs.invo.network/docs/currency-purchase** and **https://docs.invo.network/docs/game-developer-integration**.
|
|
7
7
|
|
|
8
8
|
## What it does
|
|
@@ -183,6 +183,7 @@ const purchase = await server.purchaseCurrency({
|
|
|
183
183
|
purchaseReference: crypto.randomUUID(), // idempotency key, required
|
|
184
184
|
rail: "platform",
|
|
185
185
|
paymentMethodId: "pm_...", // a tokenized payment method
|
|
186
|
+
metadata: { yourOrderId: "ord_42" }, // echoed back on the purchase.completed webhook
|
|
186
187
|
});
|
|
187
188
|
// purchase.status:
|
|
188
189
|
// "success" → captured, purchase.newBalance updated
|
|
@@ -285,14 +286,12 @@ try {
|
|
|
285
286
|
- **Claim codes** are returned only by `approveTransfer`; they're the out-of-band fallback when the recipient isn't enrolled.
|
|
286
287
|
- **`err.isReceiverNotEnrolled`** on `confirmReceipt*` is the explicit signal to switch to claim-code entry.
|
|
287
288
|
- Transfer self-claim may be disabled for your tenant; if it is, surface the claim-code path instead.
|
|
289
|
+
- **Holds:** an approve/claim can return an HTTP 202 hold instead of success — inspect `result.holdReason` (`"RISK_HOLD"`, `"GUARDIAN_APPROVAL_PENDING"`, and on confirm-receipt `"RECIPIENT_IDENTITY_PENDING"`); success has no `holdReason` (and `next: "pending_claim"`). Terminal guardian outcomes throw (`GUARDIAN_APPROVAL_REJECTED`/`_EXPIRED`).
|
|
288
290
|
|
|
289
|
-
**"You have X to collect"**
|
|
291
|
+
**"You have X to collect"**
|
|
290
292
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// each row: { transactionId, flow, amount, netAmount, sourceGame, toPhone, toIdentityId, claimCodeExpiresAt }
|
|
294
|
-
// match toPhone to the logged-in player (toIdentityId is null when the phone maps to >1 of your players)
|
|
295
|
-
```
|
|
293
|
+
- **Browser (player-token):** `client.getPendingCollect()` returns the player's own pending items. Each row's `kind` tells you the action — `"identity_gate"` → `approve*` (they initiated), `"receiving_confirm"` → `confirmReceipt*` (a peer sent to them). PII-free (no claim code / phone).
|
|
294
|
+
- **Server (game-secret):** `server.getInboundPending({ playerEmail | playerPhone })` — richer, includes `toPhone`/`toIdentityId` for routing a notification to the right account. Match `toPhone` to the player (`toIdentityId` is null when the phone maps to >1 of your players).
|
|
296
295
|
|
|
297
296
|
---
|
|
298
297
|
|
|
@@ -311,6 +310,26 @@ await client.linkDevice(linkId); // → { status: "authorized" }
|
|
|
311
310
|
await client.enrollPasskey();
|
|
312
311
|
```
|
|
313
312
|
|
|
313
|
+
**First-enrollment OTP grant.** For tenants that require it, the first `enrollPasskey()`
|
|
314
|
+
throws `ENROLLMENT_REQUIRES_AUTHORIZATION`. Send a one-time code (to the player's phone +
|
|
315
|
+
email on file), verify it, then **retry the same `enrollPasskey()`** — the server-side
|
|
316
|
+
grant is consumed automatically:
|
|
317
|
+
|
|
318
|
+
```ts
|
|
319
|
+
try {
|
|
320
|
+
await client.enrollPasskey();
|
|
321
|
+
} catch (e) {
|
|
322
|
+
if (e instanceof InvoError && e.isEnrollmentAuthorizationRequired) {
|
|
323
|
+
await client.enrollmentBegin(); // → { status: "sent", channels: ["sms","email"] }
|
|
324
|
+
await client.enrollmentVerify(codeFromUser); // 6-digit OTP
|
|
325
|
+
await client.enrollPasskey(); // retry — grant auto-consumed
|
|
326
|
+
} else if (e instanceof InvoError && e.isEnrollmentProofRequired) {
|
|
327
|
+
await client.linkDevice(linkId); // a different method already exists
|
|
328
|
+
await client.enrollPasskey();
|
|
329
|
+
} else throw e;
|
|
330
|
+
}
|
|
331
|
+
```
|
|
332
|
+
|
|
314
333
|
- **User verification is required** on every approve/claim (a missing-UV assertion fails closed).
|
|
315
334
|
- Challenges are single-use and bound to `{flow}:{transactionId}`.
|
|
316
335
|
- The SDK passes the backend's WebAuthn options through unchanged (it does not hard-code `pubKeyCredParams`/`timeout`/`attestation`).
|
|
@@ -369,7 +388,7 @@ export const POST = createWebhookHandler({
|
|
|
369
388
|
|
|
370
389
|
| Event | Fires for | Use it to |
|
|
371
390
|
|---|---|---|
|
|
372
|
-
| `purchase.completed` | every currency-purchase rail | grant currency (payload: `transaction_id, order_id, player_email, identity_id, usd_amount, currency_amount, currency_name, new_balance, rail`) |
|
|
391
|
+
| `purchase.completed` | every currency-purchase rail | grant currency (payload: `transaction_id, order_id, player_email, identity_id, usd_amount, currency_amount, currency_name, new_balance, rail, metadata`) — `metadata` echoes what you passed to `createCheckout`/`purchaseCurrency` |
|
|
373
392
|
| `purchase.failed` / `purchase.disputed` | `platform` rail only | handle failures/disputes |
|
|
374
393
|
| `purchase.refunded` | `game` / `steam` rails | handle refunds |
|
|
375
394
|
| `item.purchased` | every item purchase | **grant the in-game item** (payload includes `transaction_id, order_id, player_email, identity_id, item_id, item_name, item_quantity, unit_price, total_price, currency_name, new_balance, fee_breakdown`) |
|
|
@@ -418,6 +437,8 @@ Helpers:
|
|
|
418
437
|
| `.isInsufficientBalance` | item purchase failed (400); `required_amount` + `current_balance` on `.body` |
|
|
419
438
|
| `.isDuplicateRequest` | idempotency-keyed request was a duplicate (409) |
|
|
420
439
|
| `.retryAfter` | seconds to back off on a 429 throttle |
|
|
440
|
+
| `.isEnrollmentAuthorizationRequired` | first-enrollment needs the OTP grant → `enrollmentBegin`/`enrollmentVerify` |
|
|
441
|
+
| `.isEnrollmentProofRequired` | another method exists → prove it via `linkDevice` |
|
|
421
442
|
|
|
422
443
|
Client-side guards (bad amount, missing idempotency key, `rail:"steam"` on `purchaseCurrency`, item validation) throw `InvoError` with `.status === 0` **before** any network call. Notable backend codes: `SDK_TOKEN_EXPIRED`, `TENANT_NOT_MIGRATED`, `WEBAUTHN_NOT_ENABLED_FOR_TENANT`, `WEBAUTHN_UV_REQUIRED`, `ENROLLMENT_REQUIRES_PROOF`, `WRONG_RAIL_ENDPOINT`, `flow_paused`.
|
|
423
444
|
|
|
@@ -464,11 +485,13 @@ Every method also accepts an optional final `{ signal }` (`AbortSignal`) for can
|
|
|
464
485
|
| Method | Returns |
|
|
465
486
|
|---|---|
|
|
466
487
|
| `enrollPasskey()` | `{ status, device, raw }` |
|
|
467
|
-
| `
|
|
468
|
-
| `
|
|
488
|
+
| `enrollmentBegin()` / `enrollmentVerify(code)` | OTP grant for `ENROLLMENT_REQUIRES_AUTHORIZATION` (then retry `enrollPasskey`) |
|
|
489
|
+
| `approveSend(txnId)` / `approveTransfer(txnId)` | `{ status, next, transactionId, claimCode?, claimCodeExpiresAt?, holdReason?, risk?, guardianApproval?, pollEndpoint?, raw }` |
|
|
490
|
+
| `confirmReceiptSend(txnId)` / `confirmReceiptTransfer(txnId)` | `{ status, holdReason?, raw }` |
|
|
469
491
|
| `linkDevice(linkId)` | `{ status, raw }` |
|
|
492
|
+
| `getPendingCollect()` | `{ pending, raw }` — the player's own pending-to-collect list (player-token) |
|
|
470
493
|
|
|
471
|
-
Every method throws `InvoError` on failure
|
|
494
|
+
Every method throws `InvoError` on failure and takes an optional final `{ signal }`. Full inline types ship with the package.
|
|
472
495
|
|
|
473
496
|
---
|
|
474
497
|
|
|
@@ -480,7 +503,7 @@ npm run typecheck # tsc --noEmit
|
|
|
480
503
|
npm test # vitest
|
|
481
504
|
```
|
|
482
505
|
|
|
483
|
-
The package follows **semver**: patch = fixes, minor = additive surface, major = breaking changes (rare, with a migration note). The server contract is backward-compatible within a major, so an old pinned SDK keeps working. Pin a version and subscribe to release notes for security updates.
|
|
506
|
+
The package follows **semver**: patch = fixes, minor = additive surface, major = breaking changes (rare, with a migration note). The server contract is backward-compatible within a major, so an old pinned SDK keeps working. Pin a version and subscribe to release notes for security updates. Full history: [CHANGELOG](https://github.com/Invo-Technologies/invo-web-sdk/blob/main/CHANGELOG.md) · [release notes](https://github.com/Invo-Technologies/invo-web-sdk/blob/main/docs/RELEASES.md) (absolute links to `main`).
|
|
484
507
|
|
|
485
508
|
## License
|
|
486
509
|
|
|
@@ -17,6 +17,14 @@ var InvoError = class _InvoError extends Error {
|
|
|
17
17
|
get isTokenExpired() {
|
|
18
18
|
return this.code === "SDK_TOKEN_EXPIRED";
|
|
19
19
|
}
|
|
20
|
+
/** True if `enrollPasskey()` needs the OTP-grant flow (`enrollmentBegin`/`enrollmentVerify`). */
|
|
21
|
+
get isEnrollmentAuthorizationRequired() {
|
|
22
|
+
return this.code === "ENROLLMENT_REQUIRES_AUTHORIZATION";
|
|
23
|
+
}
|
|
24
|
+
/** True if enrolling is blocked because another method exists — use `linkDevice`. */
|
|
25
|
+
get isEnrollmentProofRequired() {
|
|
26
|
+
return this.code === "ENROLLMENT_REQUIRES_PROOF";
|
|
27
|
+
}
|
|
20
28
|
/**
|
|
21
29
|
* True if an item purchase failed because the player's balance was too low (§4.8 → 400).
|
|
22
30
|
* The backend carries `required_amount` + `current_balance` on the body for the UI.
|
|
@@ -249,5 +257,5 @@ function retryAfterMs(parsed, headers) {
|
|
|
249
257
|
}
|
|
250
258
|
|
|
251
259
|
export { Http, InvoError, assertSecureBaseUrl };
|
|
252
|
-
//# sourceMappingURL=chunk-
|
|
253
|
-
//# sourceMappingURL=chunk-
|
|
260
|
+
//# sourceMappingURL=chunk-D3XBTH4C.js.map
|
|
261
|
+
//# sourceMappingURL=chunk-D3XBTH4C.js.map
|
package/dist/index.cjs
CHANGED
|
@@ -19,6 +19,14 @@ var InvoError = class _InvoError extends Error {
|
|
|
19
19
|
get isTokenExpired() {
|
|
20
20
|
return this.code === "SDK_TOKEN_EXPIRED";
|
|
21
21
|
}
|
|
22
|
+
/** True if `enrollPasskey()` needs the OTP-grant flow (`enrollmentBegin`/`enrollmentVerify`). */
|
|
23
|
+
get isEnrollmentAuthorizationRequired() {
|
|
24
|
+
return this.code === "ENROLLMENT_REQUIRES_AUTHORIZATION";
|
|
25
|
+
}
|
|
26
|
+
/** True if enrolling is blocked because another method exists — use `linkDevice`. */
|
|
27
|
+
get isEnrollmentProofRequired() {
|
|
28
|
+
return this.code === "ENROLLMENT_REQUIRES_PROOF";
|
|
29
|
+
}
|
|
22
30
|
/**
|
|
23
31
|
* True if an item purchase failed because the player's balance was too low (§4.8 → 400).
|
|
24
32
|
* The backend carries `required_amount` + `current_balance` on the body for the UI.
|
|
@@ -332,6 +340,21 @@ function assertionToJSON(cred) {
|
|
|
332
340
|
}
|
|
333
341
|
|
|
334
342
|
// src/index.ts
|
|
343
|
+
function toPendingCollectItem(row) {
|
|
344
|
+
return {
|
|
345
|
+
transferId: String(row["transfer_id"] ?? ""),
|
|
346
|
+
kind: String(row["kind"] ?? ""),
|
|
347
|
+
flow: String(row["flow"] ?? ""),
|
|
348
|
+
amount: row["amount"] ?? null,
|
|
349
|
+
currency: String(row["currency"] ?? ""),
|
|
350
|
+
counterpartyGame: String(row["counterparty_game"] ?? ""),
|
|
351
|
+
expiresAt: row["expires_at"] ?? null,
|
|
352
|
+
stepUpRequired: row["step_up_required"] === true,
|
|
353
|
+
held: row["held"] === true,
|
|
354
|
+
holdReason: row["hold_reason"] ?? null,
|
|
355
|
+
raw: row
|
|
356
|
+
};
|
|
357
|
+
}
|
|
335
358
|
var InvoClient = class {
|
|
336
359
|
constructor(config) {
|
|
337
360
|
if (!config.token) throw new Error("InvoClient requires a player `token`.");
|
|
@@ -424,12 +447,65 @@ var InvoClient = class {
|
|
|
424
447
|
return { status: String(raw["status"] ?? ""), raw };
|
|
425
448
|
});
|
|
426
449
|
}
|
|
450
|
+
/**
|
|
451
|
+
* List the player's own pending items to collect (browser, player-token). Each row's
|
|
452
|
+
* `kind` tells you which action to call: `"identity_gate"` → `approve*` (you initiated);
|
|
453
|
+
* `"receiving_confirm"` → `confirmReceipt*` (a peer sent to you). PII-free — no claim
|
|
454
|
+
* code or phone (those are only on the server-side `getInboundPending`).
|
|
455
|
+
*/
|
|
456
|
+
async getPendingCollect(opts) {
|
|
457
|
+
return this.withTokenRetry(async () => {
|
|
458
|
+
const raw = await this.get(
|
|
459
|
+
"/api/sdk/transfers/pending",
|
|
460
|
+
opts?.signal
|
|
461
|
+
);
|
|
462
|
+
const rows = Array.isArray(raw["pending"]) ? raw["pending"] : [];
|
|
463
|
+
return { pending: rows.map(toPendingCollectItem), raw };
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
468
|
+
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
469
|
+
* this to send a 6-digit code to the player's phone + email on file, collect the code,
|
|
470
|
+
* call `enrollmentVerify(code)`, then RETRY the SAME `enrollPasskey()` —
|
|
471
|
+
* `register/complete` auto-consumes the server-side grant (30-min TTL). For
|
|
472
|
+
* `ENROLLMENT_REQUIRES_PROOF` (`err.isEnrollmentProofRequired`) use `linkDevice` instead.
|
|
473
|
+
*/
|
|
474
|
+
async enrollmentBegin(opts) {
|
|
475
|
+
return this.withTokenRetry(async () => {
|
|
476
|
+
const raw = await this.post(
|
|
477
|
+
"/api/sdk/device/enrollment/begin",
|
|
478
|
+
void 0,
|
|
479
|
+
opts?.signal
|
|
480
|
+
);
|
|
481
|
+
return {
|
|
482
|
+
status: String(raw["status"] ?? ""),
|
|
483
|
+
channels: Array.isArray(raw["channels"]) ? raw["channels"] : [],
|
|
484
|
+
raw
|
|
485
|
+
};
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
/** Verify the enrollment OTP (see {@link enrollmentBegin}); on success, retry `enrollPasskey()`. */
|
|
489
|
+
async enrollmentVerify(code, opts) {
|
|
490
|
+
if (!code) throw new Error("enrollmentVerify requires the OTP `code`.");
|
|
491
|
+
return this.withTokenRetry(async () => {
|
|
492
|
+
const raw = await this.post(
|
|
493
|
+
"/api/sdk/device/enrollment/verify",
|
|
494
|
+
{ code },
|
|
495
|
+
opts?.signal
|
|
496
|
+
);
|
|
497
|
+
return { status: String(raw["status"] ?? ""), raw };
|
|
498
|
+
});
|
|
499
|
+
}
|
|
427
500
|
// --- internals ---
|
|
428
501
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
429
502
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
430
503
|
async post(path, body, signal) {
|
|
431
504
|
return this.http.post(path, body, this.auth, { signal });
|
|
432
505
|
}
|
|
506
|
+
async get(path, signal) {
|
|
507
|
+
return this.http.get(path, this.auth, { signal });
|
|
508
|
+
}
|
|
433
509
|
/**
|
|
434
510
|
* Run a whole flow, retrying it ONCE if any call fails with SDK_TOKEN_EXPIRED
|
|
435
511
|
* and a `refreshToken` hook is configured. We re-run the entire begin→get→
|
|
@@ -483,12 +559,17 @@ var InvoClient = class {
|
|
|
483
559
|
{ webauthn_assertion: assertion },
|
|
484
560
|
signal
|
|
485
561
|
);
|
|
562
|
+
const holdReason = raw["error_code"] ?? raw["code"];
|
|
486
563
|
return {
|
|
487
564
|
status: String(raw["status"] ?? ""),
|
|
488
565
|
next: String(raw["next"] ?? ""),
|
|
489
566
|
transactionId: String(raw["transaction_id"] ?? transactionId),
|
|
490
567
|
claimCode: raw["claim_code"],
|
|
491
568
|
claimCodeExpiresAt: raw["claim_code_expires_at"],
|
|
569
|
+
holdReason: typeof holdReason === "string" ? holdReason : void 0,
|
|
570
|
+
risk: raw["risk"],
|
|
571
|
+
guardianApproval: raw["guardian_approval"] ?? void 0,
|
|
572
|
+
pollEndpoint: raw["poll_endpoint"],
|
|
492
573
|
raw
|
|
493
574
|
};
|
|
494
575
|
});
|
|
@@ -507,7 +588,12 @@ var InvoClient = class {
|
|
|
507
588
|
{ webauthn_assertion: assertion },
|
|
508
589
|
signal
|
|
509
590
|
);
|
|
510
|
-
|
|
591
|
+
const holdReason = raw["error_code"] ?? raw["code"];
|
|
592
|
+
return {
|
|
593
|
+
status: String(raw["status"] ?? ""),
|
|
594
|
+
holdReason: typeof holdReason === "string" ? holdReason : void 0,
|
|
595
|
+
raw
|
|
596
|
+
};
|
|
511
597
|
});
|
|
512
598
|
}
|
|
513
599
|
};
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ClientConfig, a as CallOptions, A as ApproveResult, b as ConfirmReceiptResult, L as LinkDeviceResult } from './types-
|
|
2
|
-
export { I as InvoError,
|
|
1
|
+
import { C as ClientConfig, a as CallOptions, A as ApproveResult, b as ConfirmReceiptResult, L as LinkDeviceResult, P as PendingCollectResult, E as EnrollmentBeginResult, c as EnrollmentVerifyResult } from './types-v8bDu2_p.cjs';
|
|
2
|
+
export { I as InvoError, d as InvoErrorInfo, e as InvoHooks, f as InvoRequestInfo, g as InvoResponseInfo, h as PendingCollectItem, R as Rail, V as VerificationMethod } from './types-v8bDu2_p.cjs';
|
|
3
3
|
|
|
4
4
|
declare class InvoClient {
|
|
5
5
|
private readonly http;
|
|
@@ -32,9 +32,28 @@ declare class InvoClient {
|
|
|
32
32
|
* begin -> navigator.credentials.get() -> complete with { link_id, webauthn_assertion }.
|
|
33
33
|
*/
|
|
34
34
|
linkDevice(linkId: string, opts?: CallOptions): Promise<LinkDeviceResult>;
|
|
35
|
+
/**
|
|
36
|
+
* List the player's own pending items to collect (browser, player-token). Each row's
|
|
37
|
+
* `kind` tells you which action to call: `"identity_gate"` → `approve*` (you initiated);
|
|
38
|
+
* `"receiving_confirm"` → `confirmReceipt*` (a peer sent to you). PII-free — no claim
|
|
39
|
+
* code or phone (those are only on the server-side `getInboundPending`).
|
|
40
|
+
*/
|
|
41
|
+
getPendingCollect(opts?: CallOptions): Promise<PendingCollectResult>;
|
|
42
|
+
/**
|
|
43
|
+
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
44
|
+
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
45
|
+
* this to send a 6-digit code to the player's phone + email on file, collect the code,
|
|
46
|
+
* call `enrollmentVerify(code)`, then RETRY the SAME `enrollPasskey()` —
|
|
47
|
+
* `register/complete` auto-consumes the server-side grant (30-min TTL). For
|
|
48
|
+
* `ENROLLMENT_REQUIRES_PROOF` (`err.isEnrollmentProofRequired`) use `linkDevice` instead.
|
|
49
|
+
*/
|
|
50
|
+
enrollmentBegin(opts?: CallOptions): Promise<EnrollmentBeginResult>;
|
|
51
|
+
/** Verify the enrollment OTP (see {@link enrollmentBegin}); on success, retry `enrollPasskey()`. */
|
|
52
|
+
enrollmentVerify(code: string, opts?: CallOptions): Promise<EnrollmentVerifyResult>;
|
|
35
53
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
36
54
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
37
55
|
private post;
|
|
56
|
+
private get;
|
|
38
57
|
/**
|
|
39
58
|
* Run a whole flow, retrying it ONCE if any call fails with SDK_TOKEN_EXPIRED
|
|
40
59
|
* and a `refreshToken` hook is configured. We re-run the entire begin→get→
|
|
@@ -49,4 +68,4 @@ declare class InvoClient {
|
|
|
49
68
|
private confirmReceipt;
|
|
50
69
|
}
|
|
51
70
|
|
|
52
|
-
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, InvoClient, LinkDeviceResult };
|
|
71
|
+
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, EnrollmentBeginResult, EnrollmentVerifyResult, InvoClient, LinkDeviceResult, PendingCollectResult };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { C as ClientConfig, a as CallOptions, A as ApproveResult, b as ConfirmReceiptResult, L as LinkDeviceResult } from './types-
|
|
2
|
-
export { I as InvoError,
|
|
1
|
+
import { C as ClientConfig, a as CallOptions, A as ApproveResult, b as ConfirmReceiptResult, L as LinkDeviceResult, P as PendingCollectResult, E as EnrollmentBeginResult, c as EnrollmentVerifyResult } from './types-v8bDu2_p.js';
|
|
2
|
+
export { I as InvoError, d as InvoErrorInfo, e as InvoHooks, f as InvoRequestInfo, g as InvoResponseInfo, h as PendingCollectItem, R as Rail, V as VerificationMethod } from './types-v8bDu2_p.js';
|
|
3
3
|
|
|
4
4
|
declare class InvoClient {
|
|
5
5
|
private readonly http;
|
|
@@ -32,9 +32,28 @@ declare class InvoClient {
|
|
|
32
32
|
* begin -> navigator.credentials.get() -> complete with { link_id, webauthn_assertion }.
|
|
33
33
|
*/
|
|
34
34
|
linkDevice(linkId: string, opts?: CallOptions): Promise<LinkDeviceResult>;
|
|
35
|
+
/**
|
|
36
|
+
* List the player's own pending items to collect (browser, player-token). Each row's
|
|
37
|
+
* `kind` tells you which action to call: `"identity_gate"` → `approve*` (you initiated);
|
|
38
|
+
* `"receiving_confirm"` → `confirmReceipt*` (a peer sent to you). PII-free — no claim
|
|
39
|
+
* code or phone (those are only on the server-side `getInboundPending`).
|
|
40
|
+
*/
|
|
41
|
+
getPendingCollect(opts?: CallOptions): Promise<PendingCollectResult>;
|
|
42
|
+
/**
|
|
43
|
+
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
44
|
+
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
45
|
+
* this to send a 6-digit code to the player's phone + email on file, collect the code,
|
|
46
|
+
* call `enrollmentVerify(code)`, then RETRY the SAME `enrollPasskey()` —
|
|
47
|
+
* `register/complete` auto-consumes the server-side grant (30-min TTL). For
|
|
48
|
+
* `ENROLLMENT_REQUIRES_PROOF` (`err.isEnrollmentProofRequired`) use `linkDevice` instead.
|
|
49
|
+
*/
|
|
50
|
+
enrollmentBegin(opts?: CallOptions): Promise<EnrollmentBeginResult>;
|
|
51
|
+
/** Verify the enrollment OTP (see {@link enrollmentBegin}); on success, retry `enrollPasskey()`. */
|
|
52
|
+
enrollmentVerify(code: string, opts?: CallOptions): Promise<EnrollmentVerifyResult>;
|
|
35
53
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
36
54
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
37
55
|
private post;
|
|
56
|
+
private get;
|
|
38
57
|
/**
|
|
39
58
|
* Run a whole flow, retrying it ONCE if any call fails with SDK_TOKEN_EXPIRED
|
|
40
59
|
* and a `refreshToken` hook is configured. We re-run the entire begin→get→
|
|
@@ -49,4 +68,4 @@ declare class InvoClient {
|
|
|
49
68
|
private confirmReceipt;
|
|
50
69
|
}
|
|
51
70
|
|
|
52
|
-
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, InvoClient, LinkDeviceResult };
|
|
71
|
+
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, EnrollmentBeginResult, EnrollmentVerifyResult, InvoClient, LinkDeviceResult, PendingCollectResult };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { assertSecureBaseUrl, Http, InvoError } from './chunk-
|
|
2
|
-
export { InvoError } from './chunk-
|
|
1
|
+
import { assertSecureBaseUrl, Http, InvoError } from './chunk-D3XBTH4C.js';
|
|
2
|
+
export { InvoError } from './chunk-D3XBTH4C.js';
|
|
3
3
|
|
|
4
4
|
// src/shared/webauthn.ts
|
|
5
5
|
function b64urlToBuffer(value) {
|
|
@@ -83,6 +83,21 @@ function assertionToJSON(cred) {
|
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
// src/index.ts
|
|
86
|
+
function toPendingCollectItem(row) {
|
|
87
|
+
return {
|
|
88
|
+
transferId: String(row["transfer_id"] ?? ""),
|
|
89
|
+
kind: String(row["kind"] ?? ""),
|
|
90
|
+
flow: String(row["flow"] ?? ""),
|
|
91
|
+
amount: row["amount"] ?? null,
|
|
92
|
+
currency: String(row["currency"] ?? ""),
|
|
93
|
+
counterpartyGame: String(row["counterparty_game"] ?? ""),
|
|
94
|
+
expiresAt: row["expires_at"] ?? null,
|
|
95
|
+
stepUpRequired: row["step_up_required"] === true,
|
|
96
|
+
held: row["held"] === true,
|
|
97
|
+
holdReason: row["hold_reason"] ?? null,
|
|
98
|
+
raw: row
|
|
99
|
+
};
|
|
100
|
+
}
|
|
86
101
|
var InvoClient = class {
|
|
87
102
|
constructor(config) {
|
|
88
103
|
if (!config.token) throw new Error("InvoClient requires a player `token`.");
|
|
@@ -175,12 +190,65 @@ var InvoClient = class {
|
|
|
175
190
|
return { status: String(raw["status"] ?? ""), raw };
|
|
176
191
|
});
|
|
177
192
|
}
|
|
193
|
+
/**
|
|
194
|
+
* List the player's own pending items to collect (browser, player-token). Each row's
|
|
195
|
+
* `kind` tells you which action to call: `"identity_gate"` → `approve*` (you initiated);
|
|
196
|
+
* `"receiving_confirm"` → `confirmReceipt*` (a peer sent to you). PII-free — no claim
|
|
197
|
+
* code or phone (those are only on the server-side `getInboundPending`).
|
|
198
|
+
*/
|
|
199
|
+
async getPendingCollect(opts) {
|
|
200
|
+
return this.withTokenRetry(async () => {
|
|
201
|
+
const raw = await this.get(
|
|
202
|
+
"/api/sdk/transfers/pending",
|
|
203
|
+
opts?.signal
|
|
204
|
+
);
|
|
205
|
+
const rows = Array.isArray(raw["pending"]) ? raw["pending"] : [];
|
|
206
|
+
return { pending: rows.map(toPendingCollectItem), raw };
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
211
|
+
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
212
|
+
* this to send a 6-digit code to the player's phone + email on file, collect the code,
|
|
213
|
+
* call `enrollmentVerify(code)`, then RETRY the SAME `enrollPasskey()` —
|
|
214
|
+
* `register/complete` auto-consumes the server-side grant (30-min TTL). For
|
|
215
|
+
* `ENROLLMENT_REQUIRES_PROOF` (`err.isEnrollmentProofRequired`) use `linkDevice` instead.
|
|
216
|
+
*/
|
|
217
|
+
async enrollmentBegin(opts) {
|
|
218
|
+
return this.withTokenRetry(async () => {
|
|
219
|
+
const raw = await this.post(
|
|
220
|
+
"/api/sdk/device/enrollment/begin",
|
|
221
|
+
void 0,
|
|
222
|
+
opts?.signal
|
|
223
|
+
);
|
|
224
|
+
return {
|
|
225
|
+
status: String(raw["status"] ?? ""),
|
|
226
|
+
channels: Array.isArray(raw["channels"]) ? raw["channels"] : [],
|
|
227
|
+
raw
|
|
228
|
+
};
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
/** Verify the enrollment OTP (see {@link enrollmentBegin}); on success, retry `enrollPasskey()`. */
|
|
232
|
+
async enrollmentVerify(code, opts) {
|
|
233
|
+
if (!code) throw new Error("enrollmentVerify requires the OTP `code`.");
|
|
234
|
+
return this.withTokenRetry(async () => {
|
|
235
|
+
const raw = await this.post(
|
|
236
|
+
"/api/sdk/device/enrollment/verify",
|
|
237
|
+
{ code },
|
|
238
|
+
opts?.signal
|
|
239
|
+
);
|
|
240
|
+
return { status: String(raw["status"] ?? ""), raw };
|
|
241
|
+
});
|
|
242
|
+
}
|
|
178
243
|
// --- internals ---
|
|
179
244
|
/** POST with the current player token. Token-expiry retry is handled one level
|
|
180
245
|
* up by withTokenRetry (which re-runs the whole ceremony, not a single call). */
|
|
181
246
|
async post(path, body, signal) {
|
|
182
247
|
return this.http.post(path, body, this.auth, { signal });
|
|
183
248
|
}
|
|
249
|
+
async get(path, signal) {
|
|
250
|
+
return this.http.get(path, this.auth, { signal });
|
|
251
|
+
}
|
|
184
252
|
/**
|
|
185
253
|
* Run a whole flow, retrying it ONCE if any call fails with SDK_TOKEN_EXPIRED
|
|
186
254
|
* and a `refreshToken` hook is configured. We re-run the entire begin→get→
|
|
@@ -234,12 +302,17 @@ var InvoClient = class {
|
|
|
234
302
|
{ webauthn_assertion: assertion },
|
|
235
303
|
signal
|
|
236
304
|
);
|
|
305
|
+
const holdReason = raw["error_code"] ?? raw["code"];
|
|
237
306
|
return {
|
|
238
307
|
status: String(raw["status"] ?? ""),
|
|
239
308
|
next: String(raw["next"] ?? ""),
|
|
240
309
|
transactionId: String(raw["transaction_id"] ?? transactionId),
|
|
241
310
|
claimCode: raw["claim_code"],
|
|
242
311
|
claimCodeExpiresAt: raw["claim_code_expires_at"],
|
|
312
|
+
holdReason: typeof holdReason === "string" ? holdReason : void 0,
|
|
313
|
+
risk: raw["risk"],
|
|
314
|
+
guardianApproval: raw["guardian_approval"] ?? void 0,
|
|
315
|
+
pollEndpoint: raw["poll_endpoint"],
|
|
243
316
|
raw
|
|
244
317
|
};
|
|
245
318
|
});
|
|
@@ -258,7 +331,12 @@ var InvoClient = class {
|
|
|
258
331
|
{ webauthn_assertion: assertion },
|
|
259
332
|
signal
|
|
260
333
|
);
|
|
261
|
-
|
|
334
|
+
const holdReason = raw["error_code"] ?? raw["code"];
|
|
335
|
+
return {
|
|
336
|
+
status: String(raw["status"] ?? ""),
|
|
337
|
+
holdReason: typeof holdReason === "string" ? holdReason : void 0,
|
|
338
|
+
raw
|
|
339
|
+
};
|
|
262
340
|
});
|
|
263
341
|
}
|
|
264
342
|
};
|
package/dist/server.cjs
CHANGED
|
@@ -21,6 +21,14 @@ var InvoError = class _InvoError extends Error {
|
|
|
21
21
|
get isTokenExpired() {
|
|
22
22
|
return this.code === "SDK_TOKEN_EXPIRED";
|
|
23
23
|
}
|
|
24
|
+
/** True if `enrollPasskey()` needs the OTP-grant flow (`enrollmentBegin`/`enrollmentVerify`). */
|
|
25
|
+
get isEnrollmentAuthorizationRequired() {
|
|
26
|
+
return this.code === "ENROLLMENT_REQUIRES_AUTHORIZATION";
|
|
27
|
+
}
|
|
28
|
+
/** True if enrolling is blocked because another method exists — use `linkDevice`. */
|
|
29
|
+
get isEnrollmentProofRequired() {
|
|
30
|
+
return this.code === "ENROLLMENT_REQUIRES_PROOF";
|
|
31
|
+
}
|
|
24
32
|
/**
|
|
25
33
|
* True if an item purchase failed because the player's balance was too low (§4.8 → 400).
|
|
26
34
|
* The backend carries `required_amount` + `current_balance` on the body for the UI.
|
|
@@ -631,6 +639,7 @@ var InvoServer = class {
|
|
|
631
639
|
if (input.savedCardId) body["saved_card_id"] = input.savedCardId;
|
|
632
640
|
if (input.playerName) body["player_name"] = input.playerName;
|
|
633
641
|
if (input.playerPhone) body["player_phone"] = input.playerPhone;
|
|
642
|
+
if (input.metadata) body["metadata"] = input.metadata;
|
|
634
643
|
const raw = await this.http.post(
|
|
635
644
|
"/api/currency-purchases/purchase-currency",
|
|
636
645
|
body,
|
package/dist/server.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as InvoError, S as ServerConfig, a as CallOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { I as InvoError, S as ServerConfig, a as CallOptions, i as PlayerToken, j as InitiateSendInput, k as InitiateResult, l as InitiateTransferInput, m as CreateCheckoutInput, n as CreateCheckoutResult, o as PurchaseInput, p as PurchaseResult, q as ConfirmPaymentResult, O as OrderDetailsResult, r as PurchaseItemInput, s as PurchaseItemResult, t as ItemHistoryQuery, u as ItemHistoryResult, v as ItemOrderQuery, w as PlayerBalanceQuery, x as PlayerBalanceResult, y as InboundPendingQuery, z as InboundPendingResult } from './types-v8bDu2_p.cjs';
|
|
2
|
+
export { B as CurrencyBalance, D as InboundPendingItem, d as InvoErrorInfo, e as InvoHooks, f as InvoRequestInfo, g as InvoResponseInfo, R as Rail, V as VerificationMethod } from './types-v8bDu2_p.cjs';
|
|
3
3
|
|
|
4
4
|
interface VerifyWebhookOptions {
|
|
5
5
|
/** Max age of the signed timestamp, in seconds. Default 300 (5 min). */
|
|
@@ -25,6 +25,8 @@ interface PurchaseCompletedData {
|
|
|
25
25
|
currency_name: string;
|
|
26
26
|
new_balance: string;
|
|
27
27
|
rail: string;
|
|
28
|
+
/** The metadata you passed to createCheckout/purchaseCurrency, echoed back (all rails). */
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
28
30
|
[key: string]: unknown;
|
|
29
31
|
}
|
|
30
32
|
interface PurchaseEventData {
|
package/dist/server.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { I as InvoError, S as ServerConfig, a as CallOptions,
|
|
2
|
-
export {
|
|
1
|
+
import { I as InvoError, S as ServerConfig, a as CallOptions, i as PlayerToken, j as InitiateSendInput, k as InitiateResult, l as InitiateTransferInput, m as CreateCheckoutInput, n as CreateCheckoutResult, o as PurchaseInput, p as PurchaseResult, q as ConfirmPaymentResult, O as OrderDetailsResult, r as PurchaseItemInput, s as PurchaseItemResult, t as ItemHistoryQuery, u as ItemHistoryResult, v as ItemOrderQuery, w as PlayerBalanceQuery, x as PlayerBalanceResult, y as InboundPendingQuery, z as InboundPendingResult } from './types-v8bDu2_p.js';
|
|
2
|
+
export { B as CurrencyBalance, D as InboundPendingItem, d as InvoErrorInfo, e as InvoHooks, f as InvoRequestInfo, g as InvoResponseInfo, R as Rail, V as VerificationMethod } from './types-v8bDu2_p.js';
|
|
3
3
|
|
|
4
4
|
interface VerifyWebhookOptions {
|
|
5
5
|
/** Max age of the signed timestamp, in seconds. Default 300 (5 min). */
|
|
@@ -25,6 +25,8 @@ interface PurchaseCompletedData {
|
|
|
25
25
|
currency_name: string;
|
|
26
26
|
new_balance: string;
|
|
27
27
|
rail: string;
|
|
28
|
+
/** The metadata you passed to createCheckout/purchaseCurrency, echoed back (all rails). */
|
|
29
|
+
metadata?: Record<string, unknown>;
|
|
28
30
|
[key: string]: unknown;
|
|
29
31
|
}
|
|
30
32
|
interface PurchaseEventData {
|
package/dist/server.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { InvoError, assertSecureBaseUrl, Http } from './chunk-
|
|
2
|
-
export { InvoError } from './chunk-
|
|
1
|
+
import { InvoError, assertSecureBaseUrl, Http } from './chunk-D3XBTH4C.js';
|
|
2
|
+
export { InvoError } from './chunk-D3XBTH4C.js';
|
|
3
3
|
import { createHmac } from 'crypto';
|
|
4
4
|
|
|
5
5
|
var DEFAULT_TOLERANCE_SEC = 300;
|
|
@@ -382,6 +382,7 @@ var InvoServer = class {
|
|
|
382
382
|
if (input.savedCardId) body["saved_card_id"] = input.savedCardId;
|
|
383
383
|
if (input.playerName) body["player_name"] = input.playerName;
|
|
384
384
|
if (input.playerPhone) body["player_phone"] = input.playerPhone;
|
|
385
|
+
if (input.metadata) body["metadata"] = input.metadata;
|
|
385
386
|
const raw = await this.http.post(
|
|
386
387
|
"/api/currency-purchases/purchase-currency",
|
|
387
388
|
body,
|
|
@@ -26,6 +26,10 @@ declare class InvoError extends Error {
|
|
|
26
26
|
get isReceiverNotEnrolled(): boolean;
|
|
27
27
|
/** True if the session/SDK token has expired and the caller should re-mint + retry. */
|
|
28
28
|
get isTokenExpired(): boolean;
|
|
29
|
+
/** True if `enrollPasskey()` needs the OTP-grant flow (`enrollmentBegin`/`enrollmentVerify`). */
|
|
30
|
+
get isEnrollmentAuthorizationRequired(): boolean;
|
|
31
|
+
/** True if enrolling is blocked because another method exists — use `linkDevice`. */
|
|
32
|
+
get isEnrollmentProofRequired(): boolean;
|
|
29
33
|
/**
|
|
30
34
|
* True if an item purchase failed because the player's balance was too low (§4.8 → 400).
|
|
31
35
|
* The backend carries `required_amount` + `current_balance` on the body for the UI.
|
|
@@ -176,6 +180,8 @@ interface PurchaseInput {
|
|
|
176
180
|
savedCardId?: string;
|
|
177
181
|
playerName?: string;
|
|
178
182
|
playerPhone?: string;
|
|
183
|
+
/** Arbitrary metadata echoed back on the purchase.completed webhook (data.metadata). */
|
|
184
|
+
metadata?: Record<string, unknown>;
|
|
179
185
|
}
|
|
180
186
|
type PurchaseStatus = "success" | "requires_action" | "pending_payment";
|
|
181
187
|
interface PurchaseResult {
|
|
@@ -306,9 +312,58 @@ interface ApproveResult {
|
|
|
306
312
|
/** transfer-approve returns the sender's claim code; send-approve does not. */
|
|
307
313
|
claimCode?: string;
|
|
308
314
|
claimCodeExpiresAt?: string;
|
|
315
|
+
/**
|
|
316
|
+
* Present when the approve came back as an HTTP 202 **hold** rather than success —
|
|
317
|
+
* e.g. `"RISK_HOLD"`, `"GUARDIAN_APPROVAL_PENDING"`, `"STEP_UP_REQUIRED"` (the last
|
|
318
|
+
* only on non-passkey approvals). Success carries no holdReason. Terminal guardian
|
|
319
|
+
* outcomes (`GUARDIAN_APPROVAL_REJECTED`/`_EXPIRED` 410, `..._CHECK_UNAVAILABLE` 503)
|
|
320
|
+
* are thrown as `InvoError` instead.
|
|
321
|
+
*/
|
|
322
|
+
holdReason?: string;
|
|
323
|
+
/** Risk-engine detail on a RISK_HOLD: `{ decision, reasons[] }`. */
|
|
324
|
+
risk?: Record<string, unknown>;
|
|
325
|
+
/** The guardian_approval audit object on GUARDIAN_APPROVAL_PENDING. */
|
|
326
|
+
guardianApproval?: unknown;
|
|
327
|
+
/** Poll endpoint for guardian status (transfer holds only). */
|
|
328
|
+
pollEndpoint?: string;
|
|
309
329
|
raw: Record<string, unknown>;
|
|
310
330
|
}
|
|
311
331
|
interface ConfirmReceiptResult {
|
|
332
|
+
status: string;
|
|
333
|
+
/** Present on a 202 hold — e.g. `"RECIPIENT_IDENTITY_PENDING"`. */
|
|
334
|
+
holdReason?: string;
|
|
335
|
+
raw: Record<string, unknown>;
|
|
336
|
+
}
|
|
337
|
+
interface PendingCollectItem {
|
|
338
|
+
/** The transaction id — note the backend key is `transfer_id`. */
|
|
339
|
+
transferId: string;
|
|
340
|
+
/** "identity_gate" (you initiated → call approve*) | "receiving_confirm" (peer send → call confirmReceipt*). */
|
|
341
|
+
kind: string;
|
|
342
|
+
/** "transfer" | "send". */
|
|
343
|
+
flow: string;
|
|
344
|
+
amount: string | null;
|
|
345
|
+
/** Currency name (not id). */
|
|
346
|
+
currency: string;
|
|
347
|
+
/** Tenant name — destination (identity_gate) or source (receiving_confirm). */
|
|
348
|
+
counterpartyGame: string;
|
|
349
|
+
expiresAt: string | null;
|
|
350
|
+
stepUpRequired: boolean;
|
|
351
|
+
held: boolean;
|
|
352
|
+
/** "guardian_pending" | "device_requires_elevation" | null. */
|
|
353
|
+
holdReason: string | null;
|
|
354
|
+
raw: Record<string, unknown>;
|
|
355
|
+
}
|
|
356
|
+
interface PendingCollectResult {
|
|
357
|
+
pending: PendingCollectItem[];
|
|
358
|
+
raw: Record<string, unknown>;
|
|
359
|
+
}
|
|
360
|
+
interface EnrollmentBeginResult {
|
|
361
|
+
status: string;
|
|
362
|
+
/** Channels the OTP was sent to, e.g. ["sms","email"]. */
|
|
363
|
+
channels: string[];
|
|
364
|
+
raw: Record<string, unknown>;
|
|
365
|
+
}
|
|
366
|
+
interface EnrollmentVerifyResult {
|
|
312
367
|
status: string;
|
|
313
368
|
raw: Record<string, unknown>;
|
|
314
369
|
}
|
|
@@ -318,4 +373,4 @@ interface LinkDeviceResult {
|
|
|
318
373
|
raw: Record<string, unknown>;
|
|
319
374
|
}
|
|
320
375
|
|
|
321
|
-
export { type ApproveResult as A, type ClientConfig as C, InvoError as I, type LinkDeviceResult as L, type OrderDetailsResult as O, type
|
|
376
|
+
export { type ApproveResult as A, type CurrencyBalance as B, type ClientConfig as C, type InboundPendingItem as D, type EnrollmentBeginResult as E, InvoError as I, type LinkDeviceResult as L, type OrderDetailsResult as O, type PendingCollectResult as P, type Rail as R, type ServerConfig as S, type VerificationMethod as V, type CallOptions as a, type ConfirmReceiptResult as b, type EnrollmentVerifyResult as c, type InvoErrorInfo as d, type InvoHooks as e, type InvoRequestInfo as f, type InvoResponseInfo as g, type PendingCollectItem as h, type PlayerToken as i, type InitiateSendInput as j, type InitiateResult as k, type InitiateTransferInput as l, type CreateCheckoutInput as m, type CreateCheckoutResult as n, type PurchaseInput as o, type PurchaseResult as p, type ConfirmPaymentResult as q, type PurchaseItemInput as r, type PurchaseItemResult as s, type ItemHistoryQuery as t, type ItemHistoryResult as u, type ItemOrderQuery as v, type PlayerBalanceQuery as w, type PlayerBalanceResult as x, type InboundPendingQuery as y, type InboundPendingResult as z };
|
|
@@ -26,6 +26,10 @@ declare class InvoError extends Error {
|
|
|
26
26
|
get isReceiverNotEnrolled(): boolean;
|
|
27
27
|
/** True if the session/SDK token has expired and the caller should re-mint + retry. */
|
|
28
28
|
get isTokenExpired(): boolean;
|
|
29
|
+
/** True if `enrollPasskey()` needs the OTP-grant flow (`enrollmentBegin`/`enrollmentVerify`). */
|
|
30
|
+
get isEnrollmentAuthorizationRequired(): boolean;
|
|
31
|
+
/** True if enrolling is blocked because another method exists — use `linkDevice`. */
|
|
32
|
+
get isEnrollmentProofRequired(): boolean;
|
|
29
33
|
/**
|
|
30
34
|
* True if an item purchase failed because the player's balance was too low (§4.8 → 400).
|
|
31
35
|
* The backend carries `required_amount` + `current_balance` on the body for the UI.
|
|
@@ -176,6 +180,8 @@ interface PurchaseInput {
|
|
|
176
180
|
savedCardId?: string;
|
|
177
181
|
playerName?: string;
|
|
178
182
|
playerPhone?: string;
|
|
183
|
+
/** Arbitrary metadata echoed back on the purchase.completed webhook (data.metadata). */
|
|
184
|
+
metadata?: Record<string, unknown>;
|
|
179
185
|
}
|
|
180
186
|
type PurchaseStatus = "success" | "requires_action" | "pending_payment";
|
|
181
187
|
interface PurchaseResult {
|
|
@@ -306,9 +312,58 @@ interface ApproveResult {
|
|
|
306
312
|
/** transfer-approve returns the sender's claim code; send-approve does not. */
|
|
307
313
|
claimCode?: string;
|
|
308
314
|
claimCodeExpiresAt?: string;
|
|
315
|
+
/**
|
|
316
|
+
* Present when the approve came back as an HTTP 202 **hold** rather than success —
|
|
317
|
+
* e.g. `"RISK_HOLD"`, `"GUARDIAN_APPROVAL_PENDING"`, `"STEP_UP_REQUIRED"` (the last
|
|
318
|
+
* only on non-passkey approvals). Success carries no holdReason. Terminal guardian
|
|
319
|
+
* outcomes (`GUARDIAN_APPROVAL_REJECTED`/`_EXPIRED` 410, `..._CHECK_UNAVAILABLE` 503)
|
|
320
|
+
* are thrown as `InvoError` instead.
|
|
321
|
+
*/
|
|
322
|
+
holdReason?: string;
|
|
323
|
+
/** Risk-engine detail on a RISK_HOLD: `{ decision, reasons[] }`. */
|
|
324
|
+
risk?: Record<string, unknown>;
|
|
325
|
+
/** The guardian_approval audit object on GUARDIAN_APPROVAL_PENDING. */
|
|
326
|
+
guardianApproval?: unknown;
|
|
327
|
+
/** Poll endpoint for guardian status (transfer holds only). */
|
|
328
|
+
pollEndpoint?: string;
|
|
309
329
|
raw: Record<string, unknown>;
|
|
310
330
|
}
|
|
311
331
|
interface ConfirmReceiptResult {
|
|
332
|
+
status: string;
|
|
333
|
+
/** Present on a 202 hold — e.g. `"RECIPIENT_IDENTITY_PENDING"`. */
|
|
334
|
+
holdReason?: string;
|
|
335
|
+
raw: Record<string, unknown>;
|
|
336
|
+
}
|
|
337
|
+
interface PendingCollectItem {
|
|
338
|
+
/** The transaction id — note the backend key is `transfer_id`. */
|
|
339
|
+
transferId: string;
|
|
340
|
+
/** "identity_gate" (you initiated → call approve*) | "receiving_confirm" (peer send → call confirmReceipt*). */
|
|
341
|
+
kind: string;
|
|
342
|
+
/** "transfer" | "send". */
|
|
343
|
+
flow: string;
|
|
344
|
+
amount: string | null;
|
|
345
|
+
/** Currency name (not id). */
|
|
346
|
+
currency: string;
|
|
347
|
+
/** Tenant name — destination (identity_gate) or source (receiving_confirm). */
|
|
348
|
+
counterpartyGame: string;
|
|
349
|
+
expiresAt: string | null;
|
|
350
|
+
stepUpRequired: boolean;
|
|
351
|
+
held: boolean;
|
|
352
|
+
/** "guardian_pending" | "device_requires_elevation" | null. */
|
|
353
|
+
holdReason: string | null;
|
|
354
|
+
raw: Record<string, unknown>;
|
|
355
|
+
}
|
|
356
|
+
interface PendingCollectResult {
|
|
357
|
+
pending: PendingCollectItem[];
|
|
358
|
+
raw: Record<string, unknown>;
|
|
359
|
+
}
|
|
360
|
+
interface EnrollmentBeginResult {
|
|
361
|
+
status: string;
|
|
362
|
+
/** Channels the OTP was sent to, e.g. ["sms","email"]. */
|
|
363
|
+
channels: string[];
|
|
364
|
+
raw: Record<string, unknown>;
|
|
365
|
+
}
|
|
366
|
+
interface EnrollmentVerifyResult {
|
|
312
367
|
status: string;
|
|
313
368
|
raw: Record<string, unknown>;
|
|
314
369
|
}
|
|
@@ -318,4 +373,4 @@ interface LinkDeviceResult {
|
|
|
318
373
|
raw: Record<string, unknown>;
|
|
319
374
|
}
|
|
320
375
|
|
|
321
|
-
export { type ApproveResult as A, type ClientConfig as C, InvoError as I, type LinkDeviceResult as L, type OrderDetailsResult as O, type
|
|
376
|
+
export { type ApproveResult as A, type CurrencyBalance as B, type ClientConfig as C, type InboundPendingItem as D, type EnrollmentBeginResult as E, InvoError as I, type LinkDeviceResult as L, type OrderDetailsResult as O, type PendingCollectResult as P, type Rail as R, type ServerConfig as S, type VerificationMethod as V, type CallOptions as a, type ConfirmReceiptResult as b, type EnrollmentVerifyResult as c, type InvoErrorInfo as d, type InvoHooks as e, type InvoRequestInfo as f, type InvoResponseInfo as g, type PendingCollectItem as h, type PlayerToken as i, type InitiateSendInput as j, type InitiateResult as k, type InitiateTransferInput as l, type CreateCheckoutInput as m, type CreateCheckoutResult as n, type PurchaseInput as o, type PurchaseResult as p, type ConfirmPaymentResult as q, type PurchaseItemInput as r, type PurchaseItemResult as s, type ItemHistoryQuery as t, type ItemHistoryResult as u, type ItemOrderQuery as v, type PlayerBalanceQuery as w, type PlayerBalanceResult as x, type InboundPendingQuery as y, type InboundPendingResult as z };
|
package/package.json
CHANGED
|
@@ -1,76 +1,76 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@invonetwork/web-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "INVO Web SDK — currency purchase + passkey (WebAuthn) verification for partner web platforms.",
|
|
5
|
-
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
-
"private": false,
|
|
7
|
-
"repository": {
|
|
8
|
-
"type": "git",
|
|
9
|
-
"url": "git+https://github.com/Invo-Technologies/invo-web-sdk.git"
|
|
10
|
-
},
|
|
11
|
-
"homepage": "https://docs.invo.network",
|
|
12
|
-
"bugs": {
|
|
13
|
-
"url": "https://github.com/Invo-Technologies/invo-web-sdk/issues"
|
|
14
|
-
},
|
|
15
|
-
"type": "module",
|
|
16
|
-
"engines": {
|
|
17
|
-
"node": ">=18"
|
|
18
|
-
},
|
|
19
|
-
"sideEffects": false,
|
|
20
|
-
"files": [
|
|
21
|
-
"dist",
|
|
22
|
-
"!dist/**/*.map",
|
|
23
|
-
"README.md",
|
|
24
|
-
"LICENSE",
|
|
25
|
-
"CHANGELOG.md"
|
|
26
|
-
],
|
|
27
|
-
"exports": {
|
|
28
|
-
".": {
|
|
29
|
-
"types": "./dist/index.d.ts",
|
|
30
|
-
"import": "./dist/index.js",
|
|
31
|
-
"require": "./dist/index.cjs"
|
|
32
|
-
},
|
|
33
|
-
"./server": {
|
|
34
|
-
"types": "./dist/server.d.ts",
|
|
35
|
-
"import": "./dist/server.js",
|
|
36
|
-
"require": "./dist/server.cjs"
|
|
37
|
-
}
|
|
38
|
-
},
|
|
39
|
-
"main": "./dist/index.cjs",
|
|
40
|
-
"module": "./dist/index.js",
|
|
41
|
-
"types": "./dist/index.d.ts",
|
|
42
|
-
"scripts": {
|
|
43
|
-
"build": "tsup",
|
|
44
|
-
"dev": "tsup --watch",
|
|
45
|
-
"typecheck": "tsc --noEmit",
|
|
46
|
-
"lint": "eslint .",
|
|
47
|
-
"test": "vitest run",
|
|
48
|
-
"test:watch": "vitest",
|
|
49
|
-
"clean": "rimraf dist",
|
|
50
|
-
"changeset": "changeset",
|
|
51
|
-
"version-packages": "changeset version",
|
|
52
|
-
"release": "npm run build && changeset publish",
|
|
53
|
-
"prepublishOnly": "npm run clean && npm run build"
|
|
54
|
-
},
|
|
55
|
-
"keywords": [
|
|
56
|
-
"invo",
|
|
57
|
-
"webauthn",
|
|
58
|
-
"passkey",
|
|
59
|
-
"payments",
|
|
60
|
-
"game-currency",
|
|
61
|
-
"sdk"
|
|
62
|
-
],
|
|
63
|
-
"publishConfig": {
|
|
64
|
-
"access": "public"
|
|
65
|
-
},
|
|
66
|
-
"devDependencies": {
|
|
67
|
-
"@changesets/cli": "^2.31.0",
|
|
68
|
-
"@eslint/js": "^10.0.1",
|
|
69
|
-
"eslint": "^10.6.0",
|
|
70
|
-
"rimraf": "^5.0.5",
|
|
71
|
-
"tsup": "^8.0.1",
|
|
72
|
-
"typescript": "^5.4.5",
|
|
73
|
-
"typescript-eslint": "^8.62.1",
|
|
74
|
-
"vitest": "^1.5.0"
|
|
75
|
-
}
|
|
76
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@invonetwork/web-sdk",
|
|
3
|
+
"version": "0.6.0",
|
|
4
|
+
"description": "INVO Web SDK — currency purchase + passkey (WebAuthn) verification for partner web platforms.",
|
|
5
|
+
"license": "SEE LICENSE IN LICENSE",
|
|
6
|
+
"private": false,
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/Invo-Technologies/invo-web-sdk.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://docs.invo.network",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/Invo-Technologies/invo-web-sdk/issues"
|
|
14
|
+
},
|
|
15
|
+
"type": "module",
|
|
16
|
+
"engines": {
|
|
17
|
+
"node": ">=18"
|
|
18
|
+
},
|
|
19
|
+
"sideEffects": false,
|
|
20
|
+
"files": [
|
|
21
|
+
"dist",
|
|
22
|
+
"!dist/**/*.map",
|
|
23
|
+
"README.md",
|
|
24
|
+
"LICENSE",
|
|
25
|
+
"CHANGELOG.md"
|
|
26
|
+
],
|
|
27
|
+
"exports": {
|
|
28
|
+
".": {
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"import": "./dist/index.js",
|
|
31
|
+
"require": "./dist/index.cjs"
|
|
32
|
+
},
|
|
33
|
+
"./server": {
|
|
34
|
+
"types": "./dist/server.d.ts",
|
|
35
|
+
"import": "./dist/server.js",
|
|
36
|
+
"require": "./dist/server.cjs"
|
|
37
|
+
}
|
|
38
|
+
},
|
|
39
|
+
"main": "./dist/index.cjs",
|
|
40
|
+
"module": "./dist/index.js",
|
|
41
|
+
"types": "./dist/index.d.ts",
|
|
42
|
+
"scripts": {
|
|
43
|
+
"build": "tsup",
|
|
44
|
+
"dev": "tsup --watch",
|
|
45
|
+
"typecheck": "tsc --noEmit",
|
|
46
|
+
"lint": "eslint .",
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"clean": "rimraf dist",
|
|
50
|
+
"changeset": "changeset",
|
|
51
|
+
"version-packages": "changeset version",
|
|
52
|
+
"release": "npm run build && changeset publish",
|
|
53
|
+
"prepublishOnly": "npm run clean && npm run build"
|
|
54
|
+
},
|
|
55
|
+
"keywords": [
|
|
56
|
+
"invo",
|
|
57
|
+
"webauthn",
|
|
58
|
+
"passkey",
|
|
59
|
+
"payments",
|
|
60
|
+
"game-currency",
|
|
61
|
+
"sdk"
|
|
62
|
+
],
|
|
63
|
+
"publishConfig": {
|
|
64
|
+
"access": "public"
|
|
65
|
+
},
|
|
66
|
+
"devDependencies": {
|
|
67
|
+
"@changesets/cli": "^2.31.0",
|
|
68
|
+
"@eslint/js": "^10.0.1",
|
|
69
|
+
"eslint": "^10.6.0",
|
|
70
|
+
"rimraf": "^5.0.5",
|
|
71
|
+
"tsup": "^8.0.1",
|
|
72
|
+
"typescript": "^5.4.5",
|
|
73
|
+
"typescript-eslint": "^8.62.1",
|
|
74
|
+
"vitest": "^1.5.0"
|
|
75
|
+
}
|
|
76
|
+
}
|