@invonetwork/web-sdk 0.6.0 → 0.8.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 +27 -0
- package/README.md +18 -1
- package/dist/index.cjs +87 -0
- package/dist/index.d.cts +16 -3
- package/dist/index.d.ts +16 -3
- package/dist/index.js +87 -0
- package/dist/server.cjs +50 -1
- package/dist/server.d.cts +12 -3
- package/dist/server.d.ts +12 -3
- package/dist/server.js +50 -1
- package/dist/{types-v8bDu2_p.d.cts → types-DLSCxpoT.d.cts} +88 -1
- package/dist/{types-v8bDu2_p.d.ts → types-DLSCxpoT.d.ts} +88 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,33 @@ All notable changes to `@invonetwork/web-sdk` are documented here. This project
|
|
|
4
4
|
[Semantic Versioning](https://semver.org/). Releases are managed with
|
|
5
5
|
[changesets](https://github.com/changesets/changesets).
|
|
6
6
|
|
|
7
|
+
## [0.8.0] — 2026-07-01
|
|
8
|
+
|
|
9
|
+
Completes the **discovery layer** for send/transfer UIs.
|
|
10
|
+
|
|
11
|
+
- **`InvoClient.getBalance()`** (browser, player-token, `GET /api/sdk/balance`) — the
|
|
12
|
+
player's balances for the token's game: `balances[]` (`currencyId`, `currencyName`,
|
|
13
|
+
`currencySymbol`/`currencySymbolUrl` (nullable), `availableBalance`/`reservedBalance`/
|
|
14
|
+
`totalBalance` as decimal strings) plus `totalValue` / `currencyCount` / `hasFunds`. A
|
|
15
|
+
player who hasn't transacted here yet returns an empty `balances` array (a `200`, not an
|
|
16
|
+
error); `404 GAME_NOT_FOUND` throws.
|
|
17
|
+
- **`InvoServer.getLinkedIdentities({ playerEmail | playerPhone })`** (server-only,
|
|
18
|
+
game-secret) — a player's linked wallet identities (game-scoped). Provide one identifier
|
|
19
|
+
(phone wins if both); no in-game match returns `notFound: true` with empty `emails`
|
|
20
|
+
instead of throwing. **Returns first-party PII — never expose to the browser.**
|
|
21
|
+
|
|
22
|
+
## [0.7.0] — 2026-07-01
|
|
23
|
+
|
|
24
|
+
Start of the **discovery layer** for send/transfer UIs.
|
|
25
|
+
|
|
26
|
+
- **`InvoClient.getDestinations({ direction })`** — one player-token call
|
|
27
|
+
(`GET /api/sdk/destinations`) returns every game the player can send/transfer to, with
|
|
28
|
+
all display metadata **inline** (game name, icon, currency name/symbol, min/max transfer
|
|
29
|
+
limits) — no per-game lookup. Includes source game/currency info and `transferMode`
|
|
30
|
+
(`universal`/`linked` + `linkedGameIds`).
|
|
31
|
+
- _(Coming in 0.7.x: `getBalance` single-game player-token read; `getLinkedIdentities`
|
|
32
|
+
server-side.)_
|
|
33
|
+
|
|
7
34
|
## [0.6.0] — 2026-07-01
|
|
8
35
|
|
|
9
36
|
Three additive browser flows the dashboard needed, built to the live backend contracts.
|
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.8.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
|
|
@@ -251,6 +251,20 @@ Move already-owned game currency from one player to another, authorized by the *
|
|
|
251
251
|
| Approve (browser) | `approveSend` | `approveTransfer` — also returns the sender's **claim code** |
|
|
252
252
|
| Recipient claim (browser) | `confirmReceiptSend` | `confirmReceiptTransfer` |
|
|
253
253
|
|
|
254
|
+
**Where can I send? (browser, v0.7.0+)** — before a player can move value, populate the "pick a destination" UI with `client.getDestinations({ direction: "transfer" | "send" })`. One player-token call returns every reachable game with display metadata inline — no per-game lookup:
|
|
255
|
+
|
|
256
|
+
```ts
|
|
257
|
+
const { availableGames, sourceCurrencyName } = await client.getDestinations({ direction: "transfer" });
|
|
258
|
+
// each: { gameId, gameName, gameIcon, currencyName, currencySymbol, minimumTransfer, maximumTransfer, … }
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
**What do I have? (browser, v0.8.0+)** — `client.getBalance()` returns the player's balances for this game (amounts are decimal strings; rows carry `currencySymbol`/`currencySymbolUrl`). A player who hasn't transacted here yet returns an empty `balances` array (show 0.00) — not an error:
|
|
262
|
+
|
|
263
|
+
```ts
|
|
264
|
+
const { balances, hasFunds, totalValue } = await client.getBalance();
|
|
265
|
+
// each: { currencyId, currencyName, currencySymbol, availableBalance, reservedBalance, totalBalance }
|
|
266
|
+
```
|
|
267
|
+
|
|
254
268
|
```ts
|
|
255
269
|
// 1. SERVER — initiate, then branch on how the sender must verify
|
|
256
270
|
const t = await server.initiateTransfer({
|
|
@@ -473,6 +487,7 @@ try {
|
|
|
473
487
|
| `getItemOrderDetails({ orderId? \| transactionId? \| clientRequestId? })` | `{ order, financialSummary, statusTimeline, raw }` |
|
|
474
488
|
| `getPlayerBalance({ playerEmail? \| playerId? })` | `{ player, balances, summary, raw }` |
|
|
475
489
|
| `getInboundPending({ playerEmail? \| playerPhone? })` | `{ inboundPending, raw }` — live unclaimed inbound sends/transfers |
|
|
490
|
+
| `getLinkedIdentities({ playerEmail? \| playerPhone? })` | `{ walletUserId, primaryEmail, primaryPhone, isMinor, emails, notFound, raw }` — **server-only** (returns PII) |
|
|
476
491
|
| `iterateItemPurchaseHistory({ playerEmail, pageSize? })` | async iterator over all history rows |
|
|
477
492
|
| `verifyWebhook(rawBody, signatureHeader, secret \| secrets, opts?)` | typed `InvoWebhookEvent` (throws on bad signature) |
|
|
478
493
|
| `verifyWebhookAsync(...)` | same as `verifyWebhook`, Web Crypto (edge/Workers/Deno/Bun) |
|
|
@@ -490,6 +505,8 @@ Every method also accepts an optional final `{ signal }` (`AbortSignal`) for can
|
|
|
490
505
|
| `confirmReceiptSend(txnId)` / `confirmReceiptTransfer(txnId)` | `{ status, holdReason?, raw }` |
|
|
491
506
|
| `linkDevice(linkId)` | `{ status, raw }` |
|
|
492
507
|
| `getPendingCollect()` | `{ pending, raw }` — the player's own pending-to-collect list (player-token) |
|
|
508
|
+
| `getDestinations({ direction? })` | `{ availableGames, sourceGameName, transferMode, … }` — where the player can send/transfer, metadata inline |
|
|
509
|
+
| `getBalance()` | `{ gameId, gameName, balances, totalValue, currencyCount, hasFunds, raw }` — the player's balances for this game |
|
|
493
510
|
|
|
494
511
|
Every method throws `InvoError` on failure and takes an optional final `{ signal }`. Full inline types ship with the package.
|
|
495
512
|
|
package/dist/index.cjs
CHANGED
|
@@ -355,6 +355,41 @@ function toPendingCollectItem(row) {
|
|
|
355
355
|
raw: row
|
|
356
356
|
};
|
|
357
357
|
}
|
|
358
|
+
function toBalanceRow(row) {
|
|
359
|
+
return {
|
|
360
|
+
currencyId: row["currency_id"] ?? "",
|
|
361
|
+
currencyName: String(row["currency_name"] ?? ""),
|
|
362
|
+
currencySymbol: row["currency_symbol"] ?? null,
|
|
363
|
+
currencySymbolUrl: row["currency_symbol_url"] ?? null,
|
|
364
|
+
availableBalance: String(row["available_balance"] ?? ""),
|
|
365
|
+
reservedBalance: String(row["reserved_balance"] ?? ""),
|
|
366
|
+
totalBalance: String(row["total_balance"] ?? ""),
|
|
367
|
+
raw: row
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
function toDestinationGame(row) {
|
|
371
|
+
const s = (k) => row[k] === void 0 || row[k] === null ? void 0 : String(row[k]);
|
|
372
|
+
return {
|
|
373
|
+
gameId: row["game_id"] ?? "",
|
|
374
|
+
gameName: String(row["game_name"] ?? ""),
|
|
375
|
+
tenantType: s("tenant_type"),
|
|
376
|
+
developerName: s("developer_name"),
|
|
377
|
+
publisherName: s("publisher_name"),
|
|
378
|
+
genre: s("genre"),
|
|
379
|
+
platform: s("platform"),
|
|
380
|
+
gameStatus: s("game_status"),
|
|
381
|
+
gameIcon: s("game_icon"),
|
|
382
|
+
gamePoster: s("game_poster"),
|
|
383
|
+
gameUrl: s("game_url"),
|
|
384
|
+
gameDescription: s("game_description"),
|
|
385
|
+
currencyName: String(row["currency_name"] ?? ""),
|
|
386
|
+
currencySymbol: String(row["currency_symbol"] ?? ""),
|
|
387
|
+
currencySymbolUrl: s("currency_symbol_url"),
|
|
388
|
+
minimumTransfer: String(row["minimum_transfer"] ?? ""),
|
|
389
|
+
maximumTransfer: String(row["maximum_transfer"] ?? ""),
|
|
390
|
+
raw: row
|
|
391
|
+
};
|
|
392
|
+
}
|
|
358
393
|
var InvoClient = class {
|
|
359
394
|
constructor(config) {
|
|
360
395
|
if (!config.token) throw new Error("InvoClient requires a player `token`.");
|
|
@@ -463,6 +498,58 @@ var InvoClient = class {
|
|
|
463
498
|
return { pending: rows.map(toPendingCollectItem), raw };
|
|
464
499
|
});
|
|
465
500
|
}
|
|
501
|
+
/**
|
|
502
|
+
* List the games/tenants this player can send/transfer to, with display metadata
|
|
503
|
+
* inline (name, icon, currency, min/max limits) — one call, no per-game lookup.
|
|
504
|
+
* Source game is the token's own game. Player-token (browser).
|
|
505
|
+
*/
|
|
506
|
+
async getDestinations(query, opts) {
|
|
507
|
+
const direction = query?.direction ?? "transfer";
|
|
508
|
+
return this.withTokenRetry(async () => {
|
|
509
|
+
const raw = await this.get(
|
|
510
|
+
`/api/sdk/destinations?direction=${encodeURIComponent(direction)}`,
|
|
511
|
+
opts?.signal
|
|
512
|
+
);
|
|
513
|
+
const games = Array.isArray(raw["available_games"]) ? raw["available_games"] : [];
|
|
514
|
+
return {
|
|
515
|
+
status: String(raw["status"] ?? ""),
|
|
516
|
+
sourceGameId: raw["source_game_id"] ?? "",
|
|
517
|
+
sourceGameName: String(raw["source_game_name"] ?? ""),
|
|
518
|
+
sourceGameIcon: raw["source_game_icon"],
|
|
519
|
+
sourceCurrencyName: String(raw["source_currency_name"] ?? ""),
|
|
520
|
+
sourceCurrencyIcon: raw["source_currency_icon"],
|
|
521
|
+
universalTransfers: raw["universal_transfers"] === true,
|
|
522
|
+
transferMode: String(raw["transfer_mode"] ?? ""),
|
|
523
|
+
availableGames: games.map(toDestinationGame),
|
|
524
|
+
totalDestinations: Number(raw["total_destinations"] ?? games.length),
|
|
525
|
+
direction: String(raw["direction"] ?? direction),
|
|
526
|
+
linkedGameIds: Array.isArray(raw["linked_game_ids"]) ? raw["linked_game_ids"] : void 0,
|
|
527
|
+
raw
|
|
528
|
+
};
|
|
529
|
+
});
|
|
530
|
+
}
|
|
531
|
+
/**
|
|
532
|
+
* The player's balances for the token's game (browser, player-token). Amounts are
|
|
533
|
+
* decimal strings. A player who hasn't transacted here yet returns `200` with an empty
|
|
534
|
+
* `balances` array (show 0.00) — not an error; a `404 GAME_NOT_FOUND` (bad game/token)
|
|
535
|
+
* throws. Rows include the currency symbol + icon URL (each may be null).
|
|
536
|
+
*/
|
|
537
|
+
async getBalance(opts) {
|
|
538
|
+
return this.withTokenRetry(async () => {
|
|
539
|
+
const raw = await this.get("/api/sdk/balance", opts?.signal);
|
|
540
|
+
const rows = Array.isArray(raw["balances"]) ? raw["balances"] : [];
|
|
541
|
+
const summary = raw["summary"] ?? {};
|
|
542
|
+
return {
|
|
543
|
+
gameId: raw["game_id"] ?? "",
|
|
544
|
+
gameName: String(raw["game_name"] ?? ""),
|
|
545
|
+
balances: rows.map(toBalanceRow),
|
|
546
|
+
totalValue: String(summary["total_value"] ?? "0"),
|
|
547
|
+
currencyCount: Number(summary["currency_count"] ?? rows.length),
|
|
548
|
+
hasFunds: summary["has_funds"] === true,
|
|
549
|
+
raw
|
|
550
|
+
};
|
|
551
|
+
});
|
|
552
|
+
}
|
|
466
553
|
/**
|
|
467
554
|
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
468
555
|
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
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, P as PendingCollectResult, E as EnrollmentBeginResult,
|
|
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, D as DestinationsQuery, c as DestinationsResult, B as BalanceResult, E as EnrollmentBeginResult, d as EnrollmentVerifyResult } from './types-DLSCxpoT.cjs';
|
|
2
|
+
export { e as BalanceRow, f as DestinationGame, I as InvoError, g as InvoErrorInfo, h as InvoHooks, i as InvoRequestInfo, j as InvoResponseInfo, k as PendingCollectItem, R as Rail, V as VerificationMethod } from './types-DLSCxpoT.cjs';
|
|
3
3
|
|
|
4
4
|
declare class InvoClient {
|
|
5
5
|
private readonly http;
|
|
@@ -39,6 +39,19 @@ declare class InvoClient {
|
|
|
39
39
|
* code or phone (those are only on the server-side `getInboundPending`).
|
|
40
40
|
*/
|
|
41
41
|
getPendingCollect(opts?: CallOptions): Promise<PendingCollectResult>;
|
|
42
|
+
/**
|
|
43
|
+
* List the games/tenants this player can send/transfer to, with display metadata
|
|
44
|
+
* inline (name, icon, currency, min/max limits) — one call, no per-game lookup.
|
|
45
|
+
* Source game is the token's own game. Player-token (browser).
|
|
46
|
+
*/
|
|
47
|
+
getDestinations(query?: DestinationsQuery, opts?: CallOptions): Promise<DestinationsResult>;
|
|
48
|
+
/**
|
|
49
|
+
* The player's balances for the token's game (browser, player-token). Amounts are
|
|
50
|
+
* decimal strings. A player who hasn't transacted here yet returns `200` with an empty
|
|
51
|
+
* `balances` array (show 0.00) — not an error; a `404 GAME_NOT_FOUND` (bad game/token)
|
|
52
|
+
* throws. Rows include the currency symbol + icon URL (each may be null).
|
|
53
|
+
*/
|
|
54
|
+
getBalance(opts?: CallOptions): Promise<BalanceResult>;
|
|
42
55
|
/**
|
|
43
56
|
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
44
57
|
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
@@ -68,4 +81,4 @@ declare class InvoClient {
|
|
|
68
81
|
private confirmReceipt;
|
|
69
82
|
}
|
|
70
83
|
|
|
71
|
-
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, EnrollmentBeginResult, EnrollmentVerifyResult, InvoClient, LinkDeviceResult, PendingCollectResult };
|
|
84
|
+
export { ApproveResult, BalanceResult, CallOptions, ClientConfig, ConfirmReceiptResult, DestinationsQuery, DestinationsResult, 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, P as PendingCollectResult, E as EnrollmentBeginResult,
|
|
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, D as DestinationsQuery, c as DestinationsResult, B as BalanceResult, E as EnrollmentBeginResult, d as EnrollmentVerifyResult } from './types-DLSCxpoT.js';
|
|
2
|
+
export { e as BalanceRow, f as DestinationGame, I as InvoError, g as InvoErrorInfo, h as InvoHooks, i as InvoRequestInfo, j as InvoResponseInfo, k as PendingCollectItem, R as Rail, V as VerificationMethod } from './types-DLSCxpoT.js';
|
|
3
3
|
|
|
4
4
|
declare class InvoClient {
|
|
5
5
|
private readonly http;
|
|
@@ -39,6 +39,19 @@ declare class InvoClient {
|
|
|
39
39
|
* code or phone (those are only on the server-side `getInboundPending`).
|
|
40
40
|
*/
|
|
41
41
|
getPendingCollect(opts?: CallOptions): Promise<PendingCollectResult>;
|
|
42
|
+
/**
|
|
43
|
+
* List the games/tenants this player can send/transfer to, with display metadata
|
|
44
|
+
* inline (name, icon, currency, min/max limits) — one call, no per-game lookup.
|
|
45
|
+
* Source game is the token's own game. Player-token (browser).
|
|
46
|
+
*/
|
|
47
|
+
getDestinations(query?: DestinationsQuery, opts?: CallOptions): Promise<DestinationsResult>;
|
|
48
|
+
/**
|
|
49
|
+
* The player's balances for the token's game (browser, player-token). Amounts are
|
|
50
|
+
* decimal strings. A player who hasn't transacted here yet returns `200` with an empty
|
|
51
|
+
* `balances` array (show 0.00) — not an error; a `404 GAME_NOT_FOUND` (bad game/token)
|
|
52
|
+
* throws. Rows include the currency symbol + icon URL (each may be null).
|
|
53
|
+
*/
|
|
54
|
+
getBalance(opts?: CallOptions): Promise<BalanceResult>;
|
|
42
55
|
/**
|
|
43
56
|
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
44
57
|
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
|
@@ -68,4 +81,4 @@ declare class InvoClient {
|
|
|
68
81
|
private confirmReceipt;
|
|
69
82
|
}
|
|
70
83
|
|
|
71
|
-
export { ApproveResult, CallOptions, ClientConfig, ConfirmReceiptResult, EnrollmentBeginResult, EnrollmentVerifyResult, InvoClient, LinkDeviceResult, PendingCollectResult };
|
|
84
|
+
export { ApproveResult, BalanceResult, CallOptions, ClientConfig, ConfirmReceiptResult, DestinationsQuery, DestinationsResult, EnrollmentBeginResult, EnrollmentVerifyResult, InvoClient, LinkDeviceResult, PendingCollectResult };
|
package/dist/index.js
CHANGED
|
@@ -98,6 +98,41 @@ function toPendingCollectItem(row) {
|
|
|
98
98
|
raw: row
|
|
99
99
|
};
|
|
100
100
|
}
|
|
101
|
+
function toBalanceRow(row) {
|
|
102
|
+
return {
|
|
103
|
+
currencyId: row["currency_id"] ?? "",
|
|
104
|
+
currencyName: String(row["currency_name"] ?? ""),
|
|
105
|
+
currencySymbol: row["currency_symbol"] ?? null,
|
|
106
|
+
currencySymbolUrl: row["currency_symbol_url"] ?? null,
|
|
107
|
+
availableBalance: String(row["available_balance"] ?? ""),
|
|
108
|
+
reservedBalance: String(row["reserved_balance"] ?? ""),
|
|
109
|
+
totalBalance: String(row["total_balance"] ?? ""),
|
|
110
|
+
raw: row
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function toDestinationGame(row) {
|
|
114
|
+
const s = (k) => row[k] === void 0 || row[k] === null ? void 0 : String(row[k]);
|
|
115
|
+
return {
|
|
116
|
+
gameId: row["game_id"] ?? "",
|
|
117
|
+
gameName: String(row["game_name"] ?? ""),
|
|
118
|
+
tenantType: s("tenant_type"),
|
|
119
|
+
developerName: s("developer_name"),
|
|
120
|
+
publisherName: s("publisher_name"),
|
|
121
|
+
genre: s("genre"),
|
|
122
|
+
platform: s("platform"),
|
|
123
|
+
gameStatus: s("game_status"),
|
|
124
|
+
gameIcon: s("game_icon"),
|
|
125
|
+
gamePoster: s("game_poster"),
|
|
126
|
+
gameUrl: s("game_url"),
|
|
127
|
+
gameDescription: s("game_description"),
|
|
128
|
+
currencyName: String(row["currency_name"] ?? ""),
|
|
129
|
+
currencySymbol: String(row["currency_symbol"] ?? ""),
|
|
130
|
+
currencySymbolUrl: s("currency_symbol_url"),
|
|
131
|
+
minimumTransfer: String(row["minimum_transfer"] ?? ""),
|
|
132
|
+
maximumTransfer: String(row["maximum_transfer"] ?? ""),
|
|
133
|
+
raw: row
|
|
134
|
+
};
|
|
135
|
+
}
|
|
101
136
|
var InvoClient = class {
|
|
102
137
|
constructor(config) {
|
|
103
138
|
if (!config.token) throw new Error("InvoClient requires a player `token`.");
|
|
@@ -206,6 +241,58 @@ var InvoClient = class {
|
|
|
206
241
|
return { pending: rows.map(toPendingCollectItem), raw };
|
|
207
242
|
});
|
|
208
243
|
}
|
|
244
|
+
/**
|
|
245
|
+
* List the games/tenants this player can send/transfer to, with display metadata
|
|
246
|
+
* inline (name, icon, currency, min/max limits) — one call, no per-game lookup.
|
|
247
|
+
* Source game is the token's own game. Player-token (browser).
|
|
248
|
+
*/
|
|
249
|
+
async getDestinations(query, opts) {
|
|
250
|
+
const direction = query?.direction ?? "transfer";
|
|
251
|
+
return this.withTokenRetry(async () => {
|
|
252
|
+
const raw = await this.get(
|
|
253
|
+
`/api/sdk/destinations?direction=${encodeURIComponent(direction)}`,
|
|
254
|
+
opts?.signal
|
|
255
|
+
);
|
|
256
|
+
const games = Array.isArray(raw["available_games"]) ? raw["available_games"] : [];
|
|
257
|
+
return {
|
|
258
|
+
status: String(raw["status"] ?? ""),
|
|
259
|
+
sourceGameId: raw["source_game_id"] ?? "",
|
|
260
|
+
sourceGameName: String(raw["source_game_name"] ?? ""),
|
|
261
|
+
sourceGameIcon: raw["source_game_icon"],
|
|
262
|
+
sourceCurrencyName: String(raw["source_currency_name"] ?? ""),
|
|
263
|
+
sourceCurrencyIcon: raw["source_currency_icon"],
|
|
264
|
+
universalTransfers: raw["universal_transfers"] === true,
|
|
265
|
+
transferMode: String(raw["transfer_mode"] ?? ""),
|
|
266
|
+
availableGames: games.map(toDestinationGame),
|
|
267
|
+
totalDestinations: Number(raw["total_destinations"] ?? games.length),
|
|
268
|
+
direction: String(raw["direction"] ?? direction),
|
|
269
|
+
linkedGameIds: Array.isArray(raw["linked_game_ids"]) ? raw["linked_game_ids"] : void 0,
|
|
270
|
+
raw
|
|
271
|
+
};
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* The player's balances for the token's game (browser, player-token). Amounts are
|
|
276
|
+
* decimal strings. A player who hasn't transacted here yet returns `200` with an empty
|
|
277
|
+
* `balances` array (show 0.00) — not an error; a `404 GAME_NOT_FOUND` (bad game/token)
|
|
278
|
+
* throws. Rows include the currency symbol + icon URL (each may be null).
|
|
279
|
+
*/
|
|
280
|
+
async getBalance(opts) {
|
|
281
|
+
return this.withTokenRetry(async () => {
|
|
282
|
+
const raw = await this.get("/api/sdk/balance", opts?.signal);
|
|
283
|
+
const rows = Array.isArray(raw["balances"]) ? raw["balances"] : [];
|
|
284
|
+
const summary = raw["summary"] ?? {};
|
|
285
|
+
return {
|
|
286
|
+
gameId: raw["game_id"] ?? "",
|
|
287
|
+
gameName: String(raw["game_name"] ?? ""),
|
|
288
|
+
balances: rows.map(toBalanceRow),
|
|
289
|
+
totalValue: String(summary["total_value"] ?? "0"),
|
|
290
|
+
currencyCount: Number(summary["currency_count"] ?? rows.length),
|
|
291
|
+
hasFunds: summary["has_funds"] === true,
|
|
292
|
+
raw
|
|
293
|
+
};
|
|
294
|
+
});
|
|
295
|
+
}
|
|
209
296
|
/**
|
|
210
297
|
* First-enrollment OTP grant (§4.2). When `enrollPasskey()` throws
|
|
211
298
|
* `ENROLLMENT_REQUIRES_AUTHORIZATION` (`err.isEnrollmentAuthorizationRequired`), call
|
package/dist/server.cjs
CHANGED
|
@@ -418,7 +418,7 @@ async function hmacHexSubtle(secret, message) {
|
|
|
418
418
|
}
|
|
419
419
|
|
|
420
420
|
// src/server.ts
|
|
421
|
-
var DEFAULT_UA = "invonetwork-web-sdk/0.
|
|
421
|
+
var DEFAULT_UA = "invonetwork-web-sdk/0.8.0 (+https://invo.network)";
|
|
422
422
|
var MAX_USD_AMOUNT = 999.99;
|
|
423
423
|
var MAX_ITEM_PRICE = 999999.99;
|
|
424
424
|
function invalidInput(label, value, why) {
|
|
@@ -458,6 +458,13 @@ function toOrderDetails(raw) {
|
|
|
458
458
|
raw
|
|
459
459
|
};
|
|
460
460
|
}
|
|
461
|
+
function toLinkedEmail(row) {
|
|
462
|
+
return {
|
|
463
|
+
email: String(row["email"] ?? ""),
|
|
464
|
+
primary: row["primary"] === true,
|
|
465
|
+
verifiedAt: row["verified_at"] ?? null
|
|
466
|
+
};
|
|
467
|
+
}
|
|
461
468
|
function toInboundPendingItem(row) {
|
|
462
469
|
return {
|
|
463
470
|
transactionId: String(row["transaction_id"] ?? ""),
|
|
@@ -877,6 +884,48 @@ var InvoServer = class {
|
|
|
877
884
|
const rows = Array.isArray(raw["inbound_pending"]) ? raw["inbound_pending"] : [];
|
|
878
885
|
return { inboundPending: rows.map(toInboundPendingItem), raw };
|
|
879
886
|
}
|
|
887
|
+
/**
|
|
888
|
+
* Look up a player's linked wallet identities (SERVER-only, game-secret). Game-scoped:
|
|
889
|
+
* returns wallet members that also have a Player row on this game. Provide a `playerEmail`
|
|
890
|
+
* or `playerPhone` (phone wins if both). No in-game match (backend 404) returns
|
|
891
|
+
* `notFound: true` with empty `emails` — not an error.
|
|
892
|
+
*
|
|
893
|
+
* ⚠️ Returns first-party PII (emails/phones) — never expose this to the browser.
|
|
894
|
+
*/
|
|
895
|
+
async getLinkedIdentities(query, opts) {
|
|
896
|
+
const phone = typeof query.playerPhone === "string" && query.playerPhone.trim() ? query.playerPhone.trim() : "";
|
|
897
|
+
const email = typeof query.playerEmail === "string" && query.playerEmail.trim() ? query.playerEmail.trim() : "";
|
|
898
|
+
if (!phone && !email) {
|
|
899
|
+
throw invalidInput("query", query, "requires a playerEmail or playerPhone");
|
|
900
|
+
}
|
|
901
|
+
const q = new URLSearchParams();
|
|
902
|
+
if (phone) q.set("player_phone", phone);
|
|
903
|
+
else q.set("player_email", email);
|
|
904
|
+
let raw;
|
|
905
|
+
try {
|
|
906
|
+
raw = await this.http.get(
|
|
907
|
+
`/api/wallet/identities?${q.toString()}`,
|
|
908
|
+
this.auth,
|
|
909
|
+
{ signal: opts?.signal }
|
|
910
|
+
);
|
|
911
|
+
} catch (e) {
|
|
912
|
+
if (e instanceof InvoError && e.status === 404) {
|
|
913
|
+
const raw404 = e.body && typeof e.body === "object" ? e.body : {};
|
|
914
|
+
return { walletUserId: null, primaryEmail: "", primaryPhone: "", isMinor: false, emails: [], notFound: true, raw: raw404 };
|
|
915
|
+
}
|
|
916
|
+
throw e;
|
|
917
|
+
}
|
|
918
|
+
const emails = Array.isArray(raw["emails"]) ? raw["emails"].map(toLinkedEmail) : [];
|
|
919
|
+
return {
|
|
920
|
+
walletUserId: raw["wallet_user_id"] ?? null,
|
|
921
|
+
primaryEmail: String(raw["primary_email"] ?? ""),
|
|
922
|
+
primaryPhone: String(raw["primary_phone"] ?? ""),
|
|
923
|
+
isMinor: raw["is_minor"] === true,
|
|
924
|
+
emails,
|
|
925
|
+
notFound: false,
|
|
926
|
+
raw
|
|
927
|
+
};
|
|
928
|
+
}
|
|
880
929
|
toInitiateResult(raw) {
|
|
881
930
|
const vm = raw["verification_method"];
|
|
882
931
|
const guardian = raw["guardian_approval"];
|
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, l as PlayerToken, m as InitiateSendInput, n as InitiateResult, o as InitiateTransferInput, p as CreateCheckoutInput, q as CreateCheckoutResult, r as PurchaseInput, s as PurchaseResult, t as ConfirmPaymentResult, O as OrderDetailsResult, u as PurchaseItemInput, v as PurchaseItemResult, w as ItemHistoryQuery, x as ItemHistoryResult, y as ItemOrderQuery, z as PlayerBalanceQuery, F as PlayerBalanceResult, G as InboundPendingQuery, H as InboundPendingResult, J as LinkedIdentitiesQuery, K as LinkedIdentitiesResult } from './types-DLSCxpoT.cjs';
|
|
2
|
+
export { M as CurrencyBalance, N as InboundPendingItem, g as InvoErrorInfo, h as InvoHooks, i as InvoRequestInfo, j as InvoResponseInfo, Q as LinkedIdentityEmail, R as Rail, V as VerificationMethod } from './types-DLSCxpoT.cjs';
|
|
3
3
|
|
|
4
4
|
interface VerifyWebhookOptions {
|
|
5
5
|
/** Max age of the signed timestamp, in seconds. Default 300 (5 min). */
|
|
@@ -216,7 +216,16 @@ declare class InvoServer {
|
|
|
216
216
|
* `transfer.claim_pending` webhook (the webhook is the wake-up; this is the list).
|
|
217
217
|
*/
|
|
218
218
|
getInboundPending(query: InboundPendingQuery, opts?: CallOptions): Promise<InboundPendingResult>;
|
|
219
|
+
/**
|
|
220
|
+
* Look up a player's linked wallet identities (SERVER-only, game-secret). Game-scoped:
|
|
221
|
+
* returns wallet members that also have a Player row on this game. Provide a `playerEmail`
|
|
222
|
+
* or `playerPhone` (phone wins if both). No in-game match (backend 404) returns
|
|
223
|
+
* `notFound: true` with empty `emails` — not an error.
|
|
224
|
+
*
|
|
225
|
+
* ⚠️ Returns first-party PII (emails/phones) — never expose this to the browser.
|
|
226
|
+
*/
|
|
227
|
+
getLinkedIdentities(query: LinkedIdentitiesQuery, opts?: CallOptions): Promise<LinkedIdentitiesResult>;
|
|
219
228
|
private toInitiateResult;
|
|
220
229
|
}
|
|
221
230
|
|
|
222
|
-
export { CallOptions, ConfirmPaymentResult, CreateCheckoutInput, CreateCheckoutResult, InboundPendingQuery, InboundPendingResult, InitiateResult, InitiateSendInput, InitiateTransferInput, InvoError, InvoServer, type InvoWebhookEvent, ItemHistoryQuery, ItemHistoryResult, ItemOrderQuery, type ItemPurchasedData, OrderDetailsResult, PlayerBalanceQuery, PlayerBalanceResult, PlayerToken, type PurchaseCompletedData, type PurchaseEventData, PurchaseInput, PurchaseItemInput, PurchaseItemResult, PurchaseResult, ServerConfig, type TransferEventData, type VerifyWebhookOptions, type WebhookHandlerOptions, createWebhookHandler, verifyWebhook, verifyWebhookAsync };
|
|
231
|
+
export { CallOptions, ConfirmPaymentResult, CreateCheckoutInput, CreateCheckoutResult, InboundPendingQuery, InboundPendingResult, InitiateResult, InitiateSendInput, InitiateTransferInput, InvoError, InvoServer, type InvoWebhookEvent, ItemHistoryQuery, ItemHistoryResult, ItemOrderQuery, type ItemPurchasedData, LinkedIdentitiesQuery, LinkedIdentitiesResult, OrderDetailsResult, PlayerBalanceQuery, PlayerBalanceResult, PlayerToken, type PurchaseCompletedData, type PurchaseEventData, PurchaseInput, PurchaseItemInput, PurchaseItemResult, PurchaseResult, ServerConfig, type TransferEventData, type VerifyWebhookOptions, type WebhookHandlerOptions, createWebhookHandler, verifyWebhook, verifyWebhookAsync };
|
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, l as PlayerToken, m as InitiateSendInput, n as InitiateResult, o as InitiateTransferInput, p as CreateCheckoutInput, q as CreateCheckoutResult, r as PurchaseInput, s as PurchaseResult, t as ConfirmPaymentResult, O as OrderDetailsResult, u as PurchaseItemInput, v as PurchaseItemResult, w as ItemHistoryQuery, x as ItemHistoryResult, y as ItemOrderQuery, z as PlayerBalanceQuery, F as PlayerBalanceResult, G as InboundPendingQuery, H as InboundPendingResult, J as LinkedIdentitiesQuery, K as LinkedIdentitiesResult } from './types-DLSCxpoT.js';
|
|
2
|
+
export { M as CurrencyBalance, N as InboundPendingItem, g as InvoErrorInfo, h as InvoHooks, i as InvoRequestInfo, j as InvoResponseInfo, Q as LinkedIdentityEmail, R as Rail, V as VerificationMethod } from './types-DLSCxpoT.js';
|
|
3
3
|
|
|
4
4
|
interface VerifyWebhookOptions {
|
|
5
5
|
/** Max age of the signed timestamp, in seconds. Default 300 (5 min). */
|
|
@@ -216,7 +216,16 @@ declare class InvoServer {
|
|
|
216
216
|
* `transfer.claim_pending` webhook (the webhook is the wake-up; this is the list).
|
|
217
217
|
*/
|
|
218
218
|
getInboundPending(query: InboundPendingQuery, opts?: CallOptions): Promise<InboundPendingResult>;
|
|
219
|
+
/**
|
|
220
|
+
* Look up a player's linked wallet identities (SERVER-only, game-secret). Game-scoped:
|
|
221
|
+
* returns wallet members that also have a Player row on this game. Provide a `playerEmail`
|
|
222
|
+
* or `playerPhone` (phone wins if both). No in-game match (backend 404) returns
|
|
223
|
+
* `notFound: true` with empty `emails` — not an error.
|
|
224
|
+
*
|
|
225
|
+
* ⚠️ Returns first-party PII (emails/phones) — never expose this to the browser.
|
|
226
|
+
*/
|
|
227
|
+
getLinkedIdentities(query: LinkedIdentitiesQuery, opts?: CallOptions): Promise<LinkedIdentitiesResult>;
|
|
219
228
|
private toInitiateResult;
|
|
220
229
|
}
|
|
221
230
|
|
|
222
|
-
export { CallOptions, ConfirmPaymentResult, CreateCheckoutInput, CreateCheckoutResult, InboundPendingQuery, InboundPendingResult, InitiateResult, InitiateSendInput, InitiateTransferInput, InvoError, InvoServer, type InvoWebhookEvent, ItemHistoryQuery, ItemHistoryResult, ItemOrderQuery, type ItemPurchasedData, OrderDetailsResult, PlayerBalanceQuery, PlayerBalanceResult, PlayerToken, type PurchaseCompletedData, type PurchaseEventData, PurchaseInput, PurchaseItemInput, PurchaseItemResult, PurchaseResult, ServerConfig, type TransferEventData, type VerifyWebhookOptions, type WebhookHandlerOptions, createWebhookHandler, verifyWebhook, verifyWebhookAsync };
|
|
231
|
+
export { CallOptions, ConfirmPaymentResult, CreateCheckoutInput, CreateCheckoutResult, InboundPendingQuery, InboundPendingResult, InitiateResult, InitiateSendInput, InitiateTransferInput, InvoError, InvoServer, type InvoWebhookEvent, ItemHistoryQuery, ItemHistoryResult, ItemOrderQuery, type ItemPurchasedData, LinkedIdentitiesQuery, LinkedIdentitiesResult, OrderDetailsResult, PlayerBalanceQuery, PlayerBalanceResult, PlayerToken, type PurchaseCompletedData, type PurchaseEventData, PurchaseInput, PurchaseItemInput, PurchaseItemResult, PurchaseResult, ServerConfig, type TransferEventData, type VerifyWebhookOptions, type WebhookHandlerOptions, createWebhookHandler, verifyWebhook, verifyWebhookAsync };
|
package/dist/server.js
CHANGED
|
@@ -161,7 +161,7 @@ async function hmacHexSubtle(secret, message) {
|
|
|
161
161
|
}
|
|
162
162
|
|
|
163
163
|
// src/server.ts
|
|
164
|
-
var DEFAULT_UA = "invonetwork-web-sdk/0.
|
|
164
|
+
var DEFAULT_UA = "invonetwork-web-sdk/0.8.0 (+https://invo.network)";
|
|
165
165
|
var MAX_USD_AMOUNT = 999.99;
|
|
166
166
|
var MAX_ITEM_PRICE = 999999.99;
|
|
167
167
|
function invalidInput(label, value, why) {
|
|
@@ -201,6 +201,13 @@ function toOrderDetails(raw) {
|
|
|
201
201
|
raw
|
|
202
202
|
};
|
|
203
203
|
}
|
|
204
|
+
function toLinkedEmail(row) {
|
|
205
|
+
return {
|
|
206
|
+
email: String(row["email"] ?? ""),
|
|
207
|
+
primary: row["primary"] === true,
|
|
208
|
+
verifiedAt: row["verified_at"] ?? null
|
|
209
|
+
};
|
|
210
|
+
}
|
|
204
211
|
function toInboundPendingItem(row) {
|
|
205
212
|
return {
|
|
206
213
|
transactionId: String(row["transaction_id"] ?? ""),
|
|
@@ -620,6 +627,48 @@ var InvoServer = class {
|
|
|
620
627
|
const rows = Array.isArray(raw["inbound_pending"]) ? raw["inbound_pending"] : [];
|
|
621
628
|
return { inboundPending: rows.map(toInboundPendingItem), raw };
|
|
622
629
|
}
|
|
630
|
+
/**
|
|
631
|
+
* Look up a player's linked wallet identities (SERVER-only, game-secret). Game-scoped:
|
|
632
|
+
* returns wallet members that also have a Player row on this game. Provide a `playerEmail`
|
|
633
|
+
* or `playerPhone` (phone wins if both). No in-game match (backend 404) returns
|
|
634
|
+
* `notFound: true` with empty `emails` — not an error.
|
|
635
|
+
*
|
|
636
|
+
* ⚠️ Returns first-party PII (emails/phones) — never expose this to the browser.
|
|
637
|
+
*/
|
|
638
|
+
async getLinkedIdentities(query, opts) {
|
|
639
|
+
const phone = typeof query.playerPhone === "string" && query.playerPhone.trim() ? query.playerPhone.trim() : "";
|
|
640
|
+
const email = typeof query.playerEmail === "string" && query.playerEmail.trim() ? query.playerEmail.trim() : "";
|
|
641
|
+
if (!phone && !email) {
|
|
642
|
+
throw invalidInput("query", query, "requires a playerEmail or playerPhone");
|
|
643
|
+
}
|
|
644
|
+
const q = new URLSearchParams();
|
|
645
|
+
if (phone) q.set("player_phone", phone);
|
|
646
|
+
else q.set("player_email", email);
|
|
647
|
+
let raw;
|
|
648
|
+
try {
|
|
649
|
+
raw = await this.http.get(
|
|
650
|
+
`/api/wallet/identities?${q.toString()}`,
|
|
651
|
+
this.auth,
|
|
652
|
+
{ signal: opts?.signal }
|
|
653
|
+
);
|
|
654
|
+
} catch (e) {
|
|
655
|
+
if (e instanceof InvoError && e.status === 404) {
|
|
656
|
+
const raw404 = e.body && typeof e.body === "object" ? e.body : {};
|
|
657
|
+
return { walletUserId: null, primaryEmail: "", primaryPhone: "", isMinor: false, emails: [], notFound: true, raw: raw404 };
|
|
658
|
+
}
|
|
659
|
+
throw e;
|
|
660
|
+
}
|
|
661
|
+
const emails = Array.isArray(raw["emails"]) ? raw["emails"].map(toLinkedEmail) : [];
|
|
662
|
+
return {
|
|
663
|
+
walletUserId: raw["wallet_user_id"] ?? null,
|
|
664
|
+
primaryEmail: String(raw["primary_email"] ?? ""),
|
|
665
|
+
primaryPhone: String(raw["primary_phone"] ?? ""),
|
|
666
|
+
isMinor: raw["is_minor"] === true,
|
|
667
|
+
emails,
|
|
668
|
+
notFound: false,
|
|
669
|
+
raw
|
|
670
|
+
};
|
|
671
|
+
}
|
|
623
672
|
toInitiateResult(raw) {
|
|
624
673
|
const vm = raw["verification_method"];
|
|
625
674
|
const guardian = raw["guardian_approval"];
|
|
@@ -357,6 +357,93 @@ interface PendingCollectResult {
|
|
|
357
357
|
pending: PendingCollectItem[];
|
|
358
358
|
raw: Record<string, unknown>;
|
|
359
359
|
}
|
|
360
|
+
interface BalanceRow {
|
|
361
|
+
currencyId: string | number;
|
|
362
|
+
currencyName: string;
|
|
363
|
+
/** Short symbol (may be null). */
|
|
364
|
+
currencySymbol: string | null;
|
|
365
|
+
/** Icon URL (may be null). */
|
|
366
|
+
currencySymbolUrl: string | null;
|
|
367
|
+
/** Decimal strings (parseFloat as needed). */
|
|
368
|
+
availableBalance: string;
|
|
369
|
+
reservedBalance: string;
|
|
370
|
+
totalBalance: string;
|
|
371
|
+
raw: Record<string, unknown>;
|
|
372
|
+
}
|
|
373
|
+
interface BalanceResult {
|
|
374
|
+
gameId: string | number;
|
|
375
|
+
gameName: string;
|
|
376
|
+
/** Empty for a player who hasn't transacted on this game yet (a 200, not an error). */
|
|
377
|
+
balances: BalanceRow[];
|
|
378
|
+
/** Sum of total_balance across rows (decimal string). */
|
|
379
|
+
totalValue: string;
|
|
380
|
+
currencyCount: number;
|
|
381
|
+
hasFunds: boolean;
|
|
382
|
+
raw: Record<string, unknown>;
|
|
383
|
+
}
|
|
384
|
+
interface LinkedIdentitiesQuery {
|
|
385
|
+
/** Provide one; phone wins if both are given. */
|
|
386
|
+
playerEmail?: string;
|
|
387
|
+
playerPhone?: string;
|
|
388
|
+
}
|
|
389
|
+
interface LinkedIdentityEmail {
|
|
390
|
+
email: string;
|
|
391
|
+
primary: boolean;
|
|
392
|
+
verifiedAt: string | null;
|
|
393
|
+
}
|
|
394
|
+
interface LinkedIdentitiesResult {
|
|
395
|
+
walletUserId: string | null;
|
|
396
|
+
primaryEmail: string;
|
|
397
|
+
primaryPhone: string;
|
|
398
|
+
isMinor: boolean;
|
|
399
|
+
emails: LinkedIdentityEmail[];
|
|
400
|
+
/** true when there was no in-game match (backend 404) — treat as "no linked identities". */
|
|
401
|
+
notFound: boolean;
|
|
402
|
+
raw: Record<string, unknown>;
|
|
403
|
+
}
|
|
404
|
+
interface DestinationsQuery {
|
|
405
|
+
/** "transfer" | "send". Defaults "transfer" (the set is identical for both today). */
|
|
406
|
+
direction?: "transfer" | "send";
|
|
407
|
+
}
|
|
408
|
+
/** A game/tenant this player can send/transfer to, with display metadata inline. */
|
|
409
|
+
interface DestinationGame {
|
|
410
|
+
gameId: string | number;
|
|
411
|
+
gameName: string;
|
|
412
|
+
tenantType?: string;
|
|
413
|
+
developerName?: string;
|
|
414
|
+
publisherName?: string;
|
|
415
|
+
genre?: string;
|
|
416
|
+
platform?: string;
|
|
417
|
+
gameStatus?: string;
|
|
418
|
+
gameIcon?: string;
|
|
419
|
+
gamePoster?: string;
|
|
420
|
+
gameUrl?: string;
|
|
421
|
+
gameDescription?: string;
|
|
422
|
+
currencyName: string;
|
|
423
|
+
currencySymbol: string;
|
|
424
|
+
currencySymbolUrl?: string;
|
|
425
|
+
/** Limits are decimal strings. */
|
|
426
|
+
minimumTransfer: string;
|
|
427
|
+
maximumTransfer: string;
|
|
428
|
+
raw: Record<string, unknown>;
|
|
429
|
+
}
|
|
430
|
+
interface DestinationsResult {
|
|
431
|
+
status: string;
|
|
432
|
+
sourceGameId: string | number;
|
|
433
|
+
sourceGameName: string;
|
|
434
|
+
sourceGameIcon?: string;
|
|
435
|
+
sourceCurrencyName: string;
|
|
436
|
+
sourceCurrencyIcon?: string;
|
|
437
|
+
universalTransfers: boolean;
|
|
438
|
+
/** "universal" (every live tenant) | "linked" (intersect linkedGameIds). */
|
|
439
|
+
transferMode: string;
|
|
440
|
+
availableGames: DestinationGame[];
|
|
441
|
+
totalDestinations: number;
|
|
442
|
+
direction: string;
|
|
443
|
+
/** Present in "linked" mode. */
|
|
444
|
+
linkedGameIds?: (string | number)[];
|
|
445
|
+
raw: Record<string, unknown>;
|
|
446
|
+
}
|
|
360
447
|
interface EnrollmentBeginResult {
|
|
361
448
|
status: string;
|
|
362
449
|
/** Channels the OTP was sent to, e.g. ["sms","email"]. */
|
|
@@ -373,4 +460,4 @@ interface LinkDeviceResult {
|
|
|
373
460
|
raw: Record<string, unknown>;
|
|
374
461
|
}
|
|
375
462
|
|
|
376
|
-
export { type ApproveResult as A, type
|
|
463
|
+
export { type ApproveResult as A, type BalanceResult as B, type ClientConfig as C, type DestinationsQuery as D, type EnrollmentBeginResult as E, type PlayerBalanceResult as F, type InboundPendingQuery as G, type InboundPendingResult as H, InvoError as I, type LinkedIdentitiesQuery as J, type LinkedIdentitiesResult as K, type LinkDeviceResult as L, type CurrencyBalance as M, type InboundPendingItem as N, type OrderDetailsResult as O, type PendingCollectResult as P, type LinkedIdentityEmail as Q, type Rail as R, type ServerConfig as S, type VerificationMethod as V, type CallOptions as a, type ConfirmReceiptResult as b, type DestinationsResult as c, type EnrollmentVerifyResult as d, type BalanceRow as e, type DestinationGame as f, type InvoErrorInfo as g, type InvoHooks as h, type InvoRequestInfo as i, type InvoResponseInfo as j, type PendingCollectItem as k, type PlayerToken as l, type InitiateSendInput as m, type InitiateResult as n, type InitiateTransferInput as o, type CreateCheckoutInput as p, type CreateCheckoutResult as q, type PurchaseInput as r, type PurchaseResult as s, type ConfirmPaymentResult as t, type PurchaseItemInput as u, type PurchaseItemResult as v, type ItemHistoryQuery as w, type ItemHistoryResult as x, type ItemOrderQuery as y, type PlayerBalanceQuery as z };
|
|
@@ -357,6 +357,93 @@ interface PendingCollectResult {
|
|
|
357
357
|
pending: PendingCollectItem[];
|
|
358
358
|
raw: Record<string, unknown>;
|
|
359
359
|
}
|
|
360
|
+
interface BalanceRow {
|
|
361
|
+
currencyId: string | number;
|
|
362
|
+
currencyName: string;
|
|
363
|
+
/** Short symbol (may be null). */
|
|
364
|
+
currencySymbol: string | null;
|
|
365
|
+
/** Icon URL (may be null). */
|
|
366
|
+
currencySymbolUrl: string | null;
|
|
367
|
+
/** Decimal strings (parseFloat as needed). */
|
|
368
|
+
availableBalance: string;
|
|
369
|
+
reservedBalance: string;
|
|
370
|
+
totalBalance: string;
|
|
371
|
+
raw: Record<string, unknown>;
|
|
372
|
+
}
|
|
373
|
+
interface BalanceResult {
|
|
374
|
+
gameId: string | number;
|
|
375
|
+
gameName: string;
|
|
376
|
+
/** Empty for a player who hasn't transacted on this game yet (a 200, not an error). */
|
|
377
|
+
balances: BalanceRow[];
|
|
378
|
+
/** Sum of total_balance across rows (decimal string). */
|
|
379
|
+
totalValue: string;
|
|
380
|
+
currencyCount: number;
|
|
381
|
+
hasFunds: boolean;
|
|
382
|
+
raw: Record<string, unknown>;
|
|
383
|
+
}
|
|
384
|
+
interface LinkedIdentitiesQuery {
|
|
385
|
+
/** Provide one; phone wins if both are given. */
|
|
386
|
+
playerEmail?: string;
|
|
387
|
+
playerPhone?: string;
|
|
388
|
+
}
|
|
389
|
+
interface LinkedIdentityEmail {
|
|
390
|
+
email: string;
|
|
391
|
+
primary: boolean;
|
|
392
|
+
verifiedAt: string | null;
|
|
393
|
+
}
|
|
394
|
+
interface LinkedIdentitiesResult {
|
|
395
|
+
walletUserId: string | null;
|
|
396
|
+
primaryEmail: string;
|
|
397
|
+
primaryPhone: string;
|
|
398
|
+
isMinor: boolean;
|
|
399
|
+
emails: LinkedIdentityEmail[];
|
|
400
|
+
/** true when there was no in-game match (backend 404) — treat as "no linked identities". */
|
|
401
|
+
notFound: boolean;
|
|
402
|
+
raw: Record<string, unknown>;
|
|
403
|
+
}
|
|
404
|
+
interface DestinationsQuery {
|
|
405
|
+
/** "transfer" | "send". Defaults "transfer" (the set is identical for both today). */
|
|
406
|
+
direction?: "transfer" | "send";
|
|
407
|
+
}
|
|
408
|
+
/** A game/tenant this player can send/transfer to, with display metadata inline. */
|
|
409
|
+
interface DestinationGame {
|
|
410
|
+
gameId: string | number;
|
|
411
|
+
gameName: string;
|
|
412
|
+
tenantType?: string;
|
|
413
|
+
developerName?: string;
|
|
414
|
+
publisherName?: string;
|
|
415
|
+
genre?: string;
|
|
416
|
+
platform?: string;
|
|
417
|
+
gameStatus?: string;
|
|
418
|
+
gameIcon?: string;
|
|
419
|
+
gamePoster?: string;
|
|
420
|
+
gameUrl?: string;
|
|
421
|
+
gameDescription?: string;
|
|
422
|
+
currencyName: string;
|
|
423
|
+
currencySymbol: string;
|
|
424
|
+
currencySymbolUrl?: string;
|
|
425
|
+
/** Limits are decimal strings. */
|
|
426
|
+
minimumTransfer: string;
|
|
427
|
+
maximumTransfer: string;
|
|
428
|
+
raw: Record<string, unknown>;
|
|
429
|
+
}
|
|
430
|
+
interface DestinationsResult {
|
|
431
|
+
status: string;
|
|
432
|
+
sourceGameId: string | number;
|
|
433
|
+
sourceGameName: string;
|
|
434
|
+
sourceGameIcon?: string;
|
|
435
|
+
sourceCurrencyName: string;
|
|
436
|
+
sourceCurrencyIcon?: string;
|
|
437
|
+
universalTransfers: boolean;
|
|
438
|
+
/** "universal" (every live tenant) | "linked" (intersect linkedGameIds). */
|
|
439
|
+
transferMode: string;
|
|
440
|
+
availableGames: DestinationGame[];
|
|
441
|
+
totalDestinations: number;
|
|
442
|
+
direction: string;
|
|
443
|
+
/** Present in "linked" mode. */
|
|
444
|
+
linkedGameIds?: (string | number)[];
|
|
445
|
+
raw: Record<string, unknown>;
|
|
446
|
+
}
|
|
360
447
|
interface EnrollmentBeginResult {
|
|
361
448
|
status: string;
|
|
362
449
|
/** Channels the OTP was sent to, e.g. ["sms","email"]. */
|
|
@@ -373,4 +460,4 @@ interface LinkDeviceResult {
|
|
|
373
460
|
raw: Record<string, unknown>;
|
|
374
461
|
}
|
|
375
462
|
|
|
376
|
-
export { type ApproveResult as A, type
|
|
463
|
+
export { type ApproveResult as A, type BalanceResult as B, type ClientConfig as C, type DestinationsQuery as D, type EnrollmentBeginResult as E, type PlayerBalanceResult as F, type InboundPendingQuery as G, type InboundPendingResult as H, InvoError as I, type LinkedIdentitiesQuery as J, type LinkedIdentitiesResult as K, type LinkDeviceResult as L, type CurrencyBalance as M, type InboundPendingItem as N, type OrderDetailsResult as O, type PendingCollectResult as P, type LinkedIdentityEmail as Q, type Rail as R, type ServerConfig as S, type VerificationMethod as V, type CallOptions as a, type ConfirmReceiptResult as b, type DestinationsResult as c, type EnrollmentVerifyResult as d, type BalanceRow as e, type DestinationGame as f, type InvoErrorInfo as g, type InvoHooks as h, type InvoRequestInfo as i, type InvoResponseInfo as j, type PendingCollectItem as k, type PlayerToken as l, type InitiateSendInput as m, type InitiateResult as n, type InitiateTransferInput as o, type CreateCheckoutInput as p, type CreateCheckoutResult as q, type PurchaseInput as r, type PurchaseResult as s, type ConfirmPaymentResult as t, type PurchaseItemInput as u, type PurchaseItemResult as v, type ItemHistoryQuery as w, type ItemHistoryResult as x, type ItemOrderQuery as y, type PlayerBalanceQuery as z };
|
package/package.json
CHANGED