1.43.0 • Published 9 months ago

@latticexyz/network v1.43.0

Weekly downloads
-
License
MIT
Repository
github
Last release
9 months ago

Network

This package includes general low level utilities to interact with Ethereum contracts, as well as specialized MUD contract/client sync utilities.

The general utilities can be used without MUD. For the specialized but much more powerful utilities, usage of solecs is required and recs is recommended.

See mud.dev/network for the detailed API documentation.

Example

This is a real-world example from an upcoming game built with MUD.

// setupContracts.ts

import {
  createNetwork,
  createContracts,
  Mappings,
  createTxQueue,
  createSyncWorker,
  createEncoder,
  NetworkComponentUpdate,
  createSystemExecutor,
} from "@latticexyz/network";

import { Component as SolecsComponent, World as WorldContract } from "@latticexyz/solecs";
import { abi as WorldAbi } from "@latticexyz/solecs/abi/World.json";
import ComponentAbi from "@latticexyz/solecs/abi/Component.json";

import {
  Component,
  Components,
  EntityIndex,
  getComponentEntities,
  getComponentValueStrict,
  removeComponent,
  Schema,
  setComponent,
  Type,
  World,
} from "@latticexyz/recs";

import { keccak256, stretch, toEthAddress } from "@latticexyz/utils";

import { defineStringComponent } from "@latticexyz/std-client";

import { bufferTime, filter, Observable, Subject } from "rxjs";
import { computed, IComputedValue } from "mobx";
import { Contract, ethers, Signer, Wallet } from "ethers";
import { JsonRpcProvider } from "@ethersproject/providers";

import { SystemTypes } from "<contracts>/types/SystemTypes";
import { SystemAbis } from "<contracts>/types/SystemAbis.mjs";
import { config } from "./config";

export type ContractComponents = {
  [key: string]: Component<Schema, { contractId: string }>;
};

export async function setupContracts<C extends ContractComponents>(world: World, components: C) {
  const SystemsRegistry = defineStringComponent(world, {
    id: "SystemsRegistry",
    metadata: { contractId: "world.component.systems" },
  });

  const ComponentsRegistry = defineStringComponent(world, {
    id: "ComponentsRegistry",
    metadata: { contractId: "world.component.components" },
  });

  components = {
    ...components,
    SystemsRegistry,
    ComponentsRegistry,
  };

  const mappings: Mappings<C> = {};

  for (const key of Object.keys(components)) {
    const { contractId } = components[key].metadata;
    mappings[keccak256(contractId)] = key;
  }

  const network = await createNetwork(config);

  const signerOrProvider = computed(() => network.signer.get() || network.providers.get().json);

  const { contracts, config: contractsConfig } = await createContracts<{ World: WorldContract }>({
    config: { World: { abi: WorldAbi, address: config.worldAddress } },
    signerOrProvider,
  });

  const { txQueue, dispose: disposeTxQueue } = createTxQueue(contracts, network);

  const systems = createSystemExecutor<SystemTypes>(world, network, SystemsRegistry, SystemAbis, {
    devMode: config.devMode,
  });

  const { ecsEvent$, config$, dispose } = createSyncWorker<C>();

  function startSync() {
    config$.next({
      provider: networkConfig.provider,
      worldContract: contractsConfig.World,
      initialBlockNumber: config.initialBlockNumber ?? 0,
      chainId: config.chainId,
      disableCache: false,
      snapshotServiceUrl: networkConfig.snapshotServiceUrl,
      streamServiceUrl: networkConfig.streamServiceUrl,
    });
  }

  const { txReduced$ } = applyNetworkUpdates(world, components, ecsEvent$, mappings);

  const encoders = createEncoders(world, ComponentsRegistry, signerOrProvider);

  return { txQueue, txReduced$, encoders, network, startSync, systems };
}

