@shipload/sdk 1.0.0-next.7 → 1.0.0-next.70
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/scan.d.ts +52 -0
- package/lib/scan.js +162 -0
- package/lib/scan.js.map +1 -0
- package/lib/scan.m.js +152 -0
- package/lib/scan.m.js.map +1 -0
- package/lib/shipload.d.ts +5696 -1503
- package/lib/shipload.js +20294 -5200
- package/lib/shipload.js.map +1 -1
- package/lib/shipload.m.js +20371 -5683
- package/lib/shipload.m.js.map +1 -1
- package/lib/testing.d.ts +1648 -0
- package/lib/testing.js +6980 -0
- package/lib/testing.js.map +1 -0
- package/lib/testing.m.js +6974 -0
- package/lib/testing.m.js.map +1 -0
- package/package.json +20 -2
- package/src/capabilities/craftable.test.ts +82 -0
- package/src/capabilities/craftable.ts +82 -0
- package/src/capabilities/crafting.test.ts +80 -0
- package/src/capabilities/crafting.ts +50 -8
- package/src/capabilities/gathering.test.ts +29 -0
- package/src/capabilities/gathering.ts +38 -20
- package/src/capabilities/hauling.ts +0 -5
- package/src/capabilities/index.ts +0 -1
- package/src/capabilities/modules.ts +27 -30
- package/src/capabilities/movement.ts +1 -1
- package/src/capabilities/storage.test.ts +26 -0
- package/src/capabilities/storage.ts +22 -7
- package/src/contracts/fund.ts +306 -0
- package/src/contracts/platform.ts +312 -3
- package/src/contracts/server.ts +2661 -466
- package/src/contracts/token.ts +170 -0
- package/src/contracts.ts +2 -0
- package/src/coordinates/address.ts +88 -0
- package/src/coordinates/constants.test.ts +15 -0
- package/src/coordinates/constants.ts +23 -0
- package/src/coordinates/index.ts +15 -0
- package/src/coordinates/memo.test.ts +47 -0
- package/src/coordinates/memo.ts +20 -0
- package/src/coordinates/permutation.ts +77 -0
- package/src/coordinates/regions.ts +48 -0
- package/src/coordinates/sectors.ts +115 -0
- package/src/data/capabilities.ts +49 -18
- package/src/data/capability-formulas.ts +26 -14
- package/src/data/catalog.test.ts +19 -0
- package/src/data/catalog.ts +13 -3
- package/src/data/charters.json +396 -0
- package/src/data/citizenry-adjectives.json +42 -0
- package/src/data/citizenry-nouns.json +50 -0
- package/src/data/colors.ts +14 -32
- package/src/data/entities.json +421 -15
- package/src/data/item-ids.ts +53 -13
- package/src/data/items.json +330 -77
- package/src/data/kind-registry.json +212 -0
- package/src/data/kind-registry.ts +192 -0
- package/src/data/metadata.ts +312 -51
- package/src/data/recipes-runtime.ts +6 -23
- package/src/data/recipes.json +2173 -173
- package/src/data/tiers.ts +9 -6
- package/src/derivation/build-methods.test.ts +71 -0
- package/src/derivation/build-methods.ts +50 -0
- package/src/derivation/capabilities.test.ts +348 -0
- package/src/derivation/capabilities.ts +707 -0
- package/src/derivation/capability-mappings.ts +60 -16
- package/src/derivation/crafting.test.ts +17 -0
- package/src/derivation/crafting.ts +57 -34
- package/src/derivation/index.ts +27 -2
- package/src/derivation/recipe-usage.test.ts +88 -0
- package/src/derivation/recipe-usage.ts +141 -0
- package/src/derivation/reserve-regen.ts +34 -0
- package/src/derivation/resources.ts +9 -1
- package/src/derivation/rollups.test.ts +55 -0
- package/src/derivation/rollups.ts +72 -0
- package/src/derivation/stars.test.ts +67 -0
- package/src/derivation/stars.ts +25 -0
- package/src/derivation/stat-scaling.ts +12 -0
- package/src/derivation/stats.ts +6 -6
- package/src/derivation/strata.ts +5 -3
- package/src/derivation/stratum.ts +26 -22
- package/src/derivation/tiers.ts +40 -7
- package/src/derivation/upgrades.ts +14 -0
- package/src/derivation/wormhole.ts +154 -0
- package/src/entities/entity.ts +102 -0
- package/src/entities/gamestate.ts +3 -28
- package/src/entities/makers.ts +144 -136
- package/src/entities/slot-multiplier.ts +43 -0
- package/src/entity/hydrate.test.ts +156 -0
- package/src/entity/hydrate.ts +86 -0
- package/src/errors.ts +21 -16
- package/src/format.ts +42 -9
- package/src/index-module.ts +411 -32
- package/src/influence/ballot.test.ts +103 -0
- package/src/influence/ballot.ts +98 -0
- package/src/influence/categories.ts +32 -0
- package/src/influence/charter-metadata.test.ts +136 -0
- package/src/influence/charter-metadata.ts +236 -0
- package/src/influence/charters.test.ts +112 -0
- package/src/influence/charters.ts +150 -0
- package/src/influence/citizenry.ts +38 -0
- package/src/influence/civic-shuttle.test.ts +202 -0
- package/src/influence/civic-shuttle.ts +142 -0
- package/src/influence/civic.test.ts +287 -0
- package/src/influence/civic.ts +269 -0
- package/src/influence/constants.ts +84 -0
- package/src/influence/decay.ts +20 -0
- package/src/influence/decomp.ts +95 -0
- package/src/influence/demand.ts +106 -0
- package/src/influence/duration.ts +101 -0
- package/src/influence/index.ts +118 -0
- package/src/influence/influence.test.ts +450 -0
- package/src/influence/quality.ts +25 -0
- package/src/influence/valuation.ts +154 -0
- package/src/managers/actions.ts +940 -93
- package/src/managers/balances.test.ts +161 -0
- package/src/managers/balances.ts +93 -0
- package/src/managers/base.ts +10 -2
- package/src/managers/cluster.test.ts +39 -0
- package/src/managers/cluster.ts +53 -0
- package/src/managers/construction-types.ts +80 -0
- package/src/managers/construction.ts +453 -0
- package/src/managers/context.ts +58 -1
- package/src/managers/coordinates.ts +14 -0
- package/src/managers/entities.ts +35 -63
- package/src/managers/epochs.ts +72 -1
- package/src/managers/index.ts +38 -1
- package/src/managers/influence.test.ts +56 -0
- package/src/managers/influence.ts +425 -0
- package/src/managers/jobs.test.ts +80 -0
- package/src/managers/jobs.ts +54 -0
- package/src/managers/locations.ts +25 -29
- package/src/managers/nft.test.ts +21 -0
- package/src/managers/nft.ts +110 -0
- package/src/managers/players.ts +25 -0
- package/src/managers/plot.ts +122 -0
- package/src/nft/atomicassets.abi.json +1342 -0
- package/src/nft/atomicassets.ts +237 -0
- package/src/nft/atomicdata.ts +130 -0
- package/src/nft/buildImmutableData.ts +388 -0
- package/src/nft/description.ts +222 -100
- package/src/nft/index.ts +3 -0
- package/src/planner/index.ts +296 -0
- package/src/planner/planner.test.ts +459 -0
- package/src/receipts.ts +22 -0
- package/src/resolution/describe-module.ts +43 -25
- package/src/resolution/display-name.ts +39 -11
- package/src/resolution/resolve-item.test.ts +48 -0
- package/src/resolution/resolve-item.ts +112 -58
- package/src/scan/index.ts +244 -0
- package/src/scan/scan-wasm.base64.ts +2 -0
- package/src/scheduling/accessor.ts +65 -23
- package/src/scheduling/availability.test.ts +320 -0
- package/src/scheduling/availability.ts +251 -0
- package/src/scheduling/cancel.test.ts +550 -0
- package/src/scheduling/cancel.ts +254 -0
- package/src/scheduling/cluster-stock.test.ts +31 -0
- package/src/scheduling/cluster-stock.ts +15 -0
- package/src/scheduling/energy.ts +47 -0
- package/src/scheduling/epoch.ts +1 -0
- package/src/scheduling/idle-resolve.ts +45 -0
- package/src/scheduling/jobs.test.ts +49 -0
- package/src/scheduling/jobs.ts +137 -0
- package/src/scheduling/lane-core.ts +128 -0
- package/src/scheduling/lanes.test.ts +250 -0
- package/src/scheduling/lanes.ts +227 -0
- package/src/scheduling/projection.ts +265 -149
- package/src/scheduling/schedule.test.ts +163 -0
- package/src/scheduling/schedule.ts +282 -116
- package/src/scheduling/task-cargo.test.ts +110 -0
- package/src/scheduling/task-cargo.ts +62 -0
- package/src/scheduling/task-effects.test.ts +35 -0
- package/src/scheduling/task-effects.ts +34 -0
- package/src/scheduling/unwrap.test.ts +86 -0
- package/src/scheduling/unwrap.ts +190 -0
- package/src/shipload.ts +63 -4
- package/src/subscriptions/manager.cluster.test.ts +51 -0
- package/src/subscriptions/manager.ts +245 -172
- package/src/subscriptions/mappers.ts +5 -8
- package/src/subscriptions/types.ts +28 -3
- package/src/testing/catalog-hash.ts +19 -0
- package/src/testing/index.ts +2 -0
- package/src/testing/projection-parity.ts +167 -0
- package/src/travel/reach.test.ts +86 -0
- package/src/travel/reach.ts +34 -0
- package/src/travel/route-build.test.ts +63 -0
- package/src/travel/route-build.ts +60 -0
- package/src/travel/route-planner.ts +288 -0
- package/src/travel/route-simulator.ts +170 -0
- package/src/travel/travel.ts +190 -123
- package/src/types/capabilities.ts +37 -8
- package/src/types/entity.ts +3 -3
- package/src/types/index.ts +0 -1
- package/src/types.ts +81 -23
- package/src/utils/cargo.test.ts +14 -0
- package/src/utils/cargo.ts +2 -0
- package/src/utils/display-name.ts +70 -0
- package/src/utils/hash.ts +22 -2
- package/src/utils/system.ts +24 -5
- package/src/capabilities/loading.ts +0 -8
- package/src/entities/container.ts +0 -123
- package/src/entities/ship-deploy.ts +0 -295
- package/src/entities/ship.ts +0 -221
- package/src/entities/warehouse.ts +0 -127
- package/src/types/entity-traits.ts +0 -69
|
@@ -0,0 +1,425 @@
|
|
|
1
|
+
import {Int64, Name, type NameType, UInt64} from '@wharfkit/antelope'
|
|
2
|
+
import {BaseManager} from './base'
|
|
3
|
+
import type {ServerContract} from '../contracts'
|
|
4
|
+
import {coordsToLocationId, locationIdToCoords, type CoordinatesType} from '../types'
|
|
5
|
+
import {
|
|
6
|
+
type BuiltCharter,
|
|
7
|
+
type WorldBuilding,
|
|
8
|
+
citizenryName,
|
|
9
|
+
contributeDuration,
|
|
10
|
+
decayActive,
|
|
11
|
+
deriveDemand,
|
|
12
|
+
pricingFromWeights,
|
|
13
|
+
valueCargoItem,
|
|
14
|
+
type DemandTriple,
|
|
15
|
+
type DemandView,
|
|
16
|
+
isCivicEntity,
|
|
17
|
+
type ValuedItem,
|
|
18
|
+
} from '../influence'
|
|
19
|
+
import {getItem} from '../data/catalog'
|
|
20
|
+
|
|
21
|
+
export interface InfluenceStanding {
|
|
22
|
+
epoch: number
|
|
23
|
+
standingLifetime: bigint
|
|
24
|
+
standingActive: bigint
|
|
25
|
+
citizenshipLifetime: bigint
|
|
26
|
+
citizenshipActive: bigint
|
|
27
|
+
locationLifetime: bigint
|
|
28
|
+
locationActive: bigint
|
|
29
|
+
spent: bigint
|
|
30
|
+
mandate: number
|
|
31
|
+
founder: Name
|
|
32
|
+
founded: number
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface CharterProgress {
|
|
36
|
+
locationId: bigint
|
|
37
|
+
lifetime: bigint
|
|
38
|
+
spent: bigint
|
|
39
|
+
unassigned: bigint
|
|
40
|
+
mandate: number
|
|
41
|
+
nextCost: bigint
|
|
42
|
+
prereqsMet: boolean
|
|
43
|
+
buildable: boolean
|
|
44
|
+
epoch: number
|
|
45
|
+
built: BuiltCharter[]
|
|
46
|
+
ballotId: bigint
|
|
47
|
+
settling: boolean
|
|
48
|
+
queue: QueuedSeat[]
|
|
49
|
+
progress: NodeProgress[]
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export interface NodeProgress {
|
|
53
|
+
nodeId: number
|
|
54
|
+
amount: bigint
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface ContributePreviewRow {
|
|
58
|
+
itemId: number
|
|
59
|
+
quantity: number
|
|
60
|
+
stats: bigint
|
|
61
|
+
valueAtomic: bigint
|
|
62
|
+
mass: number
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ContributePreview {
|
|
66
|
+
rows: ContributePreviewRow[]
|
|
67
|
+
totalAtomic: bigint
|
|
68
|
+
totalMass: number
|
|
69
|
+
durationSeconds: number
|
|
70
|
+
demand: DemandView
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface FoundedWorld {
|
|
74
|
+
locationId: bigint
|
|
75
|
+
x: number
|
|
76
|
+
y: number
|
|
77
|
+
lifetime: bigint
|
|
78
|
+
active: bigint
|
|
79
|
+
spent: bigint
|
|
80
|
+
ballotId: bigint
|
|
81
|
+
mandate: number | undefined
|
|
82
|
+
founder: Name
|
|
83
|
+
founded: number
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export interface FoundedWorldRef {
|
|
87
|
+
x: number
|
|
88
|
+
y: number
|
|
89
|
+
mandate: number
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export interface VoteOption {
|
|
93
|
+
nodeId: number
|
|
94
|
+
cost: bigint
|
|
95
|
+
seat: number
|
|
96
|
+
weight: bigint
|
|
97
|
+
rank: number
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
export interface VoteStandings {
|
|
101
|
+
locationId: bigint
|
|
102
|
+
ballotId: bigint
|
|
103
|
+
epoch: number
|
|
104
|
+
settledEpoch: number
|
|
105
|
+
seats: number
|
|
106
|
+
settling: boolean
|
|
107
|
+
queue: number[]
|
|
108
|
+
options: VoteOption[]
|
|
109
|
+
picks: number[]
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export interface BallotVote {
|
|
113
|
+
account: Name
|
|
114
|
+
picks: number[]
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
export interface Ballot {
|
|
118
|
+
ballotId: bigint
|
|
119
|
+
kind: number
|
|
120
|
+
subject: bigint
|
|
121
|
+
seats: number
|
|
122
|
+
settledEpoch: number
|
|
123
|
+
queue: number[]
|
|
124
|
+
settling: boolean
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
export interface QueuedSeat {
|
|
128
|
+
nodeId: number
|
|
129
|
+
cost: bigint
|
|
130
|
+
progress: bigint
|
|
131
|
+
gap: bigint
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
function big(value: unknown): bigint {
|
|
135
|
+
return BigInt(String(value))
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export class InfluenceManager extends BaseManager {
|
|
139
|
+
async getStanding(owner: NameType, location: CoordinatesType): Promise<InfluenceStanding> {
|
|
140
|
+
const result = (await this.server.readonly('getinfluence', {
|
|
141
|
+
owner: Name.from(owner),
|
|
142
|
+
x: Int64.from(location.x),
|
|
143
|
+
y: Int64.from(location.y),
|
|
144
|
+
})) as ServerContract.Types.influence_totals
|
|
145
|
+
|
|
146
|
+
return {
|
|
147
|
+
epoch: Number(result.epoch),
|
|
148
|
+
standingLifetime: big(result.standing_lifetime),
|
|
149
|
+
standingActive: big(result.standing_active),
|
|
150
|
+
citizenshipLifetime: big(result.citizenship_lifetime),
|
|
151
|
+
citizenshipActive: big(result.citizenship_active),
|
|
152
|
+
locationLifetime: big(result.location_lifetime),
|
|
153
|
+
locationActive: big(result.location_active),
|
|
154
|
+
spent: big(result.spent),
|
|
155
|
+
mandate: Number(result.mandate),
|
|
156
|
+
founder: Name.from(result.founder),
|
|
157
|
+
founded: Number(result.founded),
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
async getDemandConfig(): Promise<DemandTriple> {
|
|
162
|
+
const row = (await this.server.table('infdemand').get()) as
|
|
163
|
+
| ServerContract.Types.infdemand_row
|
|
164
|
+
| undefined
|
|
165
|
+
if (!row) throw new Error('influence demand config is unset')
|
|
166
|
+
return {peak: big(row.peak), base: big(row.base), floor: big(row.floor)}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
async getQualityDivisor(): Promise<number> {
|
|
170
|
+
const row = (await this.server.table('infquality').get()) as
|
|
171
|
+
| ServerContract.Types.infquality_row
|
|
172
|
+
| undefined
|
|
173
|
+
if (!row) throw new Error('influence quality config is unset')
|
|
174
|
+
return Number(row.d1)
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
async getWeights(): Promise<ServerContract.Types.infweight_row[]> {
|
|
178
|
+
return (await this.server.table('infweight').all()) as ServerContract.Types.infweight_row[]
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
async getDemand(location: CoordinatesType): Promise<DemandView> {
|
|
182
|
+
const game = await this.getGame()
|
|
183
|
+
const state = await this.getState()
|
|
184
|
+
const triple = await this.getDemandConfig()
|
|
185
|
+
return deriveDemand({
|
|
186
|
+
gameSeed: game.config.seed,
|
|
187
|
+
epochSeed: state.epochSeed,
|
|
188
|
+
coordinates: location,
|
|
189
|
+
triple,
|
|
190
|
+
})
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async getCivicOwner(): Promise<Name> {
|
|
194
|
+
const row = (await this.server.table('civicconfig').get()) as
|
|
195
|
+
| ServerContract.Types.civicconfig_row
|
|
196
|
+
| undefined
|
|
197
|
+
return row ? Name.from(row.civic_owner) : Name.from(this.server.account)
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
async isCivic(entity: {owner: NameType}): Promise<boolean> {
|
|
201
|
+
return isCivicEntity(entity, await this.getCivicOwner())
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async getCitizenryName(location: CoordinatesType): Promise<string | undefined> {
|
|
205
|
+
const game = await this.getGame()
|
|
206
|
+
return citizenryName(game.config.seed, location)
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
async previewContribution(
|
|
210
|
+
location: CoordinatesType,
|
|
211
|
+
bundle: ValuedItem[],
|
|
212
|
+
opts: {altitudeZ?: number} = {}
|
|
213
|
+
): Promise<ContributePreview> {
|
|
214
|
+
const [demand, d1, weights] = await Promise.all([
|
|
215
|
+
this.getDemand(location),
|
|
216
|
+
this.getQualityDivisor(),
|
|
217
|
+
this.getWeights(),
|
|
218
|
+
])
|
|
219
|
+
const pricing = pricingFromWeights(
|
|
220
|
+
d1,
|
|
221
|
+
weights.map((w) => ({
|
|
222
|
+
category: Number(w.category),
|
|
223
|
+
tier: Number(w.tier),
|
|
224
|
+
weightFp: big(w.weight_fp),
|
|
225
|
+
}))
|
|
226
|
+
)
|
|
227
|
+
|
|
228
|
+
let totalAtomic = 0n
|
|
229
|
+
let totalMass = 0
|
|
230
|
+
const rows = bundle.map((item) => {
|
|
231
|
+
const valueAtomic = valueCargoItem(item, demand, pricing)
|
|
232
|
+
const mass = getItem(item.itemId).mass * item.quantity
|
|
233
|
+
totalAtomic += valueAtomic
|
|
234
|
+
totalMass += mass
|
|
235
|
+
return {...item, valueAtomic, mass}
|
|
236
|
+
})
|
|
237
|
+
|
|
238
|
+
return {
|
|
239
|
+
rows,
|
|
240
|
+
totalAtomic,
|
|
241
|
+
totalMass,
|
|
242
|
+
durationSeconds: contributeDuration(totalMass, opts.altitudeZ ?? 0),
|
|
243
|
+
demand,
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
async getCharter(location: CoordinatesType): Promise<CharterProgress> {
|
|
248
|
+
const result = (await this.server.readonly('getcharter', {
|
|
249
|
+
x: Int64.from(location.x),
|
|
250
|
+
y: Int64.from(location.y),
|
|
251
|
+
})) as ServerContract.Types.charter_result
|
|
252
|
+
|
|
253
|
+
return {
|
|
254
|
+
locationId: big(result.location_id),
|
|
255
|
+
lifetime: big(result.lifetime),
|
|
256
|
+
spent: big(result.spent),
|
|
257
|
+
unassigned: big(result.unassigned),
|
|
258
|
+
mandate: Number(result.mandate),
|
|
259
|
+
nextCost: big(result.next_cost),
|
|
260
|
+
prereqsMet: Boolean(result.prereqs_met),
|
|
261
|
+
buildable: Boolean(result.buildable),
|
|
262
|
+
epoch: Number(result.epoch),
|
|
263
|
+
built: result.built.map((b) => ({
|
|
264
|
+
nodeId: Number(b.node_id),
|
|
265
|
+
repeats: Number(b.repeats),
|
|
266
|
+
})),
|
|
267
|
+
ballotId: big(result.ballot_id),
|
|
268
|
+
settling: Boolean(result.settling),
|
|
269
|
+
queue: result.queue.map((seat) => ({
|
|
270
|
+
nodeId: Number(seat.node_id),
|
|
271
|
+
cost: big(seat.cost),
|
|
272
|
+
progress: big(seat.progress),
|
|
273
|
+
gap: big(seat.gap),
|
|
274
|
+
})),
|
|
275
|
+
progress: result.progress.map((p) => ({
|
|
276
|
+
nodeId: Number(p.node_id),
|
|
277
|
+
amount: big(p.amount),
|
|
278
|
+
})),
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
async getPools(): Promise<ServerContract.Types.pool_view[]> {
|
|
283
|
+
const result = (await this.server.readonly('getpools')) as ServerContract.Types.pools_result
|
|
284
|
+
return result.pools
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
async getPool(category: number, tier: number): Promise<ServerContract.Types.pool_pair_result> {
|
|
288
|
+
return (await this.server.readonly('getpool', {
|
|
289
|
+
category,
|
|
290
|
+
tier,
|
|
291
|
+
})) as ServerContract.Types.pool_pair_result
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
async getMintConfig(): Promise<ServerContract.Types.mintcfg_result> {
|
|
295
|
+
return (await this.server.readonly('getmintcfg')) as ServerContract.Types.mintcfg_result
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
async getMintReady(): Promise<number> {
|
|
299
|
+
return Number(await this.server.readonly('getmintready'))
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
async getVoteReady(): Promise<number> {
|
|
303
|
+
return Number(await this.server.readonly('getvoteready'))
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
async getCharterReady(): Promise<FoundedWorldRef[]> {
|
|
307
|
+
const result = (await this.server.readonly(
|
|
308
|
+
'getchrtready'
|
|
309
|
+
)) as ServerContract.Types.charterready_result
|
|
310
|
+
return result.worlds.map((w) => ({
|
|
311
|
+
x: Number(w.x),
|
|
312
|
+
y: Number(w.y),
|
|
313
|
+
mandate: Number(w.mandate),
|
|
314
|
+
}))
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
async getVotes(location: CoordinatesType, player?: NameType): Promise<VoteStandings> {
|
|
318
|
+
const result = (await this.server.readonly('getvotes', {
|
|
319
|
+
x: Int64.from(location.x),
|
|
320
|
+
y: Int64.from(location.y),
|
|
321
|
+
player: Name.from(player ?? ''),
|
|
322
|
+
})) as ServerContract.Types.vote_result
|
|
323
|
+
|
|
324
|
+
return {
|
|
325
|
+
locationId: big(result.location_id),
|
|
326
|
+
ballotId: big(result.ballot_id),
|
|
327
|
+
epoch: Number(result.epoch),
|
|
328
|
+
settledEpoch: Number(result.settled_epoch),
|
|
329
|
+
seats: Number(result.seats),
|
|
330
|
+
settling: Boolean(result.settling),
|
|
331
|
+
queue: result.queue.map((n) => Number(n)),
|
|
332
|
+
options: result.options.map((option) => ({
|
|
333
|
+
nodeId: Number(option.node_id),
|
|
334
|
+
cost: big(option.cost),
|
|
335
|
+
seat: Number(option.seat),
|
|
336
|
+
weight: big(option.weight),
|
|
337
|
+
rank: Number(option.rank),
|
|
338
|
+
})),
|
|
339
|
+
picks: result.picks.map((n) => Number(n)),
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
async getBallotId(location: CoordinatesType): Promise<bigint | undefined> {
|
|
344
|
+
const row = (await this.server
|
|
345
|
+
.table('worlds')
|
|
346
|
+
.get(UInt64.from(coordsToLocationId(location)))) as
|
|
347
|
+
| ServerContract.Types.worlds_row
|
|
348
|
+
| undefined
|
|
349
|
+
return row ? big(row.ballot_id) : undefined
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
async getBallot(ballotId: bigint): Promise<Ballot | undefined> {
|
|
353
|
+
const row = (await this.server.table('ballot').get(UInt64.from(ballotId))) as
|
|
354
|
+
| ServerContract.Types.ballot_row
|
|
355
|
+
| undefined
|
|
356
|
+
if (!row) return undefined
|
|
357
|
+
const epoch = Number((await this.getState()).epoch)
|
|
358
|
+
const settledEpoch = Number(row.settled_epoch)
|
|
359
|
+
return {
|
|
360
|
+
ballotId: big(row.ballot_id),
|
|
361
|
+
kind: Number(row.kind),
|
|
362
|
+
subject: big(row.subject),
|
|
363
|
+
seats: Number(row.seats),
|
|
364
|
+
settledEpoch,
|
|
365
|
+
queue: row.queue.map((n) => Number(n)),
|
|
366
|
+
settling: settledEpoch < epoch,
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
async getBallotVotes(ballotId: bigint): Promise<BallotVote[]> {
|
|
371
|
+
const rows = (await this.server
|
|
372
|
+
.table('ballotpicks', UInt64.from(ballotId))
|
|
373
|
+
.all()) as ServerContract.Types.ballotpicks_row[]
|
|
374
|
+
return rows.map((row) => ({
|
|
375
|
+
account: Name.from(row.account),
|
|
376
|
+
picks: row.picks.map((n) => Number(n)),
|
|
377
|
+
}))
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
async getBuiltCharters(location: CoordinatesType): Promise<BuiltCharter[]> {
|
|
381
|
+
const rows = (await this.server
|
|
382
|
+
.table('mandates', coordsToLocationId(location))
|
|
383
|
+
.all()) as ServerContract.Types.mandates_row[]
|
|
384
|
+
return rows.map((row) => ({nodeId: Number(row.node_id), repeats: Number(row.repeats)}))
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async getBuildings(location: CoordinatesType): Promise<WorldBuilding[]> {
|
|
388
|
+
const rows = (await this.server
|
|
389
|
+
.table('buildings', coordsToLocationId(location))
|
|
390
|
+
.all()) as ServerContract.Types.buildings_row[]
|
|
391
|
+
return rows.map((row) => ({entityId: big(row.entity_id), building: Number(row.building)}))
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
async getFoundedWorlds(opts: {withMandate?: boolean} = {}): Promise<FoundedWorld[]> {
|
|
395
|
+
const rows = (await this.server.table('worlds').all()) as ServerContract.Types.worlds_row[]
|
|
396
|
+
const epoch = (await this.getState()).epoch
|
|
397
|
+
const worlds = rows.map((row) => ({
|
|
398
|
+
locationId: big(row.location_id),
|
|
399
|
+
...locationIdToCoords(row.location_id),
|
|
400
|
+
lifetime: big(row.lifetime),
|
|
401
|
+
active: decayActive(
|
|
402
|
+
big(row.active),
|
|
403
|
+
Math.max(0, Number(epoch) - Number(row.active_epoch))
|
|
404
|
+
),
|
|
405
|
+
spent: big(row.spent),
|
|
406
|
+
ballotId: big(row.ballot_id),
|
|
407
|
+
mandate: undefined as number | undefined,
|
|
408
|
+
founder: Name.from(row.founder),
|
|
409
|
+
founded: Number(row.founded),
|
|
410
|
+
}))
|
|
411
|
+
|
|
412
|
+
if (!opts.withMandate) return worlds
|
|
413
|
+
|
|
414
|
+
for (const world of worlds) {
|
|
415
|
+
world.mandate = (await this.getCharter({x: world.x, y: world.y})).mandate
|
|
416
|
+
}
|
|
417
|
+
return worlds
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
async isFounded(location: CoordinatesType): Promise<boolean> {
|
|
421
|
+
const id = coordsToLocationId(location)
|
|
422
|
+
const row = await this.server.table('worlds').get(UInt64.from(id))
|
|
423
|
+
return row !== undefined
|
|
424
|
+
}
|
|
425
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import {describe, expect, it} from 'bun:test'
|
|
2
|
+
import {Name} from '@wharfkit/antelope'
|
|
3
|
+
import {JobsManager} from './jobs'
|
|
4
|
+
|
|
5
|
+
const OWNER = 'eggmaple.gm'
|
|
6
|
+
const row = (over: Record<string, unknown> = {}) => ({
|
|
7
|
+
id: {toNumber: () => 7},
|
|
8
|
+
building: {toNumber: () => 42},
|
|
9
|
+
socket: {toNumber: () => 0},
|
|
10
|
+
owner: Name.from(OWNER),
|
|
11
|
+
ship_id: {toNumber: () => 100},
|
|
12
|
+
coords: {x: {toNumber: () => 12}, y: {toNumber: () => 34}},
|
|
13
|
+
starts_at: {toDate: () => new Date('2026-07-26T10:00:00Z')},
|
|
14
|
+
completes_at: {toDate: () => new Date('2026-07-26T11:00:00Z')},
|
|
15
|
+
recipe_id: {toNumber: () => 10001},
|
|
16
|
+
quantity: {toNumber: () => 5},
|
|
17
|
+
energy_paid: {toNumber: () => 0},
|
|
18
|
+
cargo: [{item: 'out'}],
|
|
19
|
+
...over,
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
function managerWith(queryImpl: () => Promise<unknown[]>, allImpl: () => Promise<unknown[]>) {
|
|
23
|
+
const table = () => ({query: () => ({all: queryImpl}), all: allImpl})
|
|
24
|
+
const ctx = {server: {table}} as never
|
|
25
|
+
return new JobsManager(ctx)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
describe('JobsManager.getOwnedJobs', () => {
|
|
29
|
+
it('parses a landed row: cargo is the output, no inputs, status derived', async () => {
|
|
30
|
+
const m = managerWith(
|
|
31
|
+
async () => [row()],
|
|
32
|
+
async () => []
|
|
33
|
+
)
|
|
34
|
+
const jobs = await m.getOwnedJobs(OWNER, {now: new Date('2026-07-26T11:30:00Z')})
|
|
35
|
+
expect(jobs).toHaveLength(1)
|
|
36
|
+
expect(jobs[0]).toMatchObject({id: 7, building: 42, quantity: 5, status: 'ready'})
|
|
37
|
+
expect(jobs[0].coords).toEqual({x: 12, y: 34})
|
|
38
|
+
expect(jobs[0].output).toEqual({item: 'out'} as never)
|
|
39
|
+
expect(jobs[0].inputs).toEqual([] as never)
|
|
40
|
+
})
|
|
41
|
+
|
|
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)},
|
|
46
|
+
deposited: false,
|
|
47
|
+
cargo: [{item: 'in'}],
|
|
48
|
+
})
|
|
49
|
+
const m = managerWith(
|
|
50
|
+
async () => [inLine],
|
|
51
|
+
async () => []
|
|
52
|
+
)
|
|
53
|
+
const jobs = await m.getOwnedJobs(OWNER, {now: new Date('2026-07-26T11:30:00Z')})
|
|
54
|
+
expect(jobs[0].status).toBe('inline')
|
|
55
|
+
expect(jobs[0].deposited).toBe(false)
|
|
56
|
+
expect(jobs[0].output).toBeNull()
|
|
57
|
+
expect(jobs[0].inputs).toEqual([{item: 'in'}] as never)
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('drops rows whose owner does not match (positional-index safety re-filter)', async () => {
|
|
61
|
+
const other = row({owner: Name.from('someoneelse.gm')})
|
|
62
|
+
const m = managerWith(
|
|
63
|
+
async () => [row(), other],
|
|
64
|
+
async () => []
|
|
65
|
+
)
|
|
66
|
+
const jobs = await m.getOwnedJobs(OWNER)
|
|
67
|
+
expect(jobs).toHaveLength(1)
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
it('falls back to a full-scan .all() when the positional query throws', async () => {
|
|
71
|
+
const m = managerWith(
|
|
72
|
+
async () => {
|
|
73
|
+
throw new Error('bad index_position')
|
|
74
|
+
},
|
|
75
|
+
async () => [row()]
|
|
76
|
+
)
|
|
77
|
+
const jobs = await m.getOwnedJobs(OWNER)
|
|
78
|
+
expect(jobs).toHaveLength(1)
|
|
79
|
+
})
|
|
80
|
+
})
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import {Name, type NameType} from '@wharfkit/antelope'
|
|
2
|
+
import {BaseManager} from './base'
|
|
3
|
+
import {jobDeposited, jobStatus, splitJobCargo, type OwnedJob} from '../scheduling/jobs'
|
|
4
|
+
import type {ServerContract} from '../contracts'
|
|
5
|
+
|
|
6
|
+
type JobRow = ServerContract.Types.craftjob_row
|
|
7
|
+
|
|
8
|
+
export class JobsManager extends BaseManager {
|
|
9
|
+
async getOwnedJobs(owner: NameType, opts?: {now?: Date}): Promise<OwnedJob[]> {
|
|
10
|
+
const ownerName = Name.from(owner)
|
|
11
|
+
const now = opts?.now ?? new Date()
|
|
12
|
+
|
|
13
|
+
let rows: JobRow[]
|
|
14
|
+
try {
|
|
15
|
+
// index_position 'tertiary' = nodeos slot 3 = owner's secondary index; no ABI metadata for it.
|
|
16
|
+
rows = (await this.server
|
|
17
|
+
.table('craftjobs')
|
|
18
|
+
.query({
|
|
19
|
+
index_position: 'tertiary',
|
|
20
|
+
key_type: 'i64',
|
|
21
|
+
from: ownerName.value,
|
|
22
|
+
to: ownerName.value,
|
|
23
|
+
})
|
|
24
|
+
.all()) as JobRow[]
|
|
25
|
+
} catch {
|
|
26
|
+
rows = (await this.server.table('craftjobs').all()) as JobRow[]
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return rows.filter((r) => ownerName.equals(r.owner)).map((r) => this.parseOwnedJob(r, now))
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private parseOwnedJob(r: JobRow, now: Date): OwnedJob {
|
|
33
|
+
const startsAt = r.starts_at.toDate()
|
|
34
|
+
const completesAt = r.completes_at.toDate()
|
|
35
|
+
const deposited = jobDeposited(r.deposited)
|
|
36
|
+
const {output, inputs} = splitJobCargo(r.cargo, deposited)
|
|
37
|
+
return {
|
|
38
|
+
id: r.id.toNumber(),
|
|
39
|
+
building: r.building.toNumber(),
|
|
40
|
+
socket: r.socket.toNumber(),
|
|
41
|
+
shipId: r.ship_id.toNumber(),
|
|
42
|
+
coords: {x: r.coords.x.toNumber(), y: r.coords.y.toNumber()},
|
|
43
|
+
startsAt,
|
|
44
|
+
completesAt,
|
|
45
|
+
recipeId: r.recipe_id.toNumber(),
|
|
46
|
+
quantity: r.quantity.toNumber(),
|
|
47
|
+
status: jobStatus({startsAt, completesAt, deposited}, now),
|
|
48
|
+
deposited,
|
|
49
|
+
output,
|
|
50
|
+
inputs,
|
|
51
|
+
outputStats: output?.stats === undefined ? undefined : BigInt(output.stats.toString()),
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {BlockTimestamp, type UInt16Type} from '@wharfkit/antelope'
|
|
2
2
|
import {BaseManager} from './base'
|
|
3
|
-
import
|
|
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(
|
|
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
|
|
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),
|
|
45
|
+
overrideMap.set(Number(o.stratum), o)
|
|
42
46
|
}
|
|
43
47
|
|
|
44
|
-
return derived.map((s) =>
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
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,21 @@
|
|
|
1
|
+
import {describe, expect, test} from 'bun:test'
|
|
2
|
+
import {resolveLockedAmount, wrapCostKey} 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
|
+
})
|
|
15
|
+
|
|
16
|
+
describe('wrapCostKey', () => {
|
|
17
|
+
test('packs item type and tier as (type << 8) | tier', () => {
|
|
18
|
+
expect(wrapCostKey(0, 1).toString()).toBe('1')
|
|
19
|
+
expect(wrapCostKey(3, 2).toString()).toBe('770')
|
|
20
|
+
})
|
|
21
|
+
})
|