1
0
mirror of https://github.com/oceanprotocol-archive/squid-js.git synced 2024-02-02 15:31:51 +01:00

Merge pull request #18 from oceanprotocol/feature/typescript

Migrated to TypeScript
This commit is contained in:
Sebastian Gerske 2018-09-25 10:30:20 +02:00 committed by GitHub
commit 32951f0aac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
29 changed files with 652 additions and 4855 deletions

View File

@ -1,13 +0,0 @@
{
"presets": [
["@babel/preset-env", { "useBuiltIns": "entry" }]
],
"plugins": [
["@babel/plugin-transform-runtime",
{
"regenerator": true
}
],
["@babel/plugin-proposal-object-rest-spread", { "useBuiltIns": true }]
]
}

View File

@ -1,3 +0,0 @@
{
"extends": ["oceanprotocol"]
}

4338
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -4,9 +4,9 @@
"description": "JavaScript client library for Ocean Protocol",
"main": "dist/squid.js",
"scripts": {
"test": "eslint ./src",
"start": "babel ./src/ --watch --out-dir ./dist/",
"build": "babel ./src/ --out-dir ./dist/",
"test": "tslint -c tslint.json 'src/**/*.ts'",
"start": "tsc -w",
"build": "tsc",
"release": "./node_modules/release-it/bin/release-it.js --src.tagName='v%s' --github.release --npm.publish --non-interactive",
"release-minor": "./node_modules/release-it/bin/release-it.js minor --src.tagName='v%s' --github.release --npm.publish --non-interactive",
"release-major": "./node_modules/release-it/bin/release-it.js major --src.tagName='v%s' --github.release --npm.publish --non-interactive",
@ -24,27 +24,17 @@
},
"homepage": "https://github.com/oceanprotocol/squid-js#readme",
"dependencies": {
"@babel/runtime": "^7.0.0",
"@oceanprotocol/keeper-contracts": "^0.2.0",
"bignumber.js": "^7.2.1",
"truffle-contract": "^3.0.6",
"web3": "0.20.6"
},
"devDependencies": {
"@babel/cli": "^7.0.0",
"@babel/core": "^7.0.1",
"@babel/plugin-proposal-object-rest-spread": "^7.0.0",
"@babel/plugin-transform-runtime": "^7.0.0",
"@babel/preset-env": "^7.0.0",
"eslint": "^5.5.0",
"eslint-config-oceanprotocol": "^1.2.0",
"eslint-config-standard": "^12.0.0",
"eslint-plugin-import": "^2.14.0",
"eslint-plugin-node": "^7.0.1",
"eslint-plugin-promise": "^4.0.0",
"eslint-plugin-security": "^1.4.0",
"eslint-plugin-standard": "^4.0.0"
},
"engines": {
"node": ">=8 <10"
},
"devDependencies": {
"@types/web3": "^1.0.6",
"tslint": "^5.11.0",
"typescript": "^3.0.3"
}
}

View File

@ -1,39 +0,0 @@
/* global fetch */
import Logger from '../utils/logger'
export default class OceanAgent {
constructor(connectionUrl) {
this.assetsUrl = connectionUrl + '/assets'
Logger.warn('OceanAgent is deprecated use the Ocean object from squid instead')
}
getAssetsMetadata() {
return fetch(this.assetsUrl + '/metadata', { method: 'GET' })
.then(res => res.json())
.then(data => JSON.parse(data))
}
publishDataAsset(asset) {
return fetch(this.assetsUrl + '/metadata',
{
method: 'POST',
body: JSON.stringify(asset),
headers: { 'Content-type': 'application/json' }
})
.then(response => {
Logger.log('Success:', response)
if (response.ok) {
Logger.log('Success:', response)
return true
}
Logger.log('Failed: ', response.status, response.statusText)
return false
// throw new Error(response.statusText ? response.statusText : `publish asset failed with status ${response.status}`)
})
.catch(error => {
Logger.log(`Publish asset to ocean database could not be completed: ${error.message()}`)
return false
})
}
}

View File

