fairDataSociety / fds.js

Ethereum Web3 Stack SDK Prototype
GNU Lesser General Public License v3.0
19 stars 13 forks source link
Fair Data Society

FDS Dapp Framework

Overview

FDS is an attempt to provide a very accessible high level framework to enable everyone to create apps using the Ethereum Web3 stack. At present it enables developers to:

Easy to use Dapp framework.

FDS make it easy for front end developers to create Dapps running on the Ethereum and Swarm networks.

The FDS Dapp Framework provides a high level javascript SDK for DApp developers to create and manage accounts, sign transactions using the associated Ethereum wallets, and interact with the Ethereum compatible blockchains and the Swarm network.

New in 0.2.0

New in 0.1.0

Features

Install

Use Node version 10. You may use Node Version Manager

npm i -D fds.js

If using the node at the command prompt, read the notes.

Quick Start

Create 2 Accounts

In FDS, most things are done in an account context, because transactions and data are authenticated and encrypted using Ethereum and Swarm compatible ECDSA algorithms before they leave your computer.

let fds = require('FDS.js')
let FDS = new fds()
let alice = await FDS.CreateAccount('alice', 'password')
let bob = await FDS.CreateAccount('bob', 'password')

Send a File from Alice to Bob

Now you have two accounts, you can send an encrypted file from alice's private key...

let file = new File([`hello world `], `test.txt`, { type: 'text/plain' })
await alice.send('bob', file, '/shared/my-application/messages')

Bob Receives It

... and bob will receive and decrypt it with his private key - without ever having to exchange a key, or trust any third parties. ✨

let messages = await bob.messages('received', '/shared/my-application/messages')
messages[0].getFile()

Examples

Use Your Own Contracts

let erc20 = b.getContract(erc20Abi, '0x35e46c...')
let totalSupply = await erc20.totalSupply()
let tx = await transfer.transfer('0xabcd...', 100)

create an issue on this repo if you'd like us to include an example of something you're working on!


API Reference

FDS Object

You must first create an FDS object to work with.

To instantiate this using the default options:

let fds = new FDS()

Config

It is also possible to specify values other than the defaults.

var fds = new FDS({
  tokenName: 'gas',
  swarmGateway: 'https://swarm.fairdatasociety.org',
  ethGateway: 'https://geth-noordung.fairdatasociety.org',
  faucetAddress: 'https://faucet-noordung.fairdatasociety.org/gimmie',
  chainID: '235813',
  httpTimeout: 1000,
  walletVersion: 1,
  scratchDir: '/tmp/something',
  ensConfig: {
    domain: 'datafund.eth',
    registryAddress: '0xA1029cb176082eca658A67fD6807B9bDfB44A695',
    subdomainRegistrarAddress: '0x0E6a3B5f6800145bAe95C48934B7b5a90Df50722',
    resolverContractAddress: '0xC91AB84FFad79279D47a715eF91F5fbE86302E4D',
  },
})

FDS Object


Description

The FDS object is used to create and manage user accounts.

Initialise FDS Object

Creates a new FDS object.

let fds = new FDS()

CreateAccount

Creates a new account with a wallet, ENS subdomain and Multibox contract, and saves it into local storage.

async FDS.CreateAccount( username, password, feedbackMessageCallback = console.log )

Inputs

Returns

promise User (User Object)

let alice = await FDS.CreateAccount('alice', 'password', (message) => { ... });

UnlockAccount

Unlocks an account that already exists in local storage.

FDS.UnlockAccount( username, password )

Inputs

Returns

User (User Object)

or

Failed (bool false)

let alice = await FDS.UnlockAccount('alice', 'password')

GetAccounts

Gets a list of the accounts held in local storage.

async FDS.GetAccounts( walletVersion = [most recent wallet version] )

Inputs

Returns

Users (Array)[User Object]

FDS.GetAccounts()

BackupAccount

Starts download of wallet backup file.

Must be in the browser environment.

async FDS.BackupAccount( subdomain )

Inputs

Returns

Success (bool)

FDS.BackupAccount('fds-ftw')

BackupAccountAsJSON

Returns a Ethereum style V3 wallet javascript object for a given username.

async FDS.BackupAccountAsJSON( username )

Inputs

Returns

WalletJSON (string)

note: take a note of the username here, you will need it when restoring this wallet.

let WalletJSON = await FDS.BackupAccountAsJSON('username')

RestoreAccount

Restores account from file object and saves it into the local storage.

async FDS.RestoreAccount( backupFile )

Inputs

Returns

promise Success (bool)

//retrieve backup from
await FDS.RestoreAccount(backupFile)

RestoreAccountFromPrivateKey

