Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

space-mvc

Package Overview
Dependencies
Maintainers
1
Versions
39
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

space-mvc

TypeScript toolset to simplify building peer-to-peer applications using IPFS, Ethereum, and OrbitDb

  • 0.3.0-beta
  • Source
  • npm
  • Socket score

Version published
Weekly downloads
0
decreased by-100%
Maintainers
1
Weekly downloads
 
Created
Source

Space MVC

A TypeScript toolset to simplify building peer-to-peer smart contract applications using Ethereum, IPFS, and OrbitDB. All the tools you'll need to get started quickly. Smart contracts, storage, MVC, and unit tests with a proven MVC pattern inspired by proven enterprise Java/.NET libraries like Spring.

Our primary goals

  • Provide a radically faster getting started experience for P2P app development.
  • Make opinionated decisions to reduce boilerplate code.
  • Implements simple, familiar MVC pattern.
  • Test Ethereum smart contracts with Truffle.
  • Mocha unit tests for business logic and full integration tests.
  • Lightweight. Less than 5MB total.
  • Use dependency injection to wire your application together.
  • Serverless. In the real sense. There's no server.
  • Apps work offline by default. Data is primarily stored in the user's browser.

SpaceMVC provides a pre-configured development environment with reasonable defaults. Start building real apps immediately.

Maintainable and Testable

  • Object-oriented design and Inversify dependency injection helps you decouple your business logic and your UI to write maintainable and testable code.
  • SpaceMVC relies heavily on Framework7 and the answers to many questions can be found in their excellent documentation. You can use it to build full featured iOS, Android & Desktop apps that look and feel native. It uses nothing but HTML, CSS, and Javascript.

Important Technology

  • Typescript - TypeScript is a typed superset of JavaScript that compiles to plain JavaScript.
  • Framework7 - Build full featured iOS, Android & Desktop apps with HTML, CSS, and Javascript
  • IPFS - A peer-to-peer hypermedia protocol designed to make the web faster, safer, and more open.
  • OrbitDB - OrbitDB is a serverless, distributed, peer-to-peer database
  • The Ethers Project - A complete Ethereum wallet implementation and utilities in JavaScript (and TypeScript).
  • Inversify - IoC container Inversify.

Getting Started

The fastest way to create a new project is to clone the SpaceMVC Starter project. Creates a super basic CRUD app to save and load lists of students for a class roster.

//TODO: this will become a truffle box or similar.

Example


    import "core-js/stable"
    import "regenerator-runtime/runtime"

    import SpaceMVC from "space-mvc";

    // Set up Inversify container with dependencies.

    //Example bindings. See iversify docs for full details. You'll bind your controllers, services, and DAOs here.
    import { FranchiseService } from "./service/franchise-service" //just an example of a service
    import { LeagueController } from "./controller/league-controller" //just ann example of a controller.

    const container = new Container()
    container.bind(FranchiseService).toSelf().inSingletonScope()
    container.bind(HomeController).toSelf().inSingletonScope()


    /**
     *  Create Framework 7 init params.
     * 
     *  See Framework7 documentation for available options: https://framework7.io/docs/app.html
     * 
     *  Please note that the routes field is optional. 
     *  SpaceMVC maps routes with controller annotations.
     *  Passing a value will disable that mechanism.
     * 
    */ 
    let f7Config = {
        root: '#app', // App root element
        id: 'example', // App bundle ID
        name: 'SpaceMVC Example', // App name
        theme: 'auto', // Automatic theme detection
    }

    /**
     * Configure the Orbit DB store definitions that we'll open. 
     * For each StoreDefinition it will open an OrbitDB store.
     * 
     * ownerAddress is the first user that will have permission to write 
     * to each store when it's opened. Later you can use the OrbitDB API to 
     * add more user permissions to it. 
     */ 

    let storeDefinitions:StoreDefinition[] = [{
        name: "player",
        type: "mfsstore",
        load: 100,
        options: {
            schema: {
                id: { unique: true },
                firstName: { unique: false },
                lastName: { unique: false }
            }
        }
    }]

    /*
     * Using a truffle contract as an example. 
     
       Contracts are available by injecting the ContractService into your services or DAOs. 
       Call getContract(name) to get the initialized ethers contract. 

    */
    let truffleJson = require('../truffle/build/contracts/YourContract.json')
    let contract:Contract = await ContractService.createContractFromTruffle(truffleJson)


    /**
     * By default the app will connect the "homestead" ethers provider. 
     * You can override this by passing a value for defaultProvider
     */ 

    let spaceMvcInit:SpaceMvcInit = {
        name: "demo-project",
        displayName: "Demo Project",
        container: container,
        f7Config: f7Config,
        storeDefinitions: storeDefinitions,
        contracts: [contract],
        defaultProvider: new ethers.providers.JsonRpcProvider("http://localhost:8545") //an example to override and connect to ganache 
    }

    await SpaceMVC.init(spaceMvcInit)

