@shipload/sdk 1.0.0-next.70 → 1.0.0-next.71

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.
@@ -35,13 +35,9 @@ export type cargo_item = ServerContract.Types.cargo_item
35
35
  export type entity_row = ServerContract.Types.entity_row
36
36
  export type craftjob_row = ServerContract.Types.craftjob_row
37
37
  export type buildjob_row = ServerContract.Types.buildjob_row
38
- export type booking_receipt = ServerContract.Types.booking_receipt
39
- export {
40
- decodeBookingReceipt,
41
- bookingReceiptLandsAtMs,
42
- bookingReceiptRuntimeSeconds,
43
- } from './receipts'
44
- export type {BookingReceipt} from './receipts'
38
+ export type window_receipt = ServerContract.Types.window_receipt
39
+ export {decodeWindowReceipt, windowReceiptStartsAtMs, windowReceiptCompletesAtMs} from './receipts'
40
+ export type {WindowReceipt} from './receipts'
45
41
 
46
42
  export type location_static = ServerContract.Types.location_static
47
43
  export type location_derived = ServerContract.Types.location_derived
@@ -289,6 +285,7 @@ export type {
289
285
  } from './scheduling/schedule'
290
286
  export {
291
287
  candidateLaneCompletesAt,
288
+ candidateCivicDepositWindow,
292
289
  laneKeyForModule,
293
290
  rawScheduleEnd,
294
291
  resolveLaneGatherer,
@@ -335,10 +332,27 @@ export {
335
332
  JOB_QUEUE_CAP,
336
333
  jobStatus,
337
334
  jobStatusLabel,
335
+ jobDropoffTask,
336
+ jobCancelRoute,
337
+ buildJobCancelRoute,
338
+ jobCancellable,
339
+ jobCancellationBlockReason,
338
340
  jobDeposited,
339
341
  splitJobCargo,
342
+ workshopAvailability,
343
+ pickupsInFlight,
344
+ } from './scheduling/jobs'
345
+ export type {
346
+ JobWindow,
347
+ JobLane,
348
+ JobLaneEntry,
349
+ JobStatus,
350
+ JobStatusInput,
351
+ JobCancelRoute,
352
+ JobCancellationBlockReason,
353
+ OwnedJob,
354
+ PickupInFlight,
340
355
  } from './scheduling/jobs'
341
- export type {JobWindow, JobLane, JobLaneEntry, JobStatus, OwnedJob} from './scheduling/jobs'
342
356
 
343
357
  export {composeIdleResolve} from './scheduling/idle-resolve'
344
358
  export type {CounterpartLookup, IdleResolveTarget} from './scheduling/idle-resolve'
@@ -24,6 +24,7 @@ import {Coordinates, PRECISION, type ClusterSlotType, type CoordinatesType} from
24
24
  import {ServerContract, TokenContract} from '../contracts'
25
25
  import {ATOMICASSETS_ABI, SHIPLOAD_COLLECTION} from '../nft/atomicassets'
26
26
  import {getItem} from '../data/catalog'
27
+ import type {JobCancelRoute} from '../scheduling/jobs'
27
28
 
28
29
  const CHARGE_K = 100n
29
30
  const ENERGY_DIVISOR = 10n
@@ -515,7 +516,6 @@ export class ActionsManager extends BaseManager {
515
516
  craftjob(
516
517
  shipId: UInt64Type,
517
518
  workshopId: UInt64Type,
518
- slot: UInt8Type,
519
519
  recipeId: UInt16Type,
520
520
  quantity: UInt32Type,
521
521
  inputs: ServerContract.ActionParams.Type.cargo_item[]
@@ -523,7 +523,6 @@ export class ActionsManager extends BaseManager {
523
523
  const params: ServerContract.ActionParams.craftjob = {
524
524
  ship_id: UInt64.from(shipId),
525
525
  workshop_id: UInt64.from(workshopId),
526
- slot: UInt8.from(slot),
527
526
  recipe_id: UInt16.from(recipeId),
528
527
  quantity: UInt32.from(quantity),
529
528
  inputs,
@@ -531,6 +530,19 @@ export class ActionsManager extends BaseManager {
531
530
  return this.server.action('craftjob', params)
532
531
  }
533
532
 
533
+ cancelcraft(jobId: UInt64Type): Action {
534
+ const params: ServerContract.ActionParams.cancelcraft = {
535
+ job_id: UInt64.from(jobId),
536
+ }
537
+ return this.server.action('cancelcraft', params)
538
+ }
539
+
540
+ canceljob(route: JobCancelRoute): Action {
541
+ if (route.kind === 'dropoff') return this.cancel(route.shipId, route.laneKey, route.count)
542
+ if (route.kind === 'build') return this.cancelbuild(route.jobId)
543
+ return this.cancelcraft(route.jobId)
544
+ }
545
+
534
546
  clustercraft(
535
547
  entityId: UInt64Type,
536
548
  recipeId: number,
@@ -565,14 +577,12 @@ export class ActionsManager extends BaseManager {
565
577
  buildjob(
566
578
  targetId: UInt64Type,
567
579
  dockId: UInt64Type,
568
- slot: UInt8Type,
569
580
  targetItemId: UInt16Type,
570
581
  inputs: ServerContract.ActionParams.Type.cargo_item[]
571
582
  ): Action {
572
583
  const params: ServerContract.ActionParams.buildjob = {
573
584
  target_id: UInt64.from(targetId),
574
585
  dock_id: UInt64.from(dockId),
575
- slot: UInt8.from(slot),
576
586
  target_item_id: UInt16.from(targetItemId),
577
587
  inputs,
578
588
  }
@@ -12,6 +12,7 @@ const row = (over: Record<string, unknown> = {}) => ({
12
12
  coords: {x: {toNumber: () => 12}, y: {toNumber: () => 34}},
13
13
  starts_at: {toDate: () => new Date('2026-07-26T10:00:00Z')},
14
14
  completes_at: {toDate: () => new Date('2026-07-26T11:00:00Z')},
15
+ arrives_at: {toDate: () => new Date('2026-07-26T09:45:00Z')},
15
16
  recipe_id: {toNumber: () => 10001},
16
17
  quantity: {toNumber: () => 5},
17
18
  energy_paid: {toNumber: () => 0},
@@ -26,37 +27,52 @@ function managerWith(queryImpl: () => Promise<unknown[]>, allImpl: () => Promise
26
27
  }
27
28
 
28
29
  describe('JobsManager.getOwnedJobs', () => {
29
- it('parses a landed row: cargo is the output, no inputs, status derived', async () => {
30
+ it('parses a deposited row: inputs then the output tail, status derived', async () => {
30
31
  const m = managerWith(
31
- async () => [row()],
32
+ async () => [row({cargo: [{item: 'in'}, {item: 'out'}]})],
32
33
  async () => []
33
34
  )
34
35
  const jobs = await m.getOwnedJobs(OWNER, {now: new Date('2026-07-26T11:30:00Z')})
35
36
  expect(jobs).toHaveLength(1)
36
37
  expect(jobs[0]).toMatchObject({id: 7, building: 42, quantity: 5, status: 'ready'})
38
+ expect(jobs[0].arrivesAt).toEqual(new Date('2026-07-26T09:45:00Z'))
37
39
  expect(jobs[0].coords).toEqual({x: 12, y: 34})
38
40
  expect(jobs[0].output).toEqual({item: 'out'} as never)
39
- expect(jobs[0].inputs).toEqual([] as never)
41
+ expect(jobs[0].inputs).toEqual([{item: 'in'}] as never)
40
42
  })
41
43
 
42
- it('reports a job In Line rather than ready, whatever its zero window says', async () => {
43
- const inLine = row({
44
- starts_at: {toDate: () => new Date(0)},
45
- completes_at: {toDate: () => new Date(0)},
44
+ it('reports an undeposited row as dropping off, whatever its window says', async () => {
45
+ const inFlight = row({
46
46
  deposited: false,
47
47
  cargo: [{item: 'in'}],
48
48
  })
49
49
  const m = managerWith(
50
- async () => [inLine],
50
+ async () => [inFlight],
51
51
  async () => []
52
52
  )
53
53
  const jobs = await m.getOwnedJobs(OWNER, {now: new Date('2026-07-26T11:30:00Z')})
54
- expect(jobs[0].status).toBe('inline')
54
+ expect(jobs[0].status).toBe('dropping')
55
55
  expect(jobs[0].deposited).toBe(false)
56
56
  expect(jobs[0].output).toBeNull()
57
57
  expect(jobs[0].inputs).toEqual([{item: 'in'}] as never)
58
58
  })
59
59
 
60
+ it('reports a cancelled row as ready with its inputs held', async () => {
61
+ const cancelled = row({
62
+ quantity: {toNumber: () => 0},
63
+ deposited: true,
64
+ cargo: [{item: 'in'}],
65
+ })
66
+ const m = managerWith(
67
+ async () => [cancelled],
68
+ async () => []
69
+ )
70
+ const jobs = await m.getOwnedJobs(OWNER, {now: new Date('2026-07-26T09:00:00Z')})
71
+ expect(jobs[0].status).toBe('ready')
72
+ expect(jobs[0].output).toBeNull()
73
+ expect(jobs[0].inputs).toEqual([{item: 'in'}] as never)
74
+ })
75
+
60
76
  it('drops rows whose owner does not match (positional-index safety re-filter)', async () => {
61
77
  const other = row({owner: Name.from('someoneelse.gm')})
62
78
  const m = managerWith(
@@ -32,19 +32,23 @@ export class JobsManager extends BaseManager {
32
32
  private parseOwnedJob(r: JobRow, now: Date): OwnedJob {
33
33
  const startsAt = r.starts_at.toDate()
34
34
  const completesAt = r.completes_at.toDate()
35
+ const arrivesAt = r.arrives_at.toDate()
35
36
  const deposited = jobDeposited(r.deposited)
36
- const {output, inputs} = splitJobCargo(r.cargo, deposited)
37
+ const quantity = r.quantity.toNumber()
38
+ const building = r.building.toNumber()
39
+ const {output, inputs} = splitJobCargo(r.cargo, deposited, quantity)
37
40
  return {
38
41
  id: r.id.toNumber(),
39
- building: r.building.toNumber(),
42
+ building,
40
43
  socket: r.socket.toNumber(),
41
44
  shipId: r.ship_id.toNumber(),
42
45
  coords: {x: r.coords.x.toNumber(), y: r.coords.y.toNumber()},
43
46
  startsAt,
44
47
  completesAt,
48
+ arrivesAt,
45
49
  recipeId: r.recipe_id.toNumber(),
46
- quantity: r.quantity.toNumber(),
47
- status: jobStatus({startsAt, completesAt, deposited}, now),
50
+ quantity,
51
+ status: jobStatus({startsAt, completesAt, deposited, quantity, building, inputs}, now),
48
52
  deposited,
49
53
  output,
50
54
  inputs,
package/src/receipts.ts CHANGED
@@ -1,22 +1,22 @@
1
1
  import {Serializer} from '@wharfkit/antelope'
2
2
  import {ServerContract} from './contracts'
3
3
 
4
- export type BookingReceipt = ServerContract.Types.booking_receipt
4
+ export type WindowReceipt = ServerContract.Types.window_receipt
5
5
 
6
- export function decodeBookingReceipt(data: unknown): BookingReceipt {
6
+ export function decodeWindowReceipt(data: unknown): WindowReceipt {
7
7
  if (data === null || data === undefined) {
8
- throw new Error('decodeBookingReceipt: no return value')
8
+ throw new Error('decodeWindowReceipt: no return value')
9
9
  }
10
10
  if (data instanceof Uint8Array || typeof data === 'string') {
11
- return Serializer.decode({data, type: ServerContract.Types.booking_receipt})
11
+ return Serializer.decode({data, type: ServerContract.Types.window_receipt})
12
12
  }
13
- return ServerContract.Types.booking_receipt.from(data as ServerContract.Types.booking_receipt)
13
+ return ServerContract.Types.window_receipt.from(data as ServerContract.Types.window_receipt)
14
14
  }
15
15
 
16
- export function bookingReceiptLandsAtMs(receipt: BookingReceipt): number {
17
- return receipt.lands_at.toMilliseconds()
16
+ export function windowReceiptStartsAtMs(receipt: WindowReceipt): number {
17
+ return receipt.starts_at.toMilliseconds()
18
18
  }
19
19
 
20
- export function bookingReceiptRuntimeSeconds(receipt: BookingReceipt): number {
21
- return Number(receipt.runtime)
20
+ export function windowReceiptCompletesAtMs(receipt: WindowReceipt): number {
21
+ return receipt.completes_at.toMilliseconds()
22
22
  }