pyre-world-kit 3.1.2 → 3.2.1
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 +1 -1
- package/dist/providers/action.provider.js +1 -1
- package/dist/providers/intel.provider.d.ts +8 -2
- package/dist/providers/intel.provider.js +159 -36
- package/dist/providers/registry.provider.d.ts +3 -2
- package/dist/providers/registry.provider.js +29 -29
- package/dist/providers/state.provider.d.ts +11 -4
- package/dist/providers/state.provider.js +165 -132
- package/dist/types/intel.types.d.ts +8 -2
- package/dist/types/state.types.d.ts +11 -16
- package/dist/types.d.ts +5 -0
- package/dist/vanity.d.ts +2 -2
- package/dist/vanity.js +8 -11
- package/package.json +1 -1
- package/readme.md +79 -18
- package/src/index.ts +1 -0
- package/src/providers/action.provider.ts +1 -2
- package/src/providers/intel.provider.ts +182 -36
- package/src/providers/registry.provider.ts +24 -22
- package/src/providers/state.provider.ts +196 -151
- package/src/types/intel.types.ts +9 -1
- package/src/types/state.types.ts +14 -18
- package/src/types.ts +6 -0
- package/src/vanity.ts +15 -13
- package/tests/test_e2e.ts +145 -23
|
@@ -2,6 +2,7 @@ import { Connection, PublicKey } from '@solana/web3.js'
|
|
|
2
2
|
|
|
3
3
|
import { isPyreMint } from '../vanity'
|
|
4
4
|
import { isBlacklistedMint } from '../util'
|
|
5
|
+
import type { Stronghold } from '../types'
|
|
5
6
|
import type {
|
|
6
7
|
State,
|
|
7
8
|
AgentGameState,
|
|
@@ -11,6 +12,10 @@ import type {
|
|
|
11
12
|
} from '../types/state.types'
|
|
12
13
|
import { Registry } from '../types/registry.types'
|
|
13
14
|
|
|
15
|
+
// Pre-warm imports — resolved once, cached as module-level promises
|
|
16
|
+
const splTokenImport = import('@solana/spl-token')
|
|
17
|
+
const torchsdkImport = import('torchsdk')
|
|
18
|
+
|
|
14
19
|
const EMPTY_COUNTS: Record<TrackedAction, number> = {
|
|
15
20
|
join: 0,
|
|
16
21
|
defect: 0,
|
|
@@ -33,6 +38,11 @@ export class StateProvider implements State {
|
|
|
33
38
|
private checkpointConfig: CheckpointConfig | null = null
|
|
34
39
|
private ticksSinceCheckpoint = 0
|
|
35
40
|
|
|
41
|
+
// Lazy vault — undefined = not resolved, null = resolved to nothing
|
|
42
|
+
private _vaultCreator: string | null | undefined = undefined
|
|
43
|
+
private _stronghold: Stronghold | null | undefined = undefined
|
|
44
|
+
private _vaultPromise: Promise<void> | null = null
|
|
45
|
+
|
|
36
46
|
constructor(
|
|
37
47
|
private connection: Connection,
|
|
38
48
|
private registry: Registry,
|
|
@@ -42,9 +52,6 @@ export class StateProvider implements State {
|
|
|
42
52
|
get state() {
|
|
43
53
|
return this._state
|
|
44
54
|
}
|
|
45
|
-
get vaultCreator() {
|
|
46
|
-
return this._state?.vaultCreator ?? null
|
|
47
|
-
}
|
|
48
55
|
get initialized() {
|
|
49
56
|
return this._state?.initialized ?? false
|
|
50
57
|
}
|
|
@@ -52,86 +59,113 @@ export class StateProvider implements State {
|
|
|
52
59
|
return this._state?.tick ?? 0
|
|
53
60
|
}
|
|
54
61
|
|
|
55
|
-
/** Configure auto-checkpoint behavior */
|
|
56
62
|
setCheckpointConfig(config: CheckpointConfig) {
|
|
57
63
|
this.checkpointConfig = config
|
|
58
64
|
}
|
|
59
65
|
|
|
60
|
-
async
|
|
61
|
-
if (this.
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
66
|
+
private async resolveVault(): Promise<void> {
|
|
67
|
+
if (this._vaultCreator !== undefined) return
|
|
68
|
+
if (!this._vaultPromise) {
|
|
69
|
+
this._vaultPromise = (async () => {
|
|
70
|
+
const { getVaultForWallet } = await torchsdkImport
|
|
71
|
+
try {
|
|
72
|
+
const vault = await getVaultForWallet(this.connection, this.publicKey)
|
|
73
|
+
if (vault) {
|
|
74
|
+
this._vaultCreator = vault.creator
|
|
75
|
+
this._stronghold = {
|
|
76
|
+
address: vault.address,
|
|
77
|
+
creator: vault.creator,
|
|
78
|
+
authority: vault.authority,
|
|
79
|
+
sol_balance: vault.sol_balance,
|
|
80
|
+
total_deposited: vault.total_deposited,
|
|
81
|
+
total_withdrawn: vault.total_withdrawn,
|
|
82
|
+
total_spent: vault.total_spent,
|
|
83
|
+
total_received: vault.total_received,
|
|
84
|
+
linked_agents: vault.linked_wallets,
|
|
85
|
+
created_at: vault.created_at,
|
|
86
|
+
}
|
|
87
|
+
} else {
|
|
88
|
+
this._vaultCreator = null
|
|
89
|
+
this._stronghold = null
|
|
90
|
+
}
|
|
91
|
+
} catch {
|
|
92
|
+
this._vaultCreator = null
|
|
93
|
+
this._stronghold = null
|
|
94
|
+
}
|
|
95
|
+
this._vaultPromise = null
|
|
96
|
+
})()
|
|
80
97
|
}
|
|
98
|
+
return this._vaultPromise
|
|
99
|
+
}
|
|
81
100
|
|
|
82
|
-
|
|
101
|
+
async getVaultCreator(): Promise<string | null> {
|
|
102
|
+
await this.resolveVault()
|
|
103
|
+
return this._vaultCreator ?? null
|
|
104
|
+
}
|
|
83
105
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (vault) {
|
|
89
|
-
state.vaultCreator = vault.creator
|
|
90
|
-
state.stronghold = {
|
|
91
|
-
address: vault.address,
|
|
92
|
-
creator: vault.creator,
|
|
93
|
-
authority: vault.authority,
|
|
94
|
-
sol_balance: vault.sol_balance,
|
|
95
|
-
total_deposited: vault.total_deposited,
|
|
96
|
-
total_withdrawn: vault.total_withdrawn,
|
|
97
|
-
total_spent: vault.total_spent,
|
|
98
|
-
total_received: vault.total_received,
|
|
99
|
-
linked_agents: vault.linked_wallets,
|
|
100
|
-
created_at: vault.created_at,
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
} catch {}
|
|
106
|
+
async getStronghold(): Promise<Stronghold | null> {
|
|
107
|
+
await this.resolveVault()
|
|
108
|
+
return this._stronghold ?? null
|
|
109
|
+
}
|
|
104
110
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
state.actionCounts.repay_loan = Math.max(state.actionCounts.repay_loan, profile.repay_loans)
|
|
122
|
-
state.actionCounts.siege = Math.max(state.actionCounts.siege, profile.sieges)
|
|
123
|
-
state.actionCounts.ascend = Math.max(state.actionCounts.ascend, profile.ascends)
|
|
124
|
-
state.actionCounts.raze = Math.max(state.actionCounts.raze, profile.razes)
|
|
125
|
-
state.actionCounts.tithe = Math.max(state.actionCounts.tithe, profile.tithes)
|
|
126
|
-
|
|
127
|
-
const totalFromCheckpoint = Object.values(state.actionCounts).reduce((a, b) => a + b, 0)
|
|
128
|
-
state.tick = totalFromCheckpoint
|
|
111
|
+
async init(): Promise<AgentGameState> {
|
|
112
|
+
if (!this._state?.initialized) {
|
|
113
|
+
const state: AgentGameState = {
|
|
114
|
+
publicKey: this.publicKey,
|
|
115
|
+
tick: 0,
|
|
116
|
+
actionCounts: { ...EMPTY_COUNTS },
|
|
117
|
+
activeLoans: new Set(),
|
|
118
|
+
founded: [],
|
|
119
|
+
rallied: new Set(),
|
|
120
|
+
voted: new Set(),
|
|
121
|
+
sentiment: new Map(),
|
|
122
|
+
recentHistory: [],
|
|
123
|
+
personalitySummary: null,
|
|
124
|
+
totalSolSpent: 0,
|
|
125
|
+
totalSolReceived: 0,
|
|
126
|
+
initialized: false,
|
|
129
127
|
}
|
|
130
|
-
} catch {}
|
|
131
128
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
129
|
+
// Fire vault resolution in background — don't block init
|
|
130
|
+
this.resolveVault()
|
|
131
|
+
|
|
132
|
+
try {
|
|
133
|
+
const profile = await this.registry.getProfile(this.publicKey)
|
|
134
|
+
if (profile) {
|
|
135
|
+
state.personalitySummary = profile.personality_summary || null
|
|
136
|
+
state.totalSolSpent = profile.total_sol_spent
|
|
137
|
+
state.totalSolReceived = profile.total_sol_received
|
|
138
|
+
|
|
139
|
+
state.actionCounts.join = Math.max(state.actionCounts.join, profile.joins)
|
|
140
|
+
state.actionCounts.defect = Math.max(state.actionCounts.defect, profile.defects)
|
|
141
|
+
state.actionCounts.rally = Math.max(state.actionCounts.rally, profile.rallies)
|
|
142
|
+
state.actionCounts.launch = Math.max(state.actionCounts.launch, profile.launches)
|
|
143
|
+
state.actionCounts.message = Math.max(state.actionCounts.message, profile.messages)
|
|
144
|
+
state.actionCounts.reinforce = Math.max(state.actionCounts.reinforce, profile.reinforces)
|
|
145
|
+
state.actionCounts.fud = Math.max(state.actionCounts.fud, profile.fuds)
|
|
146
|
+
state.actionCounts.infiltrate = Math.max(
|
|
147
|
+
state.actionCounts.infiltrate,
|
|
148
|
+
profile.infiltrates,
|
|
149
|
+
)
|
|
150
|
+
state.actionCounts.war_loan = Math.max(state.actionCounts.war_loan, profile.war_loans)
|
|
151
|
+
state.actionCounts.repay_loan = Math.max(
|
|
152
|
+
state.actionCounts.repay_loan,
|
|
153
|
+
profile.repay_loans,
|
|
154
|
+
)
|
|
155
|
+
state.actionCounts.siege = Math.max(state.actionCounts.siege, profile.sieges)
|
|
156
|
+
state.actionCounts.ascend = Math.max(state.actionCounts.ascend, profile.ascends)
|
|
157
|
+
state.actionCounts.raze = Math.max(state.actionCounts.raze, profile.razes)
|
|
158
|
+
state.actionCounts.tithe = Math.max(state.actionCounts.tithe, profile.tithes)
|
|
159
|
+
|
|
160
|
+
const totalFromCheckpoint = Object.values(state.actionCounts).reduce((a, b) => a + b, 0)
|
|
161
|
+
state.tick = totalFromCheckpoint
|
|
162
|
+
}
|
|
163
|
+
} catch {}
|
|
164
|
+
|
|
165
|
+
state.initialized = true
|
|
166
|
+
this._state = state
|
|
167
|
+
}
|
|
168
|
+
return this._state
|
|
135
169
|
}
|
|
136
170
|
|
|
137
171
|
async record(action: TrackedAction, mint?: string, description?: string): Promise<void> {
|
|
@@ -156,7 +190,11 @@ export class StateProvider implements State {
|
|
|
156
190
|
}
|
|
157
191
|
}
|
|
158
192
|
|
|
159
|
-
|
|
193
|
+
// Sync P&L from vault every 10 ticks
|
|
194
|
+
if (this._state.tick % 10 === 0) {
|
|
195
|
+
this.syncPnl()
|
|
196
|
+
}
|
|
197
|
+
|
|
160
198
|
if (this.checkpointConfig && this.ticksSinceCheckpoint >= this.checkpointConfig.interval) {
|
|
161
199
|
this.ticksSinceCheckpoint = 0
|
|
162
200
|
this.onCheckpointDue?.()
|
|
@@ -167,15 +205,15 @@ export class StateProvider implements State {
|
|
|
167
205
|
if (!this._state) return
|
|
168
206
|
const current = this._state.sentiment.get(mint) ?? 0
|
|
169
207
|
const SENTIMENT_DELTAS: Partial<Record<TrackedAction, number>> = {
|
|
170
|
-
join: 1,
|
|
171
|
-
reinforce:
|
|
172
|
-
defect: -2,
|
|
173
|
-
rally: 3,
|
|
174
|
-
infiltrate: -5,
|
|
175
|
-
message: 0.
|
|
176
|
-
fud: -
|
|
177
|
-
war_loan: 1,
|
|
178
|
-
launch: 3,
|
|
208
|
+
join: 0.1,
|
|
209
|
+
reinforce: 0.15,
|
|
210
|
+
defect: -0.2,
|
|
211
|
+
rally: 0.3,
|
|
212
|
+
infiltrate: -0.5,
|
|
213
|
+
message: 0.05,
|
|
214
|
+
fud: -0.15,
|
|
215
|
+
war_loan: 0.1,
|
|
216
|
+
launch: 0.3,
|
|
179
217
|
}
|
|
180
218
|
|
|
181
219
|
const delta = SENTIMENT_DELTAS[action] ?? 0
|
|
@@ -186,44 +224,56 @@ export class StateProvider implements State {
|
|
|
186
224
|
|
|
187
225
|
onCheckpointDue: (() => void) | null = null
|
|
188
226
|
|
|
189
|
-
|
|
227
|
+
/** Sync totalSolSpent/Received from on-chain vault data (fresh read) */
|
|
228
|
+
private async syncPnl(): Promise<void> {
|
|
190
229
|
if (!this._state) return
|
|
191
|
-
|
|
192
|
-
const { TOKEN_2022_PROGRAM_ID } = await import('@solana/spl-token')
|
|
193
|
-
const walletPk = new PublicKey(this.publicKey)
|
|
194
|
-
|
|
195
|
-
let walletValues: any[] = []
|
|
196
230
|
try {
|
|
197
|
-
const
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
231
|
+
const { getVaultForWallet } = await torchsdkImport
|
|
232
|
+
const vault = await getVaultForWallet(this.connection, this.publicKey)
|
|
233
|
+
if (vault) {
|
|
234
|
+
this._state.totalSolSpent = Math.round(vault.total_spent * 1e9)
|
|
235
|
+
this._state.totalSolReceived = Math.round(vault.total_received * 1e9)
|
|
236
|
+
}
|
|
201
237
|
} catch {}
|
|
238
|
+
}
|
|
202
239
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
const vaultPk = new PublicKey(this._state.stronghold.address)
|
|
207
|
-
const vaultAccounts = await this.connection.getParsedTokenAccountsByOwner(vaultPk, {
|
|
208
|
-
programId: TOKEN_2022_PROGRAM_ID,
|
|
209
|
-
})
|
|
210
|
-
vaultValues = vaultAccounts.value
|
|
211
|
-
} catch {}
|
|
212
|
-
}
|
|
240
|
+
async getHoldings(): Promise<Map<string, number>> {
|
|
241
|
+
const { TOKEN_2022_PROGRAM_ID } = await splTokenImport
|
|
242
|
+
const walletPk = new PublicKey(this.publicKey)
|
|
213
243
|
|
|
214
|
-
|
|
244
|
+
// Parallel scan: wallet + vault
|
|
245
|
+
const stronghold = await this.getStronghold()
|
|
246
|
+
const scanWallet = this.connection
|
|
247
|
+
.getParsedTokenAccountsByOwner(walletPk, { programId: TOKEN_2022_PROGRAM_ID })
|
|
248
|
+
.then((r) => r.value)
|
|
249
|
+
.catch(() => [] as any[])
|
|
250
|
+
|
|
251
|
+
const scanVault = stronghold
|
|
252
|
+
? this.connection
|
|
253
|
+
.getParsedTokenAccountsByOwner(new PublicKey(stronghold.address), {
|
|
254
|
+
programId: TOKEN_2022_PROGRAM_ID,
|
|
255
|
+
})
|
|
256
|
+
.then((r) => r.value)
|
|
257
|
+
.catch(() => [] as any[])
|
|
258
|
+
: Promise.resolve([] as any[])
|
|
259
|
+
|
|
260
|
+
const [walletValues, vaultValues] = await Promise.all([scanWallet, scanVault])
|
|
261
|
+
|
|
262
|
+
const holdings = new Map<string, number>()
|
|
215
263
|
for (const a of [...walletValues, ...vaultValues]) {
|
|
216
264
|
const mint = a.account.data.parsed.info.mint as string
|
|
217
265
|
const balance = Number(a.account.data.parsed.info.tokenAmount.uiAmount ?? 0)
|
|
218
266
|
if (balance > 0 && isPyreMint(mint) && !isBlacklistedMint(mint)) {
|
|
219
|
-
|
|
267
|
+
holdings.set(mint, (holdings.get(mint) ?? 0) + balance)
|
|
220
268
|
}
|
|
221
269
|
}
|
|
222
270
|
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
271
|
+
return holdings
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
async getBalance(mint: string): Promise<number> {
|
|
275
|
+
const holdings = await this.getHoldings()
|
|
276
|
+
return holdings.get(mint) ?? 0
|
|
227
277
|
}
|
|
228
278
|
|
|
229
279
|
getSentiment(mint: string): number {
|
|
@@ -238,10 +288,6 @@ export class StateProvider implements State {
|
|
|
238
288
|
return this._state?.recentHistory ?? []
|
|
239
289
|
}
|
|
240
290
|
|
|
241
|
-
getBalance(mint: string): number {
|
|
242
|
-
return this._state?.holdings.get(mint) ?? 0
|
|
243
|
-
}
|
|
244
|
-
|
|
245
291
|
hasVoted(mint: string): boolean {
|
|
246
292
|
return this._state?.voted.has(mint) ?? false
|
|
247
293
|
}
|
|
@@ -259,51 +305,50 @@ export class StateProvider implements State {
|
|
|
259
305
|
}
|
|
260
306
|
|
|
261
307
|
serialize(): SerializedGameState {
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
totalSolReceived: this._state.totalSolReceived,
|
|
296
|
-
}
|
|
308
|
+
return !this._state
|
|
309
|
+
? {
|
|
310
|
+
publicKey: this.publicKey,
|
|
311
|
+
vaultCreator: null,
|
|
312
|
+
tick: 0,
|
|
313
|
+
actionCounts: { ...EMPTY_COUNTS },
|
|
314
|
+
holdings: {},
|
|
315
|
+
activeLoans: [],
|
|
316
|
+
founded: [],
|
|
317
|
+
rallied: [],
|
|
318
|
+
voted: [],
|
|
319
|
+
sentiment: {},
|
|
320
|
+
recentHistory: [],
|
|
321
|
+
personalitySummary: null,
|
|
322
|
+
totalSolSpent: 0,
|
|
323
|
+
totalSolReceived: 0,
|
|
324
|
+
}
|
|
325
|
+
: {
|
|
326
|
+
publicKey: this._state.publicKey,
|
|
327
|
+
vaultCreator: this._vaultCreator ?? null,
|
|
328
|
+
tick: this._state.tick,
|
|
329
|
+
actionCounts: { ...this._state.actionCounts },
|
|
330
|
+
holdings: {},
|
|
331
|
+
activeLoans: Array.from(this._state.activeLoans),
|
|
332
|
+
founded: [...this._state.founded],
|
|
333
|
+
rallied: Array.from(this._state.rallied),
|
|
334
|
+
voted: Array.from(this._state.voted),
|
|
335
|
+
sentiment: Object.fromEntries(this._state.sentiment),
|
|
336
|
+
recentHistory: this._state.recentHistory.slice(-20),
|
|
337
|
+
personalitySummary: this._state.personalitySummary,
|
|
338
|
+
totalSolSpent: this._state.totalSolSpent,
|
|
339
|
+
totalSolReceived: this._state.totalSolReceived,
|
|
340
|
+
}
|
|
297
341
|
}
|
|
298
342
|
|
|
299
343
|
hydrate(saved: SerializedGameState): void {
|
|
344
|
+
if (saved.vaultCreator) {
|
|
345
|
+
this._vaultCreator = saved.vaultCreator
|
|
346
|
+
}
|
|
347
|
+
|
|
300
348
|
this._state = {
|
|
301
349
|
publicKey: saved.publicKey,
|
|
302
|
-
vaultCreator: saved.vaultCreator,
|
|
303
|
-
stronghold: null, // will be resolved on next refreshHoldings or init
|
|
304
350
|
tick: saved.tick,
|
|
305
351
|
actionCounts: { ...EMPTY_COUNTS, ...saved.actionCounts },
|
|
306
|
-
holdings: new Map(Object.entries(saved.holdings)),
|
|
307
352
|
activeLoans: new Set(saved.activeLoans),
|
|
308
353
|
founded: [...saved.founded],
|
|
309
354
|
rallied: new Set(saved.rallied),
|
package/src/types/intel.types.ts
CHANGED
|
@@ -2,21 +2,29 @@ import {
|
|
|
2
2
|
AgentFactionPosition,
|
|
3
3
|
AgentProfile,
|
|
4
4
|
AllianceCluster,
|
|
5
|
+
FactionListResult,
|
|
5
6
|
FactionPower,
|
|
6
7
|
FactionStatus,
|
|
8
|
+
NearbyResult,
|
|
7
9
|
RivalFaction,
|
|
8
10
|
WorldEvent,
|
|
9
11
|
WorldStats,
|
|
10
12
|
} from '../types'
|
|
11
13
|
|
|
12
14
|
export interface Intel {
|
|
13
|
-
getAgentFactions(wallet: string
|
|
15
|
+
getAgentFactions(wallet: string): Promise<AgentFactionPosition[]>
|
|
14
16
|
getAgentProfile(wallet: string): Promise<AgentProfile>
|
|
15
17
|
getAgentSolLamports(wallet: string): Promise<number>
|
|
16
18
|
getAllies(mints: string[], holderLimit?: number): Promise<AllianceCluster[]>
|
|
19
|
+
getAscendedFactions(limit?: number): Promise<FactionListResult>
|
|
17
20
|
getFactionPower(mint: string): Promise<FactionPower>
|
|
18
21
|
getFactionLeaderboard(opts?: { status?: FactionStatus; limit?: number }): Promise<FactionPower[]>
|
|
19
22
|
getFactionRivals(mint: string, opts?: { limit?: number }): Promise<RivalFaction[]>
|
|
23
|
+
getNearbyFactions(
|
|
24
|
+
wallet: string,
|
|
25
|
+
opts?: { depth?: number; limit?: number },
|
|
26
|
+
): Promise<NearbyResult>
|
|
27
|
+
getRisingFactions(limit?: number): Promise<FactionListResult>
|
|
20
28
|
getWorldFeed(opts?: { limit?: number; factionLimit?: number }): Promise<WorldEvent[]>
|
|
21
29
|
getWorldStats(): Promise<WorldStats>
|
|
22
30
|
}
|
package/src/types/state.types.ts
CHANGED
|
@@ -21,16 +21,10 @@ export type TrackedAction =
|
|
|
21
21
|
export interface AgentGameState {
|
|
22
22
|
/** Agent wallet public key */
|
|
23
23
|
publicKey: string
|
|
24
|
-
/** Vault creator key (resolved from on-chain vault link) */
|
|
25
|
-
vaultCreator: string | null
|
|
26
|
-
/** Vault info (null if no vault found) */
|
|
27
|
-
stronghold: Stronghold | null
|
|
28
24
|
/** Monotonic tick counter — increments on each successful action */
|
|
29
25
|
tick: number
|
|
30
26
|
/** Cumulative action counts keyed by action type */
|
|
31
27
|
actionCounts: Record<TrackedAction, number>
|
|
32
|
-
/** Token holdings: mint → balance (wallet + vault combined) */
|
|
33
|
-
holdings: Map<string, number>
|
|
34
28
|
/** Mints with active war loans */
|
|
35
29
|
activeLoans: Set<string>
|
|
36
30
|
/** Mints this agent founded */
|
|
@@ -86,9 +80,6 @@ export interface State {
|
|
|
86
80
|
/** Current game state (null before init) */
|
|
87
81
|
readonly state: AgentGameState | null
|
|
88
82
|
|
|
89
|
-
/** Vault creator key (shorthand for state.vaultCreator) */
|
|
90
|
-
readonly vaultCreator: string | null
|
|
91
|
-
|
|
92
83
|
/** Whether state has been initialized */
|
|
93
84
|
readonly initialized: boolean
|
|
94
85
|
|
|
@@ -97,20 +88,28 @@ export interface State {
|
|
|
97
88
|
|
|
98
89
|
/**
|
|
99
90
|
* Initialize state from chain.
|
|
100
|
-
*
|
|
101
|
-
*
|
|
91
|
+
* Loads action counts from registry checkpoint.
|
|
92
|
+
* Vault and holdings are resolved lazily on first access.
|
|
102
93
|
*/
|
|
103
94
|
init(): Promise<AgentGameState>
|
|
104
95
|
|
|
105
96
|
/**
|
|
106
97
|
* Record a successful action — increments tick, updates action counts,
|
|
107
|
-
* updates sentiment, appends to history
|
|
108
|
-
* Called by ActionProvider after tx confirmation.
|
|
98
|
+
* updates sentiment, appends to history.
|
|
109
99
|
*/
|
|
110
100
|
record(action: TrackedAction, mint?: string, description?: string): Promise<void>
|
|
111
101
|
|
|
112
|
-
/**
|
|
113
|
-
|
|
102
|
+
/** Get vault creator key (lazy — resolves on first call, cached after) */
|
|
103
|
+
getVaultCreator(): Promise<string | null>
|
|
104
|
+
|
|
105
|
+
/** Get stronghold info (lazy — resolves on first call, cached after) */
|
|
106
|
+
getStronghold(): Promise<Stronghold | null>
|
|
107
|
+
|
|
108
|
+
/** Get token holdings fresh from chain (wallet + vault) */
|
|
109
|
+
getHoldings(): Promise<Map<string, number>>
|
|
110
|
+
|
|
111
|
+
/** Get token balance for a specific mint (fresh from chain) */
|
|
112
|
+
getBalance(mint: string): Promise<number>
|
|
114
113
|
|
|
115
114
|
/** Get sentiment score for a faction (-10 to +10) */
|
|
116
115
|
getSentiment(mint: string): number
|
|
@@ -121,9 +120,6 @@ export interface State {
|
|
|
121
120
|
/** Get recent action history (for LLM memory block) */
|
|
122
121
|
readonly history: readonly string[]
|
|
123
122
|
|
|
124
|
-
/** Get token balance for a specific mint */
|
|
125
|
-
getBalance(mint: string): number
|
|
126
|
-
|
|
127
123
|
/** Check if agent has voted on a faction */
|
|
128
124
|
hasVoted(mint: string): boolean
|
|
129
125
|
|
package/src/types.ts
CHANGED
|
@@ -402,6 +402,12 @@ export interface FactionPower {
|
|
|
402
402
|
status: FactionStatus
|
|
403
403
|
}
|
|
404
404
|
|
|
405
|
+
/** Result from getNearbyFactions — factions + discovered agents in the social graph */
|
|
406
|
+
export interface NearbyResult extends FactionListResult {
|
|
407
|
+
/** Wallet addresses discovered as co-holders (natural allies) */
|
|
408
|
+
allies: string[]
|
|
409
|
+
}
|
|
410
|
+
|
|
405
411
|
export interface AllianceCluster {
|
|
406
412
|
factions: string[]
|
|
407
413
|
shared_members: number
|
package/src/vanity.ts
CHANGED
|
@@ -42,23 +42,25 @@ export const getBondingCurvePda = (mint: PublicKey): [PublicKey, number] =>
|
|
|
42
42
|
export const getTokenTreasuryPda = (mint: PublicKey): [PublicKey, number] =>
|
|
43
43
|
PublicKey.findProgramAddressSync([Buffer.from(TREASURY_SEED), mint.toBuffer()], PROGRAM_ID)
|
|
44
44
|
|
|
45
|
-
const getTreasuryTokenAccount = (mint: PublicKey, treasury: PublicKey)
|
|
45
|
+
const getTreasuryTokenAccount = (mint: PublicKey, treasury: PublicKey) =>
|
|
46
46
|
getAssociatedTokenAddressSync(mint, treasury, true, TOKEN_2022_PROGRAM_ID)
|
|
47
47
|
|
|
48
48
|
export const getTreasuryLockPda = (mint: PublicKey): [PublicKey, number] =>
|
|
49
49
|
PublicKey.findProgramAddressSync([Buffer.from(TREASURY_LOCK_SEED), mint.toBuffer()], PROGRAM_ID)
|
|
50
50
|
|
|
51
|
-
const getTreasuryLockTokenAccount = (mint: PublicKey, treasuryLock: PublicKey)
|
|
51
|
+
const getTreasuryLockTokenAccount = (mint: PublicKey, treasuryLock: PublicKey) =>
|
|
52
52
|
getAssociatedTokenAddressSync(mint, treasuryLock, true, TOKEN_2022_PROGRAM_ID)
|
|
53
53
|
|
|
54
|
-
const makeDummyProvider = (connection: Connection, payer: PublicKey)
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
}
|
|
54
|
+
const makeDummyProvider = (connection: Connection, payer: PublicKey) =>
|
|
55
|
+
new AnchorProvider(
|
|
56
|
+
connection,
|
|
57
|
+
{
|
|
58
|
+
publicKey: payer,
|
|
59
|
+
signTransaction: async (t: Transaction) => t,
|
|
60
|
+
signAllTransactions: async (t: Transaction[]) => t,
|
|
61
|
+
} as unknown as Wallet,
|
|
62
|
+
{},
|
|
63
|
+
)
|
|
62
64
|
|
|
63
65
|
const finalizeTransaction = async (
|
|
64
66
|
connection: Connection,
|
|
@@ -72,9 +74,9 @@ const finalizeTransaction = async (
|
|
|
72
74
|
|
|
73
75
|
// ── Vanity grinder ──
|
|
74
76
|
|
|
75
|
-
const PYRE_SUFFIX = '
|
|
77
|
+
const PYRE_SUFFIX = 'pw'
|
|
76
78
|
|
|
77
|
-
/** Grind for a keypair whose base58 address ends with "
|
|
79
|
+
/** Grind for a keypair whose base58 address ends with "pw" (pyreworld) */
|
|
78
80
|
export const grindPyreMint = (maxAttempts: number = 500_000): Keypair => {
|
|
79
81
|
for (let i = 0; i < maxAttempts; i++) {
|
|
80
82
|
const kp = Keypair.generate()
|
|
@@ -86,7 +88,7 @@ export const grindPyreMint = (maxAttempts: number = 500_000): Keypair => {
|
|
|
86
88
|
return Keypair.generate()
|
|
87
89
|
}
|
|
88
90
|
|
|
89
|
-
/** Check if a mint address is a pyre faction (ends with "
|
|
91
|
+
/** Check if a mint address is a pyre faction (ends with "pw") */
|
|
90
92
|
export const isPyreMint = (mint: string): boolean => mint.endsWith(PYRE_SUFFIX)
|
|
91
93
|
|
|
92
94
|
// ── Build create transaction with pyre vanity address ──
|