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.
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.
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')
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')
... 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()
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!
You must first create an FDS object to work with.
To instantiate this using the default options:
let fds = new FDS()
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',
},
})
The FDS object is used to create and manage user accounts.
Creates a new FDS object.
let fds = new FDS()
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
.
delimited string satisfying Namehash requirements ].Returns
promise User (User Object)
let alice = await FDS.CreateAccount('alice', 'password', (message) => { ... });
Unlocks an account that already exists in local storage.
FDS.UnlockAccount( username, password )
Inputs
.
delimited string satisfying Namehash requirements ].Returns
User (User Object)
or
Failed (bool false)
let alice = await FDS.UnlockAccount('alice', 'password')
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()
Starts download of wallet backup file.
Must be in the browser environment.
async FDS.BackupAccount( subdomain )
Inputs
.
delimited string satisfying Namehash requirements, account must exist in local storage ].Returns
Success (bool)
FDS.BackupAccount('fds-ftw')
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')
Restores account from file object and saves it into the local storage.
async FDS.RestoreAccount( backupFile )
Inputs
fds-wallet-dan1234-backup.json
]Returns
promise Success (bool)
//retrieve backup from
await FDS.RestoreAccount(backupFile)
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')
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', '{..}')
Deletes an account from localstorage.
async FDS.DeleteAccount( username )
Inputs
Returns
null
FDS.DeleteAccount('username')
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.
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) => {},
)
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')
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) => {},
)
Gets a list of stored files.
async user.stored( ** )
Inputs
Returns
StoredFiles (Array) [Hash Object]
let stored = await bob.stored()
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
value
]Returns
StoredFiles (Array) [Hash Object]
let success = await a.storeValue('key231', 'hello encrypted value world')
Retrieves an encrypted string value
that can has been stored by the user
identified by a string key
.
async user.getValue( key )
Inputs
value
]Returns
Value (string)
let value = await a.retrieveValue('key231')
// 'hello encrypted value world'
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.
async user.deployContract( abi, bytecode, args = [] )
Inputs
Returns
Contract (Contract Object)
let contract = await alice.deployContract([ { "inputs": [], ... } ] , '608060405234801561001057600080fd5b50...', ['my', 'arguments']);
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
Gets a user's balance.
async user.getBalance( ** )
Inputs
Returns
Value (string)
let balance = await alice.getBalance([ { "inputs": [], ... } ], '0xsa3bsdfs' );
191832026900000000
// true
Gets a user's balance.
async user.getBlockNumber( ** )
Inputs
Returns
Value (integer)
let bn = await alice.getBlockNumber()
123456789
// true
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..
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..
Signs a arbitary data.
async user.sign( message )
Inputs
Returns
Success (bool)
let balance = await alice.sign('message')
//0x3cff2d1..
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 objects are returned from user.messages()
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()
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 objects are used to represent files encrypted and stored into swarm.
address: 'ece513967ad1d7610f280ff1a6c619ae7458780bbd0e0ba687e60ba6e3ae47e2', file: { name: 'test.txt', type: 'text/plain' }, time: 1569241451971,
Hash objects contain references to encrypted files stored in Swarm.
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()
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()
Uses filesaver to prompt a file download from the browser environment.
async hash.gatewayLink( ** )
Inputs
Returns
GatewayLink (string)
let file = await hash.gatewayLink()
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
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
}
}
When using the Node at the command line, you may find it useful to enable top tier await functionality.
node --experimental-repl-await
Installation steps for Windows to setup FDS library to be used for development locally
Windows 10 node: 10.15.1 npm: 6.4.1
git clone https://github.com/fairDataSociety/fds.js.git
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';