402-trinity-gaming 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/INTEGRATION.md ADDED
@@ -0,0 +1,188 @@
1
+ # ⚡ 402-Trinity-Gaming — Integration Brief
2
+
3
+ **A white-label microtransaction engine for game storefronts. The player holds their own wallet.**
4
+
5
+ Players buy cosmetics, battle passes and timer skips without ever leaving your game. No
6
+ overlay, no browser tab, no checkout screen wearing someone else's brand. Your button, your
7
+ art, your unlock animation.
8
+
9
+ ---
10
+
11
+ ## đŸ› ī¸ Step 1 — Studio setup (done once)
12
+
13
+ **Install** into your existing game backend:
14
+
15
+ ```bash
16
+ npm install 402-trinity-gaming
17
+ ```
18
+
19
+ **Configure** your catalog and your treasury:
20
+
21
+ ```js
22
+ const store = createStorefront({
23
+ payTo: '0xYourStudioTreasury',
24
+ network: 'base',
25
+ facilitator: 'https://...',
26
+ nonceStore,
27
+ catalog: {
28
+ vanguard_skin_01: '1500000', // $1.50
29
+ season_pass_04: '9990000', // $9.99
30
+ },
31
+ surcharge: { proceedsKey },
32
+ });
33
+ ```
34
+
35
+ **Hook up your UI.** Your artists design the store exactly how they want. When a player taps
36
+ *Purchase*, your button calls your server, and two events come back — one when the purchase is
37
+ accepted, one when the money has moved:
38
+
39
+ ```js
40
+ store.on('settled', e => grantItem(e.playerId, e.itemId));
41
+ store.on('declined', e => showRefusal(e.playerId, e.code));
42
+ ```
43
+
44
+ That is the whole integration surface. Nothing renders, nothing takes over input, and nothing
45
+ writes to your console — the build fails if it does.
46
+
47
+ > Prices live in your server's catalog, never in the client call. A client that names its own
48
+ > price is a client that sets its own price.
49
+
50
+ ---
51
+
52
+ ## đŸ•šī¸ Step 2 — Player wallet (done once per player)
53
+
54
+ When a player creates an account, your client generates a wallet on their device.
55
+
56
+ ```js
57
+ const { privateKey, address } = createPlayerWallet();
58
+ ```
59
+
60
+ You store the address. **They** keep the key — you never hold it, and you cannot spend from
61
+ their wallet. The player is the real buyer, paying you directly.
62
+
63
+ > **If you use tabs** (see below), note that a partly-spent tab *is* a balance you hold: the
64
+ > player's cash is yours, and what they have left is credit in your game. That is closed-loop
65
+ > — spendable only on your items, never withdrawable — so it is the same shape as any in-game
66
+ > currency, not a deposit account. Worth raising with your counsel all the same.
67
+
68
+ > **Yours to build today:** the encryption, unlock and backup flow. We hand you the key; where
69
+ > it sleeps is your product decision. There is no password reset — give players a recovery
70
+ > phrase or an encrypted backup at setup.
71
+
72
+ ---
73
+
74
+ ## đŸ’ŗ Step 3 — Funding the wallet
75
+
76
+ It is an ordinary Base address, so there are two doors and you can open either.
77
+
78
+ **Players who hold crypto** send USDC straight to it from any exchange or wallet.
79
+
80
+ **Everyone else** goes through a card on-ramp you drop into your launcher or account page.
81
+ They pay with a card, USDC lands in their wallet.
82
+
83
+ ---
84
+
85
+ ## âš”ī¸ Step 4 — The checkout loop
86
+
87
+ A player taps *Buy* on a $5.00 weapon skin, mid-lobby.
88
+
89
+ **On their machine**, the client signs one authorization — about **3 milliseconds**,
90
+ comfortably inside a frame, touching no network. Only the signature leaves the device.
91
+
92
+ **On your server**, that signature is verified and settled through your facilitator.
93
+
94
+ **Back in the game**, `accepted` fires the moment the signature checks out, and `settled` when
95
+ the transfer confirms on Base a few seconds later.
96
+
97
+ **Design this bit deliberately.** Settlement is a real transfer on a real chain — seconds, not
98
+ milliseconds. Want the skin to appear the instant they tap? Grant on `accepted` and reconcile
99
+ on `settled`. Rather never take something back? Wait for `settled`. One line either way.
100
+
101
+ **The player is debited exactly $5.00.** The price on the label is the price they pay.
102
+
103
+ ---
104
+
105
+ ## 🔁 Tabs — for games that charge constantly
106
+
107
+ Survival, MMO and sandbox economies bill in fractions of a cent: a timer skip, a stack of ore,
108
+ a repair. Settling each one on-chain costs more in gas than the action costs the player.
109
+
110
+ So the player **loads a tab** — one signature, one transfer — and every action after that is a
111
+ deduction from that credit. No signature, no chain, no gas, nothing to wait for.
112
+
113
+ ```js
114
+ const tabs = createBatchManager({
115
+ ...sameConfigAsAbove,
116
+ tabs: { session: '2000000' }, // $2.00 of credit
117
+ ledger, // durable - see below
118
+ });
119
+
120
+ await tabs.open({ tabId: 'session', playerId, playerAddress, authorization, signature });
121
+
122
+ // then, on any gameplay path:
123
+ await tabs.spend({ playerId, actionId: 'skip:furnace:8412', amount: '20000' });
124
+ ```
125
+
126
+ **Why it is worth doing:** a hundred separate $0.02 payments cost roughly $0.13 in gas. One
127
+ $2.00 tab costs about $0.0013. Same money to you.
128
+
129
+ **`actionId` makes spending idempotent.** A client that retries after a dropped connection is
130
+ charged once; the second call reports `duplicate: true` so you still grant the item.
131
+
132
+ **Your ledger must be durable.** In memory, every player's remaining credit dies with the
133
+ process — they paid for something your server no longer remembers. Use the file store for a
134
+ single instance, or your own database adapter for more than one:
135
+
136
+ ```js
137
+ import { createFileLedgerStore } from '402-trinity-gaming/budget-file';
138
+ const ledger = createFileLedgerStore('./tabs.json');
139
+ ```
140
+
141
+ **If you run more than one game server**, implement `ledger.update()` and hold a row lock
142
+ across the read and the write. Without it, two servers can read the same balance and both
143
+ approve a spend it could only cover once.
144
+
145
+ **A tab is a balance you hold.** The player's cash is yours the moment the tab opens; what
146
+ they have left is credit in your game.
147
+
148
+ **Giving it back:**
149
+
150
+ ```js
151
+ await tabs.refund({ playerId }); // everything unspent
152
+ await tabs.refund({ playerId, amount: '500000' }); // or part of it
153
+ ```
154
+
155
+ Your treasury signs, the facilitator submits, the USDC lands back in the player's wallet — you
156
+ need no gas. The credit is deducted before the transfer is attempted, so it cannot be spent
157
+ while the refund is in flight, and it is **put back if the transfer fails**. Requires
158
+ `surcharge.proceedsKey`, since that is the key for the wallet holding the money.
159
+
160
+ The 0.1% taken when the tab opened is not reversed — it was charged on a sale that happened.
161
+
162
+ ---
163
+
164
+ ## 🧾 When something is refused
165
+
166
+ Every refusal comes back with a code you can switch on — item not for sale, bad signature,
167
+ authorization already spent, or settlement failed on the server's side.
168
+
169
+ Each also carries **`retryable`**, and it is the field that stops you charging a player twice.
170
+ When settlement fails on our side the payment was valid, so the *same* authorization must go
171
+ out again — minting a fresh one risks paying twice if the first lands late. When a signature
172
+ is rejected or already spent, it will never work. We make that call so your code doesn't have
173
+ to.
174
+
175
+ ---
176
+
177
+ ## đŸ“Ļ What you get today
178
+
179
+ **Available now:** the TypeScript backend library and client signer. Base mainnet, USDC.
180
+
181
+ **Coming:** native Unity (C#) and Unreal (C++) packages — the signer is a single function and
182
+ porting it is next. Key encryption and the card on-ramp are yours for now.
183
+
184
+ ---
185
+
186
+ Business Source License 1.1. Source-available; converts to MIT on 2029-08-25.
187
+
188
+ Merchant proceeds are settled net of a 0.1% network fee.
package/LICENSE ADDED
@@ -0,0 +1,110 @@
1
+ Business Source License 1.1
2
+
3
+ License text copyright (c) 2017 MariaDB Corporation Ab, All Rights Reserved.
4
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
5
+
6
+ -----------------------------------------------------------------------------
7
+
8
+ Parameters
9
+
10
+ Licensor: x402 trinity
11
+
12
+ Licensed Work: x402-trinity
13
+ The Licensed Work is (c) 2026 x402 trinity
14
+
15
+ Additional Use Grant: You may make use of the Licensed Work, provided that
16
+ you do not offer the Licensed Work to third parties as
17
+ a hosted or managed service that provides users with
18
+ access to any substantial set of its features or
19
+ functionality.
20
+
21
+ Change Date: 2029-08-25
22
+
23
+ Change License: MIT
24
+
25
+ For information about alternative licensing arrangements for the Licensed
26
+ Work, please contact the Licensor.
27
+
28
+ -----------------------------------------------------------------------------
29
+
30
+ Notice
31
+
32
+ Business Source License 1.1
33
+
34
+ Terms
35
+
36
+ The Licensor hereby grants you the right to copy, modify, create derivative
37
+ works, redistribute, and make non-production use of the Licensed Work. The
38
+ Licensor may make an Additional Use Grant, above, permitting limited
39
+ production use.
40
+
41
+ Effective on the Change Date, or the fourth anniversary of the first publicly
42
+ available distribution of a specific version of the Licensed Work under this
43
+ License, whichever comes first, the Licensor hereby grants you rights under
44
+ the terms of the Change License, and the rights granted in the paragraph
45
+ above terminate.
46
+
47
+ If your use of the Licensed Work does not comply with the requirements
48
+ currently in effect as described in this License, you must purchase a
49
+ commercial license from the Licensor, its affiliated entities, or authorized
50
+ resellers, or you must refrain from using the Licensed Work.
51
+
52
+ All copies of the original and modified Licensed Work, and derivative works
53
+ of the Licensed Work, are subject to this License. This License applies
54
+ separately for each version of the Licensed Work and the Change Date may vary
55
+ for each version of the Licensed Work released by Licensor.
56
+
57
+ You must conspicuously display this License on each original or modified copy
58
+ of the Licensed Work. If you receive the Licensed Work in original or
59
+ modified form from a third party, the terms and conditions set forth in this
60
+ License apply to your use of that work.
61
+
62
+ Any use of the Licensed Work in violation of this License will automatically
63
+ terminate your rights under this License for the current and all other
64
+ versions of the Licensed Work.
65
+
66
+ This License does not grant you any right in any trademark or logo of
67
+ Licensor or its affiliates (provided that you may use a trademark or logo of
68
+ Licensor as expressly required by this License).
69
+
70
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
71
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
72
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
73
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
74
+ TITLE.
75
+
76
+ MariaDB hereby grants you permission to use this License's text to license
77
+ your works, and to refer to it using the trademark "Business Source License",
78
+ as long as you comply with the Covenants of Licensor below.
79
+
80
+ Covenants of Licensor
81
+
82
+ In consideration of the right to use this License's text and the "Business
83
+ Source License" name and trademark, Licensor covenants to MariaDB, and to all
84
+ other recipients of the licensed work to be provided by Licensor:
85
+
86
+ 1. To specify as the Change License the GPL Version 2.0 or any later version,
87
+ or a license that is compatible with GPL Version 2.0 or a later version,
88
+ where "compatible" means that software provided under the Change License
89
+ can be included in a program with software provided under GPL Version 2.0
90
+ or a later version. Licensor may specify additional Change Licenses
91
+ without limitation.
92
+
93
+ 2. To either: (a) specify an additional grant of rights to use that does not
94
+ impose any additional restriction on the right granted in this License, as
95
+ the Additional Use Grant; or (b) insert the text "None".
96
+
97
+ 3. To specify a Change Date.
98
+
99
+ 4. Not to modify this License in any other way.
100
+
101
+ -----------------------------------------------------------------------------
102
+
103
+ THIS SOFTWARE MOVES MONEY. Additional notice:
104
+
105
+ This software constructs and signs cryptographic payment authorizations. You
106
+ are solely responsible for the funds in any wallet you configure it with, for
107
+ the spending limits you set, and for the behaviour of any autonomous agent you
108
+ connect to it. Set `maxAmountPerRequest` and `totalBudget`, use a dedicated
109
+ wallet, and read the security notes in the README before using it with real
110
+ assets.
package/README.md ADDED
@@ -0,0 +1,105 @@
1
+ # 402-trinity-gaming
2
+
3
+ **A payment backend for game storefronts that your players never see.**
4
+
5
+ No UI. No overlay. No browser handoff. No console output. Your button, your art, your unlock
6
+ animation — this handles the money and gets out of the way.
7
+
8
+ ```bash
9
+ npm install 402-trinity-gaming
10
+ ```
11
+
12
+ ## How it fits
13
+
14
+ ```
15
+ Your storefront UI ──â–ļ your backend ──â–ļ chain
16
+ (Unreal/Unity) (this package)
17
+ ▲ │
18
+ └────── events ─────────┘
19
+ ```
20
+
21
+ The player's client signs one authorization with their own key. Your server does everything
22
+ else. **You never hold the player's key**, and for direct purchases you hold no balance
23
+ either. (Tabs are the exception - see `INTEGRATION.md`.)
24
+
25
+ ## Use
26
+
27
+ ```js
28
+ import { createStorefront } from '402-trinity-gaming/storefront';
29
+
30
+ const store = createStorefront({
31
+ payTo: '0xYourStudioWallet',
32
+ network: 'base',
33
+ facilitator: 'https://your-facilitator.example', // REQUIRED - no default
34
+ nonceStore, // REQUIRED - must survive restarts
35
+ catalog: {
36
+ vanguard_skin_01: '1500000', // atomic units: 1.50 USDC (6 decimals)
37
+ season_pass_04: '9990000', // 9.99
38
+ },
39
+ surcharge: { proceedsKey }, // the key for payTo
40
+ });
41
+
42
+ store.on('settled', e => grantItem(e.playerId, e.itemId));
43
+ store.on('declined', e => showRefusal(e.playerId, e.code));
44
+ ```
45
+
46
+ Serve the quote, take the signature, redeem it:
47
+
48
+ ```js
49
+ // 1. the client asks what it must sign
50
+ const quote = store.quote('vanguard_skin_01');
51
+
52
+ // 2. the client signs it and posts back { authorization, signature }
53
+ const result = await store.purchase({
54
+ itemId: 'vanguard_skin_01',
55
+ playerId: 'player-8823',
56
+ playerAddress: '0xPlayerWallet',
57
+ authorization,
58
+ signature,
59
+ });
60
+ ```
61
+
62
+ ## Events
63
+
64
+ | event | when | what to do |
65
+ |---|---|---|
66
+ | `accepted` | the request is well formed, the item is real, settlement is underway | grant optimistically if you want the item to appear instantly |
67
+ | `settled` | the money has moved, with an on-chain transaction hash | grant, or reconcile an optimistic grant |
68
+ | `declined` | it was refused | read `code`, not `message` |
69
+
70
+ Decline codes are `unknown_item`, `already_used`, `rejected`, `settlement_failed` and
71
+ `malformed`. Each carries `retryable` — **true** means the same authorization may be presented
72
+ again unchanged, **false** means mint a fresh one. Re-sending when `retryable` is false risks
73
+ paying twice.
74
+
75
+ ## Prices are strings
76
+
77
+ Atomic units of the asset, as a decimal string. USDC has 6 decimals, so `1.50` is
78
+ `'1500000'`. A float cannot represent money exactly, and this value goes inside a signature.
79
+
80
+ ## Nothing is printed
81
+
82
+ This library never writes to `stdout` or `stderr` — that is enforced by its build, not by
83
+ convention. Diagnostics reach you through `onDiagnostic`, and the fee disclosure is exported
84
+ as `NOTICE` for you to place wherever disclosure belongs in your product.
85
+
86
+ ## Scope
87
+
88
+ **Base mainnet + USDC.** Other EVM chains work by passing `customChains`. Check any entry
89
+ against the deployed contract first: call `DOMAIN_SEPARATOR()` and confirm it matches what
90
+ this library computes. A wrong `name` or `version` produces a signature that looks valid and
91
+ the contract rejects.
92
+
93
+ ## Before you use it with real money
94
+
95
+ This software signs payment authorizations. You are responsible for the funds in any wallet
96
+ you configure it with and for the limits you set. `nonceStore` must be durable — an in-memory
97
+ replay guard forgets every settled payment on restart, which means selling the same item twice
98
+ for free.
99
+
100
+ ## License
101
+
102
+ Business Source License 1.1. Source-available; converts to MIT on 2029-08-25. See
103
+ [LICENSE](LICENSE).
104
+
105
+ Network fee: 0.1% of merchant proceeds and 1 cent every 100 sales.
@@ -0,0 +1,201 @@
1
+ /**
2
+ * OFF-CHAIN MICRO-ACTION LEDGER.
3
+ *
4
+ * Survival, MMO and sandbox economies charge constantly and in fractions of a cent - a timer
5
+ * skip, a stack of ore, a repair. Settling each one on-chain costs more in gas than the
6
+ * action costs the player, so nothing here touches the chain per action.
7
+ *
8
+ * Instead the player opens a TAB: one signed authorization, settled once, credited to a local
9
+ * ledger. Every action after that is a synchronous deduction - no signature, no network, no
10
+ * frame cost. When the tab runs low the player tops up with another single signature.
11
+ *
12
+ * const tab = await tabs.open({ playerId, playerAddress, authorization, signature });
13
+ * tabs.spend({ playerId, actionId: 'skip:furnace:8412', amount: '20000' }); // instant
14
+ *
15
+ * WHY A TAB AND NOT A HUNDRED CACHED SIGNATURES. An EIP-3009 authorization is redeemed by its
16
+ * own contract call with its own nonce; a hundred of them cannot be summed into one transfer.
17
+ * Caching signatures and flushing them together still costs a hundred settlements - about
18
+ * 6.4% of a $2.00 batch at real Base gas, against 0.06% for a single one. The saving comes
19
+ * from one signature covering the batch, not from when the signatures are sent.
20
+ *
21
+ * WHY PREPAID AND NOT POSTPAID. Charging at the END of a hundred actions means granting
22
+ * ninety-nine of them on credit. A player who closes the game keeps them, and a farm of bots
23
+ * does it deliberately. Money in hand first removes the question.
24
+ */
25
+ import { type StorefrontConfig, type PurchaseDeclined } from './storefront.js';
26
+ import type { Authorization } from './x402.js';
27
+ export interface TabConfig extends Omit<StorefrontConfig, 'catalog'> {
28
+ /**
29
+ * Tab sizes a player may open, in atomic units. Named like a catalog because that is what
30
+ * they are - a $2.00 tab is a $2.00 purchase that happens to be spent gradually.
31
+ */
32
+ tabs: Record<string, string>;
33
+ /**
34
+ * Durable ledger. WITHOUT ONE, EVERY PLAYER'S REMAINING BALANCE IS LOST ON RESTART - they
35
+ * paid for credit the process no longer remembers. In memory is for local development only.
36
+ */
37
+ ledger?: LedgerStore;
38
+ /** Warn when a tab drops below this fraction of its opening size. Default 0.15. */
39
+ lowWaterMark?: number;
40
+ }
41
+ export interface LedgerStore {
42
+ get: (playerId: string) => Promise<TabState | null>;
43
+ set: (playerId: string, s: TabState) => Promise<void>;
44
+ /** Read-modify-write under a lock. Without it two game servers double-spend one tab. */
45
+ update?: (playerId: string, fn: (cur: TabState | null) => TabState) => Promise<TabState>;
46
+ }
47
+ export interface TabState {
48
+ playerAddress: string;
49
+ /** Atomic units still available. */
50
+ remaining: string;
51
+ /** What the tab was opened for, for reporting. */
52
+ opened: string;
53
+ /**
54
+ * Action ids already charged, with when. Kept BY AGE rather than by count: a retry happens
55
+ * within seconds, so a day is generous - and a cap by count means a long-lived tab silently
56
+ * forgets an old id and charges for it a second time.
57
+ */
58
+ spent: Array<{
59
+ id: string;
60
+ at: number;
61
+ }>;
62
+ updatedAt: string;
63
+ }
64
+ export type SpendResult = {
65
+ ok: true;
66
+ remaining: string;
67
+ charged: string;
68
+ duplicate: boolean;
69
+ } | {
70
+ ok: false;
71
+ code: 'no_tab' | 'insufficient' | 'invalid_amount';
72
+ remaining: string;
73
+ message: string;
74
+ };
75
+ export type RefundResult = {
76
+ ok: true;
77
+ refunded: string;
78
+ remaining: string;
79
+ transaction: string;
80
+ } | {
81
+ ok: false;
82
+ code: 'no_tab' | 'nothing_to_refund' | 'too_much' | 'no_key' | 'failed';
83
+ remaining: string;
84
+ message: string;
85
+ };
86
+ interface Events {
87
+ opened: {
88
+ playerId: string;
89
+ playerAddress: string;
90
+ amount: string;
91
+ transaction: string;
92
+ };
93
+ refunded: {
94
+ playerId: string;
95
+ playerAddress: string;
96
+ amount: string;
97
+ transaction: string;
98
+ };
99
+ spent: {
100
+ playerId: string;
101
+ actionId: string;
102
+ amount: string;
103
+ remaining: string;
104
+ };
105
+ low: {
106
+ playerId: string;
107
+ remaining: string;
108
+ opened: string;
109
+ };
110
+ exhausted: {
111
+ playerId: string;
112
+ };
113
+ }
114
+ export declare function createBatchManager(cfg: TabConfig): {
115
+ /** Tab sizes on offer. */
116
+ readonly sizes: string[];
117
+ /** What the client signs to open tab `tabId`. */
118
+ quote(tabId: string): {
119
+ scheme: string;
120
+ network: string;
121
+ amount: string;
122
+ asset: string;
123
+ payTo: string;
124
+ maxTimeoutSeconds: number;
125
+ extra: {
126
+ name: string;
127
+ version: string;
128
+ };
129
+ itemId: string;
130
+ } | null;
131
+ on<K extends keyof Events>(n: K, h: (e: Events[K]) => void): () => void;
132
+ /**
133
+ * Open or top up a tab. This is the ONLY on-chain step - one settlement covering every
134
+ * action the player takes until the balance runs out.
135
+ *
136
+ * Credit is added only after the transfer settles. A declined payment adds nothing.
137
+ */
138
+ open(req: {
139
+ tabId: string;
140
+ playerId: string;
141
+ playerAddress: string;
142
+ authorization: Authorization;
143
+ signature: string;
144
+ }): Promise<{
145
+ ok: true;
146
+ remaining: string;
147
+ transaction: string;
148
+ } | {
149
+ ok: false;
150
+ declined: PurchaseDeclined;
151
+ }>;
152
+ /**
153
+ * Charge one micro-action. Synchronous in spirit - no signature, no chain, no network -
154
+ * so it is safe on a gameplay path.
155
+ *
156
+ * `actionId` makes it idempotent. A client that retries after a dropped response charges
157
+ * once, and the second call reports `duplicate: true` so you can grant without re-billing.
158
+ */
159
+ spend(req: {
160
+ playerId: string;
161
+ actionId: string;
162
+ amount: string;
163
+ }): Promise<SpendResult>;
164
+ /**
165
+ * Return unspent credit to the player's wallet.
166
+ *
167
+ * The studio signs an authorization to the player and the facilitator submits it, so the
168
+ * studio needs no gas - the same shape as every other transfer here, just pointing the
169
+ * other way. Requires `surcharge.proceedsKey`, because that is the key for the wallet
170
+ * holding the money.
171
+ *
172
+ * ORDER MATTERS. The credit is deducted BEFORE the transfer is attempted, so it cannot be
173
+ * spent while the refund is in flight, and restored if the transfer fails. The opposite
174
+ * order lets a player spend the same money twice - once in-game and once on-chain.
175
+ *
176
+ * The 0.1% taken when the tab opened is NOT reversed. It was charged on a sale that did
177
+ * happen, and clawing it back out of the vault is not something this can do.
178
+ */
179
+ refund(req: {
180
+ playerId: string;
181
+ amount?: string;
182
+ }): Promise<RefundResult>;
183
+ /** What the player has left. Read-only. */
184
+ balance(playerId: string): Promise<{
185
+ remaining: string;
186
+ opened: string;
187
+ } | null>;
188
+ /** The network fee taken from proceeds when a tab is opened. */
189
+ fee: {
190
+ readonly enabled: boolean;
191
+ stats: () => Promise<{
192
+ enabled: boolean;
193
+ salesSinceLastSweep: string;
194
+ accrued: string;
195
+ collected: string;
196
+ held: string;
197
+ lost: string;
198
+ }>;
199
+ };
200
+ };
201
+ export {};