@shipload/sdk 1.0.0-next.2 → 1.0.0-next.21

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 (85) hide show
  1. package/lib/shipload.d.ts +1731 -1044
  2. package/lib/shipload.js +6758 -4523
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +6649 -4479
  5. package/lib/shipload.m.js.map +1 -1
  6. package/lib/testing.d.ts +833 -0
  7. package/lib/testing.js +3647 -0
  8. package/lib/testing.js.map +1 -0
  9. package/lib/testing.m.js +3641 -0
  10. package/lib/testing.m.js.map +1 -0
  11. package/package.json +15 -2
  12. package/src/capabilities/gathering.ts +17 -7
  13. package/src/capabilities/modules.ts +9 -0
  14. package/src/capabilities/storage.ts +1 -1
  15. package/src/contracts/platform.ts +211 -3
  16. package/src/contracts/server.ts +723 -438
  17. package/src/data/capabilities.ts +9 -329
  18. package/src/data/capability-formulas.ts +76 -0
  19. package/src/data/catalog.ts +0 -5
  20. package/src/data/colors.ts +14 -28
  21. package/src/data/entities.json +46 -10
  22. package/src/data/item-ids.ts +17 -13
  23. package/src/data/items.json +308 -37
  24. package/src/data/kind-registry.json +85 -0
  25. package/src/data/kind-registry.ts +150 -0
  26. package/src/data/metadata.ts +99 -24
  27. package/src/data/recipes-runtime.ts +3 -23
  28. package/src/data/recipes.json +265 -96
  29. package/src/derivation/build-methods.ts +45 -0
  30. package/src/derivation/capabilities.ts +414 -0
  31. package/src/derivation/capability-mappings.ts +117 -0
  32. package/src/derivation/crafting.ts +23 -24
  33. package/src/derivation/index.ts +8 -2
  34. package/src/derivation/reserve-regen.ts +34 -0
  35. package/src/derivation/resources.ts +125 -38
  36. package/src/derivation/stats.ts +1 -2
  37. package/src/derivation/stratum.ts +15 -19
  38. package/src/derivation/tiers.ts +28 -7
  39. package/src/entities/entity.ts +98 -0
  40. package/src/entities/gamestate.ts +3 -28
  41. package/src/entities/makers.ts +75 -129
  42. package/src/entities/slot-multiplier.ts +37 -0
  43. package/src/errors.ts +10 -15
  44. package/src/format.ts +26 -4
  45. package/src/index-module.ts +151 -40
  46. package/src/managers/actions.ts +184 -82
  47. package/src/managers/base.ts +2 -2
  48. package/src/managers/construction-types.ts +68 -0
  49. package/src/managers/construction.ts +292 -0
  50. package/src/managers/context.ts +9 -0
  51. package/src/managers/entities.ts +18 -66
  52. package/src/managers/epochs.ts +40 -0
  53. package/src/managers/index.ts +16 -1
  54. package/src/managers/locations.ts +2 -20
  55. package/src/managers/nft.ts +28 -0
  56. package/src/managers/plot.ts +123 -0
  57. package/src/nft/atomicassets.ts +231 -0
  58. package/src/nft/atomicdata.ts +130 -0
  59. package/src/nft/buildImmutableData.ts +319 -0
  60. package/src/nft/description.ts +45 -13
  61. package/src/nft/index.ts +3 -0
  62. package/src/resolution/describe-module.ts +5 -8
  63. package/src/resolution/display-name.ts +38 -10
  64. package/src/resolution/resolve-item.ts +20 -12
  65. package/src/scheduling/accessor.ts +4 -0
  66. package/src/scheduling/projection.ts +79 -27
  67. package/src/scheduling/schedule.ts +15 -1
  68. package/src/scheduling/task-cargo.ts +46 -0
  69. package/src/shipload.ts +5 -0
  70. package/src/subscriptions/manager.ts +40 -6
  71. package/src/subscriptions/mappers.ts +3 -8
  72. package/src/subscriptions/types.ts +3 -2
  73. package/src/testing/catalog-hash.ts +19 -0
  74. package/src/testing/index.ts +2 -0
  75. package/src/testing/projection-parity.ts +143 -0
  76. package/src/travel/travel.ts +61 -2
  77. package/src/types/index.ts +0 -1
  78. package/src/types.ts +17 -12
  79. package/src/utils/cargo.ts +27 -0
  80. package/src/utils/system.ts +25 -24
  81. package/src/entities/container.ts +0 -108
  82. package/src/entities/ship-deploy.ts +0 -258
  83. package/src/entities/ship.ts +0 -204
  84. package/src/entities/warehouse.ts +0 -119
  85. package/src/types/entity-traits.ts +0 -69
