@shipload/sdk 1.0.0-next.4 → 1.0.0-next.41

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.
Files changed (134) hide show
  1. package/lib/scan.d.ts +34 -0
  2. package/lib/scan.js +136 -0
  3. package/lib/scan.js.map +1 -0
  4. package/lib/scan.m.js +129 -0
  5. package/lib/scan.m.js.map +1 -0
  6. package/lib/shipload.d.ts +2473 -973
  7. package/lib/shipload.js +11529 -5211
  8. package/lib/shipload.js.map +1 -1
  9. package/lib/shipload.m.js +11338 -5162
  10. package/lib/shipload.m.js.map +1 -1
  11. package/lib/testing.d.ts +970 -0
  12. package/lib/testing.js +4013 -0
  13. package/lib/testing.js.map +1 -0
  14. package/lib/testing.m.js +4007 -0
  15. package/lib/testing.m.js.map +1 -0
  16. package/package.json +20 -2
  17. package/src/capabilities/craftable.ts +51 -0
  18. package/src/capabilities/crafting.test.ts +7 -0
  19. package/src/capabilities/crafting.ts +5 -6
  20. package/src/capabilities/gathering.test.ts +16 -0
  21. package/src/capabilities/gathering.ts +35 -18
  22. package/src/capabilities/index.ts +0 -1
  23. package/src/capabilities/modules.ts +9 -0
  24. package/src/capabilities/storage.ts +16 -1
  25. package/src/contracts/platform.ts +231 -3
  26. package/src/contracts/server.ts +1021 -481
  27. package/src/coordinates/address.ts +88 -0
  28. package/src/coordinates/constants.test.ts +15 -0
  29. package/src/coordinates/constants.ts +23 -0
  30. package/src/coordinates/index.ts +15 -0
  31. package/src/coordinates/memo.test.ts +47 -0
  32. package/src/coordinates/memo.ts +20 -0
  33. package/src/coordinates/permutation.ts +77 -0
  34. package/src/coordinates/regions.ts +48 -0
  35. package/src/coordinates/sectors.ts +115 -0
  36. package/src/data/capabilities.ts +12 -5
  37. package/src/data/capability-formulas.ts +14 -7
  38. package/src/data/catalog.ts +0 -5
  39. package/src/data/colors.ts +14 -47
  40. package/src/data/entities.json +76 -10
  41. package/src/data/item-ids.ts +18 -12
  42. package/src/data/items.json +321 -38
  43. package/src/data/kind-registry.json +109 -0
  44. package/src/data/kind-registry.ts +165 -0
  45. package/src/data/metadata.ts +119 -33
  46. package/src/data/recipes-runtime.ts +3 -23
  47. package/src/data/recipes.json +238 -117
  48. package/src/derivation/build-methods.ts +45 -0
  49. package/src/derivation/capabilities.test.ts +151 -0
  50. package/src/derivation/capabilities.ts +512 -0
  51. package/src/derivation/capability-mappings.ts +9 -12
  52. package/src/derivation/crafting.ts +23 -24
  53. package/src/derivation/index.ts +25 -2
  54. package/src/derivation/recipe-usage.test.ts +78 -0
  55. package/src/derivation/recipe-usage.ts +141 -0
  56. package/src/derivation/reserve-regen.ts +34 -0
  57. package/src/derivation/resources.ts +125 -38
  58. package/src/derivation/rollups.test.ts +55 -0
  59. package/src/derivation/rollups.ts +56 -0
  60. package/src/derivation/stars.test.ts +51 -0
  61. package/src/derivation/stars.ts +15 -0
  62. package/src/derivation/stats.ts +6 -6
  63. package/src/derivation/stratum.ts +17 -20
  64. package/src/derivation/tiers.ts +40 -7
  65. package/src/derivation/wormhole.ts +136 -0
  66. package/src/entities/entity.ts +98 -0
  67. package/src/entities/gamestate.ts +3 -28
  68. package/src/entities/makers.ts +124 -134
  69. package/src/entities/slot-multiplier.ts +43 -0
  70. package/src/errors.ts +12 -16
  71. package/src/format.ts +26 -4
  72. package/src/index-module.ts +267 -47
  73. package/src/managers/actions.ts +528 -95
  74. package/src/managers/base.ts +6 -2
  75. package/src/managers/construction-types.ts +80 -0
  76. package/src/managers/construction.ts +412 -0
  77. package/src/managers/context.ts +20 -1
  78. package/src/managers/coordinates.ts +14 -0
  79. package/src/managers/entities.ts +18 -66
  80. package/src/managers/epochs.ts +40 -0
  81. package/src/managers/index.ts +17 -1
  82. package/src/managers/locations.ts +25 -29
  83. package/src/managers/nft.test.ts +14 -0
  84. package/src/managers/nft.ts +70 -0
  85. package/src/managers/plot.ts +122 -0
  86. package/src/nft/atomicassets.abi.json +1342 -0
  87. package/src/nft/atomicassets.ts +237 -0
  88. package/src/nft/atomicdata.ts +130 -0
  89. package/src/nft/buildImmutableData.ts +338 -0
  90. package/src/nft/description.ts +98 -24
  91. package/src/nft/index.ts +3 -0
  92. package/src/planner/index.ts +127 -0
  93. package/src/planner/planner.test.ts +319 -0
  94. package/src/resolution/describe-module.ts +18 -13
  95. package/src/resolution/display-name.ts +38 -10
  96. package/src/resolution/resolve-item.test.ts +37 -0
  97. package/src/resolution/resolve-item.ts +55 -24
  98. package/src/scan/index.ts +180 -0
  99. package/src/scan/scan-wasm.base64.ts +2 -0
  100. package/src/scheduling/accessor.ts +68 -22
  101. package/src/scheduling/availability.ts +108 -0
  102. package/src/scheduling/cancel.test.ts +348 -0
  103. package/src/scheduling/cancel.ts +209 -0
  104. package/src/scheduling/energy.ts +47 -0
  105. package/src/scheduling/idle-resolve.ts +45 -0
  106. package/src/scheduling/lane-core.ts +128 -0
  107. package/src/scheduling/lanes.test.ts +249 -0
  108. package/src/scheduling/lanes.ts +198 -0
  109. package/src/scheduling/projection.ts +209 -105
  110. package/src/scheduling/schedule.ts +241 -104
  111. package/src/scheduling/task-cargo.ts +46 -0
  112. package/src/shipload.ts +21 -1
  113. package/src/subscriptions/manager.ts +229 -142
  114. package/src/subscriptions/mappers.ts +5 -8
  115. package/src/subscriptions/types.ts +11 -3
  116. package/src/testing/catalog-hash.ts +19 -0
  117. package/src/testing/index.ts +2 -0
  118. package/src/testing/projection-parity.ts +167 -0
  119. package/src/travel/reach.ts +23 -0
  120. package/src/travel/route-planner.ts +196 -0
  121. package/src/travel/travel.ts +200 -112
  122. package/src/types/capabilities.ts +29 -6
  123. package/src/types/entity.ts +3 -3
  124. package/src/types/index.ts +0 -1
  125. package/src/types.ts +28 -13
  126. package/src/utils/cargo.ts +27 -0
  127. package/src/utils/display-name.ts +70 -0
  128. package/src/utils/system.ts +36 -24
  129. package/src/capabilities/loading.ts +0 -8
  130. package/src/entities/container.ts +0 -108
  131. package/src/entities/ship-deploy.ts +0 -259
  132. package/src/entities/ship.ts +0 -204
  133. package/src/entities/warehouse.ts +0 -119
  134. package/src/types/entity-traits.ts +0 -69
