pyre-world-kit 3.0.2 → 3.0.4
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/dist/index.d.ts +6 -7
- package/dist/index.js +2 -0
- package/dist/providers/action.provider.d.ts +1 -1
- package/dist/providers/mapper.provider.d.ts +0 -5
- package/dist/providers/mapper.provider.js +0 -5
- package/dist/providers/registry.provider.d.ts +0 -7
- package/dist/providers/registry.provider.js +0 -14
- package/dist/providers/state.provider.d.ts +0 -9
- package/dist/providers/state.provider.js +1 -30
- package/package.json +1 -1
- package/readme.md +3 -0
- package/src/index.ts +11 -6
- package/src/providers/action.provider.ts +11 -10
- package/src/providers/intel.provider.ts +3 -3
- package/src/providers/mapper.provider.ts +0 -6
- package/src/providers/registry.provider.ts +2 -24
- package/src/providers/state.provider.ts +11 -46
- package/tests/test_e2e.ts +22 -0
package/dist/index.d.ts
CHANGED
|
@@ -6,16 +6,15 @@
|
|
|
6
6
|
* so agents think in factions, not tokens.
|
|
7
7
|
*/
|
|
8
8
|
import { Connection } from '@solana/web3.js';
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
9
|
+
import { Action } from './types/action.types';
|
|
10
|
+
import { Intel } from './types/intel.types';
|
|
11
|
+
import { Registry } from './types/registry.types';
|
|
11
12
|
import { StateProvider } from './providers/state.provider';
|
|
12
|
-
import type { Action } from './types/action.types';
|
|
13
|
-
import type { Intel } from './types/intel.types';
|
|
14
13
|
import type { CheckpointConfig } from './types/state.types';
|
|
15
|
-
import { Registry } from './types/registry.types';
|
|
16
14
|
export declare class PyreKit {
|
|
17
|
-
readonly
|
|
18
|
-
readonly
|
|
15
|
+
readonly connection: Connection;
|
|
16
|
+
readonly actions: Action;
|
|
17
|
+
readonly intel: Intel;
|
|
19
18
|
readonly registry: Registry;
|
|
20
19
|
readonly state: StateProvider;
|
|
21
20
|
constructor(connection: Connection, publicKey: string);
|
package/dist/index.js
CHANGED
|
@@ -14,11 +14,13 @@ const registry_provider_1 = require("./providers/registry.provider");
|
|
|
14
14
|
const state_provider_1 = require("./providers/state.provider");
|
|
15
15
|
// ─── Top-level Kit ────────────────────────────────────────────────
|
|
16
16
|
class PyreKit {
|
|
17
|
+
connection;
|
|
17
18
|
actions;
|
|
18
19
|
intel;
|
|
19
20
|
registry;
|
|
20
21
|
state;
|
|
21
22
|
constructor(connection, publicKey) {
|
|
23
|
+
this.connection = connection;
|
|
22
24
|
this.registry = new registry_provider_1.RegistryProvider(connection);
|
|
23
25
|
this.state = new state_provider_1.StateProvider(connection, this.registry, publicKey);
|
|
24
26
|
this.actions = new action_provider_1.ActionProvider(connection, this.registry);
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Connection } from '@solana/web3.js';
|
|
2
|
-
import { Action } from '../types/action.types';
|
|
3
2
|
import { BuyQuoteResult, SellQuoteResult, TransactionResult } from 'torchsdk';
|
|
4
3
|
import { AgentLink, AllWarLoansResult, AscendParams, ClaimSpoilsParams, CommsResult, CoupParams, CreateStrongholdParams, DefectParams, ExileAgentParams, FactionDetail, FactionListParams, FactionListResult, FactionStatus, FudFactionParams, FundStrongholdParams, JoinFactionParams, JoinFactionResult, LaunchFactionParams, LaunchFactionResult, MembersResult, MessageFactionParams, RallyParams, RazeParams, RecruitAgentParams, RepayWarLoanParams, RequestWarLoanParams, SiegeParams, Stronghold, TitheParams, WarChest, WarLoan, WarLoanQuote, WithdrawAssetsParams, WithdrawFromStrongholdParams } from '../types';
|
|
4
|
+
import { Action } from '../types/action.types';
|
|
5
5
|
import { Registry } from '../types/registry.types';
|
|
6
6
|
export declare class ActionProvider implements Action {
|
|
7
7
|
private connection;
|
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre Kit Mappers
|
|
3
|
-
*
|
|
4
|
-
* Internal mapping functions between Torch SDK types and Pyre game types.
|
|
5
|
-
*/
|
|
6
1
|
import type { AllLoanPositionsResult, BuyTransactionResult, CreateTokenResult, Holder, HoldersResult, LendingInfo, LoanPositionInfo, LoanPositionWithKey, MessagesResult, TokenDetail, TokenListResult, TokenMessage, TokenStatus, TokenSummary, VaultInfo, VaultWalletLinkInfo } from 'torchsdk';
|
|
7
2
|
import type { FactionStatus, FactionStatusFilter, Strategy } from '../types';
|
|
8
3
|
import { Mapper } from '../types/mapper.types';
|
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pyre Kit Mappers
|
|
4
|
-
*
|
|
5
|
-
* Internal mapping functions between Torch SDK types and Pyre game types.
|
|
6
|
-
*/
|
|
7
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
3
|
exports.MapperProvider = void 0;
|
|
9
4
|
const mapper_types_1 = require("../types/mapper.types");
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre World Agent Registry Provider
|
|
3
|
-
*
|
|
4
|
-
* On-chain agent identity and state persistence.
|
|
5
|
-
* Agents checkpoint their action distributions and personality summaries
|
|
6
|
-
* so any machine with the wallet key can reconstruct the agent.
|
|
7
|
-
*/
|
|
8
1
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
9
2
|
import type { TransactionResult } from 'torchsdk';
|
|
10
3
|
import type { RegistryProfile, RegistryWalletLink, RegisterAgentParams, CheckpointParams, LinkAgentWalletParams, UnlinkAgentWalletParams, TransferAgentAuthorityParams } from '../types';
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pyre World Agent Registry Provider
|
|
4
|
-
*
|
|
5
|
-
* On-chain agent identity and state persistence.
|
|
6
|
-
* Agents checkpoint their action distributions and personality summaries
|
|
7
|
-
* so any machine with the wallet key can reconstruct the agent.
|
|
8
|
-
*/
|
|
9
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
10
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
11
4
|
};
|
|
@@ -16,19 +9,15 @@ exports.getAgentWalletLinkPda = getAgentWalletLinkPda;
|
|
|
16
9
|
const web3_js_1 = require("@solana/web3.js");
|
|
17
10
|
const anchor_1 = require("@coral-xyz/anchor");
|
|
18
11
|
const pyre_world_json_1 = __importDefault(require("../pyre_world.json"));
|
|
19
|
-
// ─── Program ID ─────────────────────────────────────────────────────
|
|
20
12
|
exports.REGISTRY_PROGRAM_ID = new web3_js_1.PublicKey(pyre_world_json_1.default.address);
|
|
21
|
-
// ─── PDA Seeds ──────────────────────────────────────────────────────
|
|
22
13
|
const AGENT_SEED = 'pyre_agent';
|
|
23
14
|
const AGENT_WALLET_SEED = 'pyre_agent_wallet';
|
|
24
|
-
// ─── PDA Helpers ────────────────────────────────────────────────────
|
|
25
15
|
function getAgentProfilePda(creator) {
|
|
26
16
|
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(AGENT_SEED), creator.toBuffer()], exports.REGISTRY_PROGRAM_ID);
|
|
27
17
|
}
|
|
28
18
|
function getAgentWalletLinkPda(wallet) {
|
|
29
19
|
return web3_js_1.PublicKey.findProgramAddressSync([Buffer.from(AGENT_WALLET_SEED), wallet.toBuffer()], exports.REGISTRY_PROGRAM_ID);
|
|
30
20
|
}
|
|
31
|
-
// ─── Anchor Program Helper ──────────────────────────────────────────
|
|
32
21
|
function makeDummyProvider(connection, payer) {
|
|
33
22
|
const dummyWallet = {
|
|
34
23
|
publicKey: payer,
|
|
@@ -42,7 +31,6 @@ async function finalizeTransaction(connection, tx, feePayer) {
|
|
|
42
31
|
tx.recentBlockhash = blockhash;
|
|
43
32
|
tx.feePayer = feePayer;
|
|
44
33
|
}
|
|
45
|
-
// ─── Provider ───────────────────────────────────────────────────────
|
|
46
34
|
class RegistryProvider {
|
|
47
35
|
connection;
|
|
48
36
|
constructor(connection) {
|
|
@@ -52,7 +40,6 @@ class RegistryProvider {
|
|
|
52
40
|
const provider = makeDummyProvider(this.connection, payer);
|
|
53
41
|
return new anchor_1.Program(pyre_world_json_1.default, provider);
|
|
54
42
|
}
|
|
55
|
-
// ─── Read Operations ──────────────────────────────────────────────
|
|
56
43
|
async getProfile(creator) {
|
|
57
44
|
const creatorPk = new web3_js_1.PublicKey(creator);
|
|
58
45
|
const [profilePda] = getAgentProfilePda(creatorPk);
|
|
@@ -108,7 +95,6 @@ class RegistryProvider {
|
|
|
108
95
|
return undefined;
|
|
109
96
|
}
|
|
110
97
|
}
|
|
111
|
-
// ─── Transaction Builders ─────────────────────────────────────────
|
|
112
98
|
async register(params) {
|
|
113
99
|
const creator = new web3_js_1.PublicKey(params.creator);
|
|
114
100
|
const [profile] = getAgentProfilePda(creator);
|
|
@@ -1,10 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre Kit State Provider
|
|
3
|
-
*
|
|
4
|
-
* Objective game state tracking for an agent.
|
|
5
|
-
* Owns holdings, action counts, vault resolution, tick counter.
|
|
6
|
-
* Injected into ActionProvider so every action automatically updates state.
|
|
7
|
-
*/
|
|
8
1
|
import { Connection } from '@solana/web3.js';
|
|
9
2
|
import type { State, AgentGameState, SerializedGameState, TrackedAction, CheckpointConfig } from '../types/state.types';
|
|
10
3
|
import { Registry } from '../types/registry.types';
|
|
@@ -24,9 +17,7 @@ export declare class StateProvider implements State {
|
|
|
24
17
|
setCheckpointConfig(config: CheckpointConfig): void;
|
|
25
18
|
init(): Promise<AgentGameState>;
|
|
26
19
|
record(action: TrackedAction, mint?: string, description?: string): Promise<void>;
|
|
27
|
-
/** Update sentiment score for a faction based on action type */
|
|
28
20
|
private updateSentiment;
|
|
29
|
-
/** Callback set by PyreKit to handle checkpoint triggers */
|
|
30
21
|
onCheckpointDue: (() => void) | null;
|
|
31
22
|
refreshHoldings(): Promise<void>;
|
|
32
23
|
getSentiment(mint: string): number;
|
|
@@ -1,11 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Pyre Kit State Provider
|
|
4
|
-
*
|
|
5
|
-
* Objective game state tracking for an agent.
|
|
6
|
-
* Owns holdings, action counts, vault resolution, tick counter.
|
|
7
|
-
* Injected into ActionProvider so every action automatically updates state.
|
|
8
|
-
*/
|
|
9
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
10
3
|
if (k2 === undefined) k2 = k;
|
|
11
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -72,7 +65,6 @@ class StateProvider {
|
|
|
72
65
|
this.registry = registry;
|
|
73
66
|
this.publicKey = publicKey;
|
|
74
67
|
}
|
|
75
|
-
// ─── Readonly accessors ─────────────────────────────────────────
|
|
76
68
|
get state() {
|
|
77
69
|
return this._state;
|
|
78
70
|
}
|
|
@@ -85,12 +77,10 @@ class StateProvider {
|
|
|
85
77
|
get tick() {
|
|
86
78
|
return this._state?.tick ?? 0;
|
|
87
79
|
}
|
|
88
|
-
// ─── Configuration ──────────────────────────────────────────────
|
|
89
80
|
/** Configure auto-checkpoint behavior */
|
|
90
81
|
setCheckpointConfig(config) {
|
|
91
82
|
this.checkpointConfig = config;
|
|
92
83
|
}
|
|
93
|
-
// ─── Initialization ─────────────────────────────────────────────
|
|
94
84
|
async init() {
|
|
95
85
|
if (this._state?.initialized)
|
|
96
86
|
return this._state;
|
|
@@ -113,7 +103,7 @@ class StateProvider {
|
|
|
113
103
|
initialized: false,
|
|
114
104
|
};
|
|
115
105
|
this._state = state;
|
|
116
|
-
//
|
|
106
|
+
// resolve vault link
|
|
117
107
|
const { getVaultForWallet } = await Promise.resolve().then(() => __importStar(require('torchsdk')));
|
|
118
108
|
try {
|
|
119
109
|
const vault = await getVaultForWallet(this.connection, this.publicKey);
|
|
@@ -134,14 +124,12 @@ class StateProvider {
|
|
|
134
124
|
}
|
|
135
125
|
}
|
|
136
126
|
catch { }
|
|
137
|
-
// Load registry profile — personality, action counts, SOL totals
|
|
138
127
|
try {
|
|
139
128
|
const profile = await this.registry.getProfile(this.publicKey);
|
|
140
129
|
if (profile) {
|
|
141
130
|
state.personalitySummary = profile.personality_summary || null;
|
|
142
131
|
state.totalSolSpent = profile.total_sol_spent;
|
|
143
132
|
state.totalSolReceived = profile.total_sol_received;
|
|
144
|
-
// Seed action counts from on-chain checkpoint
|
|
145
133
|
state.actionCounts.join = Math.max(state.actionCounts.join, profile.joins);
|
|
146
134
|
state.actionCounts.defect = Math.max(state.actionCounts.defect, profile.defects);
|
|
147
135
|
state.actionCounts.rally = Math.max(state.actionCounts.rally, profile.rallies);
|
|
@@ -156,48 +144,39 @@ class StateProvider {
|
|
|
156
144
|
state.actionCounts.ascend = Math.max(state.actionCounts.ascend, profile.ascends);
|
|
157
145
|
state.actionCounts.raze = Math.max(state.actionCounts.raze, profile.razes);
|
|
158
146
|
state.actionCounts.tithe = Math.max(state.actionCounts.tithe, profile.tithes);
|
|
159
|
-
// Set tick to total actions from checkpoint
|
|
160
147
|
const totalFromCheckpoint = Object.values(state.actionCounts).reduce((a, b) => a + b, 0);
|
|
161
148
|
state.tick = totalFromCheckpoint;
|
|
162
149
|
}
|
|
163
150
|
}
|
|
164
151
|
catch { }
|
|
165
|
-
// Load holdings (wallet + vault token accounts)
|
|
166
152
|
await this.refreshHoldings();
|
|
167
153
|
state.initialized = true;
|
|
168
154
|
return state;
|
|
169
155
|
}
|
|
170
|
-
// ─── Action Recording ───────────────────────────────────────────
|
|
171
156
|
async record(action, mint, description) {
|
|
172
157
|
if (!this._state)
|
|
173
158
|
throw new Error('State not initialized — call init() first');
|
|
174
159
|
this._state.tick++;
|
|
175
160
|
this._state.actionCounts[action]++;
|
|
176
161
|
this.ticksSinceCheckpoint++;
|
|
177
|
-
// Track founded factions
|
|
178
162
|
if (action === 'launch' && mint) {
|
|
179
163
|
this._state.founded.push(mint);
|
|
180
164
|
}
|
|
181
|
-
// Update sentiment for the target faction
|
|
182
165
|
if (mint) {
|
|
183
166
|
this.updateSentiment(action, mint);
|
|
184
167
|
}
|
|
185
|
-
// Track recent history for LLM memory block
|
|
186
168
|
if (description) {
|
|
187
169
|
this._state.recentHistory.push(description);
|
|
188
170
|
if (this._state.recentHistory.length > 20) {
|
|
189
171
|
this._state.recentHistory = this._state.recentHistory.slice(-20);
|
|
190
172
|
}
|
|
191
173
|
}
|
|
192
|
-
// Refresh holdings after any trade action
|
|
193
174
|
await this.refreshHoldings();
|
|
194
|
-
// Auto-checkpoint check
|
|
195
175
|
if (this.checkpointConfig && this.ticksSinceCheckpoint >= this.checkpointConfig.interval) {
|
|
196
176
|
this.ticksSinceCheckpoint = 0;
|
|
197
177
|
this.onCheckpointDue?.();
|
|
198
178
|
}
|
|
199
179
|
}
|
|
200
|
-
/** Update sentiment score for a faction based on action type */
|
|
201
180
|
updateSentiment(action, mint) {
|
|
202
181
|
if (!this._state)
|
|
203
182
|
return;
|
|
@@ -218,15 +197,12 @@ class StateProvider {
|
|
|
218
197
|
this._state.sentiment.set(mint, Math.max(-10, Math.min(10, current + delta)));
|
|
219
198
|
}
|
|
220
199
|
}
|
|
221
|
-
/** Callback set by PyreKit to handle checkpoint triggers */
|
|
222
200
|
onCheckpointDue = null;
|
|
223
|
-
// ─── Holdings ───────────────────────────────────────────────────
|
|
224
201
|
async refreshHoldings() {
|
|
225
202
|
if (!this._state)
|
|
226
203
|
return;
|
|
227
204
|
const { TOKEN_2022_PROGRAM_ID } = await Promise.resolve().then(() => __importStar(require('@solana/spl-token')));
|
|
228
205
|
const walletPk = new web3_js_1.PublicKey(this.publicKey);
|
|
229
|
-
// Scan wallet token accounts
|
|
230
206
|
let walletValues = [];
|
|
231
207
|
try {
|
|
232
208
|
const walletAccounts = await this.connection.getParsedTokenAccountsByOwner(walletPk, {
|
|
@@ -235,7 +211,6 @@ class StateProvider {
|
|
|
235
211
|
walletValues = walletAccounts.value;
|
|
236
212
|
}
|
|
237
213
|
catch { }
|
|
238
|
-
// Scan vault token accounts
|
|
239
214
|
let vaultValues = [];
|
|
240
215
|
if (this._state.stronghold) {
|
|
241
216
|
try {
|
|
@@ -247,7 +222,6 @@ class StateProvider {
|
|
|
247
222
|
}
|
|
248
223
|
catch { }
|
|
249
224
|
}
|
|
250
|
-
// Merge balances
|
|
251
225
|
const newHoldings = new Map();
|
|
252
226
|
for (const a of [...walletValues, ...vaultValues]) {
|
|
253
227
|
const mint = a.account.data.parsed.info.mint;
|
|
@@ -256,7 +230,6 @@ class StateProvider {
|
|
|
256
230
|
newHoldings.set(mint, (newHoldings.get(mint) ?? 0) + balance);
|
|
257
231
|
}
|
|
258
232
|
}
|
|
259
|
-
// Update — clear stale, set fresh
|
|
260
233
|
this._state.holdings.clear();
|
|
261
234
|
for (const [mint, balance] of newHoldings) {
|
|
262
235
|
this._state.holdings.set(mint, balance);
|
|
@@ -274,7 +247,6 @@ class StateProvider {
|
|
|
274
247
|
getBalance(mint) {
|
|
275
248
|
return this._state?.holdings.get(mint) ?? 0;
|
|
276
249
|
}
|
|
277
|
-
// ─── Dedup Guards ───────────────────────────────────────────────
|
|
278
250
|
hasVoted(mint) {
|
|
279
251
|
return this._state?.voted.has(mint) ?? false;
|
|
280
252
|
}
|
|
@@ -287,7 +259,6 @@ class StateProvider {
|
|
|
287
259
|
markRallied(mint) {
|
|
288
260
|
this._state?.rallied.add(mint);
|
|
289
261
|
}
|
|
290
|
-
// ─── Serialization ──────────────────────────────────────────────
|
|
291
262
|
serialize() {
|
|
292
263
|
if (!this._state) {
|
|
293
264
|
return {
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -192,6 +192,7 @@ kit.actions.getMembers(mint) // top holders
|
|
|
192
192
|
kit.actions.getComms(mint, opts) // trade-bundled messages
|
|
193
193
|
kit.actions.getJoinQuote(mint, sol) // buy price quote
|
|
194
194
|
kit.actions.getDefectQuote(mint, n) // sell price quote
|
|
195
|
+
kit.actions.scout(address) // look up agent's on-chain identity (read-only)
|
|
195
196
|
```
|
|
196
197
|
|
|
197
198
|
### StateProvider
|
|
@@ -260,6 +261,8 @@ score = (market_cap_sol * 0.4) + (members * 0.2) + (war_chest_sol * 0.2)
|
|
|
260
261
|
|
|
261
262
|
## Tests
|
|
262
263
|
|
|
264
|
+
46/46 passing tests.
|
|
265
|
+
|
|
263
266
|
Requires [surfpool](https://github.com/txtx/surfpool) running a local Solana fork:
|
|
264
267
|
|
|
265
268
|
```bash
|
package/src/index.ts
CHANGED
|
@@ -7,24 +7,29 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
import { Connection } from '@solana/web3.js'
|
|
10
|
+
|
|
11
|
+
import { Action } from './types/action.types'
|
|
12
|
+
import { Intel } from './types/intel.types'
|
|
13
|
+
import { Registry } from './types/registry.types'
|
|
14
|
+
|
|
10
15
|
import { ActionProvider } from './providers/action.provider'
|
|
11
16
|
import { IntelProvider } from './providers/intel.provider'
|
|
12
17
|
import { RegistryProvider } from './providers/registry.provider'
|
|
13
18
|
import { StateProvider } from './providers/state.provider'
|
|
14
|
-
|
|
15
|
-
import type {
|
|
16
|
-
import type { State, CheckpointConfig, TrackedAction } from './types/state.types'
|
|
17
|
-
import { Registry } from './types/registry.types'
|
|
19
|
+
|
|
20
|
+
import type { CheckpointConfig, TrackedAction } from './types/state.types'
|
|
18
21
|
|
|
19
22
|
// ─── Top-level Kit ────────────────────────────────────────────────
|
|
20
23
|
|
|
21
24
|
export class PyreKit {
|
|
22
|
-
readonly
|
|
23
|
-
readonly
|
|
25
|
+
readonly connection: Connection
|
|
26
|
+
readonly actions: Action
|
|
27
|
+
readonly intel: Intel
|
|
24
28
|
readonly registry: Registry
|
|
25
29
|
readonly state: StateProvider
|
|
26
30
|
|
|
27
31
|
constructor(connection: Connection, publicKey: string) {
|
|
32
|
+
this.connection = connection
|
|
28
33
|
this.registry = new RegistryProvider(connection)
|
|
29
34
|
this.state = new StateProvider(connection, this.registry, publicKey)
|
|
30
35
|
this.actions = new ActionProvider(connection, this.registry)
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Connection, GetProgramAccountsFilter, PublicKey } from '@solana/web3.js'
|
|
2
|
-
import { Action } from '../types/action.types'
|
|
3
2
|
import {
|
|
4
3
|
buildBorrowTransaction,
|
|
5
4
|
buildBuyTransaction,
|
|
@@ -37,6 +36,16 @@ import {
|
|
|
37
36
|
SellQuoteResult,
|
|
38
37
|
TransactionResult,
|
|
39
38
|
} from 'torchsdk'
|
|
39
|
+
|
|
40
|
+
import { MapperProvider } from './mapper.provider'
|
|
41
|
+
import {
|
|
42
|
+
buildCreateFactionTransaction,
|
|
43
|
+
getBondingCurvePda,
|
|
44
|
+
getTokenTreasuryPda,
|
|
45
|
+
getTreasuryLockPda,
|
|
46
|
+
isPyreMint,
|
|
47
|
+
} from '../vanity'
|
|
48
|
+
import { isBlacklistedMint } from '../util'
|
|
40
49
|
import {
|
|
41
50
|
AgentLink,
|
|
42
51
|
AllWarLoansResult,
|
|
@@ -74,15 +83,7 @@ import {
|
|
|
74
83
|
WithdrawAssetsParams,
|
|
75
84
|
WithdrawFromStrongholdParams,
|
|
76
85
|
} from '../types'
|
|
77
|
-
import {
|
|
78
|
-
import {
|
|
79
|
-
buildCreateFactionTransaction,
|
|
80
|
-
getBondingCurvePda,
|
|
81
|
-
getTokenTreasuryPda,
|
|
82
|
-
getTreasuryLockPda,
|
|
83
|
-
isPyreMint,
|
|
84
|
-
} from '../vanity'
|
|
85
|
-
import { isBlacklistedMint } from '../util'
|
|
86
|
+
import { Action } from '../types/action.types'
|
|
86
87
|
import { Registry } from '../types/registry.types'
|
|
87
88
|
|
|
88
89
|
export class ActionProvider implements Action {
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { Connection, PublicKey } from '@solana/web3.js'
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
import { getBondingCurvePda, getTokenTreasuryPda, getTreasuryLockPda, isPyreMint } from '../vanity'
|
|
4
|
+
import { isBlacklistedMint } from '../util'
|
|
3
5
|
import {
|
|
4
6
|
AgentFactionPosition,
|
|
5
7
|
AgentProfile,
|
|
@@ -13,8 +15,6 @@ import {
|
|
|
13
15
|
RivalFaction,
|
|
14
16
|
} from '../types'
|
|
15
17
|
import { Intel } from '../types/intel.types'
|
|
16
|
-
import { getBondingCurvePda, getTokenTreasuryPda, getTreasuryLockPda, isPyreMint } from '../vanity'
|
|
17
|
-
import { isBlacklistedMint } from '../util'
|
|
18
18
|
import { Action } from '../types/action.types'
|
|
19
19
|
|
|
20
20
|
export class IntelProvider implements Intel {
|
|
@@ -1,14 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre World Agent Registry Provider
|
|
3
|
-
*
|
|
4
|
-
* On-chain agent identity and state persistence.
|
|
5
|
-
* Agents checkpoint their action distributions and personality summaries
|
|
6
|
-
* so any machine with the wallet key can reconstruct the agent.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
1
|
import { Connection, PublicKey, Transaction, SystemProgram } from '@solana/web3.js'
|
|
10
2
|
import { BN, Program, AnchorProvider, type Wallet } from '@coral-xyz/anchor'
|
|
11
3
|
import type { TransactionResult } from 'torchsdk'
|
|
4
|
+
|
|
12
5
|
import type {
|
|
13
6
|
RegistryProfile,
|
|
14
7
|
RegistryWalletLink,
|
|
@@ -18,21 +11,14 @@ import type {
|
|
|
18
11
|
UnlinkAgentWalletParams,
|
|
19
12
|
TransferAgentAuthorityParams,
|
|
20
13
|
} from '../types'
|
|
21
|
-
|
|
22
|
-
import idl from '../pyre_world.json'
|
|
23
14
|
import { Registry } from '../types/registry.types'
|
|
24
15
|
|
|
25
|
-
|
|
16
|
+
import idl from '../pyre_world.json'
|
|
26
17
|
|
|
27
18
|
export const REGISTRY_PROGRAM_ID = new PublicKey(idl.address)
|
|
28
|
-
|
|
29
|
-
// ─── PDA Seeds ──────────────────────────────────────────────────────
|
|
30
|
-
|
|
31
19
|
const AGENT_SEED = 'pyre_agent'
|
|
32
20
|
const AGENT_WALLET_SEED = 'pyre_agent_wallet'
|
|
33
21
|
|
|
34
|
-
// ─── PDA Helpers ────────────────────────────────────────────────────
|
|
35
|
-
|
|
36
22
|
export function getAgentProfilePda(creator: PublicKey): [PublicKey, number] {
|
|
37
23
|
return PublicKey.findProgramAddressSync(
|
|
38
24
|
[Buffer.from(AGENT_SEED), creator.toBuffer()],
|
|
@@ -47,8 +33,6 @@ export function getAgentWalletLinkPda(wallet: PublicKey): [PublicKey, number] {
|
|
|
47
33
|
)
|
|
48
34
|
}
|
|
49
35
|
|
|
50
|
-
// ─── Anchor Program Helper ──────────────────────────────────────────
|
|
51
|
-
|
|
52
36
|
function makeDummyProvider(connection: Connection, payer: PublicKey): AnchorProvider {
|
|
53
37
|
const dummyWallet = {
|
|
54
38
|
publicKey: payer,
|
|
@@ -68,8 +52,6 @@ async function finalizeTransaction(
|
|
|
68
52
|
tx.feePayer = feePayer
|
|
69
53
|
}
|
|
70
54
|
|
|
71
|
-
// ─── Provider ───────────────────────────────────────────────────────
|
|
72
|
-
|
|
73
55
|
export class RegistryProvider implements Registry {
|
|
74
56
|
constructor(private connection: Connection) {}
|
|
75
57
|
|
|
@@ -78,8 +60,6 @@ export class RegistryProvider implements Registry {
|
|
|
78
60
|
return new Program(idl as any, provider)
|
|
79
61
|
}
|
|
80
62
|
|
|
81
|
-
// ─── Read Operations ──────────────────────────────────────────────
|
|
82
|
-
|
|
83
63
|
async getProfile(creator: string): Promise<RegistryProfile | undefined> {
|
|
84
64
|
const creatorPk = new PublicKey(creator)
|
|
85
65
|
const [profilePda] = getAgentProfilePda(creatorPk)
|
|
@@ -137,8 +117,6 @@ export class RegistryProvider implements Registry {
|
|
|
137
117
|
}
|
|
138
118
|
}
|
|
139
119
|
|
|
140
|
-
// ─── Transaction Builders ─────────────────────────────────────────
|
|
141
|
-
|
|
142
120
|
async register(params: RegisterAgentParams): Promise<TransactionResult> {
|
|
143
121
|
const creator = new PublicKey(params.creator)
|
|
144
122
|
const [profile] = getAgentProfilePda(creator)
|
|
@@ -1,12 +1,7 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre Kit State Provider
|
|
3
|
-
*
|
|
4
|
-
* Objective game state tracking for an agent.
|
|
5
|
-
* Owns holdings, action counts, vault resolution, tick counter.
|
|
6
|
-
* Injected into ActionProvider so every action automatically updates state.
|
|
7
|
-
*/
|
|
8
|
-
|
|
9
1
|
import { Connection, PublicKey } from '@solana/web3.js'
|
|
2
|
+
|
|
3
|
+
import { isPyreMint } from '../vanity'
|
|
4
|
+
import { isBlacklistedMint } from '../util'
|
|
10
5
|
import type {
|
|
11
6
|
State,
|
|
12
7
|
AgentGameState,
|
|
@@ -14,9 +9,6 @@ import type {
|
|
|
14
9
|
TrackedAction,
|
|
15
10
|
CheckpointConfig,
|
|
16
11
|
} from '../types/state.types'
|
|
17
|
-
import { RegistryProvider } from './registry.provider'
|
|
18
|
-
import { isPyreMint } from '../vanity'
|
|
19
|
-
import { isBlacklistedMint } from '../util'
|
|
20
12
|
import { Registry } from '../types/registry.types'
|
|
21
13
|
|
|
22
14
|
const EMPTY_COUNTS: Record<TrackedAction, number> = {
|
|
@@ -41,9 +33,11 @@ export class StateProvider implements State {
|
|
|
41
33
|
private checkpointConfig: CheckpointConfig | null = null
|
|
42
34
|
private ticksSinceCheckpoint = 0
|
|
43
35
|
|
|
44
|
-
constructor(
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
constructor(
|
|
37
|
+
private connection: Connection,
|
|
38
|
+
private registry: Registry,
|
|
39
|
+
private publicKey: string,
|
|
40
|
+
) {}
|
|
47
41
|
|
|
48
42
|
get state() {
|
|
49
43
|
return this._state
|
|
@@ -58,15 +52,11 @@ export class StateProvider implements State {
|
|
|
58
52
|
return this._state?.tick ?? 0
|
|
59
53
|
}
|
|
60
54
|
|
|
61
|
-
// ─── Configuration ──────────────────────────────────────────────
|
|
62
|
-
|
|
63
55
|
/** Configure auto-checkpoint behavior */
|
|
64
56
|
setCheckpointConfig(config: CheckpointConfig) {
|
|
65
57
|
this.checkpointConfig = config
|
|
66
58
|
}
|
|
67
59
|
|
|
68
|
-
// ─── Initialization ─────────────────────────────────────────────
|
|
69
|
-
|
|
70
60
|
async init(): Promise<AgentGameState> {
|
|
71
61
|
if (this._state?.initialized) return this._state
|
|
72
62
|
|
|
@@ -91,7 +81,7 @@ export class StateProvider implements State {
|
|
|
91
81
|
|
|
92
82
|
this._state = state
|
|
93
83
|
|
|
94
|
-
//
|
|
84
|
+
// resolve vault link
|
|
95
85
|
const { getVaultForWallet } = await import('torchsdk')
|
|
96
86
|
try {
|
|
97
87
|
const vault = await getVaultForWallet(this.connection, this.publicKey)
|
|
@@ -112,14 +102,13 @@ export class StateProvider implements State {
|
|
|
112
102
|
}
|
|
113
103
|
} catch {}
|
|
114
104
|
|
|
115
|
-
// Load registry profile — personality, action counts, SOL totals
|
|
116
105
|
try {
|
|
117
106
|
const profile = await this.registry.getProfile(this.publicKey)
|
|
118
107
|
if (profile) {
|
|
119
108
|
state.personalitySummary = profile.personality_summary || null
|
|
120
109
|
state.totalSolSpent = profile.total_sol_spent
|
|
121
110
|
state.totalSolReceived = profile.total_sol_received
|
|
122
|
-
|
|
111
|
+
|
|
123
112
|
state.actionCounts.join = Math.max(state.actionCounts.join, profile.joins)
|
|
124
113
|
state.actionCounts.defect = Math.max(state.actionCounts.defect, profile.defects)
|
|
125
114
|
state.actionCounts.rally = Math.max(state.actionCounts.rally, profile.rallies)
|
|
@@ -134,21 +123,17 @@ export class StateProvider implements State {
|
|
|
134
123
|
state.actionCounts.ascend = Math.max(state.actionCounts.ascend, profile.ascends)
|
|
135
124
|
state.actionCounts.raze = Math.max(state.actionCounts.raze, profile.razes)
|
|
136
125
|
state.actionCounts.tithe = Math.max(state.actionCounts.tithe, profile.tithes)
|
|
137
|
-
|
|
126
|
+
|
|
138
127
|
const totalFromCheckpoint = Object.values(state.actionCounts).reduce((a, b) => a + b, 0)
|
|
139
128
|
state.tick = totalFromCheckpoint
|
|
140
129
|
}
|
|
141
130
|
} catch {}
|
|
142
131
|
|
|
143
|
-
// Load holdings (wallet + vault token accounts)
|
|
144
132
|
await this.refreshHoldings()
|
|
145
|
-
|
|
146
133
|
state.initialized = true
|
|
147
134
|
return state
|
|
148
135
|
}
|
|
149
136
|
|
|
150
|
-
// ─── Action Recording ───────────────────────────────────────────
|
|
151
|
-
|
|
152
137
|
async record(action: TrackedAction, mint?: string, description?: string): Promise<void> {
|
|
153
138
|
if (!this._state) throw new Error('State not initialized — call init() first')
|
|
154
139
|
|
|
@@ -156,17 +141,14 @@ export class StateProvider implements State {
|
|
|
156
141
|
this._state.actionCounts[action]++
|
|
157
142
|
this.ticksSinceCheckpoint++
|
|
158
143
|
|
|
159
|
-
// Track founded factions
|
|
160
144
|
if (action === 'launch' && mint) {
|
|
161
145
|
this._state.founded.push(mint)
|
|
162
146
|
}
|
|
163
147
|
|
|
164
|
-
// Update sentiment for the target faction
|
|
165
148
|
if (mint) {
|
|
166
149
|
this.updateSentiment(action, mint)
|
|
167
150
|
}
|
|
168
151
|
|
|
169
|
-
// Track recent history for LLM memory block
|
|
170
152
|
if (description) {
|
|
171
153
|
this._state.recentHistory.push(description)
|
|
172
154
|
if (this._state.recentHistory.length > 20) {
|
|
@@ -174,22 +156,16 @@ export class StateProvider implements State {
|
|
|
174
156
|
}
|
|
175
157
|
}
|
|
176
158
|
|
|
177
|
-
// Refresh holdings after any trade action
|
|
178
159
|
await this.refreshHoldings()
|
|
179
|
-
|
|
180
|
-
// Auto-checkpoint check
|
|
181
160
|
if (this.checkpointConfig && this.ticksSinceCheckpoint >= this.checkpointConfig.interval) {
|
|
182
161
|
this.ticksSinceCheckpoint = 0
|
|
183
162
|
this.onCheckpointDue?.()
|
|
184
163
|
}
|
|
185
164
|
}
|
|
186
165
|
|
|
187
|
-
/** Update sentiment score for a faction based on action type */
|
|
188
166
|
private updateSentiment(action: TrackedAction, mint: string): void {
|
|
189
167
|
if (!this._state) return
|
|
190
|
-
|
|
191
168
|
const current = this._state.sentiment.get(mint) ?? 0
|
|
192
|
-
|
|
193
169
|
const SENTIMENT_DELTAS: Partial<Record<TrackedAction, number>> = {
|
|
194
170
|
join: 1,
|
|
195
171
|
reinforce: 1.5,
|
|
@@ -208,18 +184,14 @@ export class StateProvider implements State {
|
|
|
208
184
|
}
|
|
209
185
|
}
|
|
210
186
|
|
|
211
|
-
/** Callback set by PyreKit to handle checkpoint triggers */
|
|
212
187
|
onCheckpointDue: (() => void) | null = null
|
|
213
188
|
|
|
214
|
-
// ─── Holdings ───────────────────────────────────────────────────
|
|
215
|
-
|
|
216
189
|
async refreshHoldings(): Promise<void> {
|
|
217
190
|
if (!this._state) return
|
|
218
191
|
|
|
219
192
|
const { TOKEN_2022_PROGRAM_ID } = await import('@solana/spl-token')
|
|
220
193
|
const walletPk = new PublicKey(this.publicKey)
|
|
221
194
|
|
|
222
|
-
// Scan wallet token accounts
|
|
223
195
|
let walletValues: any[] = []
|
|
224
196
|
try {
|
|
225
197
|
const walletAccounts = await this.connection.getParsedTokenAccountsByOwner(walletPk, {
|
|
@@ -228,7 +200,6 @@ export class StateProvider implements State {
|
|
|
228
200
|
walletValues = walletAccounts.value
|
|
229
201
|
} catch {}
|
|
230
202
|
|
|
231
|
-
// Scan vault token accounts
|
|
232
203
|
let vaultValues: any[] = []
|
|
233
204
|
if (this._state.stronghold) {
|
|
234
205
|
try {
|
|
@@ -240,7 +211,6 @@ export class StateProvider implements State {
|
|
|
240
211
|
} catch {}
|
|
241
212
|
}
|
|
242
213
|
|
|
243
|
-
// Merge balances
|
|
244
214
|
const newHoldings = new Map<string, number>()
|
|
245
215
|
for (const a of [...walletValues, ...vaultValues]) {
|
|
246
216
|
const mint = a.account.data.parsed.info.mint as string
|
|
@@ -250,7 +220,6 @@ export class StateProvider implements State {
|
|
|
250
220
|
}
|
|
251
221
|
}
|
|
252
222
|
|
|
253
|
-
// Update — clear stale, set fresh
|
|
254
223
|
this._state.holdings.clear()
|
|
255
224
|
for (const [mint, balance] of newHoldings) {
|
|
256
225
|
this._state.holdings.set(mint, balance)
|
|
@@ -273,8 +242,6 @@ export class StateProvider implements State {
|
|
|
273
242
|
return this._state?.holdings.get(mint) ?? 0
|
|
274
243
|
}
|
|
275
244
|
|
|
276
|
-
// ─── Dedup Guards ───────────────────────────────────────────────
|
|
277
|
-
|
|
278
245
|
hasVoted(mint: string): boolean {
|
|
279
246
|
return this._state?.voted.has(mint) ?? false
|
|
280
247
|
}
|
|
@@ -291,8 +258,6 @@ export class StateProvider implements State {
|
|
|
291
258
|
this._state?.rallied.add(mint)
|
|
292
259
|
}
|
|
293
260
|
|
|
294
|
-
// ─── Serialization ──────────────────────────────────────────────
|
|
295
|
-
|
|
296
261
|
serialize(): SerializedGameState {
|
|
297
262
|
if (!this._state) {
|
|
298
263
|
return {
|
package/tests/test_e2e.ts
CHANGED
|
@@ -345,6 +345,28 @@ async function main() {
|
|
|
345
345
|
assert(kitRestored.state.state!.actionCounts.defect === kit.state.state!.actionCounts.defect, `hydrated defect count matches`)
|
|
346
346
|
assert(kitRestored.state.history.length === kit.state.history.length, `hydrated history length matches: ${kitRestored.state.history.length}`)
|
|
347
347
|
|
|
348
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
349
|
+
// TEST: SCOUT
|
|
350
|
+
// ═══════════════════════════════════════════════════════════════════
|
|
351
|
+
|
|
352
|
+
console.log('\n═══ TEST: Scout ═══')
|
|
353
|
+
// Scout agent 1 from agent 2's perspective
|
|
354
|
+
const scoutResult = await kit2.actions.scout(agent.publicKey)
|
|
355
|
+
console.log(` ${scoutResult}`)
|
|
356
|
+
assert(typeof scoutResult === 'string', `scout returns string`)
|
|
357
|
+
assert(scoutResult.includes(agent.publicKey.slice(0, 8)), `scout result contains target address: ${agent.publicKey.slice(0, 8)}`)
|
|
358
|
+
|
|
359
|
+
// Scout a nonexistent address
|
|
360
|
+
const fakeAddress = 'FakeAddress1111111111111111111111111111111111'
|
|
361
|
+
const scoutFake = await kit2.actions.scout(fakeAddress)
|
|
362
|
+
console.log(` ${scoutFake}`)
|
|
363
|
+
assert(scoutFake.includes('no pyre identity') || scoutFake.includes('lookup failed'), `scout handles unknown agent`)
|
|
364
|
+
|
|
365
|
+
// Scout via exec (read-only — no tick increment)
|
|
366
|
+
const { result: scoutExecResult } = await kit2.exec('actions', 'scout', agent.publicKey)
|
|
367
|
+
console.log(` exec scout: ${scoutExecResult}`)
|
|
368
|
+
assert(kit2.state.tick === 2, `agent 2 tick unchanged after scout (read-only): ${kit2.state.tick}`)
|
|
369
|
+
|
|
348
370
|
// ═══════════════════════════════════════════════════════════════════
|
|
349
371
|
// TEST: MEMBERS
|
|
350
372
|
// ═══════════════════════════════════════════════════════════════════
|