pyre-world-kit 2.0.12 → 3.0.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/.prettierrc.json +6 -0
- package/dist/index.d.ts +46 -4
- package/dist/index.js +105 -85
- package/dist/providers/action.provider.d.ts +46 -0
- package/dist/providers/action.provider.js +331 -0
- package/dist/providers/intel.provider.d.ts +29 -0
- package/dist/providers/intel.provider.js +363 -0
- package/dist/providers/mapper.provider.d.ts +197 -0
- package/dist/providers/mapper.provider.js +158 -0
- package/dist/providers/registry.provider.d.ts +25 -0
- package/dist/providers/registry.provider.js +229 -0
- package/dist/providers/state.provider.d.ts +42 -0
- package/dist/providers/state.provider.js +348 -0
- package/dist/pyre_world.json +34 -229
- package/dist/types/action.types.d.ts +41 -0
- package/dist/types/action.types.js +2 -0
- package/dist/types/intel.types.d.ts +20 -0
- package/dist/types/intel.types.js +2 -0
- package/dist/types/mapper.types.d.ts +27 -0
- package/dist/types/mapper.types.js +22 -0
- package/dist/types/registry.types.d.ts +0 -0
- package/dist/types/registry.types.js +1 -0
- package/dist/types/state.types.d.ts +112 -0
- package/dist/types/state.types.js +2 -0
- package/dist/types.d.ts +8 -24
- package/dist/util.d.ts +29 -0
- package/dist/util.js +144 -0
- package/dist/vanity.d.ts +3 -3
- package/dist/vanity.js +18 -15
- package/package.json +4 -2
- package/readme.md +184 -142
- package/src/index.ts +133 -92
- package/src/providers/action.provider.ts +443 -0
- package/src/providers/intel.provider.ts +383 -0
- package/src/providers/mapper.provider.ts +195 -0
- package/src/providers/registry.provider.ts +277 -0
- package/src/providers/state.provider.ts +357 -0
- package/src/pyre_world.json +35 -230
- package/src/types/action.types.ts +76 -0
- package/src/types/intel.types.ts +22 -0
- package/src/types/mapper.types.ts +84 -0
- package/src/types/registry.types.ts +0 -0
- package/src/types/state.types.ts +144 -0
- package/src/types.ts +329 -333
- package/src/util.ts +148 -0
- package/src/vanity.ts +27 -14
- package/tests/test_e2e.ts +339 -172
- package/src/actions.ts +0 -719
- package/src/intel.ts +0 -521
- package/src/mappers.ts +0 -302
- package/src/registry.ts +0 -317
- package/tests/test_devnet_e2e.ts +0 -401
- package/tests/test_sim.ts +0 -458
package/tests/test_devnet_e2e.ts
DELETED
|
@@ -1,401 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pyre Kit Devnet E2E Test
|
|
3
|
-
*
|
|
4
|
-
* Tests the full faction warfare flow on Solana devnet.
|
|
5
|
-
* Creates a faction with a "py" vanity mint, joins, rallies, defects.
|
|
6
|
-
*
|
|
7
|
-
* Run:
|
|
8
|
-
* npx tsx tests/test_devnet_e2e.ts
|
|
9
|
-
*
|
|
10
|
-
* Requirements:
|
|
11
|
-
* - Devnet wallet (~/.config/solana/id.json) with ~5 SOL
|
|
12
|
-
* - Torch Market program deployed to devnet
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
// Must be set before any torchsdk imports
|
|
16
|
-
process.env.TORCH_NETWORK = 'devnet'
|
|
17
|
-
|
|
18
|
-
import {
|
|
19
|
-
Connection,
|
|
20
|
-
Keypair,
|
|
21
|
-
LAMPORTS_PER_SOL,
|
|
22
|
-
Transaction,
|
|
23
|
-
SystemProgram,
|
|
24
|
-
} from '@solana/web3.js'
|
|
25
|
-
import {
|
|
26
|
-
createEphemeralAgent,
|
|
27
|
-
createStronghold,
|
|
28
|
-
fundStronghold,
|
|
29
|
-
recruitAgent,
|
|
30
|
-
launchFaction,
|
|
31
|
-
getFactions,
|
|
32
|
-
getFaction,
|
|
33
|
-
getJoinQuote,
|
|
34
|
-
joinFaction,
|
|
35
|
-
directJoinFaction,
|
|
36
|
-
getComms,
|
|
37
|
-
rally,
|
|
38
|
-
defect,
|
|
39
|
-
getMembers,
|
|
40
|
-
getStrongholdForAgent,
|
|
41
|
-
isPyreMint,
|
|
42
|
-
} from '../src/index'
|
|
43
|
-
import * as fs from 'fs'
|
|
44
|
-
import * as path from 'path'
|
|
45
|
-
import * as os from 'os'
|
|
46
|
-
|
|
47
|
-
// ============================================================================
|
|
48
|
-
// Config
|
|
49
|
-
// ============================================================================
|
|
50
|
-
|
|
51
|
-
const DEVNET_RPC = 'https://api.devnet.solana.com'
|
|
52
|
-
const WALLET_PATH = path.join(os.homedir(), '.config/solana/id.json')
|
|
53
|
-
|
|
54
|
-
// ============================================================================
|
|
55
|
-
// Helpers
|
|
56
|
-
// ============================================================================
|
|
57
|
-
|
|
58
|
-
const loadWallet = (): Keypair => {
|
|
59
|
-
const raw = JSON.parse(fs.readFileSync(WALLET_PATH, 'utf-8'))
|
|
60
|
-
return Keypair.fromSecretKey(Uint8Array.from(raw))
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const log = (msg: string) => {
|
|
64
|
-
const ts = new Date().toISOString().substr(11, 8)
|
|
65
|
-
console.log(`[${ts}] ${msg}`)
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms))
|
|
69
|
-
|
|
70
|
-
const signAndSend = async (
|
|
71
|
-
connection: Connection,
|
|
72
|
-
signer: Keypair,
|
|
73
|
-
tx: Transaction,
|
|
74
|
-
): Promise<string> => {
|
|
75
|
-
tx.partialSign(signer)
|
|
76
|
-
const sig = await connection.sendRawTransaction(tx.serialize(), {
|
|
77
|
-
skipPreflight: false,
|
|
78
|
-
preflightCommitment: 'confirmed',
|
|
79
|
-
})
|
|
80
|
-
await connection.confirmTransaction(sig, 'confirmed')
|
|
81
|
-
return sig
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
let passed = 0
|
|
85
|
-
let failed = 0
|
|
86
|
-
const ok = (name: string, detail?: string) => {
|
|
87
|
-
passed++
|
|
88
|
-
log(` ✓ ${name}${detail ? ` — ${detail}` : ''}`)
|
|
89
|
-
}
|
|
90
|
-
const fail = (name: string, err: any) => {
|
|
91
|
-
failed++
|
|
92
|
-
log(` ✗ ${name} — ${err.message || err}`)
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// ============================================================================
|
|
96
|
-
// Main
|
|
97
|
-
// ============================================================================
|
|
98
|
-
|
|
99
|
-
async function main() {
|
|
100
|
-
console.log('='.repeat(60))
|
|
101
|
-
console.log('PYRE KIT — DEVNET E2E TEST')
|
|
102
|
-
console.log('='.repeat(60))
|
|
103
|
-
|
|
104
|
-
const connection = new Connection(DEVNET_RPC, 'confirmed')
|
|
105
|
-
const wallet = loadWallet()
|
|
106
|
-
const walletAddr = wallet.publicKey.toBase58()
|
|
107
|
-
|
|
108
|
-
log(`Wallet: ${walletAddr}`)
|
|
109
|
-
const balance = await connection.getBalance(wallet.publicKey)
|
|
110
|
-
log(`Balance: ${(balance / LAMPORTS_PER_SOL).toFixed(2)} SOL`)
|
|
111
|
-
|
|
112
|
-
if (balance < 3 * LAMPORTS_PER_SOL) {
|
|
113
|
-
console.error('Need at least ~3 SOL on devnet.')
|
|
114
|
-
process.exit(1)
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
// ================================================================
|
|
118
|
-
// 1. Create ephemeral agents
|
|
119
|
-
// ================================================================
|
|
120
|
-
log('\n[1] Creating ephemeral agents')
|
|
121
|
-
const agent1 = createEphemeralAgent()
|
|
122
|
-
const agent2 = createEphemeralAgent()
|
|
123
|
-
log(` Agent 1: ${agent1.publicKey}`)
|
|
124
|
-
log(` Agent 2: ${agent2.publicKey}`)
|
|
125
|
-
|
|
126
|
-
// Fund agents from main wallet
|
|
127
|
-
const fundTx = new Transaction().add(
|
|
128
|
-
SystemProgram.transfer({
|
|
129
|
-
fromPubkey: wallet.publicKey,
|
|
130
|
-
toPubkey: agent1.keypair.publicKey,
|
|
131
|
-
lamports: 1.5 * LAMPORTS_PER_SOL,
|
|
132
|
-
}),
|
|
133
|
-
SystemProgram.transfer({
|
|
134
|
-
fromPubkey: wallet.publicKey,
|
|
135
|
-
toPubkey: agent2.keypair.publicKey,
|
|
136
|
-
lamports: 0.5 * LAMPORTS_PER_SOL,
|
|
137
|
-
}),
|
|
138
|
-
)
|
|
139
|
-
const { blockhash } = await connection.getLatestBlockhash()
|
|
140
|
-
fundTx.recentBlockhash = blockhash
|
|
141
|
-
fundTx.feePayer = wallet.publicKey
|
|
142
|
-
await signAndSend(connection, wallet, fundTx)
|
|
143
|
-
ok('Fund agents', '1.5 SOL + 0.5 SOL')
|
|
144
|
-
|
|
145
|
-
await sleep(500)
|
|
146
|
-
|
|
147
|
-
// ================================================================
|
|
148
|
-
// 2. Create stronghold
|
|
149
|
-
// ================================================================
|
|
150
|
-
log('\n[2] Creating stronghold')
|
|
151
|
-
try {
|
|
152
|
-
const result = await createStronghold(connection, {
|
|
153
|
-
creator: agent1.publicKey,
|
|
154
|
-
})
|
|
155
|
-
await signAndSend(connection, agent1.keypair, result.transaction)
|
|
156
|
-
ok('Create stronghold')
|
|
157
|
-
} catch (e: any) {
|
|
158
|
-
if (e.message?.includes('already in use')) {
|
|
159
|
-
ok('Create stronghold', 'already exists')
|
|
160
|
-
} else {
|
|
161
|
-
fail('Create stronghold', e)
|
|
162
|
-
}
|
|
163
|
-
}
|
|
164
|
-
|
|
165
|
-
await sleep(500)
|
|
166
|
-
|
|
167
|
-
// ================================================================
|
|
168
|
-
// 3. Fund stronghold
|
|
169
|
-
// ================================================================
|
|
170
|
-
log('\n[3] Funding stronghold')
|
|
171
|
-
try {
|
|
172
|
-
const result = await fundStronghold(connection, {
|
|
173
|
-
depositor: agent1.publicKey,
|
|
174
|
-
stronghold_creator: agent1.publicKey,
|
|
175
|
-
amount_sol: 1 * LAMPORTS_PER_SOL,
|
|
176
|
-
})
|
|
177
|
-
await signAndSend(connection, agent1.keypair, result.transaction)
|
|
178
|
-
ok('Fund stronghold', '1 SOL')
|
|
179
|
-
} catch (e: any) {
|
|
180
|
-
fail('Fund stronghold', e)
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
await sleep(500)
|
|
184
|
-
|
|
185
|
-
// ================================================================
|
|
186
|
-
// 4. Verify stronghold link
|
|
187
|
-
// ================================================================
|
|
188
|
-
log('\n[4] Verifying stronghold')
|
|
189
|
-
try {
|
|
190
|
-
const stronghold = await getStrongholdForAgent(connection, agent1.publicKey)
|
|
191
|
-
if (stronghold) {
|
|
192
|
-
ok('Stronghold link', `balance=${(stronghold.sol_balance / LAMPORTS_PER_SOL).toFixed(2)} SOL, agents=${stronghold.linked_agents}`)
|
|
193
|
-
} else {
|
|
194
|
-
fail('Stronghold link', { message: 'not found' })
|
|
195
|
-
}
|
|
196
|
-
} catch (e: any) {
|
|
197
|
-
fail('Stronghold link', e)
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// ================================================================
|
|
201
|
-
// 5. Launch faction (with py vanity mint!)
|
|
202
|
-
// ================================================================
|
|
203
|
-
log('\n[5] Launching faction (grinding py vanity mint...)')
|
|
204
|
-
let factionMint: string = ''
|
|
205
|
-
try {
|
|
206
|
-
const startTime = Date.now()
|
|
207
|
-
const result = await launchFaction(connection, {
|
|
208
|
-
founder: agent1.publicKey,
|
|
209
|
-
name: 'Devnet Pyre Faction',
|
|
210
|
-
symbol: 'DPYRE',
|
|
211
|
-
metadata_uri: 'https://torch.market/test-metadata.json',
|
|
212
|
-
community_faction: true,
|
|
213
|
-
})
|
|
214
|
-
const grindMs = Date.now() - startTime
|
|
215
|
-
await signAndSend(connection, agent1.keypair, result.transaction)
|
|
216
|
-
factionMint = result.mint.toBase58()
|
|
217
|
-
|
|
218
|
-
const hasPySuffix = isPyreMint(factionMint)
|
|
219
|
-
ok('Launch faction', `mint=${factionMint.slice(0, 8)}...${factionMint.slice(-4)} vanity=${hasPySuffix ? 'py✓' : 'MISS'} grind=${grindMs}ms`)
|
|
220
|
-
|
|
221
|
-
if (!hasPySuffix) {
|
|
222
|
-
log(' ⚠ Vanity grind did not find "py" suffix — faction still works but won\'t be filtered as pyre')
|
|
223
|
-
}
|
|
224
|
-
} catch (e: any) {
|
|
225
|
-
fail('Launch faction', e)
|
|
226
|
-
console.error('Cannot continue without faction. Exiting.')
|
|
227
|
-
process.exit(1)
|
|
228
|
-
}
|
|
229
|
-
|
|
230
|
-
await sleep(1000)
|
|
231
|
-
|
|
232
|
-
// ================================================================
|
|
233
|
-
// 6. List factions
|
|
234
|
-
// ================================================================
|
|
235
|
-
log('\n[6] Listing factions')
|
|
236
|
-
try {
|
|
237
|
-
const factions = await getFactions(connection, { limit: 10 })
|
|
238
|
-
const ourFaction = factions.factions.find(f => f.mint === factionMint)
|
|
239
|
-
ok('List factions', `total=${factions.total}, ours=${ourFaction ? 'found' : 'not found'}`)
|
|
240
|
-
} catch (e: any) {
|
|
241
|
-
fail('List factions', e)
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
// ================================================================
|
|
245
|
-
// 7. Get faction detail
|
|
246
|
-
// ================================================================
|
|
247
|
-
log('\n[7] Getting faction detail')
|
|
248
|
-
try {
|
|
249
|
-
const detail = await getFaction(connection, factionMint)
|
|
250
|
-
ok('Faction detail', `name=${detail.name} status=${detail.status} tier=${detail.tier}`)
|
|
251
|
-
} catch (e: any) {
|
|
252
|
-
fail('Faction detail', e)
|
|
253
|
-
}
|
|
254
|
-
|
|
255
|
-
// ================================================================
|
|
256
|
-
// 8. Get join quote
|
|
257
|
-
// ================================================================
|
|
258
|
-
log('\n[8] Getting join quote (0.1 SOL)')
|
|
259
|
-
let tokensOut = 0
|
|
260
|
-
try {
|
|
261
|
-
const quote = await getJoinQuote(connection, factionMint, 0.1 * LAMPORTS_PER_SOL)
|
|
262
|
-
tokensOut = quote.tokens_to_user
|
|
263
|
-
ok('Join quote', `tokens=${tokensOut} impact=${quote.price_impact_percent}%`)
|
|
264
|
-
} catch (e: any) {
|
|
265
|
-
fail('Join quote', e)
|
|
266
|
-
}
|
|
267
|
-
|
|
268
|
-
// ================================================================
|
|
269
|
-
// 9. Join faction via vault
|
|
270
|
-
// ================================================================
|
|
271
|
-
log('\n[9] Joining faction via vault')
|
|
272
|
-
try {
|
|
273
|
-
const result = await joinFaction(connection, {
|
|
274
|
-
mint: factionMint,
|
|
275
|
-
agent: agent1.publicKey,
|
|
276
|
-
amount_sol: 0.1 * LAMPORTS_PER_SOL,
|
|
277
|
-
strategy: 'fortify',
|
|
278
|
-
message: 'First blood. The pyre burns.',
|
|
279
|
-
stronghold: agent1.publicKey,
|
|
280
|
-
})
|
|
281
|
-
await signAndSend(connection, agent1.keypair, result.transaction)
|
|
282
|
-
ok('Join faction', result.message)
|
|
283
|
-
} catch (e: any) {
|
|
284
|
-
fail('Join faction', e)
|
|
285
|
-
}
|
|
286
|
-
|
|
287
|
-
await sleep(1000)
|
|
288
|
-
|
|
289
|
-
// ================================================================
|
|
290
|
-
// 10. Agent 2 joins directly (no vault)
|
|
291
|
-
// ================================================================
|
|
292
|
-
log('\n[10] Agent 2 joins directly')
|
|
293
|
-
try {
|
|
294
|
-
const result = await directJoinFaction(connection, {
|
|
295
|
-
mint: factionMint,
|
|
296
|
-
agent: agent2.publicKey,
|
|
297
|
-
amount_sol: 0.05 * LAMPORTS_PER_SOL,
|
|
298
|
-
strategy: 'scorched_earth',
|
|
299
|
-
message: 'Reporting for duty.',
|
|
300
|
-
})
|
|
301
|
-
await signAndSend(connection, agent2.keypair, result.transaction)
|
|
302
|
-
ok('Agent 2 join', result.message)
|
|
303
|
-
} catch (e: any) {
|
|
304
|
-
fail('Agent 2 join', e)
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
await sleep(1000)
|
|
308
|
-
|
|
309
|
-
// ================================================================
|
|
310
|
-
// 11. Read comms
|
|
311
|
-
// ================================================================
|
|
312
|
-
log('\n[11] Reading comms')
|
|
313
|
-
try {
|
|
314
|
-
const comms = await getComms(connection, factionMint)
|
|
315
|
-
ok('Read comms', `total=${comms.total}`)
|
|
316
|
-
for (const c of comms.comms) {
|
|
317
|
-
log(` ${c.sender.slice(0, 8)}...: "${c.memo}"`)
|
|
318
|
-
}
|
|
319
|
-
} catch (e: any) {
|
|
320
|
-
fail('Read comms', e)
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// ================================================================
|
|
324
|
-
// 12. Rally (agent 2 — can't rally your own faction)
|
|
325
|
-
// ================================================================
|
|
326
|
-
log('\n[12] Agent 2 rallies faction')
|
|
327
|
-
try {
|
|
328
|
-
const result = await rally(connection, {
|
|
329
|
-
mint: factionMint,
|
|
330
|
-
agent: agent2.publicKey,
|
|
331
|
-
})
|
|
332
|
-
await signAndSend(connection, agent2.keypair, result.transaction)
|
|
333
|
-
ok('Rally')
|
|
334
|
-
|
|
335
|
-
const detail = await getFaction(connection, factionMint)
|
|
336
|
-
log(` Rallies: ${detail.rallies}`)
|
|
337
|
-
} catch (e: any) {
|
|
338
|
-
fail('Rally', e)
|
|
339
|
-
}
|
|
340
|
-
|
|
341
|
-
await sleep(500)
|
|
342
|
-
|
|
343
|
-
// ================================================================
|
|
344
|
-
// 13. Defect (agent 1 sells half)
|
|
345
|
-
// ================================================================
|
|
346
|
-
log('\n[13] Agent 1 defects (partial)')
|
|
347
|
-
try {
|
|
348
|
-
const sellAmount = Math.floor(tokensOut / 2)
|
|
349
|
-
if (sellAmount < 1) {
|
|
350
|
-
ok('Defect', 'skipped — no tokens')
|
|
351
|
-
} else {
|
|
352
|
-
const result = await defect(connection, {
|
|
353
|
-
mint: factionMint,
|
|
354
|
-
agent: agent1.publicKey,
|
|
355
|
-
amount_tokens: sellAmount,
|
|
356
|
-
message: 'Strategic withdrawal.',
|
|
357
|
-
stronghold: agent1.publicKey,
|
|
358
|
-
})
|
|
359
|
-
await signAndSend(connection, agent1.keypair, result.transaction)
|
|
360
|
-
ok('Defect', `sold ${sellAmount} tokens`)
|
|
361
|
-
}
|
|
362
|
-
} catch (e: any) {
|
|
363
|
-
fail('Defect', e)
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
await sleep(500)
|
|
367
|
-
|
|
368
|
-
// ================================================================
|
|
369
|
-
// 14. Check members
|
|
370
|
-
// ================================================================
|
|
371
|
-
log('\n[14] Checking members')
|
|
372
|
-
try {
|
|
373
|
-
const members = await getMembers(connection, factionMint)
|
|
374
|
-
ok('Members', `total=${members.total_members}`)
|
|
375
|
-
for (const m of members.members.slice(0, 5)) {
|
|
376
|
-
log(` ${m.address.slice(0, 8)}... — ${m.percentage.toFixed(2)}%`)
|
|
377
|
-
}
|
|
378
|
-
} catch (e: any) {
|
|
379
|
-
fail('Members', e)
|
|
380
|
-
}
|
|
381
|
-
|
|
382
|
-
// ================================================================
|
|
383
|
-
// Summary
|
|
384
|
-
// ================================================================
|
|
385
|
-
const finalBalance = await connection.getBalance(wallet.publicKey)
|
|
386
|
-
const solSpent = (balance - finalBalance) / LAMPORTS_PER_SOL
|
|
387
|
-
|
|
388
|
-
console.log('\n' + '='.repeat(60))
|
|
389
|
-
console.log(`RESULTS: ${passed} passed, ${failed} failed`)
|
|
390
|
-
console.log(`Faction mint: ${factionMint}`)
|
|
391
|
-
console.log(`Vanity "py" suffix: ${isPyreMint(factionMint) ? 'YES' : 'NO'}`)
|
|
392
|
-
console.log(`SOL spent: ${solSpent.toFixed(4)} SOL (${(finalBalance / LAMPORTS_PER_SOL).toFixed(2)} remaining)`)
|
|
393
|
-
console.log('='.repeat(60))
|
|
394
|
-
|
|
395
|
-
process.exit(failed > 0 ? 1 : 0)
|
|
396
|
-
}
|
|
397
|
-
|
|
398
|
-
main().catch((e) => {
|
|
399
|
-
console.error('\nFATAL:', e)
|
|
400
|
-
process.exit(1)
|
|
401
|
-
})
|