@@ -0,0 +1,123 @@
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 {ServerContract} from '../contracts'
9
+ import type {BuildableTarget} from './construction-types'
10
+
11
+ export interface PlotProgressInputRow {
12
+ itemId: number
13
+ required: number
14
+ provided: number
15
+ missing: number
16
+ }
17
+
18
+ export interface PlotProgress {
19
+ targetItemId: number
20
+ rows: PlotProgressInputRow[]
21
+ massProvided: number
22
+ massRequired: number
23
+ isComplete: boolean
24
+ }
25
+
26
+ export class PlotManager extends BaseManager {
27
+ progress(
28
+ plot: ServerContract.Types.entity_row,
29
+ cargo: ServerContract.Types.cargo_row[]
30
+ ): PlotProgress {
31
+ const targetItemId = Number(plot.item_id.toString())
32
+ const recipe = getRecipe(targetItemId)
33
+ if (!recipe) {
34
+ throw new Error(`No recipe found for item ${targetItemId}`)
35
+ }
36
+
37
+ const plotId = plot.id.toString()
38
+ const plotCargo = cargo.filter((c) => c.entity_id.toString() === plotId)
39
+
40
+ const quantityByItemId = new Map<number, number>()
41
+ for (const c of plotCargo) {
42
+ const id = c.item_id.toNumber()
43
+ quantityByItemId.set(
44
+ id,
45
+ (quantityByItemId.get(id) ?? 0) + Number(c.quantity.toString())
46
+ )
47
+ }
48
+
49
+ const rows: PlotProgressInputRow[] = recipe.inputs.map((input) => {
50
+ const itemId = input.itemId
51
+ const required = input.quantity
52
+ const provided = quantityByItemId.get(itemId) ?? 0
53
+ const missing = Math.max(0, required - provided)
54
+ return {itemId, required, provided, missing}
55
+ })
56
+
57
+ const massRequired = computeInputMass(targetItemId)
58
+ const massProvided = rows.reduce((sum, r) => {
59
+ const item = getItem(r.itemId)
60
+ return sum + item.mass * r.provided
61
+ }, 0)
62
+ const isComplete = rows.every((r) => r.missing === 0)
63
+
64
+ return {targetItemId, rows, massProvided, massRequired, isComplete}
65
+ }
66
+
67
+ buildableTarget(
68
+ plot: ServerContract.Types.entity_row,
69
+ cargo: ServerContract.Types.cargo_row[],
70
+ activeTask?: ServerContract.Types.task
71
+ ): BuildableTarget {
72
+ const progress = this.progress(plot, cargo)
73
+ const targetItemId = Number(plot.item_id.toString())
74
+ const targetItem = getItem(targetItemId)
75
+ const recipe = getRecipe(targetItemId)
76
+ if (!recipe) {
77
+ throw new Error(`Plot target item ${targetItemId} has no recipe`)
78
+ }
79
+
80
+ let state: BuildableTarget['state']
81
+ const taskType = activeTask?.type.toNumber()
82
+ if (taskType === TaskType.CLAIMPLOT) {
83
+ state = 'initializing'
84
+ } else if (taskType === TaskType.BUILDPLOT) {
85
+ state = 'finalizing'
86
+ } else if (progress.isComplete) {
87
+ state = 'ready'
88
+ } else {
89
+ state = 'accepting'
90
+ }
91
+
92
+ return {
93
+ entityId: plot.id,
94
+ ownerName: plot.owner,
95
+ coordinates: plot.coordinates,
96
+ targetItemId,
97
+ targetItem,
98
+ state,
99
+ recipe,
100
+ progress,
101
+ finalizeAction: Name.from('buildplot'),
102
+ finalizerCapability: 'crafter',
103
+ activeTask,
104
+ }
105
+ }
106
+
107
+ canBuild(
108
+ plot: ServerContract.Types.entity_row,
109
+ cargo: ServerContract.Types.cargo_row[]
110
+ ): boolean {
111
+ return this.progress(plot, cargo).isComplete
112
+ }
113
+
114
+ timeToComplete(
115
+ plot: ServerContract.Types.entity_info,
116
+ crafter: ServerContract.Types.crafter_stats
117
+ ): number {
118
+ const capacity = Number(plot.capacity?.toString() ?? '0')
119
+ const speed = Number(crafter.speed.toString())
120
+ if (speed === 0) return 0
121
+ return calc_craft_duration(speed, capacity).toNumber()
122
+ }
123
+ }
@@ -0,0 +1,231 @@
1
+ import {
2
+ ABI,
3
+ type ABIDef,
4
+ Action,
5
+ type APIClient,
6
+ type NameType,
7
+ Name,
8
+ PermissionLevel,
9
+ UInt64,
10
+ } from '@wharfkit/antelope'
11
+ import {deserializeAtomicData, type SchemaField} from './atomicdata'
12
+ import {deserializeAsset, type NFTCargoItem, type NFTModuleSlot} from './deserializers'
13
+ import type {ImmutableEntry} from './buildImmutableData'
14
+
15
+ const PLACEHOLDER_AUTH = PermissionLevel.from({
16
+ actor: '............1',
17
+ permission: '............2',
18
+ })
19
+
20
+ export const ATOMICASSETS_ACCOUNT = 'atomicassets'
21
+ export const SHIPLOAD_COLLECTION = 'shipload'
22
+
23
+ const ATOMIC_ATTRIBUTE_VARIANT_NAME =
24
+ 'variant_int8_int16_int32_int64_uint8_uint16_uint32_uint64_float32_float64_string_INT8_VEC_INT16_VEC_INT32_VEC_INT64_VEC_UINT8_VEC_UINT16_VEC_UINT32_VEC_UINT64_VEC_FLOAT_VEC_DOUBLE_VEC_STRING_VEC'
25
+
26
+ const MINTASSET_ABI_DEF: ABIDef = {
27
+ version: 'eosio::abi/1.2',
28
+ types: [
29
+ {new_type_name: 'ATOMIC_ATTRIBUTE', type: ATOMIC_ATTRIBUTE_VARIANT_NAME},
30
+ {new_type_name: 'ATTRIBUTE_MAP', type: 'pair_string_ATOMIC_ATTRIBUTE[]'},
31
+ {new_type_name: 'INT8_VEC', type: 'bytes'},
32
+ {new_type_name: 'INT16_VEC', type: 'int16[]'},
33
+ {new_type_name: 'INT32_VEC', type: 'int32[]'},
34
+ {new_type_name: 'INT64_VEC', type: 'int64[]'},
35
+ {new_type_name: 'UINT8_VEC', type: 'bytes'},
36
+ {new_type_name: 'UINT16_VEC', type: 'uint16[]'},
37
+ {new_type_name: 'UINT32_VEC', type: 'uint32[]'},
38
+ {new_type_name: 'UINT64_VEC', type: 'uint64[]'},
39
+ {new_type_name: 'FLOAT_VEC', type: 'float32[]'},
40
+ {new_type_name: 'DOUBLE_VEC', type: 'float64[]'},
41
+ {new_type_name: 'STRING_VEC', type: 'string[]'},
42
+ ],
43
+ structs: [
44
+ {
45
+ name: 'pair_string_ATOMIC_ATTRIBUTE',
46
+ base: '',
47
+ fields: [
48
+ {name: 'first', type: 'string'},
49
+ {name: 'second', type: 'ATOMIC_ATTRIBUTE'},
50
+ ],
51
+ },
52
+ {
53
+ name: 'mintasset',
54
+ base: '',
55
+ fields: [
56
+ {name: 'authorized_minter', type: 'name'},
57
+ {name: 'collection_name', type: 'name'},
58
+ {name: 'schema_name', type: 'name'},
59
+ {name: 'template_id', type: 'int32'},
60
+ {name: 'new_asset_owner', type: 'name'},
61
+ {name: 'immutable_data', type: 'ATTRIBUTE_MAP'},
62
+ {name: 'mutable_data', type: 'ATTRIBUTE_MAP'},
63
+ {name: 'tokens_to_back', type: 'asset[]'},
64
+ ],
65
+ },
66
+ ],
67
+ actions: [{name: 'mintasset', type: 'mintasset', ricardian_contract: ''}],
68
+ variants: [
69
+ {
70
+ name: ATOMIC_ATTRIBUTE_VARIANT_NAME,
71
+ types: [
72
+ 'int8',
73
+ 'int16',
74
+ 'int32',
75
+ 'int64',
76
+ 'uint8',
77
+ 'uint16',
78
+ 'uint32',
79
+ 'uint64',
80
+ 'float32',
81
+ 'float64',
82
+ 'string',
83
+ 'INT8_VEC',
84
+ 'INT16_VEC',
85
+ 'INT32_VEC',
86
+ 'INT64_VEC',
87
+ 'UINT8_VEC',
88
+ 'UINT16_VEC',
89
+ 'UINT32_VEC',
90
+ 'UINT64_VEC',
91
+ 'FLOAT_VEC',
92
+ 'DOUBLE_VEC',
93
+ 'STRING_VEC',
94
+ ],
95
+ },
96
+ ],
97
+ }
98
+
99
+ export interface MintAssetParams {
100
+ authorizedMinter: NameType
101
+ collectionName: NameType
102
+ schemaName: NameType
103
+ templateId: number
104
+ newAssetOwner: NameType
105
+ immutableData: ImmutableEntry[]
106
+ }
107
+
108
+ const MINTASSET_ABI = ABI.from(MINTASSET_ABI_DEF)
109
+
110
+ export function buildMintAssetAction(params: MintAssetParams): Action {
111
+ return Action.from(
112
+ {
113
+ account: Name.from(ATOMICASSETS_ACCOUNT),
114
+ name: Name.from('mintasset'),
115
+ authorization: [PLACEHOLDER_AUTH],
116
+ data: {
117
+ authorized_minter: Name.from(params.authorizedMinter),
118
+ collection_name: Name.from(params.collectionName),
119
+ schema_name: Name.from(params.schemaName),
120
+ template_id: params.templateId,
121
+ new_asset_owner: Name.from(params.newAssetOwner),
122
+ immutable_data: params.immutableData,
123
+ mutable_data: [],
124
+ tokens_to_back: [],
125
+ },
126
+ },
127
+ MINTASSET_ABI
128
+ )
129
+ }
130
+
131
+ export interface AtomicAssetRow {
132
+ asset_id: string
133
+ collection_name: string
134
+ schema_name: string
135
+ template_id: number
136
+ ram_payer?: string
137
+ backed_tokens?: string[]
138
+ immutable_serialized_data: string | number[]
139
+ mutable_serialized_data?: string | number[]
140
+ }
141
+
142
+ export interface AtomicSchemaRow {
143
+ schema_name: string
144
+ format: SchemaField[]
145
+ }
146
+
147
+ export interface FetchAssetsOptions {
148
+ collection?: NameType
149
+ pageSize?: number
150
+ }
151
+
152
+ export async function fetchAtomicAssetsForOwner(
153
+ client: APIClient,
154
+ owner: NameType,
155
+ opts: FetchAssetsOptions = {}
156
+ ): Promise<AtomicAssetRow[]> {
157
+ const collection = opts.collection ? String(Name.from(opts.collection)) : undefined
158
+ const pageSize = opts.pageSize ?? 1000
159
+ const out: AtomicAssetRow[] = []
160
+ let lower: UInt64 | undefined
161
+ while (true) {
162
+ const res = await client.v1.chain.get_table_rows({
163
+ code: Name.from(ATOMICASSETS_ACCOUNT),
164
+ scope: String(Name.from(owner)),
165
+ table: Name.from('assets'),
166
+ limit: pageSize,
167
+ lower_bound: lower,
168
+ json: true,
169
+ })
170
+ for (const row of res.rows as AtomicAssetRow[]) {
171
+ if (!collection || row.collection_name === collection) out.push(row)
172
+ }
173
+ if (!res.more) break
174
+ lower = UInt64.from(String(res.next_key))
175
+ }
176
+ return out
177
+ }
178
+
179
+ export async function fetchAtomicSchemas(
180
+ client: APIClient,
181
+ collection: NameType
182
+ ): Promise<AtomicSchemaRow[]> {
183
+ const out: AtomicSchemaRow[] = []
184
+ let lower: Name | undefined
185
+ while (true) {
186
+ const res = await client.v1.chain.get_table_rows({
187
+ code: Name.from(ATOMICASSETS_ACCOUNT),
188
+ scope: String(Name.from(collection)),
189
+ table: Name.from('schemas'),
190
+ limit: 100,
191
+ lower_bound: lower,
192
+ json: true,
193
+ })
194
+ for (const row of res.rows as AtomicSchemaRow[]) out.push(row)
195
+ if (!res.more) break
196
+ lower = Name.from(String(res.next_key))
197
+ }
198
+ return out
199
+ }
200
+
201
+ export interface DecodedAtomicAsset {
202
+ asset_id: bigint
203
+ schema_name: string
204
+ template_id: number
205
+ item_id: number
206
+ quantity: number
207
+ stats: string
208
+ origin_x: bigint
209
+ origin_y: bigint
210
+ modules?: NFTModuleSlot[]
211
+ }
212
+
213
+ export function decodeAtomicAsset(
214
+ asset: AtomicAssetRow,
215
+ schemaFormat: SchemaField[],
216
+ itemId: number
217
+ ): DecodedAtomicAsset {
218
+ const data = deserializeAtomicData(asset.immutable_serialized_data, schemaFormat)
219
+ const cargo: NFTCargoItem = deserializeAsset(data, itemId)
220
+ return {
221
+ asset_id: BigInt(String(asset.asset_id)),
222
+ schema_name: String(asset.schema_name),
223
+ template_id: Number(asset.template_id),
224
+ item_id: cargo.item_id,
225
+ quantity: cargo.quantity,
226
+ stats: cargo.stats,
227
+ origin_x: BigInt(String(data.origin_x ?? 0)),
228
+ origin_y: BigInt(String(data.origin_y ?? 0)),
229
+ modules: cargo.modules,
230
+ }
231
+ }
@@ -0,0 +1,130 @@
1
+ export interface SchemaField {
2
+ name: string
3
+ type: string
4
+ }
5
+
6
+ export type RawData =
7
+ | Uint8Array
8
+ | string
9
+ | number[]
10
+ | {immutable_serialized_data: Uint8Array | string | number[]}
11
+
12
+ export function deserializeAtomicData(
13
+ data: RawData,
14
+ schema: SchemaField[]
15
+ ): Record<string, unknown> {
16
+ let rawData: Uint8Array | string | number[]
17
+ if (data && typeof data === 'object' && 'immutable_serialized_data' in (data as object)) {
18
+ rawData = (data as {immutable_serialized_data: Uint8Array | string | number[]})
19
+ .immutable_serialized_data
20
+ } else {
21
+ rawData = data as Uint8Array | string | number[]
22
+ }
23
+
24
+ let bytes: Uint8Array
25
+ if (typeof rawData === 'string') {
26
+ const hex = rawData
27
+ bytes = new Uint8Array(hex.length / 2)
28
+ for (let i = 0; i < hex.length; i += 2) {
29
+ bytes[i / 2] = parseInt(hex.substring(i, i + 2), 16)
30
+ }
31
+ } else if (Array.isArray(rawData)) {
32
+ bytes = new Uint8Array(rawData)
33
+ } else {
34
+ bytes = rawData
35
+ }
36
+
37
+ let offset = 0
38
+
39
+ function readVarint(): number {
40
+ let result = 0
41
+ let multiplier = 1
42
+ while (bytes[offset] >= 128) {
43
+ result += (bytes[offset] - 128) * multiplier
44
+ offset++
45
+ multiplier *= 128
46
+ }
47
+ result += bytes[offset] * multiplier
48
+ offset++
49
+ return result
50
+ }
51
+
52
+ function readVarint64(): bigint {
53
+ let result = 0n
54
+ let multiplier = 1n
55
+ while (bytes[offset] >= 128) {
56
+ result += BigInt(bytes[offset] - 128) * multiplier
57
+ offset++
58
+ multiplier *= 128n
59
+ }
60
+ result += BigInt(bytes[offset]) * multiplier
61
+ offset++
62
+ return result
63
+ }
64
+
65
+ function readZigzagInt64(): bigint {
66
+ const unsigned = readVarint64()
67
+ if (unsigned % 2n === 0n) {
68
+ return unsigned / 2n
69
+ } else {
70
+ return -(unsigned / 2n) - 1n
71
+ }
72
+ }
73
+
74
+ function readString(): string {
75
+ const length = readVarint()
76
+ const str = new TextDecoder().decode(bytes.slice(offset, offset + length))
77
+ offset += length
78
+ return str
79
+ }
80
+
81
+ const RESERVED = 4
82
+ const result: Record<string, unknown> = {}
83
+
84
+ while (offset < bytes.length) {
85
+ const fieldIndex = readVarint() - RESERVED
86
+ const field = schema[fieldIndex]
87
+ if (!field) break
88
+
89
+ switch (field.type) {
90
+ case 'uint16':
91
+ result[field.name] = readVarint()
92
+ break
93
+ case 'uint32':
94
+ result[field.name] = readVarint()
95
+ break
96
+ case 'uint64':
97
+ result[field.name] = readVarint64()
98
+ break
99
+ case 'int32':
100
+ result[field.name] = readZigzagInt64()
101
+ break
102
+ case 'int64':
103
+ result[field.name] = readZigzagInt64()
104
+ break
105
+ case 'string':
106
+ case 'image':
107
+ case 'ipfs':
108
+ result[field.name] = readString()
109
+ break
110
+ case 'uint16[]': {
111
+ const len = readVarint()
112
+ const arr: number[] = []
113
+ for (let i = 0; i < len; i++) arr.push(readVarint())
114
+ result[field.name] = arr
115
+ break
116
+ }
117
+ case 'uint64[]': {
118
+ const len = readVarint()
119
+ const arr: bigint[] = []
120
+ for (let i = 0; i < len; i++) arr.push(readVarint64())
121
+ result[field.name] = arr
122
+ break
123
+ }
124
+ default:
125
+ throw new Error(`Unknown type: ${field.type}`)
126
+ }
127
+ }
128
+
129
+ return result
130
+ }