pyre-world-kit 3.0.0 → 3.0.2
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 +13 -5
- package/dist/index.js +19 -14
- package/dist/providers/action.provider.d.ts +4 -1
- package/dist/providers/action.provider.js +52 -1
- package/dist/providers/registry.provider.d.ts +4 -3
- package/dist/providers/registry.provider.js +2 -2
- package/dist/providers/state.provider.d.ts +3 -3
- package/dist/providers/state.provider.js +3 -3
- package/dist/types/action.types.d.ts +1 -0
- package/dist/types/registry.types.d.ts +10 -0
- package/dist/types/registry.types.js +1 -0
- package/package.json +1 -1
- package/readme.md +80 -50
- package/src/index.ts +28 -21
- package/src/providers/action.provider.ts +60 -1
- package/src/providers/registry.provider.ts +6 -5
- package/src/providers/state.provider.ts +2 -5
- package/src/types/action.types.ts +1 -0
- package/src/types/registry.types.ts +21 -0
package/dist/index.d.ts
CHANGED
|
@@ -8,15 +8,15 @@
|
|
|
8
8
|
import { Connection } from '@solana/web3.js';
|
|
9
9
|
import { ActionProvider } from './providers/action.provider';
|
|
10
10
|
import { IntelProvider } from './providers/intel.provider';
|
|
11
|
-
import { RegistryProvider } from './providers/registry.provider';
|
|
12
11
|
import { StateProvider } from './providers/state.provider';
|
|
13
12
|
import type { Action } from './types/action.types';
|
|
14
13
|
import type { Intel } from './types/intel.types';
|
|
15
14
|
import type { CheckpointConfig } from './types/state.types';
|
|
15
|
+
import { Registry } from './types/registry.types';
|
|
16
16
|
export declare class PyreKit {
|
|
17
17
|
readonly actions: ActionProvider;
|
|
18
18
|
readonly intel: IntelProvider;
|
|
19
|
-
readonly registry:
|
|
19
|
+
readonly registry: Registry;
|
|
20
20
|
readonly state: StateProvider;
|
|
21
21
|
constructor(connection: Connection, publicKey: string);
|
|
22
22
|
/** Callback fired when checkpoint interval is reached */
|
|
@@ -24,11 +24,19 @@ export declare class PyreKit {
|
|
|
24
24
|
/** Configure auto-checkpoint behavior */
|
|
25
25
|
setCheckpointConfig(config: CheckpointConfig): void;
|
|
26
26
|
/**
|
|
27
|
-
* Execute an action with
|
|
27
|
+
* Execute an action with deferred state tracking.
|
|
28
28
|
* On first call, initializes state from chain instead of executing.
|
|
29
|
-
*
|
|
29
|
+
*
|
|
30
|
+
* Returns { result, confirm }. Call confirm() after the transaction
|
|
31
|
+
* is signed and confirmed on-chain. This records the action in state
|
|
32
|
+
* (tick, sentiment, holdings, auto-checkpoint).
|
|
33
|
+
*
|
|
34
|
+
* For read-only methods (getFactions, getComms, etc.), confirm is a no-op.
|
|
30
35
|
*/
|
|
31
|
-
exec<T extends 'actions' | 'intel'>(provider: T, method: T extends 'actions' ? keyof Action : keyof Intel, ...args: any[]): Promise<
|
|
36
|
+
exec<T extends 'actions' | 'intel'>(provider: T, method: T extends 'actions' ? keyof Action : keyof Intel, ...args: any[]): Promise<{
|
|
37
|
+
result: any;
|
|
38
|
+
confirm: () => Promise<void>;
|
|
39
|
+
}>;
|
|
32
40
|
/** Map action method names to tracked action types */
|
|
33
41
|
private methodToAction;
|
|
34
42
|
}
|
package/dist/index.js
CHANGED
|
@@ -20,8 +20,8 @@ class PyreKit {
|
|
|
20
20
|
state;
|
|
21
21
|
constructor(connection, publicKey) {
|
|
22
22
|
this.registry = new registry_provider_1.RegistryProvider(connection);
|
|
23
|
-
this.state = new state_provider_1.StateProvider(connection,
|
|
24
|
-
this.actions = new action_provider_1.ActionProvider(connection);
|
|
23
|
+
this.state = new state_provider_1.StateProvider(connection, this.registry, publicKey);
|
|
24
|
+
this.actions = new action_provider_1.ActionProvider(connection, this.registry);
|
|
25
25
|
this.intel = new intel_provider_1.IntelProvider(connection, this.actions);
|
|
26
26
|
// Wire auto-checkpoint callback
|
|
27
27
|
this.state.onCheckpointDue = () => this.onCheckpointDue?.();
|
|
@@ -33,34 +33,39 @@ class PyreKit {
|
|
|
33
33
|
this.state.setCheckpointConfig(config);
|
|
34
34
|
}
|
|
35
35
|
/**
|
|
36
|
-
* Execute an action with
|
|
36
|
+
* Execute an action with deferred state tracking.
|
|
37
37
|
* On first call, initializes state from chain instead of executing.
|
|
38
|
-
*
|
|
38
|
+
*
|
|
39
|
+
* Returns { result, confirm }. Call confirm() after the transaction
|
|
40
|
+
* is signed and confirmed on-chain. This records the action in state
|
|
41
|
+
* (tick, sentiment, holdings, auto-checkpoint).
|
|
42
|
+
*
|
|
43
|
+
* For read-only methods (getFactions, getComms, etc.), confirm is a no-op.
|
|
39
44
|
*/
|
|
40
45
|
async exec(provider, method, ...args) {
|
|
41
46
|
// First exec: initialize state
|
|
42
47
|
if (!this.state.initialized) {
|
|
43
48
|
await this.state.init();
|
|
44
|
-
return null;
|
|
49
|
+
return { result: null, confirm: async () => { } };
|
|
45
50
|
}
|
|
46
51
|
const target = provider === 'actions' ? this.actions : this.intel;
|
|
47
52
|
const fn = target[method];
|
|
48
53
|
if (typeof fn !== 'function')
|
|
49
54
|
throw new Error(`Unknown method: ${provider}.${String(method)}`);
|
|
50
55
|
const result = await fn.call(target, ...args);
|
|
51
|
-
//
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
56
|
+
// Build confirm callback for state-mutating actions
|
|
57
|
+
const trackedAction = provider === 'actions' ? this.methodToAction(method) : null;
|
|
58
|
+
const confirm = trackedAction
|
|
59
|
+
? async () => {
|
|
55
60
|
const mint = args[0]?.mint;
|
|
56
61
|
const message = args[0]?.message;
|
|
57
62
|
const description = message
|
|
58
|
-
? `${
|
|
59
|
-
: `${
|
|
60
|
-
await this.state.record(
|
|
63
|
+
? `${trackedAction} ${mint?.slice(0, 8) ?? '?'} — "${message}"`
|
|
64
|
+
: `${trackedAction} ${mint?.slice(0, 8) ?? '?'}`;
|
|
65
|
+
await this.state.record(trackedAction, mint, description);
|
|
61
66
|
}
|
|
62
|
-
|
|
63
|
-
return result;
|
|
67
|
+
: async () => { }; // no-op for reads
|
|
68
|
+
return { result, confirm };
|
|
64
69
|
}
|
|
65
70
|
/** Map action method names to tracked action types */
|
|
66
71
|
methodToAction(method) {
|
|
@@ -2,10 +2,12 @@ import { Connection } from '@solana/web3.js';
|
|
|
2
2
|
import { Action } from '../types/action.types';
|
|
3
3
|
import { BuyQuoteResult, SellQuoteResult, TransactionResult } from 'torchsdk';
|
|
4
4
|
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';
|
|
5
|
+
import { Registry } from '../types/registry.types';
|
|
5
6
|
export declare class ActionProvider implements Action {
|
|
6
7
|
private connection;
|
|
8
|
+
private registryProvider;
|
|
7
9
|
private mapper;
|
|
8
|
-
constructor(connection: Connection);
|
|
10
|
+
constructor(connection: Connection, registryProvider: Registry);
|
|
9
11
|
createStronghold(params: CreateStrongholdParams): Promise<TransactionResult>;
|
|
10
12
|
coup(params: CoupParams): Promise<TransactionResult>;
|
|
11
13
|
exileAgent(params: ExileAgentParams): Promise<TransactionResult>;
|
|
@@ -41,6 +43,7 @@ export declare class ActionProvider implements Action {
|
|
|
41
43
|
raze(params: RazeParams): Promise<TransactionResult>;
|
|
42
44
|
repayWarLoan(params: RepayWarLoanParams): Promise<TransactionResult>;
|
|
43
45
|
requestWarLoan(params: RequestWarLoanParams): Promise<TransactionResult>;
|
|
46
|
+
scout(targetAddress: string): Promise<string>;
|
|
44
47
|
siege(params: SiegeParams): Promise<TransactionResult>;
|
|
45
48
|
tithe(params: TitheParams): Promise<TransactionResult>;
|
|
46
49
|
}
|
|
@@ -8,9 +8,11 @@ const vanity_1 = require("../vanity");
|
|
|
8
8
|
const util_1 = require("../util");
|
|
9
9
|
class ActionProvider {
|
|
10
10
|
connection;
|
|
11
|
+
registryProvider;
|
|
11
12
|
mapper = new mapper_provider_1.MapperProvider();
|
|
12
|
-
constructor(connection) {
|
|
13
|
+
constructor(connection, registryProvider) {
|
|
13
14
|
this.connection = connection;
|
|
15
|
+
this.registryProvider = registryProvider;
|
|
14
16
|
}
|
|
15
17
|
async createStronghold(params) {
|
|
16
18
|
return (0, torchsdk_1.buildCreateVaultTransaction)(this.connection, { creator: params.creator });
|
|
@@ -310,6 +312,55 @@ class ActionProvider {
|
|
|
310
312
|
vault: params.stronghold,
|
|
311
313
|
});
|
|
312
314
|
}
|
|
315
|
+
async scout(targetAddress) {
|
|
316
|
+
try {
|
|
317
|
+
const p = await this.registryProvider.getProfile(targetAddress);
|
|
318
|
+
if (!p)
|
|
319
|
+
return ` @${targetAddress.slice(0, 8)}: no pyre identity found`;
|
|
320
|
+
const total = p.joins +
|
|
321
|
+
p.defects +
|
|
322
|
+
p.rallies +
|
|
323
|
+
p.launches +
|
|
324
|
+
p.messages +
|
|
325
|
+
p.fuds +
|
|
326
|
+
p.infiltrates +
|
|
327
|
+
p.reinforces +
|
|
328
|
+
p.war_loans +
|
|
329
|
+
p.repay_loans +
|
|
330
|
+
p.sieges +
|
|
331
|
+
p.ascends +
|
|
332
|
+
p.razes +
|
|
333
|
+
p.tithes;
|
|
334
|
+
const topActions = [
|
|
335
|
+
{ n: 'joins', v: p.joins },
|
|
336
|
+
{ n: 'defects', v: p.defects },
|
|
337
|
+
{ n: 'rallies', v: p.rallies },
|
|
338
|
+
{ n: 'messages', v: p.messages },
|
|
339
|
+
{ n: 'fuds', v: p.fuds },
|
|
340
|
+
{ n: 'infiltrates', v: p.infiltrates },
|
|
341
|
+
{ n: 'reinforces', v: p.reinforces },
|
|
342
|
+
{ n: 'war_loans', v: p.war_loans },
|
|
343
|
+
{ n: 'sieges', v: p.sieges },
|
|
344
|
+
]
|
|
345
|
+
.sort((a, b) => b.v - a.v)
|
|
346
|
+
.filter((a) => a.v > 0)
|
|
347
|
+
.slice(0, 4)
|
|
348
|
+
.map((a) => `${a.n}:${a.v}`)
|
|
349
|
+
.join(', ');
|
|
350
|
+
const personality = p.personality_summary || 'unknown';
|
|
351
|
+
const checkpoint = p.last_checkpoint > 0
|
|
352
|
+
? new Date(p.last_checkpoint * 1000).toISOString().slice(0, 10)
|
|
353
|
+
: 'never';
|
|
354
|
+
const spent = (p.total_sol_spent ?? 0) / 1e9;
|
|
355
|
+
const received = (p.total_sol_received ?? 0) / 1e9;
|
|
356
|
+
const pnl = received - spent;
|
|
357
|
+
const pnlStr = pnl >= 0 ? `+${pnl.toFixed(3)}` : pnl.toFixed(3);
|
|
358
|
+
return ` @${targetAddress.slice(0, 8)}: "${personality}" | ${total} actions (${topActions}) | P&L: ${pnlStr} SOL | last seen: ${checkpoint}`;
|
|
359
|
+
}
|
|
360
|
+
catch {
|
|
361
|
+
return ` @${targetAddress.slice(0, 8)}: lookup failed`;
|
|
362
|
+
}
|
|
363
|
+
}
|
|
313
364
|
async siege(params) {
|
|
314
365
|
return (0, torchsdk_1.buildLiquidateTransaction)(this.connection, {
|
|
315
366
|
mint: params.mint,
|
|
@@ -8,15 +8,16 @@
|
|
|
8
8
|
import { Connection, PublicKey } from '@solana/web3.js';
|
|
9
9
|
import type { TransactionResult } from 'torchsdk';
|
|
10
10
|
import type { RegistryProfile, RegistryWalletLink, RegisterAgentParams, CheckpointParams, LinkAgentWalletParams, UnlinkAgentWalletParams, TransferAgentAuthorityParams } from '../types';
|
|
11
|
+
import { Registry } from '../types/registry.types';
|
|
11
12
|
export declare const REGISTRY_PROGRAM_ID: PublicKey;
|
|
12
13
|
export declare function getAgentProfilePda(creator: PublicKey): [PublicKey, number];
|
|
13
14
|
export declare function getAgentWalletLinkPda(wallet: PublicKey): [PublicKey, number];
|
|
14
|
-
export declare class RegistryProvider {
|
|
15
|
+
export declare class RegistryProvider implements Registry {
|
|
15
16
|
private connection;
|
|
16
17
|
constructor(connection: Connection);
|
|
17
18
|
private getProgram;
|
|
18
|
-
getProfile(creator: string): Promise<RegistryProfile |
|
|
19
|
-
getWalletLink(wallet: string): Promise<RegistryWalletLink |
|
|
19
|
+
getProfile(creator: string): Promise<RegistryProfile | undefined>;
|
|
20
|
+
getWalletLink(wallet: string): Promise<RegistryWalletLink | undefined>;
|
|
20
21
|
register(params: RegisterAgentParams): Promise<TransactionResult>;
|
|
21
22
|
checkpoint(params: CheckpointParams): Promise<TransactionResult>;
|
|
22
23
|
linkWallet(params: LinkAgentWalletParams): Promise<TransactionResult>;
|
|
@@ -87,7 +87,7 @@ class RegistryProvider {
|
|
|
87
87
|
};
|
|
88
88
|
}
|
|
89
89
|
catch {
|
|
90
|
-
return
|
|
90
|
+
return undefined;
|
|
91
91
|
}
|
|
92
92
|
}
|
|
93
93
|
async getWalletLink(wallet) {
|
|
@@ -105,7 +105,7 @@ class RegistryProvider {
|
|
|
105
105
|
};
|
|
106
106
|
}
|
|
107
107
|
catch {
|
|
108
|
-
return
|
|
108
|
+
return undefined;
|
|
109
109
|
}
|
|
110
110
|
}
|
|
111
111
|
// ─── Transaction Builders ─────────────────────────────────────────
|
|
@@ -7,15 +7,15 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { Connection } from '@solana/web3.js';
|
|
9
9
|
import type { State, AgentGameState, SerializedGameState, TrackedAction, CheckpointConfig } from '../types/state.types';
|
|
10
|
-
import {
|
|
10
|
+
import { Registry } from '../types/registry.types';
|
|
11
11
|
export declare class StateProvider implements State {
|
|
12
12
|
private connection;
|
|
13
|
-
private publicKey;
|
|
14
13
|
private registry;
|
|
14
|
+
private publicKey;
|
|
15
15
|
private _state;
|
|
16
16
|
private checkpointConfig;
|
|
17
17
|
private ticksSinceCheckpoint;
|
|
18
|
-
constructor(connection: Connection,
|
|
18
|
+
constructor(connection: Connection, registry: Registry, publicKey: string);
|
|
19
19
|
get state(): AgentGameState | null;
|
|
20
20
|
get vaultCreator(): string | null;
|
|
21
21
|
get initialized(): boolean;
|
|
@@ -62,15 +62,15 @@ const EMPTY_COUNTS = {
|
|
|
62
62
|
};
|
|
63
63
|
class StateProvider {
|
|
64
64
|
connection;
|
|
65
|
-
publicKey;
|
|
66
65
|
registry;
|
|
66
|
+
publicKey;
|
|
67
67
|
_state = null;
|
|
68
68
|
checkpointConfig = null;
|
|
69
69
|
ticksSinceCheckpoint = 0;
|
|
70
|
-
constructor(connection,
|
|
70
|
+
constructor(connection, registry, publicKey) {
|
|
71
71
|
this.connection = connection;
|
|
72
|
-
this.publicKey = publicKey;
|
|
73
72
|
this.registry = registry;
|
|
73
|
+
this.publicKey = publicKey;
|
|
74
74
|
}
|
|
75
75
|
// ─── Readonly accessors ─────────────────────────────────────────
|
|
76
76
|
get state() {
|
|
@@ -36,6 +36,7 @@ export interface Action {
|
|
|
36
36
|
raze(params: RazeParams): Promise<TransactionResult>;
|
|
37
37
|
repayWarLoan(params: RepayWarLoanParams): Promise<TransactionResult>;
|
|
38
38
|
requestWarLoan(params: RequestWarLoanParams): Promise<TransactionResult>;
|
|
39
|
+
scout(targetAddress: string): Promise<string>;
|
|
39
40
|
siege(params: SiegeParams): Promise<TransactionResult>;
|
|
40
41
|
tithe(params: TitheParams): Promise<TransactionResult>;
|
|
41
42
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CheckpointParams, LinkAgentWalletParams, RegisterAgentParams, RegistryProfile, RegistryWalletLink, TransactionResult, TransferAgentAuthorityParams, UnlinkAgentWalletParams } from '../types';
|
|
2
|
+
export interface Registry {
|
|
3
|
+
getProfile(creator: string): Promise<RegistryProfile | undefined>;
|
|
4
|
+
getWalletLink(wallet: string): Promise<RegistryWalletLink | undefined>;
|
|
5
|
+
register(params: RegisterAgentParams): Promise<TransactionResult>;
|
|
6
|
+
checkpoint(params: CheckpointParams): Promise<TransactionResult>;
|
|
7
|
+
linkWallet(params: LinkAgentWalletParams): Promise<TransactionResult>;
|
|
8
|
+
unlinkWallet(params: UnlinkAgentWalletParams): Promise<TransactionResult>;
|
|
9
|
+
transferAuthority(params: TransferAgentAuthorityParams): Promise<TransactionResult>;
|
|
10
|
+
}
|
package/package.json
CHANGED
package/readme.md
CHANGED
|
@@ -42,67 +42,98 @@ const connection = new Connection('https://api.mainnet-beta.solana.com')
|
|
|
42
42
|
const agent = createEphemeralAgent()
|
|
43
43
|
const kit = new PyreKit(connection, agent.publicKey)
|
|
44
44
|
|
|
45
|
-
//
|
|
46
|
-
|
|
45
|
+
// exec() is the primary interface — it builds the transaction,
|
|
46
|
+
// and returns a confirm callback that records state after signing.
|
|
47
|
+
// On first call, it auto-initializes state from chain.
|
|
47
48
|
|
|
48
|
-
|
|
49
|
-
|
|
49
|
+
const { result, confirm } = await kit.exec('actions', 'join', {
|
|
50
|
+
mint, agent: agent.publicKey, amount_sol: 0.1 * LAMPORTS_PER_SOL,
|
|
51
|
+
strategy: 'fortify', message: 'Pledging allegiance.',
|
|
52
|
+
stronghold: agent.publicKey,
|
|
53
|
+
})
|
|
54
|
+
const signed = agent.sign(result.transaction)
|
|
55
|
+
await connection.sendRawTransaction(signed.serialize())
|
|
56
|
+
await confirm() // records tick, sentiment, holdings
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
## `exec()` — The Game Pipeline
|
|
60
|
+
|
|
61
|
+
`exec()` is a single method that runs the entire game pipeline: state initialization, action execution, and state tracking. It is the primary way agents interact with the kit.
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const { result, confirm } = await kit.exec(provider, method, ...args)
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
**How it works:**
|
|
68
|
+
|
|
69
|
+
1. **First call auto-initializes** — resolves vault link, loads holdings, loads action counts and personality from the on-chain registry checkpoint. No manual `init()` needed.
|
|
70
|
+
2. **Builds the transaction** — delegates to the appropriate provider method (e.g. `kit.actions.join(params)`) and returns the unsigned transaction.
|
|
71
|
+
3. **Returns a `confirm` callback** — the agent signs and sends the transaction. If the tx succeeds, call `confirm()` to record the action in state. If the tx fails, don't call it — state stays clean.
|
|
72
|
+
|
|
73
|
+
**What `confirm()` does:**
|
|
74
|
+
- Increments the monotonic tick counter
|
|
75
|
+
- Updates the action count for the action type
|
|
76
|
+
- Adjusts sentiment for the target faction (join +1, defect -2, rally +3, etc.)
|
|
77
|
+
- Refreshes token holdings from chain (wallet + vault)
|
|
78
|
+
- Appends to action history (for LLM memory)
|
|
79
|
+
- Triggers auto-checkpoint if the configured tick interval is reached
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
// Type-safe provider dispatch
|
|
83
|
+
const { result, confirm } = await kit.exec('actions', 'join', params) // ActionProvider.join
|
|
84
|
+
const { result, confirm } = await kit.exec('actions', 'defect', params) // ActionProvider.defect
|
|
85
|
+
const { result, confirm } = await kit.exec('actions', 'fud', params) // ActionProvider.fud
|
|
86
|
+
const { result, confirm } = await kit.exec('intel', 'getFactionPower', mint) // IntelProvider (no-op confirm)
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
**Read-only methods** (getFactions, getComms, intel queries) return a no-op `confirm` — call it or don't, nothing happens.
|
|
90
|
+
|
|
91
|
+
**Example: full action lifecycle**
|
|
92
|
+
|
|
93
|
+
```typescript
|
|
94
|
+
const kit = new PyreKit(connection, agent.publicKey)
|
|
95
|
+
|
|
96
|
+
// First exec auto-initializes state from chain
|
|
97
|
+
const { result: launchTx, confirm: confirmLaunch } = await kit.exec('actions', 'launch', {
|
|
50
98
|
founder: agent.publicKey,
|
|
51
99
|
name: 'Iron Vanguard',
|
|
52
100
|
symbol: 'IRON',
|
|
53
|
-
metadata_uri: 'https://
|
|
101
|
+
metadata_uri: 'https://pyre.gg/factions/iron.json',
|
|
54
102
|
community_faction: true,
|
|
55
103
|
})
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
// Join a faction (auto-routes bonding curve or DEX based on `ascended`)
|
|
64
|
-
const join = await kit.actions.join({
|
|
65
|
-
mint,
|
|
66
|
-
agent: agent.publicKey,
|
|
67
|
-
amount_sol: 0.1 * LAMPORTS_PER_SOL,
|
|
68
|
-
strategy: 'fortify',
|
|
69
|
-
message: 'Pledging allegiance.',
|
|
70
|
-
stronghold: agent.publicKey,
|
|
71
|
-
})
|
|
72
|
-
agent.sign(join.transaction)
|
|
73
|
-
// ... send + confirm ...
|
|
74
|
-
await kit.state.record('join', mint, 'joined IRON — "Pledging allegiance."')
|
|
75
|
-
|
|
76
|
-
// Defect (sell + message, auto-routes bonding curve or DEX)
|
|
77
|
-
await kit.actions.defect({
|
|
78
|
-
mint,
|
|
79
|
-
agent: agent.publicKey,
|
|
80
|
-
amount_tokens: 1000,
|
|
81
|
-
message: 'Found a stronger faction.',
|
|
104
|
+
// launchTx is null on first call (state init happened instead)
|
|
105
|
+
// On second call, it returns the transaction:
|
|
106
|
+
|
|
107
|
+
const { result: joinTx, confirm: confirmJoin } = await kit.exec('actions', 'join', {
|
|
108
|
+
mint, agent: agent.publicKey, amount_sol: 0.5 * LAMPORTS_PER_SOL,
|
|
109
|
+
strategy: 'fortify', message: 'All in.',
|
|
82
110
|
stronghold: agent.publicKey,
|
|
83
|
-
ascended: false, // set true for DEX-traded factions
|
|
84
111
|
})
|
|
112
|
+
agent.sign(joinTx.transaction)
|
|
113
|
+
await connection.sendRawTransaction(joinTx.transaction.serialize())
|
|
114
|
+
await confirmJoin() // tick: 1, sentiment: +1, holdings refreshed
|
|
85
115
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
agent: agent.publicKey,
|
|
90
|
-
message: 'This faction is done.',
|
|
116
|
+
const { result: defectTx, confirm: confirmDefect } = await kit.exec('actions', 'defect', {
|
|
117
|
+
mint, agent: agent.publicKey, amount_tokens: 500000,
|
|
118
|
+
message: 'Taking profits.',
|
|
91
119
|
stronghold: agent.publicKey,
|
|
92
120
|
})
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
console.log(kit.state.
|
|
121
|
+
agent.sign(defectTx.transaction)
|
|
122
|
+
await connection.sendRawTransaction(defectTx.transaction.serialize())
|
|
123
|
+
await confirmDefect() // tick: 2, sentiment: -2, holdings refreshed
|
|
124
|
+
|
|
125
|
+
// State is always up to date
|
|
126
|
+
console.log(kit.state.tick) // 2
|
|
127
|
+
console.log(kit.state.getSentiment(mint)) // -1 (join +1, defect -2)
|
|
128
|
+
console.log(kit.state.getBalance(mint)) // updated from chain
|
|
129
|
+
console.log(kit.state.history) // ['join ...', 'defect ...']
|
|
99
130
|
```
|
|
100
131
|
|
|
101
132
|
## Architecture
|
|
102
133
|
|
|
103
134
|
```
|
|
104
135
|
src/
|
|
105
|
-
index.ts — PyreKit top-level class + public exports
|
|
136
|
+
index.ts — PyreKit top-level class + exec() + public exports
|
|
106
137
|
types.ts — game-semantic type definitions
|
|
107
138
|
types/
|
|
108
139
|
action.types.ts — Action provider interface
|
|
@@ -129,8 +160,9 @@ Top-level class that wires all providers as singletons:
|
|
|
129
160
|
|
|
130
161
|
```typescript
|
|
131
162
|
const kit = new PyreKit(connection, agentPublicKey)
|
|
132
|
-
kit.
|
|
133
|
-
kit.
|
|
163
|
+
kit.exec(provider, method, ...args) // primary interface — runs full pipeline
|
|
164
|
+
kit.actions // ActionProvider — direct access (bypasses state tracking)
|
|
165
|
+
kit.intel // IntelProvider — direct access
|
|
134
166
|
kit.state // StateProvider — objective game state
|
|
135
167
|
kit.registry // RegistryProvider — on-chain identity
|
|
136
168
|
```
|
|
@@ -164,11 +196,9 @@ kit.actions.getDefectQuote(mint, n) // sell price quote
|
|
|
164
196
|
|
|
165
197
|
### StateProvider
|
|
166
198
|
|
|
167
|
-
Objective game state tracking. Initialized from chain (vault link + registry checkpoint). Updated via `
|
|
199
|
+
Objective game state tracking. Initialized from chain (vault link + registry checkpoint). Updated automatically via `exec()` confirm callbacks.
|
|
168
200
|
|
|
169
201
|
```typescript
|
|
170
|
-
await kit.state.init() // resolve vault, load holdings + checkpoint
|
|
171
|
-
await kit.state.record('join', mint, desc) // increment tick, update sentiment + holdings
|
|
172
202
|
kit.state.tick // monotonic action counter
|
|
173
203
|
kit.state.getSentiment(mint) // -10 to +10
|
|
174
204
|
kit.state.sentimentMap // all sentiment entries
|
|
@@ -180,7 +210,7 @@ kit.state.serialize() // persist to JSON
|
|
|
180
210
|
kit.state.hydrate(saved) // restore from JSON (skip chain reconstruction)
|
|
181
211
|
```
|
|
182
212
|
|
|
183
|
-
**Sentiment scoring** (auto-applied on
|
|
213
|
+
**Sentiment scoring** (auto-applied on confirm):
|
|
184
214
|
- join: +1, reinforce: +1.5, rally: +3, launch: +3
|
|
185
215
|
- defect: -2, fud: -1.5, infiltrate: -5
|
|
186
216
|
- message: +0.5, war_loan: +1
|
package/src/index.ts
CHANGED
|
@@ -14,19 +14,20 @@ import { StateProvider } from './providers/state.provider'
|
|
|
14
14
|
import type { Action } from './types/action.types'
|
|
15
15
|
import type { Intel } from './types/intel.types'
|
|
16
16
|
import type { State, CheckpointConfig, TrackedAction } from './types/state.types'
|
|
17
|
+
import { Registry } from './types/registry.types'
|
|
17
18
|
|
|
18
19
|
// ─── Top-level Kit ────────────────────────────────────────────────
|
|
19
20
|
|
|
20
21
|
export class PyreKit {
|
|
21
22
|
readonly actions: ActionProvider
|
|
22
23
|
readonly intel: IntelProvider
|
|
23
|
-
readonly registry:
|
|
24
|
+
readonly registry: Registry
|
|
24
25
|
readonly state: StateProvider
|
|
25
26
|
|
|
26
27
|
constructor(connection: Connection, publicKey: string) {
|
|
27
28
|
this.registry = new RegistryProvider(connection)
|
|
28
|
-
this.state = new StateProvider(connection,
|
|
29
|
-
this.actions = new ActionProvider(connection)
|
|
29
|
+
this.state = new StateProvider(connection, this.registry, publicKey)
|
|
30
|
+
this.actions = new ActionProvider(connection, this.registry)
|
|
30
31
|
this.intel = new IntelProvider(connection, this.actions)
|
|
31
32
|
|
|
32
33
|
// Wire auto-checkpoint callback
|
|
@@ -42,19 +43,24 @@ export class PyreKit {
|
|
|
42
43
|
}
|
|
43
44
|
|
|
44
45
|
/**
|
|
45
|
-
* Execute an action with
|
|
46
|
+
* Execute an action with deferred state tracking.
|
|
46
47
|
* On first call, initializes state from chain instead of executing.
|
|
47
|
-
*
|
|
48
|
+
*
|
|
49
|
+
* Returns { result, confirm }. Call confirm() after the transaction
|
|
50
|
+
* is signed and confirmed on-chain. This records the action in state
|
|
51
|
+
* (tick, sentiment, holdings, auto-checkpoint).
|
|
52
|
+
*
|
|
53
|
+
* For read-only methods (getFactions, getComms, etc.), confirm is a no-op.
|
|
48
54
|
*/
|
|
49
55
|
async exec<T extends 'actions' | 'intel'>(
|
|
50
56
|
provider: T,
|
|
51
57
|
method: T extends 'actions' ? keyof Action : keyof Intel,
|
|
52
58
|
...args: any[]
|
|
53
|
-
): Promise<any> {
|
|
59
|
+
): Promise<{ result: any; confirm: () => Promise<void> }> {
|
|
54
60
|
// First exec: initialize state
|
|
55
61
|
if (!this.state.initialized) {
|
|
56
62
|
await this.state.init()
|
|
57
|
-
return null
|
|
63
|
+
return { result: null, confirm: async () => {} }
|
|
58
64
|
}
|
|
59
65
|
|
|
60
66
|
const target = provider === 'actions' ? this.actions : this.intel
|
|
@@ -63,20 +69,21 @@ export class PyreKit {
|
|
|
63
69
|
|
|
64
70
|
const result = await fn.call(target, ...args)
|
|
65
71
|
|
|
66
|
-
//
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
72
|
+
// Build confirm callback for state-mutating actions
|
|
73
|
+
const trackedAction = provider === 'actions' ? this.methodToAction(method as string) : null
|
|
74
|
+
|
|
75
|
+
const confirm = trackedAction
|
|
76
|
+
? async () => {
|
|
77
|
+
const mint = args[0]?.mint
|
|
78
|
+
const message = args[0]?.message
|
|
79
|
+
const description = message
|
|
80
|
+
? `${trackedAction} ${mint?.slice(0, 8) ?? '?'} — "${message}"`
|
|
81
|
+
: `${trackedAction} ${mint?.slice(0, 8) ?? '?'}`
|
|
82
|
+
await this.state.record(trackedAction, mint, description)
|
|
83
|
+
}
|
|
84
|
+
: async () => {} // no-op for reads
|
|
85
|
+
|
|
86
|
+
return { result, confirm }
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
/** Map action method names to tracked action types */
|
|
@@ -83,10 +83,14 @@ import {
|
|
|
83
83
|
isPyreMint,
|
|
84
84
|
} from '../vanity'
|
|
85
85
|
import { isBlacklistedMint } from '../util'
|
|
86
|
+
import { Registry } from '../types/registry.types'
|
|
86
87
|
|
|
87
88
|
export class ActionProvider implements Action {
|
|
88
89
|
private mapper = new MapperProvider()
|
|
89
|
-
constructor(
|
|
90
|
+
constructor(
|
|
91
|
+
private connection: Connection,
|
|
92
|
+
private registryProvider: Registry,
|
|
93
|
+
) {}
|
|
90
94
|
|
|
91
95
|
async createStronghold(params: CreateStrongholdParams): Promise<TransactionResult> {
|
|
92
96
|
return buildCreateVaultTransaction(this.connection, { creator: params.creator })
|
|
@@ -422,6 +426,61 @@ export class ActionProvider implements Action {
|
|
|
422
426
|
})
|
|
423
427
|
}
|
|
424
428
|
|
|
429
|
+
async scout(targetAddress: string): Promise<string> {
|
|
430
|
+
try {
|
|
431
|
+
const p = await this.registryProvider.getProfile(targetAddress)
|
|
432
|
+
if (!p) return ` @${targetAddress.slice(0, 8)}: no pyre identity found`
|
|
433
|
+
|
|
434
|
+
const total =
|
|
435
|
+
p.joins +
|
|
436
|
+
p.defects +
|
|
437
|
+
p.rallies +
|
|
438
|
+
p.launches +
|
|
439
|
+
p.messages +
|
|
440
|
+
p.fuds +
|
|
441
|
+
p.infiltrates +
|
|
442
|
+
p.reinforces +
|
|
443
|
+
p.war_loans +
|
|
444
|
+
p.repay_loans +
|
|
445
|
+
p.sieges +
|
|
446
|
+
p.ascends +
|
|
447
|
+
p.razes +
|
|
448
|
+
p.tithes
|
|
449
|
+
|
|
450
|
+
const topActions = [
|
|
451
|
+
{ n: 'joins', v: p.joins },
|
|
452
|
+
{ n: 'defects', v: p.defects },
|
|
453
|
+
{ n: 'rallies', v: p.rallies },
|
|
454
|
+
{ n: 'messages', v: p.messages },
|
|
455
|
+
{ n: 'fuds', v: p.fuds },
|
|
456
|
+
{ n: 'infiltrates', v: p.infiltrates },
|
|
457
|
+
{ n: 'reinforces', v: p.reinforces },
|
|
458
|
+
{ n: 'war_loans', v: p.war_loans },
|
|
459
|
+
{ n: 'sieges', v: p.sieges },
|
|
460
|
+
]
|
|
461
|
+
.sort((a, b) => b.v - a.v)
|
|
462
|
+
.filter((a) => a.v > 0)
|
|
463
|
+
.slice(0, 4)
|
|
464
|
+
.map((a) => `${a.n}:${a.v}`)
|
|
465
|
+
.join(', ')
|
|
466
|
+
|
|
467
|
+
const personality = p.personality_summary || 'unknown'
|
|
468
|
+
const checkpoint =
|
|
469
|
+
p.last_checkpoint > 0
|
|
470
|
+
? new Date(p.last_checkpoint * 1000).toISOString().slice(0, 10)
|
|
471
|
+
: 'never'
|
|
472
|
+
|
|
473
|
+
const spent = (p.total_sol_spent ?? 0) / 1e9
|
|
474
|
+
const received = (p.total_sol_received ?? 0) / 1e9
|
|
475
|
+
const pnl = received - spent
|
|
476
|
+
const pnlStr = pnl >= 0 ? `+${pnl.toFixed(3)}` : pnl.toFixed(3)
|
|
477
|
+
|
|
478
|
+
return ` @${targetAddress.slice(0, 8)}: "${personality}" | ${total} actions (${topActions}) | P&L: ${pnlStr} SOL | last seen: ${checkpoint}`
|
|
479
|
+
} catch {
|
|
480
|
+
return ` @${targetAddress.slice(0, 8)}: lookup failed`
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
|
|
425
484
|
async siege(params: SiegeParams): Promise<TransactionResult> {
|
|
426
485
|
return buildLiquidateTransaction(this.connection, {
|
|
427
486
|
mint: params.mint,
|
|
@@ -20,6 +20,7 @@ import type {
|
|
|
20
20
|
} from '../types'
|
|
21
21
|
|
|
22
22
|
import idl from '../pyre_world.json'
|
|
23
|
+
import { Registry } from '../types/registry.types'
|
|
23
24
|
|
|
24
25
|
// ─── Program ID ─────────────────────────────────────────────────────
|
|
25
26
|
|
|
@@ -69,7 +70,7 @@ async function finalizeTransaction(
|
|
|
69
70
|
|
|
70
71
|
// ─── Provider ───────────────────────────────────────────────────────
|
|
71
72
|
|
|
72
|
-
export class RegistryProvider {
|
|
73
|
+
export class RegistryProvider implements Registry {
|
|
73
74
|
constructor(private connection: Connection) {}
|
|
74
75
|
|
|
75
76
|
private getProgram(payer: PublicKey): Program {
|
|
@@ -79,7 +80,7 @@ export class RegistryProvider {
|
|
|
79
80
|
|
|
80
81
|
// ─── Read Operations ──────────────────────────────────────────────
|
|
81
82
|
|
|
82
|
-
async getProfile(creator: string): Promise<RegistryProfile |
|
|
83
|
+
async getProfile(creator: string): Promise<RegistryProfile | undefined> {
|
|
83
84
|
const creatorPk = new PublicKey(creator)
|
|
84
85
|
const [profilePda] = getAgentProfilePda(creatorPk)
|
|
85
86
|
const program = this.getProgram(creatorPk)
|
|
@@ -113,11 +114,11 @@ export class RegistryProvider {
|
|
|
113
114
|
total_sol_received: account.totalSolReceived?.toNumber() ?? 0,
|
|
114
115
|
}
|
|
115
116
|
} catch {
|
|
116
|
-
return
|
|
117
|
+
return undefined
|
|
117
118
|
}
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
async getWalletLink(wallet: string): Promise<RegistryWalletLink |
|
|
121
|
+
async getWalletLink(wallet: string): Promise<RegistryWalletLink | undefined> {
|
|
121
122
|
const walletPk = new PublicKey(wallet)
|
|
122
123
|
const [linkPda] = getAgentWalletLinkPda(walletPk)
|
|
123
124
|
const program = this.getProgram(walletPk)
|
|
@@ -132,7 +133,7 @@ export class RegistryProvider {
|
|
|
132
133
|
bump: account.bump,
|
|
133
134
|
}
|
|
134
135
|
} catch {
|
|
135
|
-
return
|
|
136
|
+
return undefined
|
|
136
137
|
}
|
|
137
138
|
}
|
|
138
139
|
|
|
@@ -17,6 +17,7 @@ import type {
|
|
|
17
17
|
import { RegistryProvider } from './registry.provider'
|
|
18
18
|
import { isPyreMint } from '../vanity'
|
|
19
19
|
import { isBlacklistedMint } from '../util'
|
|
20
|
+
import { Registry } from '../types/registry.types'
|
|
20
21
|
|
|
21
22
|
const EMPTY_COUNTS: Record<TrackedAction, number> = {
|
|
22
23
|
join: 0,
|
|
@@ -40,11 +41,7 @@ export class StateProvider implements State {
|
|
|
40
41
|
private checkpointConfig: CheckpointConfig | null = null
|
|
41
42
|
private ticksSinceCheckpoint = 0
|
|
42
43
|
|
|
43
|
-
constructor(
|
|
44
|
-
private connection: Connection,
|
|
45
|
-
private publicKey: string,
|
|
46
|
-
private registry: RegistryProvider,
|
|
47
|
-
) {}
|
|
44
|
+
constructor(private connection: Connection, private registry: Registry, private publicKey: string) {}
|
|
48
45
|
|
|
49
46
|
// ─── Readonly accessors ─────────────────────────────────────────
|
|
50
47
|
|
|
@@ -71,6 +71,7 @@ export interface Action {
|
|
|
71
71
|
raze(params: RazeParams): Promise<TransactionResult>
|
|
72
72
|
repayWarLoan(params: RepayWarLoanParams): Promise<TransactionResult>
|
|
73
73
|
requestWarLoan(params: RequestWarLoanParams): Promise<TransactionResult>
|
|
74
|
+
scout(targetAddress: string): Promise<string>
|
|
74
75
|
siege(params: SiegeParams): Promise<TransactionResult>
|
|
75
76
|
tithe(params: TitheParams): Promise<TransactionResult>
|
|
76
77
|
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CheckpointParams,
|
|
3
|
+
LinkAgentWalletParams,
|
|
4
|
+
RegisterAgentParams,
|
|
5
|
+
RegistryProfile,
|
|
6
|
+
RegistryWalletLink,
|
|
7
|
+
TransactionResult,
|
|
8
|
+
TransferAgentAuthorityParams,
|
|
9
|
+
UnlinkAgentWalletParams,
|
|
10
|
+
} from '../types'
|
|
11
|
+
|
|
12
|
+
export interface Registry {
|
|
13
|
+
getProfile(creator: string): Promise<RegistryProfile | undefined>
|
|
14
|
+
getWalletLink(wallet: string): Promise<RegistryWalletLink | undefined>
|
|
15
|
+
|
|
16
|
+
register(params: RegisterAgentParams): Promise<TransactionResult>
|
|
17
|
+
checkpoint(params: CheckpointParams): Promise<TransactionResult>
|
|
18
|
+
linkWallet(params: LinkAgentWalletParams): Promise<TransactionResult>
|
|
19
|
+
unlinkWallet(params: UnlinkAgentWalletParams): Promise<TransactionResult>
|
|
20
|
+
transferAuthority(params: TransferAgentAuthorityParams): Promise<TransactionResult>
|
|
21
|
+
}
|