Restores account from a private key and saves it into the browser's localstorage.

async FDS.RestoreAccountFromPrivateKey( username, password, privateKey )

Inputs

Returns

promise User (User Object)

//retrieve backup from
await FDS.RestoreAccountFromPrivateKey('username', 'password', 'private-key-with-0x')

RestoreAccountFromJSON

Restores account from a json V3 wallet and saves it into the browser's localstorage.

async FDS.RestoreAccountFromJSON( username, jsonString )

Inputs

Returns

promise User (User Object)

await FDS.RestoreAccountFromJSON('username', '{..}')

DeleteAccount(username);

Deletes an account from localstorage.

async FDS.DeleteAccount( username )

Inputs

Returns

null

FDS.DeleteAccount('username')

User Object


Everything in FDS happens within a user context - this handles permissions, authorisation, encrytion and authentication under the hood so that everything is crypto-secure 🌍.

You may create or retrieve a user object using the CreateAccount, GetAccounts or UnlockAccount methods of the FDS object, then use it to interact with the FDS multiverse, Swarm and Ethereum networks.


Attributes


Functions

send

Sends a file object from one user to another user's multibox path.

async user.send( recipientSubdomain, file, multiboxPath, encryptionCallback = console.log, uploadCallback = console.log, progressMessageCallback = console.log )

Inputs

Returns

Success (Bool)

let success = await bob.send(
  'alice',
  file,
  '/shared/mail',
  (encryptionStatus) => {},
  (percentageUploaded) => {},
  (progressMessageCallback) => {},
)

messages

Checks to see if any files have been received by a user by multibox path.

async user.messages( query, multiboxPath, encryptionCallback = console.log, uploadCallback = console.log, progressMessageCallback = console.log )

Inputs

Returns

Messages (Array)[Message Object]

let messages = await bob.messages('received', '/shared/files')

store

Stores a private file. The file is encrypted using AES-256-CTR and the user's private key before it is uploaded into Swarm. An encrypted record of the location and metadata of the file is encrypted and stored into Swarm Feeds for later retrieval.

async user.store( file, encryptionCallback, uploadCallback, progressMessageCallback )

Inputs

Returns

Success (Bool)

let success = await bob.store(
  file,
  (encryptionStatus) => {},
  (percentageUploaded) => {},
  (progressMessage) => {},
)

stored

Gets a list of stored files.

async user.stored( ** )

Inputs

Returns

StoredFiles (Array) [Hash Object]

let stored = await bob.stored()

storeValue

Stores an encrypted string value that can later be retrieved using the key.

Useful for storing application state and much more. This value can only be accesed by the user.

async user.storeValue( key, value )

Inputs

Returns

StoredFiles (Array) [Hash Object]

let success = await a.storeValue('key231', 'hello encrypted value world')

getValue

Retrieves an encrypted string value that can has been stored by the user identified by a string key.

async user.getValue( key )

Inputs

Returns

Value (string)

let value = await a.retrieveValue('key231')
// 'hello encrypted value world'

deployContract

Deploys a contract from the user's account context, returns a Contract Object with which you may call your Solidity contract's functions to interact with the blockchain.

See example

async user.deployContract( abi, bytecode, args = [] )

Inputs

Returns

Contract (Contract Object)

let contract = await alice.deployContract([ { "inputs": [], ... } ] , '608060405234801561001057600080fd5b50...', ['my', 'arguments']);

getContract

Gets a [Contract Object]() with the user's account context, which you may call the functions of to interact with the blockchain.

async user.getContract( abi, address )

Inputs

Returns

Value (string)

let success = await alice.getContract([ { "inputs": [], ... } ], '0xab234...' );
// true

Get a User's Balance

Gets a user's balance.

async user.getBalance( ** )

Inputs

Returns

Value (string)

let balance = await alice.getBalance([ { "inputs": [], ... } ], '0xsa3bsdfs' );
191832026900000000
// true

Get Current BlockNumber

Gets a user's balance.

async user.getBlockNumber( ** )

Inputs

Returns

Value (integer)

let bn = await alice.getBlockNumber()
123456789
// true

Pay a User

Pays a user native balance.

async user.pay( recipientSubdomain, amount, transactionCallback = console.log, transactionSignedCallback = console.log )

Inputs

Returns

TransactionHash (string)

let balance = await alice.pay('bob', '0.1')
//0x3cf52d1..

Pay an Address

Pays a address native balance.

async user.pay( recipientAddress, amount, transactionCallback = console.log, transactionSignedCallback = console.log )

Inputs

Returns

TransactionHash (string)

let balance = await alice.pay('0x234...', '0.1')
//0x3cff2d1..

Sign Data

