@xgamesfun/solana 0.20.1 → 0.25.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/README.md +95 -52
- package/bin/xsolana.mjs +23 -8
- package/examples/blind-forge.json +2 -4
- package/examples/coin-flip-arena.json +4 -12
- package/examples/duel-arena.json +1 -4
- package/examples/elements-set.json +2 -9
- package/examples/expedition-guild.json +1 -8
- package/examples/fair-presale.json +1 -3
- package/examples/guild-missions.json +3 -10
- package/examples/halving-seasons.json +4 -9
- package/examples/hero-trials.json +15 -6
- package/examples/holder-den.json +38 -0
- package/examples/holders-drop.json +105 -0
- package/examples/ideas.json +788 -788
- package/examples/match-predictions.json +24 -0
- package/examples/merge-2048.json +5 -5
- package/examples/nft-raffle.json +1 -0
- package/examples/pack-league.json +108 -0
- package/examples/paper-hands-farm.json +4 -16
- package/examples/partner-vault.json +20 -7
- package/examples/sacrifice-raffle.json +2 -10
- package/examples/shelter-fair.json +1 -0
- package/examples/stakers-draw.json +4 -15
- package/examples/star-fleet.json +1 -8
- package/examples/starforce.json +6 -6
- package/examples/stride-sneakers.json +164 -0
- package/examples/trade-in-shop.json +2 -3
- package/js/approve/details.mjs +122 -52
- package/js/approve/ed25519.mjs +5 -1
- package/js/approve/live-check.mjs +83 -26
- package/js/approve/page.html +217 -78
- package/js/approve/page.js +43 -15
- package/js/approve/server.mjs +290 -73
- package/js/chain/base58.js +7 -1
- package/js/chain/borsh.js +24 -11
- package/js/chain/bytes.js +11 -8
- package/js/chain/core.js +35 -7
- package/js/chain/curve.js +1 -1
- package/js/chain/lookup.js +124 -36
- package/js/chain/mint.js +6 -2
- package/js/chain/pda.js +2 -2
- package/js/chain/programs.js +6 -6
- package/js/chain/rpc.js +44 -16
- package/js/chain/token.js +13 -2
- package/js/chain/token2022.js +55 -16
- package/js/chain/tx.js +32 -22
- package/js/client/accounts.js +653 -131
- package/js/client/compressed.js +4 -3
- package/js/client/grant.js +267 -83
- package/js/client/idl/loot.js +1 -1
- package/js/client/idl/loot.json +2406 -2176
- package/js/client/index.js +1 -0
- package/js/client/ix.js +3059 -664
- package/js/client/pda.js +39 -33
- package/js/client/policy.js +52 -24
- package/js/client/random.js +70 -0
- package/js/client/sizes.js +414 -16
- package/js/client/traits.js +14 -5
- package/js/connect/connect.mjs +59 -17
- package/js/economy/check.mjs +4153 -725
- package/js/economy/cost.mjs +403 -64
- package/js/economy/examples.mjs +176 -35
- package/js/economy/explain.mjs +466 -111
- package/js/economy/guide.mjs +296 -72
- package/js/economy/legal.mjs +12 -6
- package/js/economy/live.mjs +83 -19
- package/js/economy/model.mjs +462 -124
- package/js/economy/plan.mjs +1306 -219
- package/js/economy/schema.json +390 -484
- package/js/economy/secrets.mjs +17 -7
- package/js/economy/simulate.mjs +883 -223
- package/js/economy/txsize.mjs +15 -3
- package/js/economy/validate.mjs +61 -24
- package/js/mcp/server.mjs +42 -14
- package/js/mcp/tools.mjs +307 -88
- package/js/play/index.js +2864 -619
- package/js/play/keys.js +193 -0
- package/js/results/index.js +223 -30
- package/js/results/server.js +230 -0
- package/js/results/wire.js +64 -16
- package/package.json +6 -4
- package/release.json +5 -5
- package/skills/xsolana-economy/SKILL.md +39 -21
- package/skills/xsolana-economy/references/after-launch.md +58 -38
- package/skills/xsolana-economy/references/apps.md +97 -50
- package/skills/xsolana-economy/references/sentence-to-spec.md +148 -121
- package/skills/xsolana-economy/references/telling-the-person.md +61 -17
- package/types/chain/core.d.ts +4 -2
- package/types/chain/lookup.d.ts +5 -2
- package/types/chain/rpc.d.ts +3 -1
- package/types/client/accounts.d.ts +217 -56
- package/types/client/grant.d.ts +72 -27
- package/types/client/idl/loot.d.ts +602 -549
- package/types/client/index.d.ts +1 -0
- package/types/client/ix.d.ts +3884 -247
- package/types/client/pda.d.ts +22 -16
- package/types/client/policy.d.ts +39 -14
- package/types/client/random.d.ts +26 -0
- package/types/client/sizes.d.ts +93 -5
- package/types/economy/check.d.mts +5 -10
- package/types/economy/cost.d.mts +2 -1
- package/types/economy/guide.d.mts +5 -0
- package/types/economy/live.d.mts +16 -1
- package/types/economy/model.d.mts +151 -38
- package/types/economy/plan.d.mts +237 -194
- package/types/economy/simulate.d.mts +21 -13
- package/types/mcp/tools.d.mts +21 -13
- package/types/play/index.d.ts +453 -53
- package/types/play/keys.d.ts +51 -0
- package/types/results/index.d.ts +7 -6
- package/types/results/server.d.ts +126 -0
- package/types/results/wire.d.ts +1 -1
package/README.md
CHANGED
|
@@ -12,13 +12,56 @@ package `@xgamesfun/solana`:
|
|
|
12
12
|
|
|
13
13
|
An economy is a JSON spec, not a new smart contract. Every project shares the one program, and none writes its own.
|
|
14
14
|
|
|
15
|
-
> **Status:** loot 0.
|
|
16
|
-
>
|
|
15
|
+
> **Status:** these tools are for loot 0.25.0, program ID `9cwqM1TXytPnFZsLfmUyv2dg4uW6Ch9C6UJVPns7NFQ`, **devnet
|
|
16
|
+
> only** (deployed 2026-11-08, slot 519,994,814). The program is not independently audited, and nothing runs
|
|
17
|
+
> on mainnet until it is. See [SECURITY.md](SECURITY.md).
|
|
17
18
|
|
|
18
19
|
> **Disclaimer:** provided as is, with no warranty and no guarantee that the program or the tools are safe. Use them
|
|
19
20
|
> at your own risk; you are responsible for every transaction you approve and for making sure what you build is legal
|
|
20
21
|
> where it runs. Nothing here is legal or financial advice. Read [DISCLAIMER.md](DISCLAIMER.md) before you use it.
|
|
21
22
|
|
|
23
|
+
## Before you use it
|
|
24
|
+
|
|
25
|
+
- **Devnet only, and not independently audited.** Nothing here is for real money yet. Use a devnet wallet.
|
|
26
|
+
- **The program can be upgraded, and an upgrade can mean starting again.** Its upgrade authority can replace the
|
|
27
|
+
program's code, which is power over every economy on it (on mainnet that key is to be a multisig). No version so far
|
|
28
|
+
has carried accounts over from the one before: an economy made on 0.23 was made again for 0.24. Pin the package
|
|
29
|
+
version (each one names the program build it is for in `release.json`) and expect to set an economy up again after an
|
|
30
|
+
upgrade.
|
|
31
|
+
- **Players trust the project.** Its owner and authority are trusted keys with no caps: the authority mints, moves the
|
|
32
|
+
project's pool funds, decides contests and writes its NFTs. The program protects players from each other, from the
|
|
33
|
+
platform and from mistakes, not from the project they chose to play. Money held for a record (an order, a bid, a
|
|
34
|
+
farm's stakes, a contest's or lottery's pot) leaves only by that record's rules.
|
|
35
|
+
- **Players also trust the token and the collection.** A mint's issuer (a freeze authority, a pause, a transfer hook, a
|
|
36
|
+
permanent delegate) or a collection's controller can stop or move what loot holds. USDC has a freeze authority.
|
|
37
|
+
- **The chain can't see a game.** Results a game reports (a win, a score, a clear) are vouched for by a key the project
|
|
38
|
+
trusts, a results server or deciders. Checking that a player really did it is the project's job, on its own server.
|
|
39
|
+
- **The hosted results server is optional.** `https://play.xgames.fun/xsolana` (`@xgamesfun/solana/results`'s
|
|
40
|
+
default) signs vouchers for games without a server of their own. It can only pay what a grant allows, and only for a
|
|
41
|
+
grant whose owner named its key in `vouchers`. It sends nothing on chain, and it is offered as is: it can be down, and
|
|
42
|
+
it is behind for a while after each program upgrade. A game with its own server signs its own vouchers
|
|
43
|
+
(`signVoucher`), which is the better choice once it has one.
|
|
44
|
+
- **Nothing runs by itself.** Someone sends every step: settles (the player, the project's keys, or a key the player
|
|
45
|
+
named), lottery draws, auction ends, refunds (anyone), contest results (the authority or its deciders) and schedule
|
|
46
|
+
runs (the project's keys). A run nobody sends on time is missed, except a sealed schedule's fixed amount. Apps built
|
|
47
|
+
with `@xgamesfun/solana/play` send the steps a player needs. Don't count on a hosted keeper.
|
|
48
|
+
- **The rules are strict.** A prize is a fixed amount: a jackpot that grows is a lottery's pot. A lottery says where its
|
|
49
|
+
places are paid from: a pot that carries over (gifts and what earlier rounds left count), or each round's own ticket
|
|
50
|
+
money, which nothing from outside can change. A prize never shifts to a later round. A draw uses the odds
|
|
51
|
+
as written. When an outcome runs out, a box either stops selling (`stopSales`, the default) or keeps selling and
|
|
52
|
+
draws among what's left (`drawLeft`, which lets a player empty a common outcome to make a rare one likelier).
|
|
53
|
+
- **Chance comes from an oracle.** MagicBlock's VRF answers every random roll and draw. If it stops answering, rolls wait. An
|
|
54
|
+
order still unanswered after 7 days can be refunded. Once a roll has waited 10 minutes, a buyer who sees a late
|
|
55
|
+
answer coming can take a refund instead.
|
|
56
|
+
- **Fees and rent.** The platform sets two flat fees: by default 0.002 SOL a player action and 0.00001 SOL a project
|
|
57
|
+
action. Each is capped at 0.01 SOL, and a raise waits 7 days. Accounts cost rent: going live, and each settle that
|
|
58
|
+
opens or mints something. `xsolana cost` gives the totals. The platform can suspend purchases, but it never stops
|
|
59
|
+
payouts, refunds or unstakes (the one exception is a recipe that charges).
|
|
60
|
+
- **Some things aren't built,** and some limits are kept by design. Read
|
|
61
|
+
[Known limits](docs/program.md#known-limits) before promising players something unusual.
|
|
62
|
+
- **The law is yours to check.** The checker's legal flags (chance at money, resellable random items, revenue
|
|
63
|
+
sharing) are reminders, not advice. A spec with no flag isn't therefore legal.
|
|
64
|
+
|
|
22
65
|
## What an economy can be made of
|
|
23
66
|
|
|
24
67
|
- payments and splits, in tokens or with an NFT
|
|
@@ -27,7 +70,7 @@ An economy is a JSON spec, not a new smart contract. Every project shares the on
|
|
|
27
70
|
- lotteries and raffles, including no-loss lotteries
|
|
28
71
|
- prizes of any kind on every route, random or not: items, tokens, and NFTs the project holds in a stash
|
|
29
72
|
- an NFT as the price on every route that takes money
|
|
30
|
-
- staking farms with lock tiers, boosts, early exits and
|
|
73
|
+
- staking farms with lock tiers, boosts, early exits, fixed or shared rates and terms
|
|
31
74
|
- crafting recipes
|
|
32
75
|
- holds and contests, with prizes by rank or by stake
|
|
33
76
|
- auctions: the highest bid wins, the outbid refunded at once
|
|
@@ -59,13 +102,13 @@ codex plugin add xsolana@xgamesfun
|
|
|
59
102
|
```
|
|
60
103
|
|
|
61
104
|
**Any agent with MCP** (Cursor, opencode, Cline…): run the server with
|
|
62
|
-
`npx -y --package=@xgamesfun/solana@0.
|
|
105
|
+
`npx -y --package=@xgamesfun/solana@0.25.0 xsolana mcp`. Or let `npx -y @xgamesfun/solana@0.25.0 connect` register it, with
|
|
63
106
|
the skill, for Claude Code and Codex.
|
|
64
107
|
|
|
65
|
-
Then ask for an economy, for example
|
|
66
|
-
monthly draw"
|
|
108
|
+
Then ask for an economy, for example _"a fishing game where each cast costs 0.02 SOL, with a rare golden fish and a
|
|
109
|
+
monthly draw"_.
|
|
67
110
|
|
|
68
|
-
Going live is always yours: `npx -y @xgamesfun/solana@0.
|
|
111
|
+
Going live is always yours: `npx -y @xgamesfun/solana@0.25.0 approve` opens a page on your computer where you connect a
|
|
69
112
|
devnet wallet and approve each transaction. The agent never signs and never asks for a key.
|
|
70
113
|
|
|
71
114
|
## Use it from a terminal
|
|
@@ -73,12 +116,12 @@ devnet wallet and approve each transaction. The agent never signs and never asks
|
|
|
73
116
|
Every tool runs from the CLI too, on a spec file (`xsolana.json` by default):
|
|
74
117
|
|
|
75
118
|
```bash
|
|
76
|
-
npx -y @xgamesfun/solana@0.
|
|
77
|
-
npx -y @xgamesfun/solana@0.
|
|
78
|
-
npx -y @xgamesfun/solana@0.
|
|
79
|
-
npx -y @xgamesfun/solana@0.
|
|
80
|
-
npx -y @xgamesfun/solana@0.
|
|
81
|
-
npx -y @xgamesfun/solana@0.
|
|
119
|
+
npx -y @xgamesfun/solana@0.25.0 examples shop with loot boxes # the nearest worked examples
|
|
120
|
+
npx -y @xgamesfun/solana@0.25.0 check xsolana.json # refusals and warnings
|
|
121
|
+
npx -y @xgamesfun/solana@0.25.0 simulate xsolana.json # where the money goes, day by day
|
|
122
|
+
npx -y @xgamesfun/solana@0.25.0 cost xsolana.json # what going live and each action cost
|
|
123
|
+
npx -y @xgamesfun/solana@0.25.0 explain xsolana.json # the economy in plain words
|
|
124
|
+
npx -y @xgamesfun/solana@0.25.0 approve xsolana.json # go live, approved in your own wallet
|
|
82
125
|
```
|
|
83
126
|
|
|
84
127
|
`xsolana help` lists every command. Every command names the exact version, so `npx` runs that release and never whatever
|
|
@@ -95,45 +138,45 @@ import * as loot from '@xgamesfun/solana/client';
|
|
|
95
138
|
const ix = loot.openBoxIx({ player, project, box, nonce }); // one builder per instruction, no Solana SDK
|
|
96
139
|
```
|
|
97
140
|
|
|
98
|
-
| Import
|
|
99
|
-
|
|
|
100
|
-
| `@xgamesfun/solana`
|
|
101
|
-
| `@xgamesfun/solana/client`
|
|
102
|
-
| `@xgamesfun/solana/play`
|
|
103
|
-
| `@xgamesfun/solana/results`
|
|
104
|
-
| `@xgamesfun/solana/chain/*`
|
|
105
|
-
| `@xgamesfun/solana/idl.json`
|
|
106
|
-
| `@xgamesfun/solana/release.json` | the program build, IDL and client this release is pinned to
|
|
141
|
+
| Import | What |
|
|
142
|
+
| -------------------------------- | ------------------------------------------------------------------------------------ |
|
|
143
|
+
| `@xgamesfun/solana` | the economy tools: `check`, `simulate`, `plan`, `cost`, `explainEconomy`, `model` |
|
|
144
|
+
| `@xgamesfun/solana/client` | every PDA, one builder per instruction, account and receipt decoders, grant vouchers |
|
|
145
|
+
| `@xgamesfun/solana/play` | `solanaApp`: what a player does with a live economy, from a browser app |
|
|
146
|
+
| `@xgamesfun/solana/results` | results and vouchers a game's server signs |
|
|
147
|
+
| `@xgamesfun/solana/chain/*` | browser-safe Solana primitives: base58, Borsh, transactions, PDAs, tokens, Core |
|
|
148
|
+
| `@xgamesfun/solana/idl.json` | the program's IDL, the authority for account and argument layouts |
|
|
149
|
+
| `@xgamesfun/solana/release.json` | the program build, IDL and client this release is pinned to |
|
|
107
150
|
|
|
108
151
|
The client, chain and play modules run in browsers and Node 22 or later, with no bundler required. The package
|
|
109
152
|
ships TypeScript declarations for every entry point.
|
|
110
153
|
|
|
111
154
|
## Documentation
|
|
112
155
|
|
|
113
|
-
|
|
|
114
|
-
|
|
|
115
|
-
| [`docs/program.md`](docs/program.md)
|
|
116
|
-
| [`docs/nfts.md`](docs/nfts.md)
|
|
117
|
-
| [`docs/harnesses.md`](docs/harnesses.md)
|
|
118
|
-
| [`skills/xsolana-economy`](skills/xsolana-economy/SKILL.md)
|
|
119
|
-
| [`examples/`](examples)
|
|
120
|
-
| [`evals/`](evals/README.md)
|
|
121
|
-
| [`CHANGELOG.md`](CHANGELOG.md), [`SECURITY.md`](SECURITY.md) | versions, the trust model, reporting a vulnerability
|
|
156
|
+
| | |
|
|
157
|
+
| ------------------------------------------------------------ | ------------------------------------------------------------------------------------------- |
|
|
158
|
+
| [`docs/program.md`](docs/program.md) | the program: who signs, accounts, every instruction, fees, limits, receipts, costs |
|
|
159
|
+
| [`docs/nfts.md`](docs/nfts.md) | NFTs and tokens, with and without the project's authority |
|
|
160
|
+
| [`docs/harnesses.md`](docs/harnesses.md) | how the plugin reaches Claude Code and Codex, and the release checklist |
|
|
161
|
+
| [`skills/xsolana-economy`](skills/xsolana-economy/SKILL.md) | the skill an agent follows |
|
|
162
|
+
| [`examples/`](examples) | whole economies that check and go live in the tests; `ideas.json`, 112 real economies rated |
|
|
163
|
+
| [`evals/`](evals/README.md) | fresh-session evals of agents building on loot |
|
|
164
|
+
| [`CHANGELOG.md`](CHANGELOG.md), [`SECURITY.md`](SECURITY.md) | versions, the trust model, reporting a vulnerability |
|
|
122
165
|
|
|
123
166
|
## Layout
|
|
124
167
|
|
|
125
|
-
| Path
|
|
126
|
-
|
|
|
127
|
-
| `js/chain/`
|
|
128
|
-
| `js/client/`
|
|
129
|
-
| `js/economy/`
|
|
130
|
-
| `js/play/`, `js/results/`
|
|
131
|
-
| `js/approve/`, `js/mcp/`, `js/connect/` | the approval page, the MCP server and its tools, `xsolana connect`
|
|
132
|
-
| `js/sim/`, `js/test/`
|
|
133
|
-
| `bin/xsolana.mjs`
|
|
134
|
-
| `skills/`, `plugin/`
|
|
135
|
-
| `scripts/`
|
|
136
|
-
| `release.json`
|
|
168
|
+
| Path | What |
|
|
169
|
+
| --------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
170
|
+
| `js/chain/` | browser-safe Solana primitives, no SDK |
|
|
171
|
+
| `js/client/` | the client; `idl/` is the program's IDL |
|
|
172
|
+
| `js/economy/` | the economy spec (version 2, `schema.json`), checker, simulation, setup plan, cost, explainer, guide |
|
|
173
|
+
| `js/play/`, `js/results/` | a player's side of a live economy; results a server vouches for |
|
|
174
|
+
| `js/approve/`, `js/mcp/`, `js/connect/` | the approval page, the MCP server and its tools, `xsolana connect` |
|
|
175
|
+
| `js/sim/`, `js/test/` | LiteSVM running the real program; the tests and their pinned fixtures |
|
|
176
|
+
| `bin/xsolana.mjs` | the CLI |
|
|
177
|
+
| `skills/`, `plugin/` | the skill (copied to `plugin/skills`, `.claude/skills`, `.agents/skills`) and the plugin |
|
|
178
|
+
| `scripts/` | fixtures, skill sync, IDL sync, release manifest, a devnet end-to-end run |
|
|
179
|
+
| `release.json` | the program binary, IDL and client hashes this version is pinned to |
|
|
137
180
|
|
|
138
181
|
## Development
|
|
139
182
|
|
|
@@ -143,20 +186,20 @@ Node 22 or later.
|
|
|
143
186
|
npm ci
|
|
144
187
|
npm run fixtures # downloads the loot program from devnet and the programs it calls from mainnet, each checked by hash
|
|
145
188
|
npm test # every instruction the client builds, and every example's whole setup, against the real program in LiteSVM
|
|
146
|
-
npm run lint # ESLint
|
|
189
|
+
npm run lint # ESLint and Prettier (npm run format fixes the formatting)
|
|
147
190
|
npm run check # fixtures, skill copies and release.json in step, lint, then the tests
|
|
148
191
|
```
|
|
149
192
|
|
|
150
193
|
Nothing in the tests deploys or spends SOL.
|
|
151
194
|
|
|
152
|
-
| Variable
|
|
153
|
-
|
|
|
154
|
-
| `XSOLANA_RPC_URL`
|
|
155
|
-
| `XSOLANA_NO_OPEN`
|
|
156
|
-
| `XSOLANA_DEBUG`
|
|
157
|
-
| `XSOLANA_PROGRAM_DIR`
|
|
158
|
-
`node bin/xsolana.mjs connect --local` registers this checkout's MCP server and the skill with Claude Code and Codex
|
|
159
|
-
(`--remove` takes them out again).
|
|
195
|
+
| Variable | What it does |
|
|
196
|
+
| -------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- |
|
|
197
|
+
| `XSOLANA_RPC_URL` | a devnet RPC of your own for `xsolana approve` and `xsolana status` (a mainnet URL is refused) |
|
|
198
|
+
| `XSOLANA_NO_OPEN` | `xsolana approve` prints its link without opening a browser |
|
|
199
|
+
| `XSOLANA_DEBUG` | the CLI prints a failure's whole stack, not one line |
|
|
200
|
+
| `XSOLANA_PROGRAM_DIR` | the tests run that program build's `target/deploy/loot.so`, and check the IDL against it | To try the tools in your own agent from a clone, |
|
|
201
|
+
| `node bin/xsolana.mjs connect --local` registers this checkout's MCP server and the skill with Claude Code and Codex |
|
|
202
|
+
| (`--remove` takes them out again). |
|
|
160
203
|
|
|
161
204
|
After editing `skills/`, run `npm run sync-skills`. Changes to tool texts, the skill or the plugin are best measured
|
|
162
205
|
with the evals before and after ([`evals/README.md`](evals/README.md)). [`AGENTS.md`](AGENTS.md) has the rules for
|
package/bin/xsolana.mjs
CHANGED
|
@@ -74,7 +74,8 @@ function parseArgs(rest) {
|
|
|
74
74
|
flags.add(name);
|
|
75
75
|
if (eq > 0) values.set(name, a.slice(eq + 1));
|
|
76
76
|
else if (VALUED.has(name)) {
|
|
77
|
-
if (i + 1 >= rest.length || rest[i + 1].startsWith('--'))
|
|
77
|
+
if (i + 1 >= rest.length || rest[i + 1].startsWith('--'))
|
|
78
|
+
throw new UsageError(`${name} needs a value (${name} <value> or ${name}=<value>).`);
|
|
78
79
|
values.set(name, rest[++i]);
|
|
79
80
|
}
|
|
80
81
|
}
|
|
@@ -85,7 +86,8 @@ function parseArgs(rest) {
|
|
|
85
86
|
function portOf(value) {
|
|
86
87
|
if (value === undefined) return undefined;
|
|
87
88
|
const n = Number(value);
|
|
88
|
-
if (!/^\d+$/.test(String(value)) || n < 1 || n > 65535)
|
|
89
|
+
if (!/^\d+$/.test(String(value)) || n < 1 || n > 65535)
|
|
90
|
+
throw new UsageError(`--port must be a whole number from 1 to 65535, not ${JSON.stringify(value)}.`);
|
|
89
91
|
return n;
|
|
90
92
|
}
|
|
91
93
|
|
|
@@ -93,8 +95,11 @@ async function main(argv) {
|
|
|
93
95
|
const [command, ...rest] = argv;
|
|
94
96
|
const { flags, values, positional } = parseArgs(rest);
|
|
95
97
|
const takes = Object.hasOwn(FLAGS, command) ? FLAGS[command] : null;
|
|
96
|
-
const unknown = takes && [...flags].find(
|
|
97
|
-
if (unknown)
|
|
98
|
+
const unknown = takes && [...flags].find(f => !takes.includes(f));
|
|
99
|
+
if (unknown)
|
|
100
|
+
throw new UsageError(
|
|
101
|
+
`“${command}” takes no ${unknown} flag (${takes.length ? `only ${takes.join(', ')}` : 'it takes none'}).`,
|
|
102
|
+
);
|
|
98
103
|
|
|
99
104
|
async function tool(name, input) {
|
|
100
105
|
const { runTool } = await import('../js/mcp/server.mjs');
|
|
@@ -135,7 +140,13 @@ async function main(argv) {
|
|
|
135
140
|
}
|
|
136
141
|
case 'connect': {
|
|
137
142
|
const { connect } = await import('../js/connect/connect.mjs');
|
|
138
|
-
process.exitCode = await connect({
|
|
143
|
+
process.exitCode = await connect({
|
|
144
|
+
agent: values.get('--agent'),
|
|
145
|
+
local: flags.has('--local'),
|
|
146
|
+
remove: flags.has('--remove'),
|
|
147
|
+
dryRun: flags.has('--dry-run'),
|
|
148
|
+
scope: values.get('--scope'),
|
|
149
|
+
});
|
|
139
150
|
break;
|
|
140
151
|
}
|
|
141
152
|
case 'tool': {
|
|
@@ -145,12 +156,15 @@ async function main(argv) {
|
|
|
145
156
|
break;
|
|
146
157
|
}
|
|
147
158
|
const from = values.get('--args-file');
|
|
148
|
-
const raw = from ? await readFile(from, 'utf8') : positional[1] ?? '{}';
|
|
159
|
+
const raw = from ? await readFile(from, 'utf8') : (positional[1] ?? '{}');
|
|
149
160
|
let input;
|
|
150
161
|
try {
|
|
151
162
|
input = JSON.parse(raw);
|
|
152
163
|
} catch (e) {
|
|
153
|
-
throw new UsageError(
|
|
164
|
+
throw new UsageError(
|
|
165
|
+
`The arguments ${from ? `in ${from} ` : ''}are not JSON (${e.message}). Give them as one word, as in: xsolana tool xsolana_check '{"file":"xsolana.json"}'.`,
|
|
166
|
+
{ cause: e },
|
|
167
|
+
);
|
|
154
168
|
}
|
|
155
169
|
await tool(positional[0], input);
|
|
156
170
|
break;
|
|
@@ -176,7 +190,8 @@ async function main(argv) {
|
|
|
176
190
|
/** One line for a failure: what went wrong, without a stack (a missing file names the file). */
|
|
177
191
|
function oneLine(e) {
|
|
178
192
|
if (e?.code === 'ENOENT' && e.path) return `${e.path} does not exist.`;
|
|
179
|
-
if (e?.code === 'EADDRINUSE')
|
|
193
|
+
if (e?.code === 'EADDRINUSE')
|
|
194
|
+
return `Port ${e.port} is in use: pick another with --port, or leave it out for any free one.`;
|
|
180
195
|
return String(e?.message ?? e);
|
|
181
196
|
}
|
|
182
197
|
|
|
@@ -26,11 +26,6 @@
|
|
|
26
26
|
"currency": "sol",
|
|
27
27
|
"seed": 5,
|
|
28
28
|
"about": "Pays the winning flips. 88% of every flip comes back into it."
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"key": "backers",
|
|
32
|
-
"currency": "sol",
|
|
33
|
-
"about": "The 2% edge, shared by everyone who stakes ARENA."
|
|
34
29
|
}
|
|
35
30
|
],
|
|
36
31
|
"boxes": [
|
|
@@ -48,7 +43,7 @@
|
|
|
48
43
|
"percent": 10
|
|
49
44
|
},
|
|
50
45
|
{
|
|
51
|
-
"to": "
|
|
46
|
+
"to": "farm:backers",
|
|
52
47
|
"percent": 2
|
|
53
48
|
}
|
|
54
49
|
],
|
|
@@ -70,12 +65,9 @@
|
|
|
70
65
|
{
|
|
71
66
|
"key": "weekly",
|
|
72
67
|
"name": "Weekly draw",
|
|
68
|
+
"pot": 0,
|
|
73
69
|
"price": 0.01,
|
|
74
|
-
"places": [
|
|
75
|
-
50,
|
|
76
|
-
30,
|
|
77
|
-
20
|
|
78
|
-
],
|
|
70
|
+
"places": [50, 30, 20],
|
|
79
71
|
"every": "7d",
|
|
80
72
|
"firstDraw": "publish+7d"
|
|
81
73
|
}
|
|
@@ -96,7 +88,7 @@
|
|
|
96
88
|
"key": "backers",
|
|
97
89
|
"name": "Back the house",
|
|
98
90
|
"stakes": "arena",
|
|
99
|
-
"rewards": "
|
|
91
|
+
"rewards": "sol",
|
|
100
92
|
"tiers": [
|
|
101
93
|
{
|
|
102
94
|
"lock": "1d",
|
package/examples/duel-arena.json
CHANGED
|
@@ -46,13 +46,6 @@
|
|
|
46
46
|
"name": "Elemental Badge"
|
|
47
47
|
}
|
|
48
48
|
],
|
|
49
|
-
"pools": [
|
|
50
|
-
{
|
|
51
|
-
"key": "spark-rewards",
|
|
52
|
-
"currency": "spark",
|
|
53
|
-
"about": "Names the reward token: both farms mint SPARK at their rates, so nothing waits here."
|
|
54
|
-
}
|
|
55
|
-
],
|
|
56
49
|
"recipes": [
|
|
57
50
|
{
|
|
58
51
|
"key": "bind",
|
|
@@ -232,7 +225,7 @@
|
|
|
232
225
|
"key": "altar",
|
|
233
226
|
"name": "The altar",
|
|
234
227
|
"stakes": "collectibles",
|
|
235
|
-
"rewards": "spark
|
|
228
|
+
"rewards": "spark",
|
|
236
229
|
"rate": {
|
|
237
230
|
"perDay": 10,
|
|
238
231
|
"minted": true
|
|
@@ -249,7 +242,7 @@
|
|
|
249
242
|
"name": "The sanctum",
|
|
250
243
|
"stakes": "collectibles",
|
|
251
244
|
"item": "badge",
|
|
252
|
-
"rewards": "spark
|
|
245
|
+
"rewards": "spark",
|
|
253
246
|
"rate": {
|
|
254
247
|
"perDay": 100,
|
|
255
248
|
"minted": true
|
|
@@ -38,13 +38,6 @@
|
|
|
38
38
|
"name": "Rare Relic"
|
|
39
39
|
}
|
|
40
40
|
],
|
|
41
|
-
"pools": [
|
|
42
|
-
{
|
|
43
|
-
"key": "dust-rewards",
|
|
44
|
-
"currency": "dust",
|
|
45
|
-
"about": "Names the guild's reward token: the guild mints DUST at its rate, so nothing waits here."
|
|
46
|
-
}
|
|
47
|
-
],
|
|
48
41
|
"boxes": [
|
|
49
42
|
{
|
|
50
43
|
"key": "chest",
|
|
@@ -110,7 +103,7 @@
|
|
|
110
103
|
"name": "The guild",
|
|
111
104
|
"stakes": "collectibles",
|
|
112
105
|
"item": "hero",
|
|
113
|
-
"rewards": "dust
|
|
106
|
+
"rewards": "dust",
|
|
114
107
|
"rate": {
|
|
115
108
|
"perDay": 10,
|
|
116
109
|
"minted": true
|
|
@@ -20,13 +20,6 @@
|
|
|
20
20
|
"collection": {
|
|
21
21
|
"name": "Guild Missions"
|
|
22
22
|
},
|
|
23
|
-
"pools": [
|
|
24
|
-
{
|
|
25
|
-
"key": "gem-rewards",
|
|
26
|
-
"currency": "gem",
|
|
27
|
-
"about": "Names the guild's token: every farm here mints it, so nothing waits in this pool."
|
|
28
|
-
}
|
|
29
|
-
],
|
|
30
23
|
"traits": [
|
|
31
24
|
{
|
|
32
25
|
"collection": "Cvb5ZbtpUMk8yNG9GzC5nQ7FkB2xPVUZzZaxXqgNbvxR",
|
|
@@ -43,7 +36,7 @@
|
|
|
43
36
|
"gate": {
|
|
44
37
|
"collection": "Cvb5ZbtpUMk8yNG9GzC5nQ7FkB2xPVUZzZaxXqgNbvxR"
|
|
45
38
|
},
|
|
46
|
-
"rewards": "gem
|
|
39
|
+
"rewards": "gem",
|
|
47
40
|
"rate": {
|
|
48
41
|
"perDay": 5,
|
|
49
42
|
"minted": true
|
|
@@ -77,7 +70,7 @@
|
|
|
77
70
|
"attribute": "level",
|
|
78
71
|
"atLeast": 3
|
|
79
72
|
},
|
|
80
|
-
"rewards": "gem
|
|
73
|
+
"rewards": "gem",
|
|
81
74
|
"rate": {
|
|
82
75
|
"perDay": 0,
|
|
83
76
|
"minted": true
|
|
@@ -110,7 +103,7 @@
|
|
|
110
103
|
"atLeast": 6
|
|
111
104
|
}
|
|
112
105
|
],
|
|
113
|
-
"rewards": "gem
|
|
106
|
+
"rewards": "gem",
|
|
114
107
|
"rate": {
|
|
115
108
|
"perDay": 0,
|
|
116
109
|
"minted": true
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"version": 2,
|
|
3
3
|
"network": "devnet",
|
|
4
4
|
"name": "Halving Seasons",
|
|
5
|
-
"prompt": "Rewards mint into the play pool on a schedule that halves every 30 days; a soulbound season pass claims 10 PLAY a day from it; 10% of the play pool drips into the vault
|
|
5
|
+
"prompt": "Rewards mint into the play pool on a schedule that halves every 30 days; a soulbound season pass claims 10 PLAY a day from it; 10% of the play pool drips into the vault every day, shared by everyone who stakes PLAY.",
|
|
6
6
|
"currency": "sol",
|
|
7
7
|
"tokens": [
|
|
8
8
|
{
|
|
@@ -36,11 +36,6 @@
|
|
|
36
36
|
"key": "season",
|
|
37
37
|
"currency": "play",
|
|
38
38
|
"about": "What the season mints, before it is claimed."
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"key": "interest",
|
|
42
|
-
"currency": "play",
|
|
43
|
-
"about": "The vault's interest."
|
|
44
39
|
}
|
|
45
40
|
],
|
|
46
41
|
"schedules": [
|
|
@@ -57,9 +52,9 @@
|
|
|
57
52
|
{
|
|
58
53
|
"key": "drip",
|
|
59
54
|
"name": "Interest drip",
|
|
60
|
-
"does": "
|
|
55
|
+
"does": "pay",
|
|
61
56
|
"from": "season",
|
|
62
|
-
"to": "
|
|
57
|
+
"to": "farm:vault",
|
|
63
58
|
"percent": 10,
|
|
64
59
|
"every": "1d"
|
|
65
60
|
}
|
|
@@ -100,7 +95,7 @@
|
|
|
100
95
|
"key": "vault",
|
|
101
96
|
"name": "The vault",
|
|
102
97
|
"stakes": "play",
|
|
103
|
-
"rewards": "
|
|
98
|
+
"rewards": "play",
|
|
104
99
|
"tiers": [
|
|
105
100
|
{
|
|
106
101
|
"lock": "1d",
|
|
@@ -13,9 +13,6 @@
|
|
|
13
13
|
{ "key": "hero", "name": "Hero", "price": 0.05 },
|
|
14
14
|
{ "key": "relic", "name": "Relic" }
|
|
15
15
|
],
|
|
16
|
-
"pools": [
|
|
17
|
-
{ "key": "gem-rewards", "currency": "gem", "about": "Names the expedition's token: it pays nothing, its result is a roll." }
|
|
18
|
-
],
|
|
19
16
|
"boxes": [
|
|
20
17
|
{
|
|
21
18
|
"key": "enchant",
|
|
@@ -29,7 +26,13 @@
|
|
|
29
26
|
{ "gives": "nothing", "chance": 25, "shifts": [{ "attribute": "level", "by": -1 }] },
|
|
30
27
|
{ "gives": "nothing", "chance": 5, "then": "burn" }
|
|
31
28
|
],
|
|
32
|
-
"odds": [
|
|
29
|
+
"odds": [
|
|
30
|
+
{
|
|
31
|
+
"outcome": 0,
|
|
32
|
+
"when": { "item": "hero", "attribute": "level", "atLeast": 0 },
|
|
33
|
+
"add": { "perPointPercent": 10, "upTo": 10 }
|
|
34
|
+
}
|
|
35
|
+
]
|
|
33
36
|
},
|
|
34
37
|
{
|
|
35
38
|
"key": "expedition-result",
|
|
@@ -42,7 +45,13 @@
|
|
|
42
45
|
{ "gives": "nothing", "chance": 30, "shifts": [{ "attribute": "affection", "by": -2 }] },
|
|
43
46
|
{ "gives": "nothing", "chance": 10, "then": "treasury" }
|
|
44
47
|
],
|
|
45
|
-
"odds": [
|
|
48
|
+
"odds": [
|
|
49
|
+
{
|
|
50
|
+
"outcome": 0,
|
|
51
|
+
"when": { "item": "hero", "attribute": "level", "atLeast": 0 },
|
|
52
|
+
"add": { "perPointPercent": 20, "upTo": 10 }
|
|
53
|
+
}
|
|
54
|
+
]
|
|
46
55
|
},
|
|
47
56
|
{
|
|
48
57
|
"key": "forge",
|
|
@@ -84,7 +93,7 @@
|
|
|
84
93
|
"stakes": "collectibles",
|
|
85
94
|
"item": "hero",
|
|
86
95
|
"custody": "freeze",
|
|
87
|
-
"rewards": "gem
|
|
96
|
+
"rewards": "gem",
|
|
88
97
|
"rate": { "perDay": 0, "minted": true },
|
|
89
98
|
"tiers": [{ "lock": "1d", "multiplier": 1, "roll": "expedition-result" }]
|
|
90
99
|
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 2,
|
|
3
|
+
"network": "devnet",
|
|
4
|
+
"name": "Holder Den",
|
|
5
|
+
"prompt": "Holders of our NFT collection stake them without the NFT leaving their wallet and earn 10 DUST a day each. Locking for 30 days doubles it, 90 days triples it. NFTs with a gold background earn 25% more. Every day staked adds a point to the NFT, which the game shows as its rank.",
|
|
6
|
+
"currency": "dust",
|
|
7
|
+
"tokens": [{ "key": "dust", "source": "project", "name": "Den Dust", "symbol": "DUST", "decimals": 6 }],
|
|
8
|
+
"collection": false,
|
|
9
|
+
"farms": [
|
|
10
|
+
{
|
|
11
|
+
"key": "den",
|
|
12
|
+
"name": "The Den",
|
|
13
|
+
"stakes": "collectibles",
|
|
14
|
+
"custody": "freeze",
|
|
15
|
+
"gate": { "collection": "5N3f6KXYGvtX4zCVD3DeQoEGbzahifQiFtkxfTfEyiRz" },
|
|
16
|
+
"rewards": "dust",
|
|
17
|
+
"rate": { "perDay": 10, "minted": true },
|
|
18
|
+
"tiers": [
|
|
19
|
+
{ "lock": "0d", "multiplier": 1 },
|
|
20
|
+
{ "lock": "30d", "multiplier": 2 },
|
|
21
|
+
{ "lock": "90d", "multiplier": 3 }
|
|
22
|
+
],
|
|
23
|
+
"boosts": [
|
|
24
|
+
{
|
|
25
|
+
"when": {
|
|
26
|
+
"collection": "5N3f6KXYGvtX4zCVD3DeQoEGbzahifQiFtkxfTfEyiRz",
|
|
27
|
+
"attribute": "Background",
|
|
28
|
+
"equals": "Gold"
|
|
29
|
+
},
|
|
30
|
+
"add": { "addPercent": 25 }
|
|
31
|
+
}
|
|
32
|
+
],
|
|
33
|
+
"maxBoostPercent": 25,
|
|
34
|
+
"growth": { "attribute": "points", "perDay": 1 }
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"scenario": { "days": 90, "perDay": { "farm:den": 30 }, "staked": { "den": 1500 } }
|
|
38
|
+
}
|