@ -1,181 +0,0 @@
import Web3 from 'web3'
import ContractLoader from '../keeper/contractLoader'
import Logger from '../utils/logger'
const DEFAULT_GAS = 300000
export default class OceanKeeper {
constructor(uri, network) {
const web3Provider = new Web3.providers.HttpProvider(uri)
this.web3 = new Web3(web3Provider)
this.defaultGas = DEFAULT_GAS
this.network = network || 'development'
Logger.warn('OceanKeeper is deprecated use the Ocean object from squid instead')
}
async initContracts() {
this.oceanToken = await ContractLoader.load('OceanToken', this.network, this.web3)
this.oceanMarket = await ContractLoader.load('OceanMarket', this.network, this.web3)
this.oceanAuth = await ContractLoader.load('OceanAuth', this.network, this.web3)
return {
oceanToken: this.oceanToken,
oceanMarket: this.oceanMarket,
oceanAuth: this.oceanAuth
}
}
// web3 wrappers
sign(accountAddress, message) {
return this.web3.eth.sign(accountAddress, message)
}
getMessageHash(message) {
return this.web3.sha3(`\x19Ethereum Signed Message:\n${message.length}${message}`)
}
// call functions (costs no gas)
checkAsset(assetId) {
return this.oceanMarket.checkAsset(assetId)
}
getBalance(accountAddress) {
return this.oceanToken.balanceOf.call(accountAddress)
}
getAssetPrice(assetId) {
return this.oceanMarket.getAssetPrice(assetId).then((price) => price.toNumber())
}
getOrderStatus(orderId) {
return this.oceanAuth.statusOfAccessRequest(orderId)
}
verifyOrderPayment(orderId) {
return this.oceanMarket.verifyPaymentReceived(orderId)
}
getEncryptedAccessToken(orderId, senderAddress) {
return this.oceanAuth.getEncryptedAccessToken(orderId, { from: senderAddress })
}
async getConsumerOrders(consumerAddress) {
let accessConsentEvent = this.oceanAuth.AccessConsentRequested({ _consumer: consumerAddress }, {
fromBlock: 0,
toBlock: 'latest'
})
let _resolve = null
let _reject = null
const promise = new Promise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
const getEvents = () => {
accessConsentEvent.get((error, logs) => {
if (error) {
_reject(error)
throw new Error(error)
} else {
_resolve(logs)
}
})
return promise
}
const events = await getEvents().then((events) => events)
// let orders = await this.buildOrdersFromEvents(events, consumerAddress).then((result) => result)
let orders = events
.filter(obj => (obj.args._consumer === consumerAddress))
.map(async (event) => ({
...event.args,
timeout: event.args._timeout.toNumber(),
status: await this.getOrderStatus(event.args._id).then((status) => status.toNumber()),
paid: await this.verifyOrderPayment(event.args._id).then((received) => received),
key: null
}))
Logger.debug('got orders: ', orders)
return orders
}
// Transactions with gas cost
requestTokens(senderAddress, numTokens) {
return this.oceanMarket.requestTokens(numTokens, { from: senderAddress })
}
async registerDataAsset(name, description, price, publisherAddress) {
const assetId = await this.oceanMarket.generateId(name + description)
const result = await this.oceanMarket.register(
assetId,
price,
{ from: publisherAddress, gas: this.defaultGas }
)
Logger.log('registered: ', result)
return assetId
}
async sendPayment(assetId, order, publisherAddress, senderAddress) {
let assetPrice = await this.oceanMarket.getAssetPrice(assetId).then((price) => price.toNumber())
this.oceanMarket.sendPayment(order.id, publisherAddress, assetPrice, order.timeout, {
from: senderAddress,
gas: 2000000
})
}
cancelAccessRequest(orderId, senderAddress) {
return this.oceanAuth.cancelAccessRequest(orderId, { from: senderAddress })
}
orchestrateResourcePurchase(
assetId, publisherId, price, privateKey, publicKey, timeout, senderAddress,
initialRequestEventHandler, accessCommittedEventHandler, tokenPublishedEventHandler) {
const { oceanToken, oceanMarket, oceanAuth } = this
// Allow OceanMarket contract to transfer funds on the consumer's behalf
oceanToken.approve(oceanMarket.address, price, { from: senderAddress, gas: 2000000 })
// Submit the access request
oceanAuth.initiateAccessRequest(
assetId, publisherId, publicKey,
timeout, { from: senderAddress, gas: 1000000 }
)
const resourceFilter = { _resourceId: assetId, _consumer: senderAddress }
const initRequestEvent = oceanAuth.AccessConsentRequested(resourceFilter)
let order = {}
this._listenOnce(
initRequestEvent,
'AccessConsentRequested',
(result, error) => {
order = initialRequestEventHandler(result, error)
const requestIdFilter = { _id: order.id }
const accessCommittedEvent = oceanAuth.AccessRequestCommitted(requestIdFilter)
const tokenPublishedEvent = oceanAuth.EncryptedTokenPublished(requestIdFilter)
this._listenOnce(
accessCommittedEvent,
'AccessRequestCommitted',
(result, error) => {
accessCommittedEventHandler(result, order, error)
}
)
this._listenOnce(
tokenPublishedEvent,
'EncryptedTokenPublished',
(result, error) => {
tokenPublishedEventHandler(result, order, error)
}
)
})
return order
}
// Helper functions (private)
_listenOnce(event, eventName, callback) {
event.watch((error, result) => { // eslint-disable-line security/detect-non-literal-fs-filename
event.stopWatching()
if (error) {
Logger.log(`Error in keeper ${eventName} event: `, error)
}
callback(result, error)
})
}
}

