@shipload/sdk 0.7.0 → 1.0.0-beta1

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 (95) hide show
  1. package/lib/shipload.d.ts +2730 -287
  2. package/lib/shipload.js +10862 -2228
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +10434 -2170
  5. package/lib/shipload.m.js.map +1 -1
  6. package/package.json +11 -20
  7. package/src/capabilities/crafting.ts +22 -0
  8. package/src/capabilities/gathering.ts +36 -0
  9. package/src/capabilities/guards.ts +38 -0
  10. package/src/capabilities/hauling.ts +22 -0
  11. package/src/capabilities/index.ts +8 -0
  12. package/src/capabilities/loading.ts +8 -0
  13. package/src/capabilities/modules.ts +86 -0
  14. package/src/capabilities/movement.ts +29 -0
  15. package/src/capabilities/storage.ts +159 -0
  16. package/src/contracts/platform.ts +30 -30
  17. package/src/contracts/server.ts +1387 -283
  18. package/src/data/capabilities.ts +408 -0
  19. package/src/data/catalog.ts +135 -0
  20. package/src/data/categories.ts +55 -0
  21. package/src/data/colors.ts +84 -0
  22. package/src/data/entities.json +50 -0
  23. package/src/data/item-ids.ts +75 -0
  24. package/src/data/items.json +252 -0
  25. package/src/data/locations.ts +53 -0
  26. package/src/data/metadata.ts +208 -0
  27. package/src/data/nebula-adjectives.json +211 -0
  28. package/src/data/nebula-nouns.json +151 -0
  29. package/src/data/recipes-runtime.ts +65 -0
  30. package/src/data/recipes.json +878 -0
  31. package/src/data/syllables.json +1790 -0
  32. package/src/data/tiers.ts +45 -0
  33. package/src/derivation/crafting.ts +350 -0
  34. package/src/derivation/index.ts +32 -0
  35. package/src/derivation/location-size.ts +15 -0
  36. package/src/derivation/resources.ts +112 -0
  37. package/src/derivation/stats.ts +146 -0
  38. package/src/derivation/strata.ts +43 -0
  39. package/src/derivation/stratum.ts +134 -0
  40. package/src/derivation/tiers.ts +54 -0
  41. package/src/entities/cargo-utils.ts +84 -0
  42. package/src/entities/container.ts +108 -0
  43. package/src/entities/entity-inventory.ts +39 -0
  44. package/src/entities/gamestate.ts +152 -0
  45. package/src/entities/inventory-accessor.ts +42 -0
  46. package/src/entities/location.ts +60 -0
  47. package/src/entities/makers.ts +196 -0
  48. package/src/entities/player.ts +15 -0
  49. package/src/entities/ship-deploy.ts +258 -0
  50. package/src/entities/ship.ts +204 -0
  51. package/src/entities/warehouse.ts +119 -0
  52. package/src/errors.ts +100 -9
  53. package/src/format.ts +12 -0
  54. package/src/index-module.ts +317 -7
  55. package/src/managers/actions.ts +250 -0
  56. package/src/managers/base.ts +25 -0
  57. package/src/managers/context.ts +114 -0
  58. package/src/managers/entities.ts +103 -0
  59. package/src/managers/epochs.ts +47 -0
  60. package/src/managers/index.ts +9 -0
  61. package/src/managers/locations.ts +68 -0
  62. package/src/managers/players.ts +13 -0
  63. package/src/nft/description.ts +176 -0
  64. package/src/nft/deserializers.ts +83 -0
  65. package/src/nft/index.ts +2 -0
  66. package/src/resolution/describe-module.ts +166 -0
  67. package/src/resolution/display-name.ts +39 -0
  68. package/src/resolution/resolve-item.ts +358 -0
  69. package/src/scheduling/accessor.ts +82 -0
  70. package/src/{epoch.ts → scheduling/epoch.ts} +1 -1
  71. package/src/scheduling/projection.ts +463 -0
  72. package/src/scheduling/schedule.ts +179 -0
  73. package/src/shipload.ts +47 -160
  74. package/src/subscriptions/connection.ts +154 -0
  75. package/src/subscriptions/debug.ts +17 -0
  76. package/src/subscriptions/index.ts +5 -0
  77. package/src/subscriptions/manager.ts +240 -0
  78. package/src/subscriptions/mappers.ts +28 -0
  79. package/src/subscriptions/types.ts +143 -0
  80. package/src/travel/travel.ts +500 -0
  81. package/src/types/capabilities.ts +76 -0
  82. package/src/types/entity-traits.ts +69 -0
  83. package/src/types/entity.ts +39 -0
  84. package/src/types/index.ts +3 -0
  85. package/src/types.ts +140 -35
  86. package/src/{hash.ts → utils/hash.ts} +2 -2
  87. package/src/utils/system.ts +168 -0
  88. package/src/goods.ts +0 -124
  89. package/src/market.ts +0 -214
  90. package/src/rolls.ts +0 -8
  91. package/src/ship.ts +0 -36
  92. package/src/state.ts +0 -0
  93. package/src/syllables.ts +0 -1184
  94. package/src/system.ts +0 -36
  95. package/src/travel.ts +0 -259