Dependency Injection

Use Inversify to configure and inject dependencies into our services, DAOs, controllers, and more. You can also extend this behavior and bind your own objects to the container. You can also inject the services that SpaceMVC exports into your own classes.

MVC

SpaceMVC implements the Model-View-Controller pattern.

Controllers

URL routes are mapped to controller objects with the @routeMap() annotation.

  1. Bind your controller in singleton scope with Inversify
  2. Routes are mapped by the @routeMap() annotation. Each annotation must have a globally unique path. When that URL is accessed the method it's mapped to will be called.
  3. The controller method returns a ModelView object. It returns the model to render and the view is a Framework7 component with a template.
  4. SpaceMVC creates the component and passes the model data to it.
  5. See Framework7 documentation for on-page event options.

Services

Services are where your business logic goes. A service is a POJO annotated with the @service() annotation.

  1. Bind service in singleton scope with inversify.
  2. Create methods and associated unit tests.
  3. Inject ContractService to make calls to smart contracts.
  4. Inject your data access objects (DAOs) to store data in OrbitDB or IPFS.

DAOs

Data Access Objects (DAOs) store and retreive data from OrbitDB and IPFS. A DAO is a POJO with a @dao() annotation.

  1. Bind DAO in singleton scope with inversify.
  2. Create methods and associated unit tests.
  3. Inject DAO into service to store and retrieve data.

IPFS DAO

A common pattern is to create a DTO and store the properties in IPFS.

SpaceMVC provides a generic DAO named IpfsDAO that you can inject into your services. It provides convenience methods to put/get your DTOs in IPFS and keep a reference to the cid that loaded it.

Importing Truffle Contract

SpaceMVC uses ethers.js under the hood for contract communication but we also use Truffle to develop Solidity unit test suites.

We have a basic interface that's agnostic to implementation but an easy way to import Truffle JSON files.

interface Contract {
    name:string,
    networks:Network[],
    abi:any
}

interface Network {
    networkId:string, //network ID is exposed by provider.send("net_version")
    address:string //the address where the contract is deployed.
}

Example: This will grab all the networking information out of the Truffle JSON and into the right format.

import { ContractService } from "space-mvc"

let truffleJson = require('../truffle/build/contracts/YourContract.json')

let contract:Contract = await ContractService.createContractFromTruffle(truffleJson)

Store Definition

A store definition contains info to open an OrbitDB store when the application starts.

  • Name - the name of the store
  • Type - the type of Orbit store to open. Options are log, feed, keyvalue, docs, counter, and mfsstore
  • Load - the number of records to load into memory when the store is loaded
  • Options - options that will be passed to store initialization
    • Schema (optional): schema for mfsstore

OrbitDB documentation

mfsstore

mfsstore is a key-value store for browser (or node) use and lazily loads records and allows multiple indexed columns

interface StoreDefinition {
    name: string 
    type: string 
    load?: number
    options: {
        schema?: any
    }
}

Example

let globalStoreDefinitions:StoreDefinition[] = [{
    name: "player",
    type: "mfsstore",
    load: 100,
    options: {
        schema: {
            id: { unique: true },
            firstName: { unique: false },
            lastName: { unique: false }
        }
    }
}]

Metastore Service

A Metastore is an object that loads and connects to a group of OrbitDB stores. This allows you to define all of the stores that your application needs and open them all at once.

A Metastore named "WALLET_METASTORE" is created by default. It's only writeable by the user's wallet address. The app will open and load all of the stores and OrbitDB will sync all of the stores to all of the user's devices.

Creating a custom Metastore

    // Open the schema associated with the wallet and cache it.
    interface Metastore {
        name:string
        writeAccess?: string[]
        storeDefinitions?:StoreDefinition[]

        addresses?: any
        stores?: any
    }

    let metastore = {
        //Fill out name, writeAccess, and storeDefinitions from interface above. 
    }

    await metastoreService.loadStoreAddresses(metastore)
    await metastoreService.loadStores(metastore)
    await metastoreService.cacheMetastore(metastore)

    //To load a store later
    await metastoreService.getStore("YOUR METASTORE NAME", "THE ORBITDB STORE NAME IN STORE DEFINITION")

    //Load a store from the default wallet metastore
    let store = metastoreService.getWalletStore("student")


Events

  • spacemvc:initFinish - Fired when SpaceMVC has finished initializing.

Build

Production:

npm run build

Development:

npm run build:dev

Tests:

npm run test
  • dist/index-browser.js - Browser build
  • dist/index-node.js - Node build

FAQs

Package last updated on 02 Jan 2021

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc