mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
#162: new squid classes, and skeleton for the secret store.
This commit is contained in:
parent
82a149ec48
commit
e4461e1be1
92
SQUID_INTERFACE.md
Normal file
92
SQUID_INTERFACE.md
Normal file
@ -0,0 +1,92 @@
|
||||
## Ocean
|
||||
- Ocean(config(web3Provider, nodeURI, gas, network, providerURI))
|
||||
- getInstance()
|
||||
- getMessageHash(message) => hash of the given message
|
||||
- createDIDRecord(content) => ocean specific DID with an id based on hash of the given string message
|
||||
- registerProvider(url, provider_address)
|
||||
- getProviders()
|
||||
|
||||
## Account
|
||||
- getAccounts() => list of accounts along with token and eth balances
|
||||
- getTokenBalance()
|
||||
- getEthBalance()
|
||||
- requestTokens(amount) => bool
|
||||
|
||||
## Order
|
||||
- purchaseAsset(assetDID, price, timeout, conditions)
|
||||
- getOrderStatus(orderId) => integer representing the order status as defined in the keeper
|
||||
- getOrders() => list of orders
|
||||
- verifyOrderPayment(orderId) => true / false
|
||||
|
||||
## Asset / Metadata
|
||||
- publishAsset(assetDID, assetDDO, price)
|
||||
- updateAsset(assetDDO)
|
||||
- retireAsset(assetDID)
|
||||
- getAssetPrice(assetDID)
|
||||
- getAssetMetadata(assetDID) => asset DDO
|
||||
- getAssetsMetadata(<search-params>) => list of assets DDOs
|
||||
- resolveAssetDID(did) => DDO of the given DID
|
||||
- getAssets() => asset ids from keeper
|
||||
- checkAsset(assetDID) => true / false
|
||||
- getAssetConditions
|
||||
|
||||
|
||||
#######################################################
|
||||
#######################################################
|
||||
#######################################################
|
||||
## Keeper API:
|
||||
* register tribe actor
|
||||
* publish service agreement conditions
|
||||
* setup/execute service agreement
|
||||
* fulfill condition
|
||||
* dispute service delivery, quality, content, results
|
||||
* submit proof of service delivery
|
||||
* query transaction history
|
||||
* verify actor
|
||||
|
||||
#######################################################
|
||||
## Use cases:
|
||||
|
||||
### Publisher
|
||||
* publish one service
|
||||
* squid.publishService(metadata) => serviceDID, didDocument
|
||||
* view my published services
|
||||
* squid.listServices(type, matchStr, labels, tags, publishers))
|
||||
* view my sold services
|
||||
* squid.listSoldServices(actorAddress)
|
||||
* update service
|
||||
* squid.updateService(serviceDID, metadata, price)
|
||||
* revoke service
|
||||
* squid.revokeService(serviceDID, reason)
|
||||
|
||||
### Consumer
|
||||
* view / find services
|
||||
* squid.listServices(type, matchStr, labels, tags, publishers)
|
||||
* buy/access service
|
||||
* squid.buyService(serviceId, ) => orderId, service ?
|
||||
* view my purchased services
|
||||
* squid.listPurchasedServices(actorAddress)
|
||||
* checkPurchaseStatus(orderId)
|
||||
* dispute purchased service
|
||||
* squid.openServiceDispute(orderId)
|
||||
* rate service
|
||||
* squid.rateService(orderId, rating)
|
||||
|
||||
### Tribe / Marketplace
|
||||
* register on ocean with an `ethereum` address and DID Record
|
||||
* Uses `squid` or directly access keeper contracts
|
||||
* provide API to allow the following interactions:
|
||||
* publish a service
|
||||
* update a service
|
||||
* revoke a service
|
||||
* buy/use/access a service
|
||||
* search available services
|
||||
*
|
||||
* tribe admin:
|
||||
* view publishers
|
||||
* view disputes
|
||||
|
||||
### Curator
|
||||
|
||||
### Verifier
|
||||
|
37
src/account.js
Normal file
37
src/account.js
Normal file
@ -0,0 +1,37 @@
|
||||
import KeeperBase from './keeper/keeper-base'
|
||||
|
||||
export default class Account extends KeeperBase {
|
||||
constructor(web3Helper, token) {
|
||||
super(web3Helper)
|
||||
this.token = token
|
||||
return (async () => {
|
||||
return this
|
||||
})()
|
||||
}
|
||||
|
||||
async list() {
|
||||
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)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
currentAccount() {
|
||||
return this.helper.getCurrentAccount()
|
||||
}
|
||||
|
||||
tokenBalance() {
|
||||
return this.token.getTokenBalance()
|
||||
}
|
||||
|
||||
ethBalance() {
|
||||
return this.token.getEthBalance()
|
||||
}
|
||||
}
|
@ -40,4 +40,23 @@ export default class MetaData {
|
||||
return false
|
||||
})
|
||||
}
|
||||
async publishDataAsset(assetMetadata, price) {
|
||||
// Register on-chain (in the keeper)
|
||||
const { market } = this.contracts
|
||||
const assetDID = await this.generateDID(assetMetadata)
|
||||
const result = await market.register(
|
||||
assetDID,
|
||||
price,
|
||||
{ from: this.getCurrentAccount(), gas: this.defaultGas }
|
||||
)
|
||||
if (!result) {
|
||||
throw Error('Register asset in ocean keeper failed.')
|
||||
}
|
||||
// Register in oceandb
|
||||
const assetDDO = this.createAssetDDO(assetDID, assetMetadata)
|
||||
this.metadata.publishDataAsset(assetDID, assetDDO)
|
||||
return assetDDO
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
121
src/ocean.js
121
src/ocean.js
@ -1,11 +1,12 @@
|
||||
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'
|
||||
import ContractLoader from './keeper/contractLoader'
|
||||
|
||||
const DEFAULT_GAS = 300000
|
||||
const contractsToLoad = { market: 'OceanMarket', token: 'OceanToken', auth: 'OceanAuth' }
|
||||
|
||||
export default class Ocean {
|
||||
constructor(config) {
|
||||
@ -16,33 +17,20 @@ export default class Ocean {
|
||||
|
||||
this.helper = new Web3Helper(this._web3)
|
||||
this.metadata = new MetaData(this._providerUri)
|
||||
this.contracts = {}
|
||||
|
||||
return (async () => {
|
||||
this._network = config.network || (await this.helper.getNetworkName()).toLowerCase() || 'development'
|
||||
for (const key of contractsToLoad) {
|
||||
this.contracts[key] = await ContractLoader.load(contractsToLoad[key], this.helper)
|
||||
}
|
||||
|
||||
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.contracts.token.getTokenBalance(account),
|
||||
eth: await this.contracts.token.getEthBalance(account)
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
|
||||
async getOrdersByConsumer(consumerAddress) {
|
||||
let accessConsentEvent = this.contracts.auth.AccessConsentRequested({ _consumer: consumerAddress }, {
|
||||
let accessConsentEvent = this.auth.contract.AccessConsentRequested({ _consumer: consumerAddress }, {
|
||||
fromBlock: 0,
|
||||
toBlock: 'latest'
|
||||
})
|
||||
@ -80,47 +68,6 @@ export default class Ocean {
|
||||
return orders
|
||||
}
|
||||
|
||||
purchaseAsset(
|
||||
assetId, publisherId, price, privateKey, publicKey, timeout, senderAddress,
|
||||
initialRequestEventHandler, accessCommittedEventHandler, tokenPublishedEventHandler) {
|
||||
const { token, market, auth } = this.contracts
|
||||
// Allow market contract to transfer funds on the consumer's behalf
|
||||
token.approve(market.address, price, { from: senderAddress, gas: 2000000 })
|
||||
// Submit the access request
|
||||
auth.initiateAccessRequest(
|
||||
assetId, publisherId, publicKey,
|
||||
timeout, { from: senderAddress, gas: 1000000 }
|
||||
)
|
||||
|
||||
const resourceFilter = { _resourceId: assetId, _consumer: senderAddress }
|
||||
const initRequestEvent = auth.AccessConsentRequested(resourceFilter)
|
||||
let order = {}
|
||||
this._listenOnce(
|
||||
initRequestEvent,
|
||||
'AccessConsentRequested',
|
||||
(result, error) => {
|
||||
order = initialRequestEventHandler(result, error)
|
||||
const requestIdFilter = { _id: order.id }
|
||||
const accessCommittedEvent = auth.AccessRequestCommitted(requestIdFilter)
|
||||
const tokenPublishedEvent = auth.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
|
||||
@ -134,38 +81,9 @@ export default class Ocean {
|
||||
}
|
||||
|
||||
// The new interface
|
||||
async publishDataAsset(assetMetadata, price) {
|
||||
// Register on-chain (in the keeper)
|
||||
const { market } = this.contracts
|
||||
const assetDID = await this.generateDID(assetMetadata)
|
||||
const result = await market.register(
|
||||
assetDID,
|
||||
price,
|
||||
{ from: this.getCurrentAccount(), gas: this.defaultGas }
|
||||
)
|
||||
if (!result) {
|
||||
throw Error('Register asset in ocean keeper failed.')
|
||||
}
|
||||
// Register in oceandb
|
||||
const assetDDO = this.createAssetDDO(assetDID, assetMetadata)
|
||||
this.metadata.publishDataAsset(assetDID, assetDDO)
|
||||
return assetDDO
|
||||
}
|
||||
|
||||
getCurrentAccount() {
|
||||
return this.helper.getCurrentAccount()
|
||||
}
|
||||
|
||||
getTokenBalance() {
|
||||
return this.contracts.token.getTokenBalance()
|
||||
}
|
||||
|
||||
getEthBalance() {
|
||||
return this.contracts.token.getEthBalance()
|
||||
}
|
||||
|
||||
requestTokens(numTokens) {
|
||||
return this.contracts.market.requestTokens(numTokens, { from: this.getCurrentAccount() })
|
||||
return this.market.requestTokens(numTokens, { from: this.getCurrentAccount() })
|
||||
}
|
||||
|
||||
getMessageHash(message) {
|
||||
@ -173,23 +91,6 @@ export default class Ocean {
|
||||
}
|
||||
|
||||
async generateDID(content) {
|
||||
return 'did:ocn:' + (await this.contracts.market.generateId(content)).toString()
|
||||
}
|
||||
|
||||
createAssetDDO(assetDID, assetMetadata) {
|
||||
return {
|
||||
'@context': 'https://w3id.org/did/v1',
|
||||
id: assetDID,
|
||||
publicKey: [],
|
||||
authentication: [],
|
||||
service: [],
|
||||
metadata: assetMetadata
|
||||
}
|
||||
}
|
||||
|
||||
resolveDID(did) {
|
||||
const providerURL = this.contracts.market.resolveAssetDID(did)
|
||||
const metadataGuy = new MetaData(providerURL)
|
||||
return metadataGuy.getAssetDDO(did)
|
||||
return 'did:ocn:' + (await this.market.generateId(content)).toString()
|
||||
}
|
||||
}
|
||||
|
52
src/order.js
Normal file
52
src/order.js
Normal file
@ -0,0 +1,52 @@
|
||||
import KeeperBase from './keeper/keeper-base'
|
||||
|
||||
export default class Order extends KeeperBase {
|
||||
constructor(web3Helper, market, token, auth) {
|
||||
super(web3Helper)
|
||||
this.market = market
|
||||
this.token = token
|
||||
this.auth = auth
|
||||
return (async () => {
|
||||
return this
|
||||
})()
|
||||
}
|
||||
|
||||
buyService(serviceDID, publisherId, price, timeout, senderAddress, initialRequestEventHandler,
|
||||
accessCommittedEventHandler, tokenPublishedEventHandler) {
|
||||
// Allow market contract to transfer funds on the consumer's behalf
|
||||
const { token, market, auth } = this
|
||||
token.contract.approve(market.address, price, { from: senderAddress, gas: 2000000 })
|
||||
// Submit the access request
|
||||
auth.contract.initiateAccessRequest(
|
||||
serviceDID, publisherId, timeout, { from: senderAddress, gas: 1000000 }
|
||||
)
|
||||
|
||||
const resourceFilter = { _resourceId: serviceDID, _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
|
||||
}
|
||||
}
|
22
src/secret_store/ParityClient.js
Normal file
22
src/secret_store/ParityClient.js
Normal file
@ -0,0 +1,22 @@
|
||||
export default class ParityClient {
|
||||
constructor(url) {
|
||||
this.url = url
|
||||
this.web3 = null
|
||||
}
|
||||
|
||||
signDocumentKeyId() {
|
||||
return ''
|
||||
}
|
||||
|
||||
generateDocumentKeyFromKey() {
|
||||
return ''
|
||||
}
|
||||
|
||||
encryptDocument() {
|
||||
return ''
|
||||
}
|
||||
|
||||
decryptDocument() {
|
||||
return ''
|
||||
}
|
||||
}
|
18
src/secret_store/SecretStore.js
Normal file
18
src/secret_store/SecretStore.js
Normal file
@ -0,0 +1,18 @@
|
||||
export default class SecretStore {
|
||||
constructor(url, threshold) {
|
||||
this.url = url
|
||||
this.threshold = threshold | 1
|
||||
}
|
||||
|
||||
generateServerKey() {
|
||||
return ''
|
||||
}
|
||||
|
||||
storeDocumentKey() {
|
||||
return ''
|
||||
}
|
||||
|
||||
retrieveDocumentKey() {
|
||||
return ''
|
||||
}
|
||||
}
|
36
src/service.js
Normal file
36
src/service.js
Normal file
@ -0,0 +1,36 @@
|
||||
import KeeperBase from './keeper/keeper-base'
|
||||
import MetaData from './metadata'
|
||||
|
||||
export default class Service extends KeeperBase {
|
||||
constructor(web3Helper, market) {
|
||||
super(web3Helper)
|
||||
this.market = market
|
||||
return (async () => {
|
||||
return this
|
||||
})()
|
||||
}
|
||||
|
||||
serviceMetadata(assetDID) {
|
||||
return ''
|
||||
}
|
||||
serviceTribe() {
|
||||
return ''
|
||||
}
|
||||
|
||||
createDDO(did, metadata) {
|
||||
return {
|
||||
'@context': 'https://w3id.org/did/v1',
|
||||
id: did,
|
||||
publicKey: [],
|
||||
authentication: [],
|
||||
service: [],
|
||||
metadata: metadata
|
||||
}
|
||||
}
|
||||
|
||||
resolveDID(did) {
|
||||
const providerURL = this.market.resolveDID(did)
|
||||
const metadataGuy = new MetaData(providerURL)
|
||||
return metadataGuy.getAssetDDO(did)
|
||||
}
|
||||
}
|
25
src/tribe.js
Normal file
25
src/tribe.js
Normal file
@ -0,0 +1,25 @@
|
||||
import KeeperBase from './keeper/keeper-base'
|
||||
|
||||
export default class Tribe extends KeeperBase {
|
||||
constructor(web3Helper) {
|
||||
super(web3Helper)
|
||||
|
||||
return (async () => {
|
||||
return this
|
||||
})()
|
||||
}
|
||||
|
||||
// did ddo for tribes/marketplaces
|
||||
registerTribe() {
|
||||
return ''
|
||||
}
|
||||
|
||||
tribessList() {
|
||||
return ''
|
||||
}
|
||||
|
||||
resolveTribeDID() {
|
||||
// verify DDO
|
||||
return 'DDO'
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user