@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.
- package/lib/shipload.d.ts +231 -86
- package/lib/shipload.js +378 -53
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +368 -51
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +50 -7
- package/lib/testing.js +151 -22
- package/lib/testing.js.map +1 -1
- package/lib/testing.m.js +151 -22
- package/lib/testing.m.js.map +1 -1
- package/package.json +1 -1
- package/src/contracts/server.ts +138 -18
- package/src/index-module.ts +22 -8
- package/src/managers/actions.ts +14 -4
- package/src/managers/jobs.test.ts +25 -9
- package/src/managers/jobs.ts +8 -4
- package/src/receipts.ts +9 -9
- package/src/scheduling/jobs.test.ts +417 -18
- package/src/scheduling/jobs.ts +222 -16
- package/src/scheduling/lanes.ts +53 -1
package/src/index-module.ts
CHANGED
|
@@ -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
|
|
39
|
-
export {
|
|
40
|
-
|
|
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'
|
package/src/managers/actions.ts
CHANGED
|
@@ -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
|
|
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
|
|
43
|
-
const
|
|
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 () => [
|
|
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('
|
|
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(
|
package/src/managers/jobs.ts
CHANGED
|
@@ -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
|
|
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
|
|
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
|
|
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
|
|
4
|
+
export type WindowReceipt = ServerContract.Types.window_receipt
|
|
5
5
|
|
|
6
|
-
export function
|
|
6
|
+
export function decodeWindowReceipt(data: unknown): WindowReceipt {
|
|
7
7
|
if (data === null || data === undefined) {
|
|
8
|
-
throw new Error('
|
|
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.
|
|
11
|
+
return Serializer.decode({data, type: ServerContract.Types.window_receipt})
|
|
12
12
|
}
|
|
13
|
-
return ServerContract.Types.
|
|
13
|
+
return ServerContract.Types.window_receipt.from(data as ServerContract.Types.window_receipt)
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
export function
|
|
17
|
-
return receipt.
|
|
16
|
+
export function windowReceiptStartsAtMs(receipt: WindowReceipt): number {
|
|
17
|
+
return receipt.starts_at.toMilliseconds()
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
export function
|
|
21
|
-
return
|
|
20
|
+
export function windowReceiptCompletesAtMs(receipt: WindowReceipt): number {
|
|
21
|
+
return receipt.completes_at.toMilliseconds()
|
|
22
22
|
}
|