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.
@@ -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 init(): Promise<AgentGameState> {
61
- if (this._state?.initialized) return this._state
62
-
63
- const state: AgentGameState = {
64
- publicKey: this.publicKey,
65
- vaultCreator: null,
66
- stronghold: null,
67
- tick: 0,
68
- actionCounts: { ...EMPTY_COUNTS },
69
- holdings: new Map(),
70
- activeLoans: new Set(),
71
- founded: [],
72
- rallied: new Set(),
73
- voted: new Set(),
74
- sentiment: new Map(),
75
- recentHistory: [],
76
- personalitySummary: null,
77
- totalSolSpent: 0,
78
- totalSolReceived: 0,
79
- initialized: false,
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
- this._state = state
101
+ async getVaultCreator(): Promise<string | null> {
102
+ await this.resolveVault()
103
+ return this._vaultCreator ?? null
104
+ }
83
105
 
84
- // resolve vault link
85
- const { getVaultForWallet } = await import('torchsdk')
86
- try {
87
- const vault = await getVaultForWallet(this.connection, this.publicKey)
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
- try {
106
- const profile = await this.registry.getProfile(this.publicKey)
107
- if (profile) {
108
- state.personalitySummary = profile.personality_summary || null
109
- state.totalSolSpent = profile.total_sol_spent
110
- state.totalSolReceived = profile.total_sol_received
111
-
112
- state.actionCounts.join = Math.max(state.actionCounts.join, profile.joins)
113
- state.actionCounts.defect = Math.max(state.actionCounts.defect, profile.defects)
114
- state.actionCounts.rally = Math.max(state.actionCounts.rally, profile.rallies)
115
- state.actionCounts.launch = Math.max(state.actionCounts.launch, profile.launches)
116
- state.actionCounts.message = Math.max(state.actionCounts.message, profile.messages)
117
- state.actionCounts.reinforce = Math.max(state.actionCounts.reinforce, profile.reinforces)
118
- state.actionCounts.fud = Math.max(state.actionCounts.fud, profile.fuds)
119
- state.actionCounts.infiltrate = Math.max(state.actionCounts.infiltrate, profile.infiltrates)
120
- state.actionCounts.war_loan = Math.max(state.actionCounts.war_loan, profile.war_loans)
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
- await this.refreshHoldings()
133
- state.initialized = true
134
- return state
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
- await this.refreshHoldings()
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: 1.5,
172
- defect: -2,
173
- rally: 3,
174
- infiltrate: -5,
175
- message: 0.5,
176
- fud: -1.5,
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
- async refreshHoldings(): Promise<void> {
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 walletAccounts = await this.connection.getParsedTokenAccountsByOwner(walletPk, {
198
- programId: TOKEN_2022_PROGRAM_ID,
199
- })
200
- walletValues = walletAccounts.value
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
- let vaultValues: any[] = []
204
- if (this._state.stronghold) {
205
- try {
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
- const newHoldings = new Map<string, number>()
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
- newHoldings.set(mint, (newHoldings.get(mint) ?? 0) + balance)
267
+ holdings.set(mint, (holdings.get(mint) ?? 0) + balance)
220
268
  }
221
269
  }
222
270
 
223
- this._state.holdings.clear()
224
- for (const [mint, balance] of newHoldings) {
225
- this._state.holdings.set(mint, balance)
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
- if (!this._state) {
263
- return {
264
- publicKey: this.publicKey,
265
- vaultCreator: null,
266
- tick: 0,
267
- actionCounts: { ...EMPTY_COUNTS },
268
- holdings: {},
269
- activeLoans: [],
270
- founded: [],
271
- rallied: [],
272
- voted: [],
273
- sentiment: {},
274
- recentHistory: [],
275
- personalitySummary: null,
276
- totalSolSpent: 0,
277
- totalSolReceived: 0,
278
- }
279
- }
280
-
281
- return {
282
- publicKey: this._state.publicKey,
283
- vaultCreator: this._state.vaultCreator,
284
- tick: this._state.tick,
285
- actionCounts: { ...this._state.actionCounts },
286
- holdings: Object.fromEntries(this._state.holdings),
287
- activeLoans: Array.from(this._state.activeLoans),
288
- founded: [...this._state.founded],
289
- rallied: Array.from(this._state.rallied),
290
- voted: Array.from(this._state.voted),
291
- sentiment: Object.fromEntries(this._state.sentiment),
292
- recentHistory: this._state.recentHistory.slice(-20),
293
- personalitySummary: this._state.personalitySummary,
294
- totalSolSpent: this._state.totalSolSpent,
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),
@@ -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, factionLimit?: number): Promise<AgentFactionPosition[]>
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
  }
@@ -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
- * Resolves vault link, loads holdings, loads action counts from registry checkpoint.
101
- * Must be called before any action. Returns the resolved state.
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, refreshes holdings.
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
- /** Refresh holdings from on-chain (wallet + vault token accounts) */
113
- refreshHoldings(): Promise<void>
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): 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): 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): AnchorProvider => {
55
- const dummyWallet = {
56
- publicKey: payer,
57
- signTransaction: async (t: Transaction) => t,
58
- signAllTransactions: async (t: Transaction[]) => t,
59
- }
60
- return new AnchorProvider(connection, dummyWallet as unknown as Wallet, {})
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 = 'py'
77
+ const PYRE_SUFFIX = 'pw'
76
78
 
77
- /** Grind for a keypair whose base58 address ends with "py" */
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 "py") */
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 ──