@@ -15,93 +15,116 @@ import type { ConnectedWallet } from '@/hooks/useCardano';
1515import { useChallengeStore } from '@/stores/challenge' ;
1616
1717const tx3File = `tx create_ship(
18- p_pos_x: Int, // Ship Position X
19- p_pos_y: Int, // Ship Position Y
20- ship_name: Bytes, // Name of the ship
21- pilot_name: Bytes, // Name of the pilot
22- tip_slot: Int, // TODO: remove when tip_slot() implemented
18+ p_pos_x: Int, // Ship Position X
19+ p_pos_y: Int, // Ship Position Y
20+ ship_name: Bytes, // Name of the ship
21+ pilot_name: Bytes, // Name of the pilot
22+ tip_slot: Int, // TODO: remove when tip_slot() implemented
23+ last_move_timestamp: Int,
2324) {
24- locals {
25- initial_fuel: 480 , // Should be taken from spaceTime datum
26- ship_mint_lovelace_fee: 1000000, // Should be taken from asteria script datum
27- spacetime_policy_hash: 0x0291ae7aebaf064b785542093c2b13169effb34462301e68d4b44f43,
28- spacetime_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#1,
29- asteria_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#0,
30- pellet_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#2,
31- }
25+ locals {
26+ initial_fuel: 5 , // Should be taken from spaceTime datum
27+ ship_mint_lovelace_fee: 1000000, // Should be taken from asteria script datum
28+ spacetime_policy_hash: 0x0291ae7aebaf064b785542093c2b13169effb34462301e68d4b44f43,
29+ spacetime_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#1,
30+ asteria_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#0,
31+ pellet_policy_ref: 0x3d308c0f3deb1eff764cbb765452c53d30704748681d7acd61c7775aeb8a8e46#2,
32+ }
3233
33- validity {
34- until_slot: tip_slot, // tip_slot() + 300
35- }
34+ validity {
35+ until_slot: tip_slot, // tip_slot() + 300
36+ }
3637
37- reference SpacetimeRef {
38- ref: spacetime_policy_ref,
39- }
38+ reference SpacetimeRef {
39+ ref: spacetime_policy_ref,
40+ }
4041
41- reference AsteriaRef {
42- ref: asteria_policy_ref,
43- }
42+ reference AsteriaRef {
43+ ref: asteria_policy_ref,
44+ }
4445
45- reference PelletRef {
46- ref: pellet_policy_ref,
47- }
46+ reference PelletRef {
47+ ref: pellet_policy_ref,
48+ }
4849
49- input source {
50- from: Player,
51- min_amount: fees + Ada(ship_mint_lovelace_fee),
52- }
50+ input* gas {
51+ from: Player,
52+ min_amount: fees + Ada(ship_mint_lovelace_fee) + min_utxo(pilot_token) + min_utxo(new_ship) + min_utxo(gas_change ),
53+ }
5354
54- input asteria {
55- from: AsteriaPolicy,
56- min_amount: AdminToken(1),
57- datum_is: AsteriaDatum,
58- }
59-
60- mint {
61- amount: AnyAsset(spacetime_policy_hash, pilot_name, 1) + AnyAsset(spacetime_policy_hash, ship_name, 1),
62- redeemer: (),
63- }
55+ input asteria {
56+ from: AsteriaPolicy,
57+ min_amount: AdminToken(1),
58+ datum_is: AsteriaDatum,
59+ redeemer: AsteriaRedeemer::AddNewShip {},
60+ }
61+
62+ mint {
63+ amount: AnyAsset(spacetime_policy_hash, pilot_name, 1) + AnyAsset(spacetime_policy_hash, ship_name, 1),
64+ redeemer: ShipyardRedeemer::MintShip {},
65+ }
6466
65- mint {
66- amount: Fuel(initial_fuel),
67- redeemer: () ,
68- }
67+ mint {
68+ amount: Fuel(initial_fuel),
69+ redeemer: FuelRedeemer::MintFuel {} ,
70+ }
6971
70- output {
71- to: Player,
72- amount: source - fees - Ada(ship_mint_lovelace_fee) + AnyAsset(spacetime_policy_hash, pilot_name, 1),
73- }
72+ output pilot_token {
73+ to: Player,
74+ amount: AnyAsset(spacetime_policy_hash, pilot_name, 1) + min_utxo(pilot_token ),
75+ }
7476
75- output {
76- to: AsteriaPolicy,
77- amount: asteria + Ada(ship_mint_lovelace_fee),
78- datum: AsteriaDatum {
79- ship_counter: asteria.ship_counter + 1,
80- shipyard_policy: asteria.shipyard_policy,
81- },
82- }
77+ output updated_asteria {
78+ to: AsteriaPolicy,
79+ amount: asteria + Ada(ship_mint_lovelace_fee),
80+ datum: AsteriaDatum {
81+ ship_counter: asteria.ship_counter + 1,
82+ shipyard_policy: asteria.shipyard_policy,
83+ },
84+ }
8385
84- output {
85- to: SpacetimePolicy,
86- amount: AnyAsset(spacetime_policy_hash, ship_name, 1) + Fuel(initial_fuel),
87- datum: ShipDatum {
88- pos_x: p_pos_x,
89- pos_y: p_pos_y,
90- ship_token_name: ship_name,
91- pilot_token_name: pilot_name,
92- last_move_latest_time: tip_slot,
93- },
94- }
86+ output new_ship {
87+ to: SpacetimePolicy,
88+ amount: AnyAsset(spacetime_policy_hash, ship_name, 1) + Fuel(initial_fuel) + min_utxo(new_ship),
89+ datum: ShipDatum {
90+ pos_x: p_pos_x,
91+ pos_y: p_pos_y,
92+ ship_token_name: ship_name,
93+ pilot_token_name: pilot_name,
94+ last_move_latest_time: last_move_timestamp,
95+ },
96+ }
97+
98+ output gas_change {
99+ to: Player,
100+ amount: gas - fees - Ada(ship_mint_lovelace_fee) - min_utxo(pilot_token) - min_utxo(new_ship),
101+ }
102+
103+ collateral {
104+ from: Player,
105+ min_amount: fees,
106+ }
95107}` ;
96108
97- const jsFile = `const result = await protocol.createShipTx({
109+ const jsFile = `const playerAddress = process.env.PLAYER_ADDRESS;
110+ const positionX = 4; // Replace with your desired start X position
111+ const positionY = -50; // Replace with your desired start Y position
112+ const shipName = "SHIP0"; // Replace 0 with the next ship number
113+ const pilotName = "PILOT0"; // Replace 0 with the next ship number
114+ const tipSlot = 165246231; // Replace with the latest block slot
115+ const lastMoveTimestamp = Date.now() + 300_000;
116+
117+ const args: CreateShipParams = {
98118 player: playerAddress,
99119 pPosX: positionX,
100120 pPosY: positionY,
101- pilotName: new TextEncoder().encode(\`PILOT\${shipNumber}\`),
102- shipName: new TextEncoder().encode(\`SHIP\${shipNumber}\`),
103- tipSlot: blockSlotValue + 300, // 5 minutes from last block
104- });` ;
121+ pilotName: new TextEncoder().encode(pilotName),
122+ shipName: new TextEncoder().encode(shipName),
123+ tipSlot: tipSlot + 300, // 5 minutes from last block
124+ lastMoveTimestamp,
125+ };
126+
127+ const response = await client.createShipTx(args);` ;
105128
106129interface CreateShipProps {
107130 isActive : boolean ;
@@ -116,6 +139,8 @@ export default function CreateShip(props: CreateShipProps) {
116139 const [ position , setPosition ] = useState < { x : number ; y : number } | null > ( null ) ;
117140 const [ wallet , setWallet ] = useState < ConnectedWallet | null > ( null ) ;
118141 const [ address , setAddress ] = useState < string > ( '' ) ;
142+ const [ shipNumber , setShipNumber ] = useState < number | undefined > ( undefined ) ;
143+ const [ tipSlot , setTipSlot ] = useState < number | undefined > ( undefined ) ;
119144
120145 const errors = formState . errors || { } ;
121146 const dataTx = formState . data ?. tx ;
@@ -155,6 +180,36 @@ export default function CreateShip(props: CreateShipProps) {
155180 setAddress ( connectedWallet ?. changeAddress || '' ) ;
156181 }
157182
183+ const handleFetchShipNumber = async ( ) => {
184+ const shipRes = await ( await fetch ( "https://8000-ethereal-audience-bb83g6.us1.demeter.run/graphql" , {
185+ "headers" : { "content-type" : "application/json" } ,
186+ "body" : "{\"query\":\"query { nextShipTokenName(spacetimePolicyId: \\\"0291ae7aebaf064b785542093c2b13169effb34462301e68d4b44f43\\\", spacetimeAddress: \\\"addr1wypfrtn6awhsvjmc24pqj0ptzvtfalang33rq8ng6j6y7scnlkytx\\\") { shipName pilotName } }\",\"variables\":{}}" ,
187+ "method" : "POST"
188+ } ) ) . json ( ) ;
189+
190+ console . log ( shipRes ) ;
191+
192+ setShipNumber ( parseInt ( shipRes . data . nextShipTokenName . shipName . replace ( 'SHIP' , '' ) ) ) ;
193+ }
194+
195+ const updateShipNumber = ( event : ChangeEvent < HTMLInputElement > ) => {
196+ setShipNumber ( parseInt ( event . target . value ) ) ;
197+ }
198+
199+ const handleFetchLastSlot = async ( ) => {
200+ const slotRes = await ( await fetch ( "https://8000-ethereal-audience-bb83g6.us1.demeter.run/graphql" , {
201+ "headers" : { "content-type" : "application/json" } ,
202+ "body" : "{\"query\":\"query { lastSlot { slot } }\"}" ,
203+ "method" : "POST"
204+ } ) ) . json ( ) ;
205+
206+ setTipSlot ( slotRes . data . lastSlot . slot ) ;
207+ }
208+
209+ const updateTipSlot = ( event : ChangeEvent < HTMLInputElement > ) => {
210+ setTipSlot ( parseInt ( event . target . value ) ) ;
211+ }
212+
158213 const handleSubmit = async ( event : React . FormEvent < HTMLFormElement > ) => {
159214 event . preventDefault ( ) ;
160215 setSubmitting ( true ) ;
@@ -179,9 +234,9 @@ export default function CreateShip(props: CreateShipProps) {
179234
180235 return (
181236 < Tabs className = "w-full h-full overflow-hidden" contentClassName = "overflow-auto" >
182- { /* <Tab label="Description">
237+ < Tab label = "Description" >
183238 < CreateShipDescription />
184- </Tab> */ }
239+ </ Tab >
185240
186241 < Tab label = "Tx Form" >
187242 < form className = "flex flex-col gap-8 justify-between h-full" onSubmit = { handleSubmit } >
@@ -199,7 +254,7 @@ export default function CreateShip(props: CreateShipProps) {
199254
200255 < ConnectWallet onWalletConnected = { handleWallet } />
201256
202- < div className = "w-full flex flex-row gap-x-4" >
257+ < div className = "w-full flex flex-row gap-x-4 mt-[-16px] " >
203258 < Input
204259 name = "shipNumber"
205260 type = "number"
@@ -208,16 +263,25 @@ export default function CreateShip(props: CreateShipProps) {
208263 label = "Ship Number"
209264 error = { errors . shipNumber }
210265 disabled = { submitting }
266+ button = "fetch last"
267+ onClickButton = { handleFetchShipNumber }
268+ value = { shipNumber }
269+ onChange = { updateShipNumber }
211270 required
212271 />
272+
213273 < Input
214274 name = "blockSlot"
215275 type = "number"
216276 placeholder = "Latest block slot"
217277 containerClassName = "flex-1"
218278 label = "Latest block slot"
219- error = { errors . shipNumber }
279+ error = { errors . blockSlot }
220280 disabled = { submitting }
281+ button = "fetch last"
282+ onClickButton = { handleFetchLastSlot }
283+ value = { tipSlot }
284+ onChange = { updateTipSlot }
221285 required
222286 />
223287 </ div >
0 commit comments