View File

@ -1,25 +0,0 @@
import ContractLoader from './contractLoader'
import KeeperBase from './keeper-base'
export default class OceanAuth extends KeeperBase {
constructor(web3Helper) {
super(web3Helper)
return (async () => {
this.contract = await ContractLoader.load('OceanAuth', this._web3Helper)
return this
})()
}
cancelAccessRequest(orderId, senderAddress) {
return this.contract.cancelAccessRequest(orderId, { from: senderAddress })
}
getOrderStatus(orderId) {
return this.contract.statusOfAccessRequest(orderId)
}
getEncryptedAccessToken(orderId, senderAddress) {
return this.contract.getEncryptedAccessToken(orderId, { from: senderAddress })
}
}

30
src/keeper/auth.ts Normal file
View File

@ -0,0 +1,30 @@
import Config from "../utils/config";
import Web3Helper from "../utils/Web3Helper";
import ContractLoader from "./contractLoader";
import KeeperBase from "./keeper-base";
export default class OceanAuth extends KeeperBase {
public static async getInstance(config: Config, web3Helper) {
const auth = new OceanAuth(config, web3Helper);
auth.contract = await ContractLoader.load("OceanAuth", auth.web3Helper);
return auth;
}
private constructor(config: Config, web3Helper: Web3Helper) {
super(config, web3Helper);
}
public cancelAccessRequest(orderId: string, senderAddress: string) {
return this.contract.cancelAccessRequest(orderId, {from: senderAddress});
}
public getOrderStatus(orderId: string) {
return this.contract.statusOfAccessRequest(orderId);
}
public getEncryptedAccessToken(orderId: string, senderAddress: string) {
return this.contract.getEncryptedAccessToken(orderId, {from: senderAddress});
}
}

View File

