317 lines
9.7 KiB
TypeScript
317 lines
9.7 KiB
TypeScript
import {
|
|
TemplateStoreManager,
|
|
AgreementStoreManager,
|
|
ConditionStoreManager
|
|
} from '../managers'
|
|
import DIDRegistry from '../DIDRegistry'
|
|
import { LockRewardCondition } from '../conditions/LockRewardCondition'
|
|
import { AccessSecretStoreCondition } from '../conditions/AccessSecretStoreCondition'
|
|
import { EscrowReward } from '../conditions/EscrowReward'
|
|
import { DDO } from '../../../ddo/DDO'
|
|
import { generateId, LoggerInstance, Logger, zeroX } from '../../../utils'
|
|
|
|
import {
|
|
ComputeExecutionCondition,
|
|
Condition,
|
|
ConditionState,
|
|
conditionStateNames
|
|
} from '../conditions'
|
|
import { ServiceType } from '../../../ddo/Service'
|
|
|
|
export interface Conditions {
|
|
lockRewardCondition: LockRewardCondition
|
|
accessSecretStoreCondition?: AccessSecretStoreCondition
|
|
computeExecutionCondition?: ComputeExecutionCondition
|
|
escrowReward: EscrowReward
|
|
}
|
|
|
|
export interface AgreementConditionsStatus {
|
|
[condition: string]: {
|
|
condition: string
|
|
contractName: string
|
|
state: ConditionState
|
|
blocked: boolean
|
|
blockedBy: string[]
|
|
}
|
|
}
|
|
|
|
export class AgreementTemplateBase {
|
|
public templateName: string
|
|
|
|
public templateManager: TemplateStoreManager
|
|
|
|
public agreementStoreManager: AgreementStoreManager
|
|
|
|
public didRegistry: DIDRegistry
|
|
|
|
public conditions: Conditions
|
|
|
|
private logger: Logger
|
|
|
|
public constructor(
|
|
templateManager: TemplateStoreManager,
|
|
agreementStoreManager: AgreementStoreManager,
|
|
didRegistry: DIDRegistry,
|
|
conditions: Conditions
|
|
) {
|
|
this.templateManager = templateManager
|
|
this.agreementStoreManager = agreementStoreManager
|
|
this.didRegistry = didRegistry
|
|
this.conditions = conditions
|
|
|
|
this.logger = LoggerInstance
|
|
this.templateName = 'invalid'
|
|
}
|
|
|
|
public async createAgreementFromDDO(
|
|
agreementId: string,
|
|
ddo: DDO,
|
|
serviceType: ServiceType,
|
|
consumer: string,
|
|
provider: string,
|
|
from?: string
|
|
) {
|
|
return !!(await this.createFullAgreement(
|
|
ddo.shortId(),
|
|
ddo.findServiceByType(serviceType).attributes.main.price,
|
|
consumer,
|
|
provider,
|
|
from,
|
|
agreementId
|
|
))
|
|
}
|
|
|
|
public async getConditionIdsFromDDO(
|
|
agreementId: string,
|
|
ddo: DDO,
|
|
consumer: string,
|
|
from?: string
|
|
) {
|
|
return this.createFullAgreementData(
|
|
agreementId,
|
|
ddo.shortId(),
|
|
ddo.findServiceByType('metadata').attributes.main.price,
|
|
consumer
|
|
)
|
|
}
|
|
|
|
public getName() {
|
|
return this.templateName
|
|
}
|
|
|
|
public getId() {
|
|
return this.templateManager.generateId(this.getName())
|
|
}
|
|
|
|
/**
|
|
* Create a agreement using EscrowAccessSecretStoreTemplate using only the most important information.
|
|
* @param {string} did Asset DID.
|
|
* @param {number} amount Asset price.
|
|
* @param {string} consumer ethereum address of consumer.
|
|
* @param {string} provider ethereum address of service provider (brizo address)
|
|
* @param {string} from Consumer address.
|
|
* @param {string} agreementId bytes32 agreement id.
|
|
*
|
|
* @return {Promise<string>} Agreement ID.
|
|
*/
|
|
public async createFullAgreement(
|
|
did: string,
|
|
amount: number | string,
|
|
consumer: string,
|
|
provider: string,
|
|
from?: string,
|
|
agreementId: string = generateId()
|
|
): Promise<string> {
|
|
const conditionIds = await this.createFullAgreementData(
|
|
agreementId,
|
|
did,
|
|
amount,
|
|
consumer
|
|
)
|
|
|
|
const timeouts = [0, 0, 0]
|
|
const timelocks = [0, 0, 0]
|
|
await this.agreementStoreManager.createAgreement(
|
|
agreementId,
|
|
did,
|
|
this.getId(),
|
|
conditionIds,
|
|
timelocks,
|
|
timeouts,
|
|
[consumer, provider],
|
|
from
|
|
)
|
|
return zeroX(agreementId)
|
|
}
|
|
|
|
protected async createFullAgreementData(
|
|
agreementId: string,
|
|
did: string,
|
|
amount: number | string,
|
|
consumer: string
|
|
): Promise<string[]> {
|
|
return null
|
|
}
|
|
|
|
/**
|
|
* Conditions address list.
|
|
* @return {Promise<string[]>} Conditions address.
|
|
*/
|
|
public async getConditionTypes(): Promise<string[]> {
|
|
return this.templateManager.getConditionTypes(this.getId())
|
|
}
|
|
|
|
/**
|
|
* List of condition contracts.
|
|
* @return {Promise<Condition[]>} Conditions contracts.
|
|
*/
|
|
public async getConditions(): Promise<Condition[]> {
|
|
return this.templateManager.getConditions(await this.getConditionTypes())
|
|
}
|
|
|
|
public async getServiceAgreementTemplate() {
|
|
return null
|
|
}
|
|
|
|
public async getServiceAgreementTemplateConditions() {
|
|
const serviceAgreementTemplate = await this.getServiceAgreementTemplate()
|
|
return serviceAgreementTemplate.conditions
|
|
}
|
|
|
|
public async getServiceAgreementTemplateConditionByRef(ref: string) {
|
|
const name = (await this.getServiceAgreementTemplateConditions()).find(
|
|
({ name: conditionRef }) => conditionRef === ref
|
|
).contractName
|
|
return (await this.getConditions()).find(
|
|
(condition) => condition.contractName === name
|
|
)
|
|
}
|
|
|
|
public async getServiceAgreementTemplateDependencies() {
|
|
const serviceAgreementTemplate = await this.getServiceAgreementTemplate()
|
|
return serviceAgreementTemplate.conditionDependency
|
|
}
|
|
|
|
/**
|
|
* Returns the status of the conditions.
|
|
* @param {string} agreementId Agreement ID.
|
|
* @param {ConditionStoreManager} conditionStoreManager
|
|
* @return {Promise} Conditions status.
|
|
*/
|
|
public async getAgreementStatus(
|
|
agreementId: string,
|
|
conditionStoreManager: ConditionStoreManager
|
|
): Promise<AgreementConditionsStatus | false> {
|
|
const dependencies = await this.getServiceAgreementTemplateDependencies()
|
|
const { conditionIds } = await this.agreementStoreManager.getAgreement(
|
|
agreementId
|
|
)
|
|
if (!conditionIds.length) {
|
|
// this.logger.error(`Agreement not creeated yet: "${agreementId}"`)
|
|
return false
|
|
}
|
|
|
|
const conditionIdByCondition = (await this.getConditions()).reduce(
|
|
(acc, { contractName }, i) => ({
|
|
...acc,
|
|
[contractName]: conditionIds[i]
|
|
}),
|
|
{}
|
|
)
|
|
|
|
const statesPromises = Object.keys(dependencies).map(async (ref, i) => {
|
|
const { contractName } = await this.getServiceAgreementTemplateConditionByRef(
|
|
ref
|
|
)
|
|
return {
|
|
ref,
|
|
contractName,
|
|
state: (
|
|
await conditionStoreManager.getCondition(
|
|
conditionIdByCondition[contractName]
|
|
)
|
|
).state
|
|
}
|
|
})
|
|
const states = await Promise.all(statesPromises)
|
|
|
|
return states.reduce((acc, { contractName, ref, state }) => {
|
|
const blockers = dependencies[ref]
|
|
.map((dependency) => states.find((_) => _.ref === dependency))
|
|
.filter((condition) => condition.state !== ConditionState.Fulfilled)
|
|
return {
|
|
...acc,
|
|
[ref]: {
|
|
condition: ref,
|
|
contractName,
|
|
state,
|
|
blocked: !!blockers.length,
|
|
blockedBy: blockers.map((_) => _.ref)
|
|
}
|
|
}
|
|
}, {})
|
|
}
|
|
|
|
/**
|
|
* Prints the agreement status.
|
|
* @param {string} agreementId Agreement ID.
|
|
* @param {ConditionStoreManager} conditionStoreManager
|
|
*/
|
|
public async printAgreementStatus(
|
|
agreementId: string,
|
|
conditionStoreManager: ConditionStoreManager
|
|
) {
|
|
const status = await this.getAgreementStatus(agreementId, conditionStoreManager)
|
|
|
|
this.logger.bypass('-'.repeat(80))
|
|
this.logger.bypass('Template:', this.templateName)
|
|
this.logger.bypass('Agreement ID:', agreementId)
|
|
this.logger.bypass('-'.repeat(40))
|
|
if (!status) {
|
|
this.logger.bypass('Agreement not created yet!')
|
|
}
|
|
Object.values(status || []).forEach(
|
|
({ condition, contractName, state, blocked, blockedBy }, i) => {
|
|
if (i) {
|
|
this.logger.bypass('-'.repeat(20))
|
|
}
|
|
this.logger.bypass(`${condition} (${contractName})`)
|
|
this.logger.bypass(' Status:', state, `(${conditionStateNames[state]})`)
|
|
if (blocked) {
|
|
this.logger.bypass(' Blocked by:', blockedBy)
|
|
}
|
|
}
|
|
)
|
|
this.logger.bypass('-'.repeat(80))
|
|
}
|
|
|
|
/**
|
|
* Generates and returns the agreement creation event.
|
|
* @param {string} agreementId Agreement ID.
|
|
* @return {Event} Agreement created event.
|
|
*/
|
|
public getAgreementCreatedEvent(agreementId: string) {
|
|
return this.agreementStoreManager.getAgreementCreatedEvent(agreementId)
|
|
}
|
|
|
|
/**
|
|
* Return actor type ids for this template (specified by subclass)
|
|
*
|
|
*/
|
|
public async getActorTypeIds() {
|
|
const { actorTypeIds } = await this.templateManager.getTemplate(this.getId())
|
|
return actorTypeIds
|
|
}
|
|
|
|
/**
|
|
* Return actor types (strings) for this template (specified by subclass)
|
|
*
|
|
*/
|
|
public async getActorTypes() {
|
|
const actorTypeIds = await this.getActorTypeIds()
|
|
return actorTypeIds.map((typeId) =>
|
|
this.templateManager.getActorTypeValue(typeId)
|
|
)
|
|
}
|
|
}
|