mirror of
https://github.com/oceanprotocol-archive/squid-js.git
synced 2024-02-02 15:31:51 +01:00
Clean and simplify template related typings.
This commit is contained in:
parent
76c4b2b1fb
commit
51aa0fbf64
@ -1,4 +1,5 @@
|
||||
import Config from "./models/Config"
|
||||
import Logger, { LogLevel } from "./utils/Logger"
|
||||
|
||||
/**
|
||||
* Stores the configuration of the library.
|
||||
@ -16,6 +17,12 @@ export default class ConfigProvider {
|
||||
* @param {Config} Library config.
|
||||
*/
|
||||
public static setConfig(config: Config) {
|
||||
Logger.setLevel(
|
||||
typeof config.verbose !== "number"
|
||||
? (config.verbose ? LogLevel.Log : LogLevel.None)
|
||||
: config.verbose as LogLevel,
|
||||
)
|
||||
|
||||
ConfigProvider.config = config
|
||||
}
|
||||
|
||||
|
@ -1,48 +0,0 @@
|
||||
import { Event } from "./Event"
|
||||
|
||||
export interface Parameter {
|
||||
name: string
|
||||
type: string
|
||||
value: any
|
||||
}
|
||||
|
||||
export interface Dependency {
|
||||
/**
|
||||
* @example "lockPayment"
|
||||
*/
|
||||
name: string
|
||||
/**
|
||||
* @example 0
|
||||
*/
|
||||
timeout: number
|
||||
}
|
||||
|
||||
export interface Condition {
|
||||
name: string
|
||||
/**
|
||||
* @example "AccessCondition"
|
||||
*/
|
||||
contractName: string
|
||||
/**
|
||||
* @example "lockPayment"
|
||||
*/
|
||||
functionName: string
|
||||
/**
|
||||
* @example 0
|
||||
*/
|
||||
timeout: number
|
||||
/**
|
||||
* @example "0x12122434"
|
||||
*/
|
||||
conditionKey: string
|
||||
parameters: Parameter[]
|
||||
events: Event[]
|
||||
/**
|
||||
* @example []
|
||||
*/
|
||||
dependencies: Dependency[]
|
||||
/**
|
||||
* @example false
|
||||
*/
|
||||
isTerminalCondition: boolean
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import { Event } from "./Event"
|
||||
|
||||
export interface Contract {
|
||||
contractName: string
|
||||
fulfillmentOperator: number
|
||||
events: Event[]
|
||||
}
|
@ -1,20 +0,0 @@
|
||||
export interface EventHandler {
|
||||
/**
|
||||
* @example "serviceAgreement"
|
||||
*/
|
||||
moduleName: string
|
||||
/**
|
||||
* @example "fulfillAgreement"
|
||||
*/
|
||||
functionName: string
|
||||
/**
|
||||
* @example "0.1"
|
||||
*/
|
||||
version: string
|
||||
}
|
||||
|
||||
export interface Event {
|
||||
name: string
|
||||
actorType: string
|
||||
handler: EventHandler
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import { Condition } from "./Condition"
|
||||
import { Contract } from "./Contract"
|
||||
import { MetaData } from "./MetaData"
|
||||
import { ServiceAgreementTemplate } from "./ServiceAgreementTemplate"
|
||||
|
||||
export type ServiceType = "Authorization" | "Metadata" | "Access" | "Compute" | "FitchainCompute"
|
||||
|
||||
@ -22,11 +23,12 @@ export interface ServiceMetadata extends ServiceCommon {
|
||||
|
||||
export interface ServiceAccess extends ServiceCommon {
|
||||
type: "Access"
|
||||
name?: string,
|
||||
description?: string
|
||||
creator?: string
|
||||
templateId?: string
|
||||
purchaseEndpoint?: string
|
||||
description?: string
|
||||
serviceAgreementContract?: Contract
|
||||
conditions?: Condition[]
|
||||
serviceAgreementTemplate?: ServiceAgreementTemplate
|
||||
}
|
||||
|
||||
export interface ServiceCompute extends ServiceCommon {
|
||||
|
33
src/ddo/ServiceAgreementTemplate.ts
Normal file
33
src/ddo/ServiceAgreementTemplate.ts
Normal file
@ -0,0 +1,33 @@
|
||||
export interface ServiceAgreementTemplateParameter {
|
||||
name: string
|
||||
type: string
|
||||
value: string
|
||||
}
|
||||
|
||||
export interface ServiceAgreementTemplateEvent {
|
||||
name: string
|
||||
actorType: string
|
||||
handler: {
|
||||
moduleName: string
|
||||
functionName: string
|
||||
version: string
|
||||
}
|
||||
}
|
||||
|
||||
export interface ServiceAgreementTemplateCondition {
|
||||
name: string
|
||||
timelock: number
|
||||
timeout: number
|
||||
contractName: string
|
||||
functionName: string
|
||||
parameters: ServiceAgreementTemplateParameter[]
|
||||
events: ServiceAgreementTemplateEvent[]
|
||||
}
|
||||
|
||||
export interface ServiceAgreementTemplate {
|
||||
contractName: string
|
||||
events: ServiceAgreementTemplateEvent[]
|
||||
fulfillmentOrder: string[]
|
||||
conditionDependency: {[condition: string]: string[]}
|
||||
conditions: ServiceAgreementTemplateCondition[]
|
||||
}
|
@ -14,7 +14,7 @@ import Web3Provider from "./Web3Provider"
|
||||
* - Ocean Tokens: the intrinsic tokens circulated inside Ocean network, which is used in the voting of TCRs.
|
||||
* - Marketplace: the core marketplace where people can transact with each other with Ocean tokens.
|
||||
*/
|
||||
export default class Keeper {
|
||||
export class Keeper {
|
||||
|
||||
/**
|
||||
* Returns Keeper instance.
|
||||
@ -150,3 +150,5 @@ export default class Keeper {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export default Keeper
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { LogLevel } from "../utils/Logger"
|
||||
export { LogLevel } from "../utils/Logger"
|
||||
|
||||
export default class Config {
|
||||
export class Config {
|
||||
/* Aquarius Config */
|
||||
// the url to the aquarius
|
||||
public aquariusUri: string
|
||||
@ -30,3 +31,5 @@ export default class Config {
|
||||
/* Squid config */
|
||||
public verbose: boolean | LogLevel
|
||||
}
|
||||
|
||||
export default Config
|
||||
|
@ -16,7 +16,7 @@ import { Service } from "../ddo/Service"
|
||||
import ContractEvent from "../keeper/Event"
|
||||
import Config from "../models/Config"
|
||||
import SecretStoreProvider from "../secretstore/SecretStoreProvider"
|
||||
import Logger, { LogLevel } from "../utils/Logger"
|
||||
import { Logger, LogLevel } from "../utils/Logger"
|
||||
import Account from "./Account"
|
||||
import DID from "./DID"
|
||||
import ServiceAgreement from "./ServiceAgreements/ServiceAgreement"
|
||||
@ -36,6 +36,7 @@ export default class Ocean {
|
||||
*/
|
||||
public static async getInstance(config: Config): Promise<Ocean> {
|
||||
// Must be defined on instance level, right now, calling getInstance twice is going to rewrite that
|
||||
// WARN: is called on ConfigProvider.setConfig too (to work fine on test)
|
||||
Logger.setLevel(
|
||||
typeof config.verbose !== "number"
|
||||
? (config.verbose ? LogLevel.Log : LogLevel.None)
|
||||
|
@ -1,14 +0,0 @@
|
||||
import { Event } from "../../ddo/Event"
|
||||
import MethodReflection from "../../models/MethodReflection"
|
||||
import Parameter from "./Parameter"
|
||||
|
||||
export default class Condition {
|
||||
public methodReflection: MethodReflection
|
||||
public condtionKey: string
|
||||
public dependencies: string[]
|
||||
public dependencyTimeoutFlags: number[]
|
||||
public isTerminalCondition: boolean
|
||||
public timeout: number
|
||||
public events: Event[]
|
||||
public parameters: Parameter[]
|
||||
}
|
@ -1,7 +0,0 @@
|
||||
import EventHandler from "./EventHandler"
|
||||
|
||||
export default class Event {
|
||||
public name: string = "PaymentLocked"
|
||||
public actorType: string = "publisher"
|
||||
public handler: EventHandler
|
||||
}
|
@ -1,5 +0,0 @@
|
||||
export default class EventHandler {
|
||||
public moduleName: string = "accessControl"
|
||||
public functionName: string = "grantAccess"
|
||||
public version: string = "0.1"
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
import Event from "./Event"
|
||||
import Parameter from "./Parameter"
|
||||
|
||||
export default class Method {
|
||||
public name: string
|
||||
public contractName: string
|
||||
public methodName: string
|
||||
public timeout: number
|
||||
public parameters: Parameter[]
|
||||
public events: Event[]
|
||||
public dependencies: string[]
|
||||
public dependencyTimeoutFlags: number[]
|
||||
public isTerminalCondition: boolean
|
||||
}
|
@ -1,4 +0,0 @@
|
||||
export default class Parameter {
|
||||
public name: string
|
||||
public type: string
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
import { Condition } from "../../ddo/Condition"
|
||||
import { ServiceAgreementTemplateCondition } from "../../ddo/ServiceAgreementTemplate"
|
||||
import { DDO } from "../../ddo/DDO"
|
||||
import { ServiceAccess } from "../../ddo/Service"
|
||||
import Keeper from "../../keeper/Keeper"
|
||||
@ -7,21 +7,22 @@ import ValuePair from "../../models/ValuePair"
|
||||
import Logger from "../../utils/Logger"
|
||||
import Account from "../Account"
|
||||
import DID from "../DID"
|
||||
import OceanBase from "../OceanBase"
|
||||
import { signText } from "../../utils"
|
||||
|
||||
export default class ServiceAgreement extends OceanBase {
|
||||
|
||||
// TODO: move this class to helpers, it only contains pure functions
|
||||
export default class ServiceAgreement {
|
||||
|
||||
public static async signServiceAgreement(
|
||||
ddo: DDO,
|
||||
serviceDefinitionId: string,
|
||||
serviceAgreementId: string,
|
||||
valuesMap: {[value: string]: string},
|
||||
consumer: Account,
|
||||
): Promise<string> {
|
||||
|
||||
Logger.log("Signing SA with serviceAgreementId", serviceAgreementId)
|
||||
|
||||
const service = ddo.findServiceById<"Access">(serviceDefinitionId)
|
||||
const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
|
||||
const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, valuesMap)
|
||||
const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
|
||||
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
|
||||
|
||||
@ -38,31 +39,6 @@ export default class ServiceAgreement extends OceanBase {
|
||||
return serviceAgreementHashSignature
|
||||
}
|
||||
|
||||
public static async executeServiceAgreement(
|
||||
did: DID,
|
||||
ddo: DDO,
|
||||
serviceDefinitionId: string,
|
||||
serviceAgreementId: string,
|
||||
serviceAgreementHashSignature: string,
|
||||
consumer: Account,
|
||||
publisher: Account,
|
||||
): Promise<ServiceAgreement> {
|
||||
|
||||
Logger.log("Executing SA with serviceAgreementId", serviceAgreementId)
|
||||
|
||||
const service = ddo.findServiceById<"Access">(serviceDefinitionId)
|
||||
const values: ValuePair[][] = ServiceAgreement.getValuesFromService(service, serviceAgreementId)
|
||||
const valueHashes: string[] = ServiceAgreement.createValueHashes(values)
|
||||
const timeoutValues: number[] = ServiceAgreement.getTimeoutValuesFromService(service)
|
||||
|
||||
// todo get consumer from ddo
|
||||
const serviceAgreement: ServiceAgreement = await ServiceAgreement.executeAgreement(did, ddo,
|
||||
serviceDefinitionId, serviceAgreementId, valueHashes, timeoutValues, serviceAgreementHashSignature,
|
||||
consumer.getId(), publisher)
|
||||
|
||||
return serviceAgreement
|
||||
}
|
||||
|
||||
private static async createSAHashSignature(
|
||||
service: ServiceAccess,
|
||||
serviceAgreementId: string,
|
||||
@ -75,88 +51,20 @@ export default class ServiceAgreement extends OceanBase {
|
||||
throw new Error("TemplateId not found in ddo.")
|
||||
}
|
||||
|
||||
const conditionKeys: string[] = service.conditions.map((condition) => {
|
||||
return condition.conditionKey
|
||||
})
|
||||
|
||||
if (conditionKeys.length !== valueHashes.length) {
|
||||
throw new Error("Hashing SA failed!")
|
||||
}
|
||||
|
||||
const serviceAgreementHash = ServiceAgreement.hashServiceAgreement(
|
||||
service.templateId,
|
||||
serviceAgreementId,
|
||||
conditionKeys,
|
||||
valueHashes,
|
||||
timeoutValues)
|
||||
|
||||
let serviceAgreementHashSignature: string
|
||||
const web3 = Web3Provider.getWeb3()
|
||||
if ((web3 as any).currentProvider.isMetaMask) {
|
||||
// password is injected by metamask, dont try to set it!
|
||||
serviceAgreementHashSignature = await web3.eth.personal.sign(serviceAgreementHash, consumer.getId(), null)
|
||||
} else {
|
||||
serviceAgreementHashSignature = await web3.eth.sign(serviceAgreementHash, consumer.getId())
|
||||
}
|
||||
let serviceAgreementHashSignature = await signText(serviceAgreementHash, consumer.getId(), consumer.getPassword())
|
||||
|
||||
return serviceAgreementHashSignature
|
||||
}
|
||||
|
||||
private static async executeAgreement(
|
||||
did: DID,
|
||||
ddo: DDO,
|
||||
serviceDefinitionId: string,
|
||||
serviceAgreementId: string,
|
||||
valueHashes: string[],
|
||||
timeoutValues: number[],
|
||||
serviceAgreementHashSignature: string,
|
||||
consumerAddress: string,
|
||||
publisher: Account,
|
||||
): Promise<ServiceAgreement> {
|
||||
|
||||
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||
|
||||
const service = ddo.findServiceById<"Access">(serviceDefinitionId)
|
||||
|
||||
if (!service.templateId) {
|
||||
throw new Error(`TemplateId not found in service "${service.type}" ddo.`)
|
||||
}
|
||||
|
||||
const templateActive = await serviceAgreement.getTemplateStatus(service.templateId)
|
||||
|
||||
if (!templateActive) {
|
||||
throw new Error(`Template with id ${service.templateId} is not active.`)
|
||||
}
|
||||
|
||||
const executeAgreementReceipt = await serviceAgreement
|
||||
.initializeAgreement(
|
||||
service.templateId,
|
||||
serviceAgreementHashSignature,
|
||||
consumerAddress,
|
||||
valueHashes,
|
||||
timeoutValues,
|
||||
serviceAgreementId,
|
||||
did,
|
||||
publisher.getId(),
|
||||
)
|
||||
|
||||
if (!executeAgreementReceipt.status) {
|
||||
throw new Error("executing service agreement failed.")
|
||||
}
|
||||
return new ServiceAgreement(
|
||||
executeAgreementReceipt.events.AgreementInitialized.returnValues.agreementId,
|
||||
)
|
||||
}
|
||||
|
||||
private static createValueHashes(parameterValuePairs: ValuePair[][]): string[] {
|
||||
|
||||
const hashes: string[] = []
|
||||
parameterValuePairs.map((valuePairs: ValuePair[]) => {
|
||||
|
||||
hashes.push(ServiceAgreement.hashValuePairArray(valuePairs))
|
||||
})
|
||||
|
||||
return hashes
|
||||
return parameterValuePairs
|
||||
.map((valuePairs: ValuePair[]) => ServiceAgreement.hashValuePairArray(valuePairs))
|
||||
}
|
||||
|
||||
private static hashValuePairArray(valuePairs: ValuePair[]): string {
|
||||
@ -178,70 +86,35 @@ export default class ServiceAgreement extends OceanBase {
|
||||
private static hashServiceAgreement(
|
||||
serviceAgreementTemplateId: string,
|
||||
serviceAgreementId: string,
|
||||
conditionKeys: string[],
|
||||
valueHashes: string[],
|
||||
timeouts: number[],
|
||||
): string {
|
||||
|
||||
const args = [
|
||||
{type: "bytes32", value: serviceAgreementTemplateId} as ValuePair,
|
||||
{type: "bytes32[]", value: conditionKeys} as ValuePair,
|
||||
{type: "bytes32[]", value: valueHashes} as ValuePair,
|
||||
{type: "uint256[]", value: timeouts} as ValuePair,
|
||||
{type: "bytes32", value: "0x" + serviceAgreementId} as ValuePair,
|
||||
{type: "bytes32", value: serviceAgreementTemplateId},
|
||||
{type: "bytes32[]", value: valueHashes},
|
||||
{type: "uint256[]", value: timeouts},
|
||||
{type: "bytes32", value: "0x" + serviceAgreementId},
|
||||
]
|
||||
|
||||
return (Web3Provider as any).getWeb3().utils.soliditySha3(...args).toString("hex")
|
||||
}
|
||||
|
||||
private static getTimeoutValuesFromService(service: ServiceAccess): number[] {
|
||||
const timeoutValues: number[] = service.conditions.map((condition: Condition) => {
|
||||
return condition.timeout
|
||||
})
|
||||
const timeoutValues: number[] = service.serviceAgreementTemplate.conditions
|
||||
.map((condition: ServiceAgreementTemplateCondition) => condition.timeout)
|
||||
|
||||
return timeoutValues
|
||||
}
|
||||
|
||||
private static getValuesFromService(service: ServiceAccess, serviceAgreementId: string): ValuePair[][] {
|
||||
|
||||
const values: ValuePair[][] = []
|
||||
|
||||
service.conditions.forEach((condition, i) => {
|
||||
const contionValues: ValuePair[] = []
|
||||
condition.parameters.forEach((parameter) => {
|
||||
|
||||
contionValues.push({
|
||||
type: parameter.type,
|
||||
value: parameter.name === "serviceId" ? serviceAgreementId : parameter.value,
|
||||
} as ValuePair)
|
||||
})
|
||||
|
||||
values[i] = contionValues
|
||||
})
|
||||
|
||||
return values
|
||||
}
|
||||
|
||||
constructor(serviceAgreementId: string) {
|
||||
super(serviceAgreementId)
|
||||
}
|
||||
|
||||
public async payAsset(assetId: string, price: number, consumer: Account): Promise<boolean> {
|
||||
const {paymentConditions, token} = <any>await Keeper.getInstance()
|
||||
|
||||
await token.approve(paymentConditions.getAddress(), price, consumer.getId())
|
||||
|
||||
const lockPaymentReceipt = await paymentConditions.lockPayment(this.getId(), assetId, price, consumer.getId())
|
||||
|
||||
return lockPaymentReceipt.status
|
||||
}
|
||||
|
||||
public async grantAccess(documentId: string, publisher: Account): Promise<boolean> {
|
||||
const {accessConditions} = <any>await Keeper.getInstance()
|
||||
|
||||
const grantAccessReceipt =
|
||||
await accessConditions.grantAccess(this.getId(), documentId, publisher.getId())
|
||||
|
||||
return !!grantAccessReceipt.events.AccessGranted
|
||||
private static getValuesFromService(service: ServiceAccess, valuesMap: {[key: string]: string}): ValuePair[][] {
|
||||
return (service.serviceAgreementTemplate.conditions || [])
|
||||
.map(condition =>
|
||||
(condition.parameters || [])
|
||||
.map(({type, name}) => ({
|
||||
type,
|
||||
value: valuesMap[name.replace(/^_/, "")] || "",
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
|
@ -1,221 +0,0 @@
|
||||
import { Condition as DDOCondition, Dependency, Parameter } from "../../ddo/Condition"
|
||||
import { MetaData } from "../../ddo/MetaData"
|
||||
import ContractReflector from "../../keeper/ContractReflector"
|
||||
import Keeper from "../../keeper/Keeper"
|
||||
import Web3Provider from "../../keeper/Web3Provider"
|
||||
import MethodReflection from "../../models/MethodReflection"
|
||||
import ValuePair from "../../models/ValuePair"
|
||||
import Logger from "../../utils/Logger"
|
||||
import Account from "../Account"
|
||||
import OceanBase from "../OceanBase"
|
||||
import Condition from "./Condition"
|
||||
import Method from "./Method"
|
||||
import TemplateBase from "./Templates/TemplateBase"
|
||||
|
||||
export default class ServiceAgreementTemplate extends OceanBase {
|
||||
|
||||
private static generateConditionsKey(serviceAgreementTemplateId: string, methodReflection: MethodReflection): string {
|
||||
const values = [
|
||||
{type: "bytes32", value: serviceAgreementTemplateId} as ValuePair,
|
||||
{type: "address", value: methodReflection.address} as ValuePair,
|
||||
{type: "bytes4", value: methodReflection.signature} as ValuePair,
|
||||
]
|
||||
return (Web3Provider as any).getWeb3().utils.soliditySha3(...values).toString("hex")
|
||||
}
|
||||
|
||||
public constructor(private template: TemplateBase) {
|
||||
super(template.id)
|
||||
}
|
||||
|
||||
public async register(templateOwnerAddress: string): Promise<boolean> {
|
||||
|
||||
const dependencyMatrix: number[] =
|
||||
await Promise.all(this.template.Methods.map(async (method: Method) => {
|
||||
return this.compressDependencies(method.dependencies, method.dependencyTimeoutFlags)
|
||||
}))
|
||||
|
||||
const fulfillmentIndices: number[] = this.template.Methods
|
||||
.map((method: Method, i: number) => method.isTerminalCondition ? i : null)
|
||||
.filter((index: number) => index !== null)
|
||||
|
||||
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||
|
||||
const owner = await this.getOwner()
|
||||
|
||||
if (owner.getId() === templateOwnerAddress) {
|
||||
// tslint:disable-next-line
|
||||
Logger.error(`Template with id "${this.template.id}" is already registered to your account "${templateOwnerAddress}".`)
|
||||
return false
|
||||
}
|
||||
|
||||
if (!owner.getId().startsWith("0x00000")) {
|
||||
Logger.error(`Template with id "${this.template.id}" already registered by someone else.`)
|
||||
return false
|
||||
}
|
||||
|
||||
let receipt
|
||||
try {
|
||||
receipt = await serviceAgreement
|
||||
.setupTemplate(
|
||||
this.template.id,
|
||||
await this.getMethodReflections(),
|
||||
dependencyMatrix,
|
||||
fulfillmentIndices,
|
||||
this.template.fulfillmentOperator,
|
||||
templateOwnerAddress)
|
||||
} catch (e) {
|
||||
Logger.error(e)
|
||||
throw new Error(`Is not possible to setup the agreement template`)
|
||||
}
|
||||
const {templateId, provider} = receipt.events.TemplateSetup.returnValues
|
||||
|
||||
if (templateId !== this.template.id) {
|
||||
// tslint:disable-next-line
|
||||
throw new Error(`TemplateId missmatch on ${this.template.templateName}! Should be "${this.template.id}" but is ${templateId}`)
|
||||
}
|
||||
|
||||
if (provider !== templateOwnerAddress) {
|
||||
// tslint:disable-next-line
|
||||
throw new Error(`Template owner missmatch on ${this.template.templateName}! Should be "${templateOwnerAddress}" but is ${provider}`)
|
||||
}
|
||||
|
||||
if (!receipt.status) {
|
||||
Logger.error(`Registering template failed, status was "false".`)
|
||||
}
|
||||
|
||||
return receipt.status
|
||||
}
|
||||
|
||||
/**
|
||||
* gets the status of a service agreement template
|
||||
*/
|
||||
public async getStatus(): Promise<boolean> {
|
||||
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||
return serviceAgreement.getTemplateStatus(this.getId())
|
||||
}
|
||||
|
||||
public async getOwner(): Promise<Account> {
|
||||
const {serviceAgreement} = <any>await Keeper.getInstance()
|
||||
|
||||
return new Account(await serviceAgreement.getTemplateOwner(this.id))
|
||||
}
|
||||
|
||||
public async getConditions(metadata: MetaData, assetId: string): Promise<DDOCondition[]> {
|
||||
const conditions = await this.blendConditions()
|
||||
return conditions.map((condition: Condition, index: number): DDOCondition => {
|
||||
|
||||
const mapParameterValueToName = (name) => {
|
||||
|
||||
switch (name) {
|
||||
case "price":
|
||||
return metadata.base.price
|
||||
case "assetId":
|
||||
return assetId
|
||||
case "documentKeyId":
|
||||
return assetId
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
const parameters: Parameter[] = condition.parameters.map((parameter: Parameter) => {
|
||||
return {
|
||||
name: parameter.name,
|
||||
type: parameter.type,
|
||||
value: mapParameterValueToName(parameter.name),
|
||||
} as Parameter
|
||||
})
|
||||
|
||||
// Logger.log(`${condition.methodReflection.contractName}.${condition.methodReflection.methodName}`,
|
||||
// JSON.stringify(parameters, null, 2))
|
||||
|
||||
const dependencies: Dependency[] = condition.dependencies.map((dep, i) => {
|
||||
return {
|
||||
name: dep,
|
||||
timeout: condition.dependencyTimeoutFlags[i],
|
||||
} as Dependency
|
||||
})
|
||||
|
||||
return {
|
||||
name: condition.methodReflection.methodName,
|
||||
dependencies,
|
||||
timeout: condition.timeout,
|
||||
isTerminalCondition: condition.isTerminalCondition,
|
||||
conditionKey: condition.condtionKey,
|
||||
contractName: condition.methodReflection.contractName,
|
||||
functionName: condition.methodReflection.methodName,
|
||||
index,
|
||||
parameters,
|
||||
events: condition.events,
|
||||
} as DDOCondition
|
||||
})
|
||||
}
|
||||
|
||||
private async blendConditions(): Promise<Condition[]> {
|
||||
const methodReflections = await this.getMethodReflections()
|
||||
|
||||
const conditions: Condition[] = methodReflections.map((methodReflection, i) => {
|
||||
const method: Method = this.template.Methods[i]
|
||||
return {
|
||||
methodReflection,
|
||||
timeout: method.timeout,
|
||||
events: method.events,
|
||||
parameters: method.parameters,
|
||||
dependencies: method.dependencies,
|
||||
dependencyTimeoutFlags: method.dependencyTimeoutFlags,
|
||||
isTerminalCondition: method.isTerminalCondition,
|
||||
condtionKey: ServiceAgreementTemplate
|
||||
.generateConditionsKey(this.getId(), methodReflection),
|
||||
} as Condition
|
||||
})
|
||||
|
||||
Logger.debug("Conditions", JSON.stringify(conditions, null, 2))
|
||||
|
||||
return conditions
|
||||
}
|
||||
|
||||
private compressDependencies(dependencies: string[], dependencyTimeoutFlags: number[]): number {
|
||||
|
||||
if (dependencies.length !== dependencyTimeoutFlags.length) {
|
||||
throw new Error("Deps and timeouts need the same length")
|
||||
}
|
||||
|
||||
const mappedDependencies: number[] = []
|
||||
const mappedDependencyTimeoutFlags: number[] = []
|
||||
|
||||
this.template.Methods.forEach((m, i) => {
|
||||
const di = dependencies.findIndex((d) => d === m.name)
|
||||
mappedDependencies.push(di > -1 ? 1 : 0)
|
||||
mappedDependencyTimeoutFlags.push((di > -1 && dependencyTimeoutFlags[di]) ? 1 : 0)
|
||||
})
|
||||
|
||||
if (mappedDependencies.length !== mappedDependencyTimeoutFlags.length) {
|
||||
throw new Error("Deps and timeouts need the same length")
|
||||
}
|
||||
|
||||
// Logger.log(dependencies, mappedDependencies, dependencyTimeoutFlags, mappedDependencyTimeoutFlags)
|
||||
|
||||
let compressedDependencyValue: number = 0
|
||||
const numBits: number = 2 // 1st for dependency, 2nd for timeout flag
|
||||
mappedDependencies.forEach((d: number, i: number) => {
|
||||
const t: number = mappedDependencyTimeoutFlags[i]
|
||||
const offset: number = i * numBits
|
||||
// tslint:disable-next-line
|
||||
compressedDependencyValue |= d * 2 ** (offset + 0) // the dependency bit
|
||||
// tslint:disable-next-line
|
||||
compressedDependencyValue |= t * 2 ** (offset + 1) // the timeout bit
|
||||
})
|
||||
|
||||
return compressedDependencyValue
|
||||
}
|
||||
|
||||
private async getMethodReflections(): Promise<MethodReflection[]> {
|
||||
const methodReflections: MethodReflection[] = []
|
||||
for (const method of this.template.Methods) {
|
||||
methodReflections.push(
|
||||
await ContractReflector.reflectContractMethod(method.contractName, method.methodName),
|
||||
)
|
||||
}
|
||||
return methodReflections
|
||||
}
|
||||
}
|
@ -1,141 +0,0 @@
|
||||
import Event from "../Event"
|
||||
import EventHandler from "../EventHandler"
|
||||
import Method from "../Method"
|
||||
import Parameter from "../Parameter"
|
||||
import TemplateBase from "./TemplateBase"
|
||||
|
||||
export default class Access extends TemplateBase {
|
||||
|
||||
public templateName: string = "Access"
|
||||
public id: string = "0x044852b2a670ade5407e78fb2863c51de9fcb96542a07186fe3aeda6bb8a116d"
|
||||
public Methods: Method[] = [
|
||||
{
|
||||
name: "lockPayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "lockPayment",
|
||||
timeout: 0,
|
||||
parameters: [
|
||||
{
|
||||
name: "assetId",
|
||||
type: "bytes32",
|
||||
} as Parameter, {
|
||||
name: "price",
|
||||
type: "uint256",
|
||||
} as Parameter,
|
||||
],
|
||||
events: [
|
||||
{
|
||||
name: "PaymentLocked",
|
||||
actorType: "publisher",
|
||||
handler: {
|
||||
moduleName: "accessControl",
|
||||
functionName: "grantAccess",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
],
|
||||
dependencies: [],
|
||||
dependencyTimeoutFlags: [],
|
||||
isTerminalCondition: false,
|
||||
} as Method, {
|
||||
name: "grantAccess",
|
||||
contractName: "AccessConditions",
|
||||
methodName: "grantAccess",
|
||||
timeout: 0,
|
||||
parameters: [
|
||||
{
|
||||
name: "documentKeyId",
|
||||
type: "bytes32",
|
||||
} as Parameter,
|
||||
],
|
||||
events: [
|
||||
{
|
||||
name: "AccessGranted",
|
||||
actorType: "publisher",
|
||||
handler: {
|
||||
moduleName: "payment",
|
||||
functionName: "releasePayment",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
{
|
||||
name: "AccessGranted",
|
||||
actorType: "consumer",
|
||||
handler: {
|
||||
moduleName: "accessControl",
|
||||
functionName: "consumeAsset",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
{
|
||||
name: "AccessTimeout",
|
||||
actorType: "consumer",
|
||||
handler: {
|
||||
moduleName: "payment",
|
||||
functionName: "refundPayment",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
],
|
||||
dependencies: ["lockPayment"],
|
||||
dependencyTimeoutFlags: [0],
|
||||
isTerminalCondition: false,
|
||||
} as Method, {
|
||||
name: "releasePayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "releasePayment",
|
||||
timeout: 0,
|
||||
parameters: [
|
||||
{
|
||||
name: "assetId",
|
||||
type: "bytes32",
|
||||
} as Parameter, {
|
||||
name: "price",
|
||||
type: "uint256",
|
||||
} as Parameter,
|
||||
],
|
||||
events: [
|
||||
{
|
||||
name: "PaymentReleased",
|
||||
actorType: "consumer",
|
||||
handler: {
|
||||
moduleName: "serviceAgreement",
|
||||
functionName: "fulfillAgreement",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
],
|
||||
dependencies: ["grantAccess"],
|
||||
dependencyTimeoutFlags: [0],
|
||||
isTerminalCondition: true,
|
||||
} as Method, {
|
||||
name: "refundPayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "refundPayment",
|
||||
timeout: 10 * 60,
|
||||
parameters: [
|
||||
{
|
||||
name: "assetId",
|
||||
type: "bytes32",
|
||||
} as Parameter, {
|
||||
name: "price",
|
||||
type: "uint256",
|
||||
} as Parameter,
|
||||
],
|
||||
events: [
|
||||
{
|
||||
name: "PaymentRefund",
|
||||
actorType: "publisher",
|
||||
handler: {
|
||||
moduleName: "serviceAgreement",
|
||||
functionName: "terminateAgreement",
|
||||
version: "0.1",
|
||||
} as EventHandler,
|
||||
} as Event,
|
||||
],
|
||||
dependencies: ["lockPayment", "grantAccess"],
|
||||
dependencyTimeoutFlags: [0, 1],
|
||||
isTerminalCondition: true,
|
||||
} as Method,
|
||||
]
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
import Method from "../Method"
|
||||
import TemplateBase from "./TemplateBase"
|
||||
|
||||
export default class FitchainCompute extends TemplateBase {
|
||||
|
||||
public templateName: string = "FitchainCompute"
|
||||
public id: string = "0xc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc6"
|
||||
public Methods: Method[] = [
|
||||
{
|
||||
name: "lockPayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "lockPayment",
|
||||
timeout: 0,
|
||||
dependencies: [],
|
||||
dependencyTimeoutFlags: [],
|
||||
isTerminalCondition: false,
|
||||
} as Method,
|
||||
{
|
||||
name: "grantAccess",
|
||||
contractName: "AccessConditions",
|
||||
methodName: "grantAccess",
|
||||
timeout: 10,
|
||||
dependencies: ["lockPayment"],
|
||||
dependencyTimeoutFlags: [0],
|
||||
isTerminalCondition: false,
|
||||
} as Method,
|
||||
{
|
||||
name: "releasePayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "releasePayment",
|
||||
timeout: 10,
|
||||
dependencies: ["grantAccess"],
|
||||
dependencyTimeoutFlags: [0],
|
||||
isTerminalCondition: true,
|
||||
} as Method,
|
||||
{
|
||||
name: "refundPayment",
|
||||
contractName: "PaymentConditions",
|
||||
methodName: "refundPayment",
|
||||
timeout: 10,
|
||||
dependencies: ["lockPayment", "grantAccess"],
|
||||
dependencyTimeoutFlags: [0, 1],
|
||||
isTerminalCondition: true,
|
||||
} as Method,
|
||||
]
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
import Method from "../Method"
|
||||
|
||||
export default abstract class TemplateBase {
|
||||
public Methods: Method[]
|
||||
public templateName: string
|
||||
public fulfillmentOperator: number = 1
|
||||
public id: string = "0x00000000000000000000000000000000000000000000000000000000000000"
|
||||
}
|
Loading…
Reference in New Issue
Block a user