@ -1,28 +0,0 @@
import TruffleContract from 'truffle-contract'
import Logger from '../utils/logger'
const contracts = []
export default class ContractLoader {
static async _doLoad(what, web3Helper) {
const where = (await web3Helper.getNetworkName()).toLowerCase()
Logger.log('Loading', what, 'from', where)
try {
/* eslint-disable-next-line security/detect-non-literal-require */
const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}`)
// Logger.log('Loaded artifact', artifact)
const contract = TruffleContract(artifact)
Logger.log('Getting instance of', what, 'from', where, 'at', artifact.address)
contract.setProvider(web3Helper.web3.currentProvider)
contracts[what] = await contract.at(artifact.address)
return contracts[what]
} catch (err) {
Logger.error('Failed to load', what, 'from', where)
}
}
static async load(what, where, provider) {
return contracts[what] || ContractLoader._doLoad(what, where, provider)
}
}

View File

@ -0,0 +1,29 @@
import * as TruffleContract from "truffle-contract";
import Logger from "../utils/logger";
import Web3Helper from "../utils/Web3Helper";
const contracts: Map<string, object> = new Map<string, object>();
export default class ContractLoader {
public static async load(what: string, web3Helper: Web3Helper) {
return contracts.get(what) || await ContractLoader._doLoad(what, web3Helper);
}
private static async _doLoad(what: string, web3Helper: Web3Helper): Promise<object> {
const where = (await web3Helper.getNetworkName()).toLowerCase();
Logger.log("Loading", what, "from", where);
try {
/* eslint-disable-next-line security/detect-non-literal-require */
const artifact = require(`@oceanprotocol/keeper-contracts/artifacts/${what}.${where}`);
// Logger.log('Loaded artifact', artifact)
const contract = TruffleContract(artifact);
Logger.log("Getting instance of", what, "from", where, "at", artifact.address);
contract.setProvider(web3Helper.web3.currentProvider);
contracts.set(what, await contract.at(artifact.address));
return contracts.get(what);
} catch (err) {
Logger.error("Failed to load", what, "from", where);
}
}
}

View File

@ -1,6 +0,0 @@
export default class KeeperBase {
constructor(web3Helper) {
this._web3Helper = web3Helper
this.contract = null
}
}

15
src/keeper/keeper-base.ts Normal file
View File

@ -0,0 +1,15 @@
import Config from "../utils/config";
import Web3Helper from "../utils/Web3Helper";
export default class KeeperBase {
public contract: any = null;
protected config: Config;
protected web3Helper: Web3Helper;
constructor(config: Config, web3Helper: Web3Helper) {
this.config = config;
this.web3Helper = web3Helper;
}
}

View File

@ -1,53 +0,0 @@
import ContractLoader from './contractLoader'
import KeeperBase from './keeper-base'
import Logger from '../utils/logger'
export default class OceanMarket extends KeeperBase {
constructor(web3Helper) {
super(web3Helper)
return (async () => {
this.contract = await ContractLoader.load('OceanMarket', this._web3Helper)
return this
})()
}
// call functions (costs no gas)
checkAsset(assetId) {
return this.contract.checkAsset(assetId)
}
verifyOrderPayment(orderId) {
return this.contract.verifyPaymentReceived(orderId)
}
getAssetPrice(assetId) {
return this.contract.getAssetPrice(assetId)
.then((price) => price.toNumber())
}
// Transactions with gas cost
requestTokens(amount, address) {
return this.contract.requestTokens(amount, { from: address })
}
async registerAsset(name, description, price, publisherAddress) {
const assetId = await this.contract.generateId(name + description)
const result = await this.contract.register(
assetId,
price,
{ from: publisherAddress, gas: this.defaultGas }
)
Logger.log('registered: ', result)
return assetId
}
async payAsset(assetId, order, publisherAddress, senderAddress) {
let assetPrice = await this.contract.getAssetPrice(assetId).then((price) => price.toNumber())
this.contract.sendPayment(order.id, publisherAddress, assetPrice, order.timeout, {
from: senderAddress,
gas: 2000000
})
}
}

61
src/keeper/market.ts Normal file
View File

@ -0,0 +1,61 @@
import BigNumber from "bignumber.js";
import Config from "../utils/config";
import Logger from "../utils/logger";
import Web3Helper from "../utils/Web3Helper";
import ContractLoader from "./contractLoader";
import KeeperBase from "./keeper-base";
export default class OceanMarket extends KeeperBase {
public static async getInstance(config: Config, web3Helper: Web3Helper) {
const market = new OceanMarket(config, web3Helper);
market.contract = await ContractLoader.load("OceanMarket", market.web3Helper);
return market;
}
private constructor(config: Config, web3Helper: Web3Helper) {
super(config, web3Helper);
}
// call functions (costs no gas)
public checkAsset(assetId: string) {
return this.contract.checkAsset(assetId);
}
public verifyOrderPayment(orderId: string): boolean {
return this.contract.verifyPaymentReceived(orderId);
}
public getAssetPrice(assetId: string) {
return this.contract.getAssetPrice(assetId)
.then((price: BigNumber) => price.toNumber());
}
// Transactions with gas cost
public requestTokens(amount: number, address: string) {
return this.contract.requestTokens(amount, {from: address});
}
public async registerAsset(name: string, description: string, price: number, publisherAddress: string) {
const assetId = await this.contract.generateId(name + description);
const result = await this.contract.register(
assetId,
price, {
from: publisherAddress,
gas: this.config.defaultGas,
},
);
Logger.log("registered: ", result);
return assetId;
}
public async payAsset(assetId: string, order: any, publisherAddress: string, senderAddress: string) {
const assetPrice = await this.contract.getAssetPrice(assetId)
.then((price: BigNumber) => price.toNumber());
this.contract.sendPayment(order.id, publisherAddress, assetPrice, order.timeout, {
from: senderAddress,
gas: 2000000,
});
}
}

View File

@ -1,30 +0,0 @@
import ContractLoader from './contractLoader'
import KeeperBase from './keeper-base'
import Logger from '../utils/logger'
export default class OceanToken extends KeeperBase {
constructor(web3Helper) {
super(web3Helper)
return (async () => {
this.contract = await ContractLoader.load('OceanToken', this._web3Helper)
return this
})()
}
getTokenBalance(accountAddress) {
return this.contract.balanceOf.call(accountAddress)
}
async getEthBalance(account) {
return new Promise((resolve, reject) => {
Logger.log('getting balance for', account)
this._web3Helper.web3.eth.getBalance(account, 'latest', (err, balance) => {
if (err) return reject(err)
Logger.log('balance', balance)
resolve(balance)
})
})
}
}

36
src/keeper/token.ts Normal file
View File

@ -0,0 +1,36 @@
import Config from "../utils/config";
import Logger from "../utils/logger";
import Web3Helper from "../utils/Web3Helper";
import ContractLoader from "./contractLoader";
import KeeperBase from "./keeper-base";
export default class OceanToken extends KeeperBase {
public static async getInstance(config: Config, web3Helper: Web3Helper) {
const token = new OceanToken(config, web3Helper);
token.contract = await ContractLoader.load("OceanToken", token.web3Helper);
return token;
}
private constructor(config: Config, web3Helper: Web3Helper) {
super(config, web3Helper);
}
public getTokenBalance(accountAddress: string) {
return this.contract.balanceOf.call(accountAddress);
}
public async getEthBalance(account: string): Promise<number> {
return new Promise<number>((resolve, reject) => {
Logger.log("getting balance for", account);
this.web3Helper.web3.eth.getBalance(account, "latest", (err: any, balance: number) => {
if (err) {
return reject(err);
}
Logger.log("balance", balance);
resolve(balance);
});
});
}
}

View File

@ -1,37 +0,0 @@
/* global fetch */
import Logger from './utils/logger'
export default class MetaData {
constructor(providerUri) {
this.assetsUrl = providerUri + '/assets'
}
getAssetsMetadata() {
return fetch(this.assetsUrl + '/metadata', { method: 'GET' })
.then(res => res.json())
.then(data => JSON.parse(data))
}
publishDataAsset(asset) {
return fetch(this.assetsUrl + '/metadata',
{
method: 'POST',
body: JSON.stringify(asset),
headers: { 'Content-type': 'application/json' }
})
.then(response => {
Logger.log('Success:', response)
if (response.ok) {
Logger.log('Success:', response)
return true
}
Logger.log('Failed: ', response.status, response.statusText)
return false
// throw new Error(response.statusText ? response.statusText : `publish asset failed with status ${response.status}`)
})
.catch(error => {
Logger.log(`Publish asset to ocean database could not be completed: ${error.message()}`)
return false
})
}
}

45
src/metadata.ts Normal file
View File

@ -0,0 +1,45 @@
import Config from "./utils/config";
import Logger from "./utils/logger";
declare var fetch;
export default class MetaData {
private assetsUrl: string;
constructor(config: Config) {
const providerUri = config.providerUri || null;
this.assetsUrl = providerUri + "/assets";
}
public getAssetsMetadata() {
return fetch(this.assetsUrl + "/metadata", {method: "GET"})
.then((res) => res.json())
.then((data) => JSON.parse(data));
}
public publishDataAsset(asset: object) {
return fetch(this.assetsUrl + "/metadata",
{
method: "POST",
body: JSON.stringify(asset),
headers: {"Content-type": "application/json"},
})
.then((response: any) => {
Logger.log("Success:", response);
if (response.ok) {
Logger.log("Success:", response);
return true;
}
Logger.log("Failed: ", response.status, response.statusText);
return false;
// throw new Error(response.statusText ? response.statusText :
// `publish asset failed with status ${response.status}`)
})
.catch((error: Error) => {
Logger.log(`Publish asset to ocean database could not be completed: ${error.message}`);
return false;
});
}
}

View File

@ -1,144 +0,0 @@
import Web3 from 'web3'
import OceanMarket from './keeper/market'
import OceanAuth from './keeper/auth'
import OceanToken from './keeper/token'
import Logger from './utils/logger'
import Web3Helper from './utils/Web3Helper'
import MetaData from './metadata'
const DEFAULT_GAS = 300000
export default class Ocean {
constructor(config) {
const web3Provider = config.web3Provider || new Web3.providers.HttpProvider(config.nodeUri)
this._web3 = new Web3(web3Provider)
this._defaultGas = config.gas || DEFAULT_GAS
this._providerUri = config.providerUri || null
this.helper = new Web3Helper(this._web3)
this.metadata = new MetaData(this._providerUri)
return (async () => {
this._network = config.network || (await this.helper.getNetworkName()).toLowerCase() || 'development'
this.market = await new OceanMarket(this.helper)
this.auth = await new OceanAuth(this.helper)
this.token = await new OceanToken(this.helper)
return this
})()
}
async getAccounts() {
return Promise.all((await this.helper.getAccounts()).map(async (account) => {
// await ocean.market.requestTokens(account, 1000)
return {
name: account,
balance: {
ocn: await this.token.getTokenBalance(account),
eth: await this.token.getEthBalance(account)
}
}
}))
}
async getOrdersByConsumer(consumerAddress) {
let accessConsentEvent = this.auth.contract.AccessConsentRequested({ _consumer: consumerAddress }, {
fromBlock: 0,
toBlock: 'latest'
})
let _resolve = null
let _reject = null
const promise = new Promise((resolve, reject) => {
_resolve = resolve
_reject = reject
})
const getEvents = () => {
accessConsentEvent.get((error, logs) => {
if (error) {
_reject(error)
throw new Error(error)
} else {
_resolve(logs)
}
})
return promise
}
const events = await getEvents().then((events) => events)
// let orders = await this.buildOrdersFromEvents(events, consumerAddress).then((result) => result)
let orders = events
.filter(obj => (obj.args._consumer === consumerAddress))
.map(async (event) => ({
...event.args,
timeout: event.args._timeout.toNumber(),
status: await this.auth.getOrderStatus(event.args._id).then((status) => status.toNumber()),
paid: await this.market.verifyOrderPayment(event.args._id).then((received) => received),
key: null
}))
Logger.debug('got orders: ', orders)
return orders
}
async purchaseAsset(
assetId, publisherId, price, privateKey, publicKey, timeout, senderAddress,
initialRequestEventHandler, accessCommittedEventHandler, tokenPublishedEventHandler) {
const { token, market, auth } = this
try {
// Allow market contract to transfer funds on the consumer's behalf
await token.contract.approve(market.contract.address, price, { from: senderAddress, gas: 2000000 })
} catch (err) {
Logger.log('token approve', err)
}
try {
// Submit the access request
await auth.contract.initiateAccessRequest(
assetId, publisherId, publicKey,
timeout, { from: senderAddress, gas: 1000000 }
)
} catch (err) {
Logger.log('initiateAccessRequest', err)
}
const resourceFilter = { _resourceId: assetId, _consumer: senderAddress }
const initRequestEvent = auth.contract.AccessConsentRequested(resourceFilter)
let order = {}
this._listenOnce(
initRequestEvent,
'AccessConsentRequested',
(result, error) => {
order = initialRequestEventHandler(result, error)
const requestIdFilter = { _id: order.id }
const accessCommittedEvent = auth.contract.AccessRequestCommitted(requestIdFilter)
const tokenPublishedEvent = auth.contract.EncryptedTokenPublished(requestIdFilter)
this._listenOnce(
accessCommittedEvent,
'AccessRequestCommitted',
(result, error) => {
accessCommittedEventHandler(result, order, error)
}
)
this._listenOnce(
tokenPublishedEvent,
'EncryptedTokenPublished',
(result, error) => {
tokenPublishedEventHandler(result, order, error)
}
)
})
return order
}
// Helper functions (private)
_listenOnce(event, eventName, callback) {
// eslint-disable-next-line security/detect-non-literal-fs-filename
event.watch((error, result) => {
event.stopWatching()
if (error) {
Logger.log(`Error in keeper ${eventName} event: `, error)
}
callback(result, error)
})
}
}

153
src/ocean.ts Normal file
View File

@ -0,0 +1,153 @@
import BigNumber from "bignumber.js";
import OceanAuth from "./keeper/auth";
import OceanMarket from "./keeper/market";
import OceanToken from "./keeper/token";
import MetaData from "./metadata";
import Config from "./utils/config";
import Logger from "./utils/logger";
import Web3Helper from "./utils/Web3Helper";
export default class Ocean {
public static async getInstance(config) {
const ocean = new Ocean(config);
ocean.market = await OceanMarket.getInstance(config, ocean.helper);
ocean.auth = await OceanAuth.getInstance(config, ocean.helper);
ocean.token = await OceanToken.getInstance(config, ocean.helper);
return ocean;
}
public token: OceanToken;
public market: OceanMarket;
public auth: OceanAuth;
public helper: Web3Helper;
public metadata: MetaData;
private config: Config;
private constructor(config: Config) {
this.config = config;
this.helper = new Web3Helper(config);
this.metadata = new MetaData(config);
}
public async getAccounts() {
return Promise.all((await this.helper.getAccounts()).map(async (account: string) => {
// await ocean.market.requestTokens(account, 1000)
const {token} = this;
return {
name: account,
balance: {
eth: await token.getEthBalance(account),
ocn: await token.getTokenBalance(account),
},
};
}));
}
public async getOrdersByConsumer(consumerAddress: string) {
const {auth} = this;
const accessConsentEvent = auth.contract.AccessConsentRequested({_consumer: consumerAddress}, {
fromBlock: 0,
toBlock: "latest",
});
let outerResolve = null;
let outerReject = null;
const promise = new Promise<any[]>((resolve, reject) => {
outerResolve = resolve;
outerReject = reject;
});
const getEvents = (): Promise<any[]> => {
accessConsentEvent.get((error: any, logs: any[]) => {
if (error) {
outerReject(error);
throw new Error(error);
} else {
outerResolve(logs);
}
});
return promise;
};
const events = await getEvents().then((result) => result);
// let orders = await this.buildOrdersFromEvents(events, consumerAddress).then((result) => result)
const orders = events
.filter((obj: any) => (obj.args._consumer === consumerAddress))
.map(async (event: any) => ({
...event.args,
timeout: event.args._timeout.toNumber(),
status: await this.auth.getOrderStatus(event.args._id)
.then((status: BigNumber) => status.toNumber()),
paid: this.market.verifyOrderPayment(event.args._id),
key: null,
}));
Logger.debug("got orders: ", orders);
return orders;
}
public async purchaseAsset(
assetId: string, publisherId: string, price: number, privateKey: string, publicKey: string, timeout: number,
senderAddress: string, initialRequestEventHandler, accessCommittedEventHandler, tokenPublishedEventHandler) {
const {token, market, auth, config} = this;
try {
// Allow market contract to transfer funds on the consumer"s behalf
await token.contract.approve(market.contract.address, price, {from: senderAddress, gas: config.defaultGas});
} catch (err) {
Logger.log("token approve", err);
}
try {
// Submit the access request
await auth.contract.initiateAccessRequest(
assetId, publisherId, publicKey,
timeout, {from: senderAddress, gas: 1000000},
);
} catch (err) {
Logger.log("initiateAccessRequest", err);
}
const resourceFilter = {_resourceId: assetId, _consumer: senderAddress};
const initRequestEvent = auth.contract.AccessConsentRequested(resourceFilter);
let order: any = {};
this._listenOnce(
initRequestEvent,
"AccessConsentRequested",
(result: any, error: any) => {
order = initialRequestEventHandler(result, error);
const requestIdFilter = {_id: order.id};
const accessCommittedEvent = auth.contract.AccessRequestCommitted(requestIdFilter);
const tokenPublishedEvent = auth.contract.EncryptedTokenPublished(requestIdFilter);
this._listenOnce(
accessCommittedEvent,
"AccessRequestCommitted",
(accessRequestCommittedResult: any, accessRequestCommittedError: any) => {
accessCommittedEventHandler(accessRequestCommittedResult, order, accessRequestCommittedError);
},
);
this._listenOnce(
tokenPublishedEvent,
"EncryptedTokenPublished",
(encryptedTokenPublishedResult: any, encryptedTokenPublishedError: any) => {
tokenPublishedEventHandler(encryptedTokenPublishedResult, order, encryptedTokenPublishedError);
},
);
});
return order;
}
// Helper functions (private)
public _listenOnce(event: any, eventName: string, callback) {
// eslint-disable-next-line security/detect-non-literal-fs-filename
event.watch((error: any, result: any) => {
event.stopWatching();
if (error) {
Logger.log(`Error in keeper ${eventName} event: `, error);
}
callback(result, error);
});
}
}

View File

@ -1,11 +0,0 @@
import OceanAgent from './deprecated/ocean-agent'
import OceanKeeper from './deprecated/ocean-keeper'
import Ocean from './ocean'
import Logger from './utils/logger'
export {
Ocean,
OceanAgent, // deprecated
OceanKeeper, // deprecated
Logger
}

7
src/squid.ts Normal file
View File

@ -0,0 +1,7 @@
import Ocean from "./ocean";
import Logger from "./utils/logger";
export {
Ocean,
Logger,
};

View File

@ -1,52 +0,0 @@
export default class Web3Helper {
constructor(web3) {
this.web3 = web3
}
async getAccounts() {
return new Promise((resolve, reject) => {
this.web3.eth.getAccounts((err, accounts) => {
if (err) {
throw err
}
resolve(accounts)
})
})
}
async getNetworkName() {
return new Promise((resolve, reject) => {
let network = 'unknown'
this.web3.version.getNetwork((err, networkId) => {
if (err) {
throw err
}
switch (networkId) {
case '1':
network = 'Main'
break
case '2':
network = 'Morden'
break
case '3':
network = 'Ropsten'
break
case '4':
network = 'Rinkeby'
break
case '42':
network = 'Kovan'
break
default:
network = 'development'
}
resolve(network)
})
})
}
// web3 wrappers
sign(accountAddress, message) {
return this.web3.eth.sign(accountAddress, message)
}
}

59
src/utils/Web3Helper.ts Normal file
View File

@ -0,0 +1,59 @@
import Web3 = require("web3");
import Config from "./config";
export default class Web3Helper {
public web3: Web3;
public constructor(config: Config) {
const web3Provider = config.web3Provider || new Web3.providers.HttpProvider(config.nodeUri);
this.web3 = new Web3(web3Provider);
}
public async getAccounts(): Promise<any[]> {
return new Promise<any[]>((resolve, reject) => {
this.web3.eth.getAccounts((err: any, accounts: string[]) => {
if (err) {
throw err;
}
resolve(accounts);
});
});
}
public async getNetworkName(): Promise<string> {
return new Promise<string>((resolve, reject) => {
let network: string = "unknown";
// @ts-ignore old version of web3, lets get to 1.0
this.web3.version.getNetwork((err, networkId) => {
if (err) {
throw err;
}
switch (networkId) {
case "1":
network = "Main";
break;
case "2":
network = "Morden";
break;
case "3":
network = "Ropsten";
break;
case "4":
network = "Rinkeby";
break;
case "42":
network = "Kovan";
break;
default:
network = "development";
}
resolve(network);
});
});
}
// web3 wrappers
public sign(accountAddress: string, message: string) {
return this.web3.eth.sign(accountAddress, message);
}
}

7
src/utils/config.ts Normal file
View File

@ -0,0 +1,7 @@
export default class Config {
public defaultGas: number = 300000;
public providerUri: string;
public nodeUri: string;
public web3Provider: any;
}

View File

@ -1,22 +0,0 @@
export default class Logger {
static dispatch(verb, ...args) {
/* eslint-disable-next-line no-console */
console[verb](...args)
}
static log(...args) {
Logger.dispatch('log', ...args)
}
static debug(...args) {
Logger.dispatch('debug', ...args)
}
static warn(...args) {
Logger.dispatch('warn', ...args)
}
static error(...args) {
Logger.dispatch('error', ...args)
}
}

22
src/utils/logger.ts Normal file
View File

@ -0,0 +1,22 @@
export default class Logger {
public static log(...args: any[]) {
Logger.dispatch("log", ...args);
}
public static debug(...args: any[]) {
Logger.dispatch("debug", ...args);
}
public static warn(...args: any[]) {
Logger.dispatch("warn", ...args);
}
public static error(...args: any[]) {
Logger.dispatch("error", ...args);
}
private static dispatch(verb: string, ...args: any[]) {
/* eslint-disable-next-line no-console */
console[verb](...args);
}
}

22
tsconfig.json Normal file
View File

@ -0,0 +1,22 @@
{
"compilerOptions": {
"lib": [
"es6",
"es7"
],
"module": "commonjs",
"noImplicitAny": false,
"removeComments": true,
"preserveConstEnums": true,
"outDir": "./dist/",
"rootDir": "./src/",
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}

11
tslint.json Normal file
View File

@ -0,0 +1,11 @@
{
"defaultSeverity": "error",
"extends": [
"tslint:recommended"
],
"jsRules": {},
"rules": {
"object-literal-sort-keys": false
},
"rulesDirectory": []
}