async function createEncoders(
  world: World,
  components: Component<{ value: Type.String }>,
  signerOrProvider: IComputedValue<JsonRpcProvider | Signer>
) {
  const encoders = {} as Record<string, ReturnType<typeof createEncoder>>;

  async function fetchAndCreateEncoder(entity: EntityIndex) {
    const componentAddress = toEthAddress(world.entities[entity]);
    const componentId = getComponentValueStrict(components, entity).value;
    const componentContract = new Contract(
      componentAddress,
      ComponentAbi.abi,
      signerOrProvider.get()
    ) as SolecsComponent;
    const [componentSchemaPropNames, componentSchemaTypes] = await componentContract.getSchema();
    encoders[componentId] = createEncoder(componentSchemaPropNames, componentSchemaTypes);
  }

  // Initial setup
  for (const entity of getComponentEntities(components)) fetchAndCreateEncoder(entity);

  // Keep up to date
  const subscription = components.update$.subscribe((update) => fetchAndCreateEncoder(update.entity));
  world.registerDisposer(() => subscription?.unsubscribe());

  return encoders;
}

/**
 * Sets up synchronization between contract components and client components
 */
function applyNetworkUpdates<C extends Components>(
  world: World,
  components: C,
  ecsEvent$: Observable<NetworkComponentUpdate<C>>,
  mappings: Mappings<C>
) {
  const txReduced$ = new Subject<string>();

  const ecsEventSub = ecsEvent$.subscribe((update) => {
    const entityIndex = world.entityToIndex.get(update.entity) ?? world.registerEntity({ id: update.entity });
    const componentKey = mappings[update.component];

    if (update.value === undefined) {
      // undefined value means component removed
      removeComponent(components[componentKey] as Component<Schema>, entityIndex);
    } else {
      setComponent(components[componentKey] as Component<Schema>, entityIndex, update.value);
    }

    if (update.lastEventInTx) txReduced$.next(update.txHash);
  });

  return { txReduced$: txReduced$.asObservable() };
}
2.0.0-main-0d434816

10 months ago

2.0.0-alpha.1.258

11 months ago

2.0.0-alpha.1.259

11 months ago

2.0.0-main-b38f2df1

10 months ago

2.0.0-main-b0a1a727

10 months ago

2.0.0-next.2

9 months ago

2.0.0-next.0

10 months ago

2.0.0-next.1

9 months ago

2.0.0-main-e9258dae

10 months ago

2.0.0-main-8dc847d4

10 months ago

2.0.0-main-8d51a034

10 months ago

2.0.0-alpha.1.261

10 months ago

2.0.0-alpha.1.260

11 months ago

2.0.0-alpha.1.263

10 months ago

2.0.0-alpha.1.262

10 months ago

2.0.0-alpha.1.265

10 months ago

2.0.0-alpha.1.264

10 months ago

2.0.0-alpha.1.267

10 months ago

2.0.0-alpha.1.266

10 months ago

2.0.0-alpha.1.268

10 months ago

2.0.0-main-70e4d8eb

10 months ago

2.0.0-main-53522998

10 months ago

2.0.0-main-f03531d9

10 months ago

2.0.0-main-78b3b1de

10 months ago

2.0.0-main-69a96f10

10 months ago

2.0.0-main-e259ef79

10 months ago

2.0.0-main-4e4a3415

10 months ago

2.0.0-main-5e9eb5a7

10 months ago

2.0.0-main-eeb15cc0

10 months ago

2.0.0-main-c963b46c

10 months ago

2.0.0-main-de2245b6

10 months ago

2.0.0-main-168a4cb4

10 months ago

2.0.0-main-6de86f16

10 months ago

2.0.0-main-a7b30c79

10 months ago

2.0.0-main-0c4f9fea

10 months ago

2.0.0-main-353b9aa2

10 months ago

2.0.0-main-db19ea39

10 months ago

2.0.0-main-df85e0c0

10 months ago

2.0.0-main-184d5b52

10 months ago

2.0.0-main-c36ffd13

10 months ago

2.0.0-main-1e2ad78e

10 months ago

2.0.0-main-4bb7e8cb

10 months ago

2.0.0-main-9cdcd02e

10 months ago

2.0.0-main-48909d15

10 months ago

2.0.0-main-708122b7

10 months ago

2.0.0-alpha.1.252

11 months ago

2.0.0-alpha.1.251

11 months ago

2.0.0-alpha.1.254

11 months ago

2.0.0-alpha.1.253

11 months ago

2.0.0-alpha.1.256

11 months ago

2.0.0-alpha.1.255

11 months ago

2.0.0-alpha.1.257

11 months ago

2.0.0-alpha.1.120

12 months ago

2.0.0-alpha.1.243

11 months ago

2.0.0-alpha.1.122

12 months ago

2.0.0-alpha.1.97

12 months ago