package/package.json CHANGED
@@ -1,25 +1,27 @@
1
1
  {
2
2
  "name": "@shipload/sdk",
3
3
  "description": "SDKs for Shipload",
4
- "version": "0.7.0",
4
+ "version": "1.0.0-beta1",
5
5
  "homepage": "https://github.com/shipload/sdk",
6
6
  "license": "MIT",
7
7
  "main": "lib/shipload.js",
8
8
  "module": "lib/shipload.m.js",
9
9
  "types": "lib/shipload.d.ts",
10
- "unpkg": "lib/shipload.bundle.js",
11
10
  "sideEffects": false,
12
11
  "files": [
13
12
  "lib/*",
14
13
  "src/*"
15
14
  ],
16
15
  "scripts": {
17
- "prepare": "make"
16
+ "prepare": "make",
17
+ "check": "tsc --noEmit",
18
+ "build": "make build",
19
+ "test": "make test"
18
20
  },
19
21
  "dependencies": {
20
- "@wharfkit/antelope": "^1.0.2",
21
- "@wharfkit/contract": "^1.1.5",
22
- "@wharfkit/session": "^1.3.1",
22
+ "@wharfkit/antelope": "1.2.0",
23
+ "@wharfkit/common": "1.5.0",
24
+ "@wharfkit/contract": "1.2.1",
23
25
  "tslib": "^2.1.0"
24
26
  },
25
27
  "devDependencies": {
@@ -30,34 +32,23 @@
30
32
  "@rollup/plugin-json": "^4.1.0",
31
33
  "@rollup/plugin-node-resolve": "^14.1.0",
32
34
  "@rollup/plugin-replace": "^5.0.1",
33
- "@rollup/plugin-typescript": "^10.0.1",
35
+ "@rollup/plugin-typescript": "^12.1.0",
34
36
  "@rollup/plugin-virtual": "^2.0.3",
37
+ "@types/bun": "latest",
35
38
  "@types/chai": "^4.3.1",
36
- "@types/mocha": "^9.0.0",
37
39
  "@types/node": "^18.7.18",
38
- "@typescript-eslint/eslint-plugin": "^5.20.0",
39
- "@typescript-eslint/parser": "^5.20.0",
40
40
  "@wharfkit/mock-data": "^1.3.0",
41
41
  "@wharfkit/wallet-plugin-privatekey": "^1.1.0",
42
42
  "chai": "^4.3.4",
43
- "eslint": "^8.13.0",
44
- "eslint-config-prettier": "^8.1.0",
45
- "eslint-plugin-prettier": "^4.0.0",
46
43
  "gh-pages": "^4.0.0",
47
- "mocha": "^10.0.0",
48
44
  "node-fetch": "^2.6.1",
49
- "nyc": "^15.1.0",
50
45
  "onchange": "^7.1.0",
51
- "prettier": "^2.2.1",
52
46
  "rollup": "^2.70.2",
53
47
  "rollup-plugin-cleanup": "^3.2.1",
54
48
  "rollup-plugin-dts": "^4.2.1",
55
49
  "rollup-plugin-terser": "^7.0.2",
56
- "ts-node": "^10.9.1",
57
- "tsconfig-paths": "^4.1.1",
58
50
  "typedoc": "^0.23.14",
59
51
  "typedoc-plugin-mermaid": "^1.10.0",
60
- "typescript": "^4.1.2",
61
- "yarn-deduplicate": "^6.0.2"
52
+ "typescript": "^5.4.0"
62
53
  }
63
54
  }