@@ -1,6 +1,7 @@
1
1
  import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
2
  import {BaseManager} from './base'
3
3
  import {type EpochInfo, getCurrentEpoch, getEpochInfo} from '../scheduling/epoch'
4
+ import type {ServerContract} from '../contracts'
4
5
 
5
6
  export class EpochsManager extends BaseManager {
6
7
  async getCurrentHeight(): Promise<UInt64> {
@@ -8,6 +9,11 @@ export class EpochsManager extends BaseManager {
8
9
  return getCurrentEpoch(game)
9
10
  }
10
11
 
12
+ async getFinalizedEpoch(reload = false): Promise<UInt64> {
13
+ const state = await this.getState(reload)
14
+ return state.currentEpoch
15
+ }
16
+
11
17
  async getCurrent(): Promise<EpochInfo> {
12
18
  const game = await this.getGame()
13
19
  const epoch = await this.getCurrentHeight()
@@ -44,4 +50,38 @@ export class EpochsManager extends BaseManager {
44
50
  const remaining = await this.getTimeRemaining()
45
51
  return durationMs <= remaining
46
52
  }
53
+
54
+ async getEpochRow(epoch: UInt64Type): Promise<ServerContract.Types.epoch_row | undefined> {
55
+ const target = UInt64.from(epoch)
56
+ return this.server.table('epoch').get(target)
57
+ }
58
+
59
+ async getActiveEpochInfo(): Promise<ServerContract.Types.epoch_row | undefined> {
60
+ const rows = await this.server.table('epoch').all()
61
+ if (rows.length === 0) {
62
+ return undefined
63
+ }
64
+ return rows[rows.length - 1]
65
+ }
66
+
67
+ async getOracles(): Promise<ServerContract.Types.oracle_row[]> {
68
+ return this.server.table('oracles').all()
69
+ }
70
+
71
+ async getThreshold(): Promise<number> {
72
+ const cfg = await this.server.table('oraclecfg').get()
73
+ return cfg ? Number(cfg.threshold) : 0
74
+ }
75
+
76
+ async getCommitsFor(epoch: UInt64Type): Promise<ServerContract.Types.commit_row[]> {
77
+ const target = UInt64.from(epoch)
78
+ const rows = await this.server.table('commit').all()
79
+ return rows.filter((r) => r.epoch.equals(target))
80
+ }
81
+
82
+ async getRevealsFor(epoch: UInt64Type): Promise<ServerContract.Types.reveal_row[]> {
83
+ const target = UInt64.from(epoch)
84
+ const rows = await this.server.table('reveal').all()
85
+ return rows.filter((r) => r.epoch.equals(target))
86
+ }
47
87
  }
@@ -1,9 +1,25 @@
1
1
  export {GameContext} from './context'
2
2
  export {BaseManager} from './base'
3
3
  export {EntitiesManager} from './entities'
4
- export type {EntityType} from './entities'
4
+ export type {EntityTypeName} from './entities'
5
5
  export {PlayersManager} from './players'
6
6
  export {LocationsManager} from './locations'
7
7
  export type {LocationStratum} from './locations'
8
8
  export {EpochsManager} from './epochs'
9
9
  export {ActionsManager} from './actions'
10
+ export {NftManager} from './nft'
11
+ export type {NftConfigForItem} from './nft'
12
+ export {PlotManager} from './plot'
13
+ export type {PlotProgress, PlotProgressInputRow} from './plot'
14
+ export {ConstructionManager} from './construction'
15
+ export type {
16
+ BuildableTarget,
17
+ BuildState,
18
+ SourceEntityRef,
19
+ SourceCargoStack,
20
+ FinalizerEntityRef,
21
+ FinalizerCapability,
22
+ InboundTransfer,
23
+ ScheduledBuild,
24
+ Reservation,
25
+ } from './construction-types'
@@ -1,10 +1,10 @@
1
- import {type UInt16Type, UInt64, type UInt64Type} from '@wharfkit/antelope'
1
+ import {BlockTimestamp, type UInt16Type} from '@wharfkit/antelope'
2
2
  import {BaseManager} from './base'
3
- import {type CoordinatesType, coordsToLocationId, type Distance} from '../types'
3
+ import type {CoordinatesType, Distance} from '../types'
4
4
  import {hasSystem} from '../utils/system'
5
5
  import {findNearbyPlanets} from '../travel/travel'
6
6
  import type {ServerContract} from '../contracts'
7
- import {type DerivedStratum, deriveStrata} from '../derivation'
7
+ import {type DerivedStratum, deriveStrata, getEffectiveReserve} from '../derivation'
8
8
 
9
9
  export interface LocationStratum extends DerivedStratum {
10
10
  reserveMax: number
@@ -24,7 +24,10 @@ export class LocationsManager extends BaseManager {
24
24
  return findNearbyPlanets(game.config.seed, origin, maxDistance)
25
25
  }
26
26
 
27
- async getStrata(coords: CoordinatesType): Promise<LocationStratum[]> {
27
+ async getStrata(
28
+ coords: CoordinatesType,
29
+ now: BlockTimestamp = BlockTimestamp.fromMilliseconds(Date.now())
30
+ ): Promise<LocationStratum[]> {
28
31
  const game = await this.getGame()
29
32
  const state = await this.getState()
30
33
 
@@ -36,33 +39,26 @@ export class LocationsManager extends BaseManager {
36
39
  y: coords.y,
37
40
  })) as ServerContract.Types.stratum_remaining[]
38
41
 
39
- const overrideMap = new Map<number, number>()
42
+ const epochSeconds = Number(game.config.epochtime)
43
+ const overrideMap = new Map<number, ServerContract.Types.stratum_remaining>()
40
44
  for (const o of overrides) {
41
- overrideMap.set(Number(o.stratum), Number(o.remaining))
45
+ overrideMap.set(Number(o.stratum), o)
42
46
  }
43
47
 
44
- return derived.map((s) => ({
45
- ...s,
46
- reserveMax: s.reserve,
47
- reserve: overrideMap.get(s.index) ?? s.reserve,
48
- }))
49
- }
50
-
51
- async getLocationEntity(
52
- id: UInt64Type
53
- ): Promise<ServerContract.Types.location_row | undefined> {
54
- const row = await this.server.table('location').get(UInt64.from(id))
55
- return row ?? undefined
56
- }
57
-
58
- async getLocationEntityAt(
59
- coords: CoordinatesType
60
- ): Promise<ServerContract.Types.location_row | undefined> {
61
- const id = coordsToLocationId(coords)
62
- return this.getLocationEntity(id)
63
- }
64
-
65
- async getAllLocationEntities(): Promise<ServerContract.Types.location_row[]> {
66
- return this.server.table('location').all()
48
+ return derived.map((s) => {
49
+ const override = overrideMap.get(s.index)
50
+ const reserve = override
51
+ ? getEffectiveReserve(
52
+ {
53
+ remaining: override.remaining,
54
+ max_reserve: s.reserve,
55
+ last_block: override.last_block,
56
+ },
57
+ now,
58
+ epochSeconds
59
+ )
60
+ : s.reserve
61
+ return {...s, reserveMax: s.reserve, reserve}
62
+ })
67
63
  }
68
64
  }
@@ -0,0 +1,14 @@
1
+ import {describe, expect, test} from 'bun:test'
2
+ import {resolveLockedAmount} from './nft'
3
+
4
+ describe('resolveLockedAmount', () => {
5
+ test('no fee refunds the full cost', () => {
6
+ expect(resolveLockedAmount(5_0000n, 0)).toBe(5_0000n)
7
+ })
8
+ test('2% fee floors the fee and refunds the remainder', () => {
9
+ expect(resolveLockedAmount(5_0000n, 200)).toBe(4_9000n)
10
+ })
11
+ test('rounding floors the fee (contract uses integer division)', () => {
12
+ expect(resolveLockedAmount(101n, 250)).toBe(99n) // fee = floor(101*250/10000)=2
13
+ })
14
+ })
@@ -0,0 +1,70 @@
1
+ import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
+ import {BaseManager} from './base'
3
+ import type {PlatformContract, ServerContract} from '../contracts'
4
+
5
+ export interface NftConfigForItem {
6
+ templateId: number
7
+ schemaName: string
8
+ }
9
+
10
+ export interface WrapDeposit {
11
+ cost: bigint
12
+ refund: bigint
13
+ feePct: number
14
+ symbol: string
15
+ precision: number
16
+ tokenContract: string
17
+ }
18
+
19
+ export function resolveLockedAmount(cost: bigint, feePctBasisPoints: number): bigint {
20
+ const fee = (cost * BigInt(feePctBasisPoints)) / 10_000n
21
+ return cost - fee
22
+ }
23
+
24
+ export class NftManager extends BaseManager {
25
+ private cache = new Map<string, NftConfigForItem | null>()
26
+
27
+ async getNftConfigForItem(itemId: UInt64Type): Promise<NftConfigForItem | undefined> {
28
+ const id = UInt64.from(itemId)
29
+ const key = id.toString()
30
+ if (this.cache.has(key)) {
31
+ return this.cache.get(key) ?? undefined
32
+ }
33
+ const row = (await this.server.table('nftconfig').get(id)) as
34
+ | ServerContract.Types.nftconfig_row
35
+ | undefined
36
+ const result: NftConfigForItem | null = row
37
+ ? {templateId: Number(row.template_id), schemaName: String(row.schema_name)}
38
+ : null
39
+ this.cache.set(key, result)
40
+ return result ?? undefined
41
+ }
42
+
43
+ async getWrapDeposit(itemType: number, tier: number): Promise<WrapDeposit | null> {
44
+ const key = UInt64.from((BigInt(itemType) << 8n) | BigInt(tier))
45
+ const costRow = (await this.server.table('wrapcost').get(key)) as
46
+ | ServerContract.Types.wrapcost_row
47
+ | undefined
48
+ const cost = costRow ? BigInt(costRow.amount.toString()) : 0n
49
+ if (cost === 0n) return null
50
+
51
+ const cfg = (await this.server.table('wrapconfig').get()) as
52
+ | ServerContract.Types.wrapconfig_row
53
+ | undefined
54
+ const feePctBasisPoints = cfg ? Number(cfg.fee_pct) : 0
55
+
56
+ const depositCfg = (await this.platform.table('depositcfg').get()) as
57
+ | PlatformContract.Types.depositcfg_row
58
+ | undefined
59
+ if (!depositCfg) return null
60
+
61
+ return {
62
+ cost,
63
+ refund: resolveLockedAmount(cost, feePctBasisPoints),
64
+ feePct: feePctBasisPoints / 100,
65
+ symbol: depositCfg.token_symbol.code.toString(),
66
+ precision: depositCfg.token_symbol.precision,
67
+ tokenContract: depositCfg.token_contract.toString(),
68
+ }
69
+ }
70
+ }
@@ -0,0 +1,122 @@
1
+ import {Name} from '@wharfkit/antelope'
2
+ import {getItem} from '../data/catalog'
3
+ import {getRecipe} from '../data/recipes-runtime'
4
+ import {computeInputMass} from '../derivation/crafting'
5
+ import {calc_craft_duration} from '../capabilities/crafting'
6
+ import {TaskType} from '../types'
7
+ import {BaseManager} from './base'
8
+ import type {CrafterStats} from '../types/capabilities'
9
+ import type {ServerContract} from '../contracts'
10
+ import type {BuildableTarget, ScheduledBuild} from './construction-types'
11
+
12
+ export interface PlotProgressInputRow {
13
+ itemId: number
14
+ required: number
15
+ provided: number
16
+ missing: number
17
+ }
18
+
19
+ export interface PlotProgress {
20
+ targetItemId: number
21
+ rows: PlotProgressInputRow[]
22
+ massProvided: number
23
+ massRequired: number
24
+ isComplete: boolean
25
+ }
26
+
27
+ export class PlotManager extends BaseManager {
28
+ progress(
29
+ plot: ServerContract.Types.entity_row,
30
+ cargo: ServerContract.Types.cargo_row[]
31
+ ): PlotProgress {
32
+ const targetItemId = Number(plot.item_id.toString())
33
+ const recipe = getRecipe(targetItemId)
34
+ if (!recipe) {
35
+ throw new Error(`No recipe found for item ${targetItemId}`)
36
+ }
37
+
38
+ const plotId = plot.id.toString()
39
+ const plotCargo = cargo.filter((c) => c.entity_id.toString() === plotId)
40
+
41
+ const quantityByItemId = new Map<number, number>()
42
+ for (const c of plotCargo) {
43
+ const id = c.item_id.toNumber()
44
+ quantityByItemId.set(
45
+ id,
46
+ (quantityByItemId.get(id) ?? 0) + Number(c.quantity.toString())
47
+ )
48
+ }
49
+
50
+ const rows: PlotProgressInputRow[] = recipe.inputs.map((input) => {
51
+ const itemId = input.itemId
52
+ const required = input.quantity
53
+ const provided = quantityByItemId.get(itemId) ?? 0
54
+ const missing = Math.max(0, required - provided)
55
+ return {itemId, required, provided, missing}
56
+ })
57
+
58
+ const massRequired = computeInputMass(targetItemId)
59
+ const massProvided = rows.reduce((sum, r) => {
60
+ const item = getItem(r.itemId)
61
+ return sum + item.mass * r.provided
62
+ }, 0)
63
+ const isComplete = rows.every((r) => r.missing === 0)
64
+
65
+ return {targetItemId, rows, massProvided, massRequired, isComplete}
66
+ }
67
+
68
+ buildableTarget(
69
+ plot: ServerContract.Types.entity_row,
70
+ cargo: ServerContract.Types.cargo_row[],
71
+ activeTask?: ServerContract.Types.task,
72
+ scheduledBuild?: ScheduledBuild
73
+ ): BuildableTarget {
74
+ const progress = this.progress(plot, cargo)
75
+ const targetItemId = Number(plot.item_id.toString())
76
+ const targetItem = getItem(targetItemId)
77
+ const recipe = getRecipe(targetItemId)
78
+ if (!recipe) {
79
+ throw new Error(`Plot target item ${targetItemId} has no recipe`)
80
+ }
81
+
82
+ let state: BuildableTarget['state']
83
+ if (scheduledBuild?.hasStarted) {
84
+ state = 'finalizing'
85
+ } else if (scheduledBuild) {
86
+ state = 'scheduled'
87
+ } else if (progress.isComplete) {
88
+ state = 'ready'
89
+ } else {
90
+ state = 'accepting'
91
+ }
92
+
93
+ return {
94
+ entityId: plot.id,
95
+ ownerName: plot.owner,
96
+ coordinates: plot.coordinates,
97
+ targetItemId,
98
+ targetItem,
99
+ state,
100
+ recipe,
101
+ progress,
102
+ finalizeAction: Name.from('buildplot'),
103
+ finalizerCapability: 'crafter',
104
+ activeTask,
105
+ scheduledBuild,
106
+ }
107
+ }
108
+
109
+ canBuild(
110
+ plot: ServerContract.Types.entity_row,
111
+ cargo: ServerContract.Types.cargo_row[]
112
+ ): boolean {
113
+ return this.progress(plot, cargo).isComplete
114
+ }
115
+
116
+ timeToComplete(plot: ServerContract.Types.entity_info, crafter: CrafterStats): number {
117
+ const capacity = Number(plot.capacity?.toString() ?? '0')
118
+ const speed = Number(crafter.speed.toString())
119
+ if (speed === 0) return 0
120
+ return calc_craft_duration(speed, capacity).toNumber()
121
+ }
122
+ }