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

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 +1709 -1044
  2. package/lib/shipload.js +6762 -4658
  3. package/lib/shipload.js.map +1 -1
  4. package/lib/shipload.m.js +6653 -4614
  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 +149 -40
  46. package/src/managers/actions.ts +184 -82
  47. package/src/managers/base.ts +2 -2
  48. package/src/managers/construction-types.ts +47 -0
  49. package/src/managers/construction.ts +147 -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 +14 -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
@@ -1,99 +1,51 @@
1
1
  import {Name, type NameType, type UInt64Type} from '@wharfkit/antelope'
2
2
  import {BaseManager} from './base'
3
- import {Ship} from '../entities/ship'
4
- import {Warehouse} from '../entities/warehouse'
5
- import {Container} from '../entities/container'
3
+ import {Entity} from '../entities/entity'
4
+ import type {EntityTypeName} from '../data/kind-registry'
6
5
  import type {ServerContract} from '../contracts'
7
6
 
8
- export type EntityType = 'ship' | 'warehouse' | 'container' | 'location'
7
+ export type {EntityTypeName} from '../data/kind-registry'
9
8
 
10
9
  export class EntitiesManager extends BaseManager {
11
- async getEntity(type: EntityType, id: UInt64Type): Promise<Ship | Warehouse | Container> {
10
+ async getEntity(id: UInt64Type): Promise<Entity> {
12
11
  const result = await this.server.readonly('getentity', {
13
- entity_type: Name.from(type),
14
12
  entity_id: id,
15
13
  })
16
- const entityInfo = result as ServerContract.Types.entity_info
17
- return this.wrapEntity(entityInfo)
14
+ return new Entity(result as ServerContract.Types.entity_info)
15
+ }
16
+
17
+ async getProjection(id: UInt64Type, taskCount?: number): Promise<unknown> {
18
+ return this.server.readonly('getprojstate', {
19
+ entity_id: id,
20
+ task_count: taskCount,
21
+ })
18
22
  }
19
23
 
20
24
  async getEntities(
21
25
  owner: NameType | ServerContract.Types.player_row,
22
- type?: EntityType
23
- ): Promise<(Ship | Warehouse | Container)[]> {
26
+ kind?: EntityTypeName
27
+ ): Promise<Entity[]> {
24
28
  const ownerName = this.resolveOwner(owner)
25
29
  const result = await this.server.readonly('getentities', {
26
30
  owner: ownerName,
27
- entity_type: type ? Name.from(type) : null,
31
+ entity_type: kind,
28
32
  })
29
33
  const entities = result as ServerContract.Types.entity_info[]
30
- return entities.map((entity) => this.wrapEntity(entity))
34
+ return entities.map((e) => new Entity(e))
31
35
  }
32
36
 
33
37
  async getSummaries(
34
38
  owner: NameType | ServerContract.Types.player_row,
35
- type?: EntityType
39
+ kind?: EntityTypeName
36
40
  ): Promise<ServerContract.Types.entity_summary[]> {
37
41
  const ownerName = this.resolveOwner(owner)
38
42
  const result = await this.server.readonly('getsummaries', {
39
43
  owner: ownerName,
40
- entity_type: type ? Name.from(type) : null,
44
+ entity_type: kind,
41
45
  })
42
46
  return result as ServerContract.Types.entity_summary[]
43
47
  }
44
48
 
45
- async getShip(id: UInt64Type): Promise<Ship> {
46
- return (await this.getEntity('ship', id)) as Ship
47
- }
48
-
49
- async getWarehouse(id: UInt64Type): Promise<Warehouse> {
50
- return (await this.getEntity('warehouse', id)) as Warehouse
51
- }
52
-
53
- async getContainer(id: UInt64Type): Promise<Container> {
54
- return (await this.getEntity('container', id)) as Container
55
- }
56
-
57
- async getShips(owner: NameType | ServerContract.Types.player_row): Promise<Ship[]> {
58
- return (await this.getEntities(owner, 'ship')) as Ship[]
59
- }
60
-
61
- async getWarehouses(owner: NameType | ServerContract.Types.player_row): Promise<Warehouse[]> {
62
- return (await this.getEntities(owner, 'warehouse')) as Warehouse[]
63
- }
64
-
65
- async getContainers(owner: NameType | ServerContract.Types.player_row): Promise<Container[]> {
66
- return (await this.getEntities(owner, 'container')) as Container[]
67
- }
68
-
69
- async getShipSummaries(
70
- owner: NameType | ServerContract.Types.player_row
71
- ): Promise<ServerContract.Types.entity_summary[]> {
72
- return this.getSummaries(owner, 'ship')
73
- }
74
-
75
- async getWarehouseSummaries(
76
- owner: NameType | ServerContract.Types.player_row
77
- ): Promise<ServerContract.Types.entity_summary[]> {
78
- return this.getSummaries(owner, 'warehouse')
79
- }
80
-
81
- async getContainerSummaries(
82
- owner: NameType | ServerContract.Types.player_row
83
- ): Promise<ServerContract.Types.entity_summary[]> {
84
- return this.getSummaries(owner, 'container')
85
- }
86
-
87
- private wrapEntity(entity: ServerContract.Types.entity_info): Ship | Warehouse | Container {
88
- if (entity.type.equals('ship')) {
89
- return new Ship(entity)
90
- } else if (entity.type.equals('warehouse')) {
91
- return new Warehouse(entity)
92
- } else {
93
- return new Container(entity)
94
- }
95
- }
96
-
97
49
  private resolveOwner(owner: NameType | ServerContract.Types.player_row): Name {
98
50
  if (typeof owner === 'object' && owner !== null && 'owner' in owner) {
99
51
  return owner.owner
@@ -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,22 @@
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
+ } from './construction-types'
@@ -1,6 +1,6 @@
1
- import {type UInt16Type, UInt64, type UInt64Type} from '@wharfkit/antelope'
1
+ import 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'
@@ -47,22 +47,4 @@ export class LocationsManager extends BaseManager {
47
47
  reserve: overrideMap.get(s.index) ?? s.reserve,
48
48
  }))
49
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()
67
- }
68
50
  }
@@ -0,0 +1,28 @@
1
+ import {UInt64, type UInt64Type} from '@wharfkit/antelope'
2
+ import {BaseManager} from './base'
3
+ import type {ServerContract} from '../contracts'
4
+
5
+ export interface NftConfigForItem {
6
+ templateId: number
7
+ schemaName: string
8
+ }
9
+
10
+ export class NftManager extends BaseManager {
11
+ private cache = new Map<string, NftConfigForItem | null>()
12
+
13
+ async getNftConfigForItem(itemId: UInt64Type): Promise<NftConfigForItem | undefined> {
14
+ const id = UInt64.from(itemId)
15
+ const key = id.toString()
16
+ if (this.cache.has(key)) {
17
+ return this.cache.get(key) ?? undefined
18
+ }
19
+ const row = (await this.server.table('nftconfig').get(id)) as
20
+ | ServerContract.Types.nftconfig_row
21
+ | undefined
22
+ const result: NftConfigForItem | null = row
23
+ ? {templateId: Number(row.template_id), schemaName: String(row.schema_name)}
24
+ : null
25
+ this.cache.set(key, result)
26
+ return result ?? undefined
27
+ }
28
+ }
@@ -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
+ }