2.0.0-alpha.1.242

11 months ago

2.0.0-alpha.1.121

12 months ago

2.0.0-alpha.1.98

12 months ago

2.0.0-alpha.1.95

12 months ago

2.0.0-alpha.1.244

11 months ago

2.0.0-alpha.1.96

12 months ago

2.0.0-alpha.1.247

11 months ago

2.0.0-alpha.1.126

12 months ago

2.0.0-alpha.1.125

12 months ago

2.0.0-alpha.1.249

11 months ago

2.0.0-alpha.1.128

12 months ago

2.0.0-alpha.1.248

11 months ago

2.0.0-alpha.1.127

12 months ago

2.0.0-alpha.1.129

12 months ago

2.0.0-alpha.1.250

11 months ago

2.0.0-alpha.1.131

12 months ago

2.0.0-alpha.1.130

12 months ago

2.0.0-alpha.1.133

12 months ago

2.0.0-alpha.1.132

12 months ago

2.0.0-alpha.1.135

12 months ago

2.0.0-alpha.1.134

12 months ago

2.0.0-alpha.1.137

12 months ago

2.0.0-alpha.1.136

12 months ago

2.0.0-alpha.1.139

12 months ago

2.0.0-alpha.1.138

12 months ago

2.0.0-alpha.1.221

11 months ago

2.0.0-alpha.1.100

12 months ago

2.0.0-alpha.1.223

11 months ago

2.0.0-alpha.1.102

12 months ago

2.0.0-alpha.1.222

11 months ago

2.0.0-alpha.1.101

12 months ago

2.0.0-alpha.1.225

11 months ago

2.0.0-alpha.1.104

12 months ago

2.0.0-alpha.1.224

11 months ago

2.0.0-alpha.1.103

12 months ago

2.0.0-alpha.1.227

11 months ago

2.0.0-alpha.1.106

12 months ago

2.0.0-alpha.1.226

11 months ago

2.0.0-alpha.1.105

12 months ago

2.0.0-alpha.1.229

11 months ago

2.0.0-alpha.1.108

12 months ago

2.0.0-alpha.1.228

11 months ago

2.0.0-alpha.1.107

12 months ago

2.0.0-alpha.1.109

12 months ago

2.0.0-alpha.1.230

11 months ago

2.0.0-alpha.1.232

11 months ago

2.0.0-alpha.1.111

12 months ago

2.0.0-alpha.1.231

11 months ago

2.0.0-alpha.1.110

12 months ago

2.0.0-alpha.1.234

11 months ago

2.0.0-alpha.1.113

12 months ago

2.0.0-alpha.1.233

11 months ago

2.0.0-alpha.1.112

12 months ago

2.0.0-alpha.1.236

11 months ago

2.0.0-alpha.1.115

12 months ago

2.0.0-alpha.1.235

11 months ago

2.0.0-alpha.1.114

12 months ago

2.0.0-alpha.1.238

11 months ago

2.0.0-alpha.1.117

12 months ago

2.0.0-alpha.1.237

11 months ago

2.0.0-alpha.1.116

12 months ago

2.0.0-alpha.1.119

12 months ago

2.0.0-alpha.1.239

11 months ago

2.0.0-alpha.1.118

12 months ago

2.0.0-alpha.1.160

12 months ago

2.0.0-alpha.1.162

12 months ago

2.0.0-alpha.1.161

12 months ago

2.0.0-alpha.1.164

12 months ago

2.0.0-alpha.1.163

12 months ago

2.0.0-alpha.1.166

12 months ago

2.0.0-alpha.1.165

12 months ago

2.0.0-alpha.1.168

12 months ago

2.0.0-alpha.1.167

12 months ago

2.0.0-alpha.1.169

12 months ago

2.0.0-alpha.1.171

12 months ago

2.0.0-alpha.1.170

12 months ago

2.0.0-alpha.1.173

12 months ago

2.0.0-alpha.1.172

12 months ago

2.0.0-alpha.1.175

12 months ago

2.0.0-alpha.1.174

12 months ago

2.0.0-alpha.1.177

12 months ago

2.0.0-alpha.1.176

12 months ago

2.0.0-alpha.1.179

12 months ago

2.0.0-alpha.1.178

12 months ago

2.0.0-alpha.1.140

12 months ago

2.0.0-alpha.1.142