Signs a arbitary data.

async user.sign( message )

Inputs

Returns

Success (bool)

let balance = await alice.sign('message')
//0x3cff2d1..

Recover Address from Signature

Checks a message and signature and returns the address.

async user.recover( message, sig )

Inputs

Returns

Address (address)

let balance = await alice.recover('message', '0xabc...')
//0x3cff2d1..

Message Object


Description

Message objects are returned from user.messages()


Attributes


Functions

getFile

Retrieves and decrypts a file from Swarm.

async message.getFile( decryptProgressCallback = console.log, downloadProgressCallback = console.log )

Inputs

Returns

File (File)

let file = await message.getFile()

saveAs

Uses filesaver to prompt a file download from the browser environment.

async message.saveAs( decryptProgressCallback = console.log, downloadProgressCallback = console.log )

Inputs

Returns

File (File)

let file = await message.saveAs()

Hash Object


Description

Hash objects are used to represent files encrypted and stored into swarm.


Attributes

address: 'ece513967ad1d7610f280ff1a6c619ae7458780bbd0e0ba687e60ba6e3ae47e2', file: { name: 'test.txt', type: 'text/plain' }, time: 1569241451971,

Hash objects contain references to encrypted files stored in Swarm.


Functions

getFile

Retrieves and decrypts a file from Swarm.

async hash.getFile( decryptProgressCallback = console.log, downloadProgressCallback = console.log )

Inputs

Returns

promise File (File)

let file = await hash.getFile()

saveAs

Uses filesaver to prompt a file download from the browser environment.

async hash.saveAs( decryptProgressCallback = console.log, downloadProgressCallback = console.log )

Inputs

Returns

null

let file = await hash.saveAs()

gatewayLink

Uses filesaver to prompt a file download from the browser environment.

async hash.gatewayLink( ** )

Inputs

Returns

GatewayLink (string)

let file = await hash.gatewayLink()

Contract Object


The contract object exposes any Solidity methods, which can be called just like normal functions.

It is returned from GetContract or DeployContract.

async contract.myMethod( arg1, arg2, ... )

myMethod can be any function, getter or setter of your contract

Inputs


Notes


Notes on the Node Environment

File Objects in Node

Because the node environment does not include the file object, you must include a stub file object so that FDS has knowledge of what meta information is associated with the file.

class File {
  constructor(content, name, options) {
    this.content = content
    this.name = name
    this.type = options.type
  }
}

Node REPL

When using the Node at the command line, you may find it useful to enable top tier await functionality.

node --experimental-repl-await

Multibox Contract

alt text

Troubleshooting Windows installation

Installation steps for Windows to setup FDS library to be used for development locally

Windows 10 node: 10.15.1 npm: 6.4.1

  1. Clone the FDS repo:
git clone https://github.com/fairDataSociety/fds.js.git
  1. Change directory to the FDS repo
  2. Run:
npm link

If you see the following errors:

npm WARN tarball tarball data for file-saver@1.3.8 seems to be corrupted. Trying one more time.
npm WARN tar ENOENT: no such file or directory, open 'C:\fds.js\node_modules\.staging\type-is-55fc7b2b\package.json'
...
npm ERR! code EINTEGRITY
npm ERR! Verification failed while extracting file-saver@1.3.8:

Install latest file-saver

npm install file-saver --save

If you get python errors like:

gyp ERR! stack Error: Command failed: C:\Users\TestUser\Anaconda3\python.exe -c import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack   File "<string>", line 1
gyp ERR! stack     import sys; print "%s.%s.%s" % sys.version_info[:3];
gyp ERR! stack SyntaxError: invalid syntax
gyp ERR! stack     at ChildProcess.exithandler (child_process.js:294:12)
gyp ERR! stack     at ChildProcess.emit (events.js:182:13)
gyp ERR! stack     at maybeClose (internal/child_process.js:962:16)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (internal/child_process.js:251:5)
....

This means you have the python 3 installed, if you already have python27 installed, set the environment variable by running:

npm config set python "path to python 2.7 exe"

If you encounter this error:

Error: Can't find Python executable "python", you can set the PYTHON env variable

This means python is not installed. Python 2.7 is required on the system. Download the installer from https://www.python.org/downloads/release/python-2716/

After installation is complete, open new command prompt window, change directory to the FDS repo and run: npm link

The libray should compile and build and if you come across vulnerabilities message:

Added 354 packages from 216 contributors and audited 172164 packages in 64.674s
found 2 high severity vulnerabilities
run `npm audit fix` to fix them, or `npm audit` for details

run twice:

npm audit fix

Now FDS repo is available to be imported in your project:

import FDS from 'fds';