@@ -0,0 +1,22 @@
1
+ import {UInt16, UInt32} from '@wharfkit/antelope'
2
+ import {CRAFT_ENERGY_DIVISOR} from '../types'
3
+ import type {EntityCapabilities} from '../types/capabilities'
4
+ import type {ServerContract} from '../contracts'
5
+
6
+ export interface CrafterCapability {
7
+ crafter: ServerContract.Types.crafter_stats
8
+ }
9
+
10
+ export function capsHasCrafter(caps: EntityCapabilities): boolean {
11
+ return caps.crafter !== undefined
12
+ }
13
+
14
+ export function calc_craft_duration(speed: number, totalInputMass: number): UInt32 {
15
+ const duration = Math.floor(totalInputMass / speed)
16
+ return UInt32.from(Math.max(duration, 1))
17
+ }
18
+
19
+ export function calc_craft_energy(drain: number, totalInputMass: number): UInt16 {
20
+ const raw = Math.floor((totalInputMass * drain) / CRAFT_ENERGY_DIVISOR)
21
+ return UInt16.from(Math.min(raw, 65535))
22
+ }
@@ -0,0 +1,36 @@
1
+ import {UInt16, UInt32} from '@wharfkit/antelope'
2
+ import type {ServerContract} from '../contracts'
3
+ import {PRECISION} from '../types'
4
+
5
+ const GATHER_TIME_SCALE = 100
6
+ const DEPTH_PENALTY_DIVISOR = 5000
7
+ const SPEED_TIME_SCALE = 300
8
+
9
+ export function calc_gather_duration(
10
+ gatherer: ServerContract.Types.gatherer_stats,
11
+ itemMass: number,
12
+ quantity: number,
13
+ stratum: number,
14
+ richness: number
15
+ ): UInt32 {
16
+ const yieldValue = gatherer.yield.toNumber()
17
+ const speed = gatherer.speed.toNumber()
18
+
19
+ if (yieldValue === 0 || speed === 0 || richness === 0) return UInt32.from(0)
20
+
21
+ const massFactor = Math.sqrt(itemMass)
22
+ const depthPenalty = 1 + stratum / DEPTH_PENALTY_DIVISOR
23
+ const richnessMul = richness / 1000
24
+ const gatherTime =
25
+ (quantity * massFactor * GATHER_TIME_SCALE * depthPenalty) / (yieldValue * richnessMul)
26
+ const speedTime = SPEED_TIME_SCALE * Math.log(1 + stratum / speed)
27
+ return UInt32.from(Math.floor(gatherTime + speedTime))
28
+ }
29
+
30
+ export function calc_gather_energy(
31
+ gatherer: ServerContract.Types.gatherer_stats,
32
+ duration: number
33
+ ): UInt16 {
34
+ const energy = Math.floor((duration * gatherer.drain.toNumber()) / PRECISION)
35
+ return UInt16.from(energy)
36
+ }
@@ -0,0 +1,38 @@
1
+ import type {
2
+ EnergyCapability,
3
+ GathererCapability,
4
+ LoaderCapability,
5
+ MassCapability,
6
+ MovementCapability,
7
+ ScheduleCapability,
8
+ StorageCapability,
9
+ } from '../types/capabilities'
10
+ import type {Entity} from '../types/entity'
11
+
12
+ export function canMove(e: Entity): e is Entity & MovementCapability & EnergyCapability {
13
+ return 'engines' in e && 'generator' in e && 'energy' in e
14
+ }
15
+
16
+ export function hasEnergy(e: Entity): e is Entity & EnergyCapability {
17
+ return 'energy' in e
18
+ }
19
+
20
+ export function hasStorage(e: Entity): e is Entity & StorageCapability {
21
+ return 'capacity' in e && 'cargo' in e
22
+ }
23
+
24
+ export function hasLoaders(e: Entity): e is Entity & LoaderCapability {
25
+ return 'loaders' in e && e.loaders !== undefined
26
+ }
27
+
28
+ export function hasMass(e: Entity): e is Entity & MassCapability {
29
+ return 'hullmass' in e
30
+ }
31
+
32
+ export function hasSchedule(e: Entity): e is Entity & ScheduleCapability {
33
+ return 'schedule' in e
34
+ }
35
+
36
+ export function hasGatherer(e: Entity): e is Entity & GathererCapability {
37
+ return 'gatherer' in e && e.gatherer !== undefined
38
+ }
@@ -0,0 +1,22 @@
1
+ const BASE_HAUL_PENALTY_MILLI = 300
2
+ const HAULER_EFFICIENCY_DENOM = 10000
3
+ const PRECISION = 10000
4
+
5
+ export function computeHaulPenalty(
6
+ totalThrust: number,
7
+ haulCount: number,
8
+ avgEfficiency: number
9
+ ): number {
10
+ if (haulCount === 0) return totalThrust
11
+ const penaltyMilli =
12
+ 1000 +
13
+ Math.floor(
14
+ (haulCount * BASE_HAUL_PENALTY_MILLI * (HAULER_EFFICIENCY_DENOM - avgEfficiency)) /
15
+ HAULER_EFFICIENCY_DENOM
16
+ )
17
+ return Math.floor((totalThrust * 1000) / penaltyMilli)
18
+ }
19
+
20
+ export function computeHaulerDrain(distance: number, drain: number, haulCount: number): number {
21
+ return Math.floor(distance / PRECISION) * drain * haulCount
22
+ }
@@ -0,0 +1,8 @@
1
+ export * from './guards'
2
+ export * from './movement'
3
+ export * from './storage'
4
+ export * from './loading'
5
+ export * from './gathering'
6
+ export * from './crafting'
7
+ export * from './modules'
8
+ export * from './hauling'
@@ -0,0 +1,8 @@
1
+ import {UInt32, type UInt64} from '@wharfkit/antelope'
2
+ import type {LoaderCapability} from '../types/capabilities'
3
+
4
+ export function calcLoadDuration(entity: LoaderCapability, cargoMass: UInt64): UInt32 {
5
+ const totalThrust = entity.loaders.thrust.toNumber() * entity.loaders.quantity.toNumber()
6
+ if (totalThrust === 0) return UInt32.from(0)
7
+ return UInt32.from(Math.ceil(Number(cargoMass) / totalThrust))
8
+ }
@@ -0,0 +1,86 @@
1
+ import {
2
+ ITEM_CRAFTER_T1,
3
+ ITEM_ENGINE_T1,
4
+ ITEM_GATHERER_T1,
5
+ ITEM_GENERATOR_T1,
6
+ ITEM_HAULER_T1,
7
+ ITEM_LOADER_T1,
8
+ ITEM_STORAGE_T1,
9
+ } from '../data/item-ids'
10
+
11
+ export const MODULE_ANY = 0
12
+ export const MODULE_ENGINE = 1
13
+ export const MODULE_GENERATOR = 2
14
+ export const MODULE_GATHERER = 3
15
+ export const MODULE_LOADER = 4
16
+ export const MODULE_WARP = 5
17
+ export const MODULE_CRAFTER = 6
18
+ export const MODULE_LAUNCHER = 7
19
+ export const MODULE_STORAGE = 8
20
+ export const MODULE_HAULER = 9
21
+
22
+ export interface PackedModule {
23
+ itemId: number
24
+ stats: bigint
25
+ }
26
+
27
+ export interface ModuleEntry {
28
+ type: number
29
+ installed?: PackedModule
30
+ }
31
+
32
+ export function moduleAccepts(slotType: number, moduleType: number): boolean {
33
+ return slotType === MODULE_ANY || slotType === moduleType
34
+ }
35
+
36
+ export function getModuleCapabilityType(itemId: number): number {
37
+ switch (itemId) {
38
+ case ITEM_ENGINE_T1:
39
+ return MODULE_ENGINE
40
+ case ITEM_GENERATOR_T1:
41
+ return MODULE_GENERATOR
42
+ case ITEM_GATHERER_T1:
43
+ return MODULE_GATHERER
44
+ case ITEM_LOADER_T1:
45
+ return MODULE_LOADER
46
+ case ITEM_CRAFTER_T1:
47
+ return MODULE_CRAFTER
48
+ case ITEM_STORAGE_T1:
49
+ return MODULE_STORAGE
50
+ case ITEM_HAULER_T1:
51
+ return MODULE_HAULER
52
+ default:
53
+ return 0xff
54
+ }
55
+ }
56
+
57
+ export function isModuleItem(itemId: number): boolean {
58
+ return getModuleCapabilityType(itemId) !== 0xff
59
+ }
60
+
61
+ export function moduleSlotTypeToCode(slotType: string): number {
62
+ switch (slotType) {
63
+ case 'any':
64
+ return MODULE_ANY
65
+ case 'engine':
66
+ return MODULE_ENGINE
67
+ case 'generator':
68
+ return MODULE_GENERATOR
69
+ case 'gatherer':
70
+ return MODULE_GATHERER
71
+ case 'loader':
72
+ return MODULE_LOADER
73
+ case 'warp':
74
+ return MODULE_WARP
75
+ case 'crafter':
76
+ return MODULE_CRAFTER
77
+ case 'launcher':
78
+ return MODULE_LAUNCHER
79
+ case 'storage':
80
+ return MODULE_STORAGE
81
+ case 'hauler':
82
+ return MODULE_HAULER
83
+ default:
84
+ return MODULE_ANY
85
+ }
86
+ }
@@ -0,0 +1,29 @@
1
+ import {UInt32, UInt64} from '@wharfkit/antelope'
2
+ import type {EnergyCapability, MovementCapability} from '../types/capabilities'
3
+ import {PRECISION} from '../types'
4
+
5
+ export function maxTravelDistance(entity: MovementCapability): UInt32 {
6
+ return UInt32.from(entity.generator.capacity)
7
+ .dividing(entity.engines.drain)
8
+ .multiplying(PRECISION)
9
+ }
10
+
11
+ export function calcEnergyUsage(entity: MovementCapability, distance: UInt64): UInt64 {
12
+ return distance.dividing(PRECISION).multiplying(entity.engines.drain)
13
+ }
14
+
15
+ export function hasEnergyForDistance(
16
+ entity: MovementCapability & EnergyCapability,
17
+ distance: UInt64
18
+ ): boolean {
19
+ const usage = calcEnergyUsage(entity, distance)
20
+ return UInt64.from(entity.energy).gte(usage)
21
+ }
22
+
23
+ export function energyPercent(entity: MovementCapability & EnergyCapability): number {
24
+ return (Number(entity.energy) / Number(entity.generator.capacity)) * 100
25
+ }
26
+
27
+ export function needsRecharge(entity: MovementCapability & EnergyCapability): boolean {
28
+ return UInt64.from(entity.energy).lt(entity.generator.capacity)
29
+ }
@@ -0,0 +1,159 @@
1
+ import {UInt16, UInt32, UInt64, type UInt64Type} from '@wharfkit/antelope'
2
+ import {ServerContract} from '../contracts'
3
+ import type {StorageCapability} from '../types/capabilities'
4
+ import {getItem} from '../data/catalog'
5
+ import {INSUFFICIENT_ITEM_QUANTITY} from '../errors'
6
+
7
+ export interface HasCargo {
8
+ cargo: ServerContract.Types.cargo_item[]
9
+ }
10
+
11
+ export interface HasCapacity {
12
+ capacity: UInt32
13
+ }
14
+
15
+ export interface HasCargomass {
16
+ cargomass: UInt32
17
+ }
18
+
19
+ interface MassInput {
20
+ item_id: UInt16
21
+ quantity: UInt32
22
+ modules: ServerContract.Types.module_entry[]
23
+ }
24
+
25
+ export function calcCargoItemMass(item: MassInput): UInt64 {
26
+ const itemDef = getItem(item.item_id)
27
+ let mass = UInt64.from(itemDef.mass).multiplying(item.quantity)
28
+
29
+ for (const mod of item.modules) {
30
+ if (mod.installed) {
31
+ const modDef = getItem(mod.installed.item_id)
32
+ mass = mass.adding(UInt64.from(modDef.mass))
33
+ }
34
+ }
35
+
36
+ return mass
37
+ }
38
+
39
+ export function calcCargoMass(entity: HasCargo): UInt64 {
40
+ let mass = UInt64.from(0)
41
+ for (const item of entity.cargo) {
42
+ mass = mass.adding(calcCargoItemMass(item))
43
+ }
44
+ return mass
45
+ }
46
+
47
+ export function calcStacksMass(stacks: CargoStack[]): UInt64 {
48
+ let mass = UInt64.from(0)
49
+ for (const s of stacks) {
50
+ mass = mass.adding(calcCargoItemMass(s))
51
+ }
52
+ return mass
53
+ }
54
+
55
+ export function availableCapacity(entity: StorageCapability): UInt64 {
56
+ const cargoMass = calcCargoMass(entity)
57
+ return entity.capacity.gt(cargoMass)
58
+ ? UInt64.from(entity.capacity).subtracting(cargoMass)
59
+ : UInt64.from(0)
60
+ }
61
+
62
+ export function availableCapacityFromMass(capacity: UInt64Type, cargoMass: UInt64Type): UInt64 {
63
+ const cap = UInt64.from(capacity)
64
+ const mass = UInt64.from(cargoMass)
65
+ return cap.gt(mass) ? cap.subtracting(mass) : UInt64.from(0)
66
+ }
67
+
68
+ export function hasSpace(entity: StorageCapability, goodMass: UInt64, quantity: number): boolean {
69
+ const additional = goodMass.multiplying(quantity)
70
+ return availableCapacity(entity).gte(additional)
71
+ }
72
+
73
+ export function hasSpaceForMass(
74
+ capacity: UInt64Type,
75
+ currentMass: UInt64Type,
76
+ additionalMass: UInt64Type
77
+ ): boolean {
78
+ return UInt64.from(currentMass).adding(additionalMass).lte(capacity)
79
+ }
80
+
81
+ export function isFull(entity: HasCapacity & HasCargomass): boolean {
82
+ return UInt64.from(entity.cargomass).gte(entity.capacity)
83
+ }
84
+
85
+ export function isFullFromMass(capacity: UInt64Type, cargoMass: UInt64Type): boolean {
86
+ return UInt64.from(cargoMass).gte(capacity)
87
+ }
88
+
89
+ export interface CargoStack {
90
+ item_id: UInt16
91
+ quantity: UInt32
92
+ stats: UInt64
93
+ modules: ServerContract.Types.module_entry[]
94
+ }
95
+
96
+ export function cargoItemToStack(item: ServerContract.Types.cargo_item): CargoStack {
97
+ return {
98
+ item_id: UInt16.from(item.item_id),
99
+ quantity: UInt32.from(item.quantity),
100
+ stats: item.stats,
101
+ modules: item.modules ?? [],
102
+ }
103
+ }
104
+
105
+ export function stackToCargoItem(stack: CargoStack): ServerContract.Types.cargo_item {
106
+ return ServerContract.Types.cargo_item.from({
107
+ item_id: stack.item_id,
108
+ quantity: stack.quantity,
109
+ stats: stack.stats,
110
+ modules: stack.modules,
111
+ })
112
+ }
113
+
114
+ function statsEquals(a: UInt64, b: UInt64): boolean {
115
+ return a.equals(b)
116
+ }
117
+
118
+ function stackIdentityEqual(a: CargoStack, b: CargoStack): boolean {
119
+ return a.item_id.equals(b.item_id) && statsEquals(a.stats, b.stats)
120
+ }
121
+
122
+ export function stackKey(s: CargoStack): string {
123
+ return `${s.item_id.toNumber()}:${s.stats.toString()}`
124
+ }
125
+
126
+ export function stacksEqual(a: CargoStack, b: CargoStack): boolean {
127
+ return stackIdentityEqual(a, b) && a.quantity.equals(b.quantity)
128
+ }
129
+
130
+ export function mergeStacks(stacks: CargoStack[], add: CargoStack): CargoStack[] {
131
+ const idx = stacks.findIndex((s) => stackIdentityEqual(s, add))
132
+ if (idx === -1) {
133
+ return [...stacks, {...add}]
134
+ }
135
+ const result = stacks.slice()
136
+ result[idx] = {
137
+ ...result[idx],
138
+ quantity: UInt32.from(result[idx].quantity.adding(add.quantity)),
139
+ }
140
+ return result
141
+ }
142
+
143
+ export function removeFromStacks(stacks: CargoStack[], remove: CargoStack): CargoStack[] {
144
+ const idx = stacks.findIndex((s) => stackIdentityEqual(s, remove))
145
+ if (idx === -1) {
146
+ throw new Error(INSUFFICIENT_ITEM_QUANTITY)
147
+ }
148
+ const target = stacks[idx]
149
+ if (target.quantity.lt(remove.quantity)) {
150
+ throw new Error(INSUFFICIENT_ITEM_QUANTITY)
151
+ }
152
+ const remaining = UInt32.from(target.quantity.subtracting(remove.quantity))
153
+ if (remaining.equals(UInt32.from(0))) {
154
+ return [...stacks.slice(0, idx), ...stacks.slice(idx + 1)]
155
+ }
156
+ const result = stacks.slice()
157
+ result[idx] = {...target, quantity: remaining}
158
+ return result
159
+ }
@@ -19,98 +19,98 @@ export namespace Types {
19
19
  @Struct.type('cleartable')
20
20
  export class cleartable extends Struct {
21
21
  @Struct.field(Name)
22
- table_name!: Name
22
+ declare table_name: Name
23
23
  @Struct.field(Name, {optional: true})
24
- scope?: Name
24
+ declare scope?: Name
25
25
  @Struct.field(UInt64, {optional: true})
26
- max_rows?: UInt64
26
+ declare max_rows?: UInt64
27
27
  }
28
28
  @Struct.type('company_row')
29
29
  export class company_row extends Struct {
30
30
  @Struct.field(Name)
31
- account!: Name
31
+ declare account: Name
32
32
  @Struct.field('string')
33
- name!: string
33
+ declare name: string
34
34
  }
35
35
  @Struct.type('enable')
36
36
  export class enable extends Struct {
37
37
  @Struct.field('bool')
38
- enabled!: boolean
38
+ declare enabled: boolean
39
39
  }
40
40
  @Struct.type('enablegame')
41
41
  export class enablegame extends Struct {
42
42
  @Struct.field(Name)
43
- contract!: Name
43
+ declare contract: Name
44
44
  @Struct.field('bool')
45
- enabled!: boolean
45
+ declare enabled: boolean
46
46
  }
47
47
  @Struct.type('foundcompany')
48
48
  export class foundcompany extends Struct {
49
49
  @Struct.field(Name)
50
- account!: Name
50
+ declare account: Name
51
51
  @Struct.field('string')
52
- name!: string
52
+ declare name: string
53
53
  }
54
54
  @Struct.type('game_config')
55
55
  export class game_config extends Struct {
56
56
  @Struct.field(Checksum256)
57
- seed!: Checksum256
57
+ declare seed: Checksum256
58
58
  @Struct.field(UInt32)
59
- epochtime!: UInt32
59
+ declare epochtime: UInt32
60
60
  @Struct.field(TimePointSec)
61
- start!: TimePointSec
61
+ declare start: TimePointSec
62
62
  @Struct.field(TimePointSec)
63
- end!: TimePointSec
63
+ declare end: TimePointSec
64
64
  }
65
65
  @Struct.type('game_meta')
66
66
  export class game_meta extends Struct {
67
67
  @Struct.field('string')
68
- name!: string
68
+ declare name: string
69
69
  @Struct.field('string')
70
- description!: string
70
+ declare description: string
71
71
  @Struct.field('string')
72
- url!: string
72
+ declare url: string
73
73
  @Struct.field('string')
74
- version!: string
74
+ declare version: string
75
75
  }
76
76
  @Struct.type('game_state')
77
77
  export class game_state extends Struct {
78
78
  @Struct.field('bool')
79
- enabled!: boolean
79
+ declare enabled: boolean
80
80
  }
81
81
  @Struct.type('game_row')
82
82
  export class game_row extends Struct {
83
83
  @Struct.field(Name)
84
- contract!: Name
84
+ declare contract: Name
85
85
  @Struct.field(game_config)
86
- config!: game_config
86
+ declare config: game_config
87
87
  @Struct.field(game_meta)
88
- meta!: game_meta
88
+ declare meta: game_meta
89
89
  @Struct.field(game_state)
90
- state!: game_state
90
+ declare state: game_state
91
91
  }
92
92
  @Struct.type('startgame')
93
93
  export class startgame extends Struct {
94
94
  @Struct.field(Name)
95
- contract!: Name
95
+ declare contract: Name
96
96
  @Struct.field(game_config)
97
- config!: game_config
97
+ declare config: game_config
98
98
  @Struct.field(game_meta)
99
- meta!: game_meta
99
+ declare meta: game_meta
100
100
  @Struct.field(game_state)
101
- state!: game_state
101
+ declare state: game_state
102
102
  }
103
103
  @Struct.type('state_row')
104
104
  export class state_row extends Struct {
105
105
  @Struct.field('bool')
106
- enabled!: boolean
106
+ declare enabled: boolean
107
107
  }
108
108
  @Struct.type('updategame')
109
109
  export class updategame extends Struct {
110
110
  @Struct.field(Name)
111
- contract!: Name
111
+ declare contract: Name
112
112
  @Struct.field(game_meta)
113
- meta!: game_meta
113
+ declare meta: game_meta
114
114
  }
115
115
  @Struct.type('wipe')
116
116
  export class wipe extends Struct {}