12 months ago

2.0.0-alpha.1.141

12 months ago

2.0.0-alpha.1.144

12 months ago

2.0.0-alpha.1.143

12 months ago

2.0.0-alpha.1.146

12 months ago

2.0.0-alpha.1.145

12 months ago

2.0.0-alpha.1.148

12 months ago

2.0.0-alpha.1.82

12 months ago

2.0.0-alpha.1.147

12 months ago

2.0.0-alpha.1.83

12 months ago

2.0.0-alpha.1.149

12 months ago

2.0.0-alpha.1.151

12 months ago

2.0.0-alpha.1.150

12 months ago

2.0.0-alpha.1.153

12 months ago

2.0.0-alpha.1.88

12 months ago

2.0.0-alpha.1.152

12 months ago

2.0.0-alpha.1.89

12 months ago

2.0.0-alpha.1.155

12 months ago

2.0.0-alpha.1.86

12 months ago

2.0.0-alpha.1.154

12 months ago

2.0.0-alpha.1.87

12 months ago

2.0.0-alpha.1.157

12 months ago

2.0.0-alpha.1.84

12 months ago

2.0.0-alpha.1.156

12 months ago

2.0.0-alpha.1.85

12 months ago

2.0.0-alpha.1.159

12 months ago

2.0.0-alpha.1.93

12 months ago

2.0.0-alpha.1.158

12 months ago

2.0.0-alpha.1.94

12 months ago

2.0.0-alpha.1.91

12 months ago

2.0.0-alpha.1.92

12 months ago

2.0.0-alpha.1.90

12 months ago

2.0.0-alpha.1.180

12 months ago

2.0.0-alpha.1.182

12 months ago

2.0.0-alpha.1.181

12 months ago

2.0.0-alpha.1.184

12 months ago

2.0.0-alpha.1.183

12 months ago

2.0.0-alpha.1.186

12 months ago

2.0.0-alpha.1.185

12 months ago

2.0.0-alpha.1.188

12 months ago

2.0.0-alpha.1.187

12 months ago

2.0.0-alpha.1.189

12 months ago

2.0.0-alpha.1.191

12 months ago

2.0.0-alpha.1.190

12 months ago

2.0.0-alpha.1.193

12 months ago

2.0.0-alpha.1.192

12 months ago

2.0.0-alpha.1.195

12 months ago

2.0.0-alpha.1.194

12 months ago

2.0.0-alpha.1.197

12 months ago

2.0.0-alpha.1.196

12 months ago

2.0.0-alpha.1.199

11 months ago

2.0.0-alpha.1.198

12 months ago

2.0.0-alpha.1.201

11 months ago

2.0.0-alpha.1.200

11 months ago

2.0.0-alpha.1.203

11 months ago

2.0.0-alpha.1.202

11 months ago

2.0.0-alpha.1.205

11 months ago

2.0.0-alpha.1.204

11 months ago

2.0.0-alpha.1.207

11 months ago

2.0.0-alpha.1.206

11 months ago

2.0.0-alpha.1.209

11 months ago

2.0.0-alpha.1.208

11 months ago

2.0.0-alpha.1.210

11 months ago

2.0.0-alpha.1.212

11 months ago

2.0.0-alpha.1.211

11 months ago

2.0.0-alpha.1.214

11 months ago

2.0.0-alpha.1.213

11 months ago

2.0.0-alpha.1.216

11 months ago

2.0.0-alpha.1.215

11 months ago

2.0.0-alpha.1.218

11 months ago

2.0.0-alpha.1.217

11 months ago

2.0.0-alpha.7

1 year ago

2.0.0-alpha.8

1 year ago

2.0.0-alpha.9

1 year ago

2.0.0-alpha.3

1 year ago

2.0.0-alpha.4

1 year ago

2.0.0-alpha.5

1 year ago

1.41.1-alpha.0

1 year ago

2.0.0-alpha.6

1 year ago

2.0.0-alpha.94

1 year ago

2.0.0-alpha.0

1 year ago

2.0.0-alpha.1

1 year ago

2.0.0-alpha.93

1 year ago

2.0.0-alpha.2

1 year ago

2.0.0-alpha.92

1 year ago

1.40.0

1 year ago

2.0.0-alpha.91

1 year ago

2.0.0-alpha.90

1 year ago

2.0.0-alpha.88

1 year ago

2.0.0-alpha.87

1 year ago

2.0.0-alpha.86

1 year ago

2.0.0-alpha.85

1 year ago

2.0.0-alpha.84

1 year ago

2.0.0-alpha.83

1 year ago

2.0.0-alpha.81

1 year ago

2.0.0-alpha.89

1 year ago

2.0.0-alpha.80

1 year ago

2.0.0-alpha.76

1 year ago

2.0.0-alpha.75

1 year ago

2.0.0-alpha.74

1 year ago

2.0.0-alpha.73

1 year ago

2.0.0-alpha.72

1 year ago

1.41.0

1 year ago

2.0.0-alpha.79

1 year ago

2.0.0-alpha.78

1 year ago

2.0.0-alpha.66

1 year ago

2.0.0-alpha.65

1 year ago

2.0.0-alpha.64

1 year ago

2.0.0-alpha.63

1 year ago

2.0.0-alpha.62

1 year ago

2.0.0-alpha.61

1 year ago

2.0.0-alpha.60

1 year ago

2.0.0-alpha.69

1 year ago

2.0.0-alpha.68

1 year ago

2.0.0-alpha.67

1 year ago

2.0.0-alpha.55

1 year ago

2.0.0-alpha.54

1 year ago

2.0.0-alpha.53

1 year ago

2.0.0-alpha.52

1 year ago

2.0.0-alpha.51

1 year ago

2.0.0-alpha.50

1 year ago

1.42.0

1 year ago

2.0.0-alpha.59

1 year ago

2.0.0-alpha.58

1 year ago

2.0.0-alpha.57

1 year ago

2.0.0-alpha.56

1 year ago

2.0.0-alpha.44

1 year ago

2.0.0-alpha.43

1 year ago

2.0.0-alpha.41

1 year ago

2.0.0-alpha.40

1 year ago

2.0.0-alpha.49

1 year ago

2.0.0-alpha.48

1 year ago

2.0.0-alpha.47

1 year ago

2.0.0-alpha.46

1 year ago

2.0.0-alpha.45

1 year ago

2.0.0-alpha.39

1 year ago

2.0.0-alpha.38

1 year ago

2.0.0-alpha.37

1 year ago

2.0.0-alpha.36

1 year ago

1.43.0

1 year ago

1.41.1-alpha.41

1 year ago

1.37.0

1 year ago

1.35.0

1 year ago

1.37.1

1 year ago

1.39.0

1 year ago

1.36.1

1 year ago

1.34.0

1 year ago

1.38.0

1 year ago

1.33.1

1 year ago

1.31.3

1 year ago

1.29.0

1 year ago

1.27.1

1 year ago

1.32.0

1 year ago

1.30.0

1 year ago

1.30.1

1 year ago

1.26.0

2 years ago

1.28.1

1 year ago

1.28.0

1 year ago

1.31.1

1 year ago

1.31.2

1 year ago

1.31.0

1 year ago

1.15.0

2 years ago

1.2.0

2 years ago

1.1.0

2 years ago

1.13.0

2 years ago

1.0.0

2 years ago

1.12.0

2 years ago

1.19.0

2 years ago

1.18.0

2 years ago

1.17.0

2 years ago

1.16.0

2 years ago

1.14.2

2 years ago

1.9.0

2 years ago

1.8.0

2 years ago

1.7.1

2 years ago

1.7.0

2 years ago

1.6.0

2 years ago

1.5.1

2 years ago

1.5.0

2 years ago

1.4.1

2 years ago

1.4.0

2 years ago

1.3.0

2 years ago

0.16.3

2 years ago

0.16.4

2 years ago

1.21.0

2 years ago

1.22.0

2 years ago

1.20.0

2 years ago

1.24.1

2 years ago

1.25.1

2 years ago

1.23.0

2 years ago

1.24.0

2 years ago

1.23.1

2 years ago

1.11.0

2 years ago

1.10.0

2 years ago

0.16.2

2 years ago

0.16.1

2 years ago

0.16.0

2 years ago

0.15.1

2 years ago

0.15.0

2 years ago

0.14.2

2 years ago

0.14.1

2 years ago

0.14.0

2 years ago

0.13.0

2 years ago

0.12.0

2 years ago

0.11.1

2 years ago

0.10.0

2 years ago

0.9.0

2 years ago