@acurast/cli
Version:
A cli to interact with the Acurast Cloud.
1,293 lines • 50.9 kB
JavaScript
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
import { ApiPromise, WsProvider } from '@polkadot/api';
import '@polkadot/api-augment';
import { AssignmentStrategyVariant, CUSTOM_TYPES, } from './types.js';
import { firstValueFrom, ReplaySubject } from 'rxjs';
import { BigNumber } from 'bignumber.js';
import { RPC } from '../../config.js';
export const ACURAST_DECIMALS = 12;
const getHumanReadableError = (api, dispatchError) => {
if (!dispatchError) {
return;
}
if (dispatchError.isModule) {
// for module errors, we have the section indexed, lookup
const decoded = api.registry.findMetaError(dispatchError.asModule);
const { docs, name, section } = decoded;
const message = `${section}.${name}: ${docs.join(' ')}`;
console.log('DispatchError:', message);
console.log('DispatchError:', dispatchError.toString());
return message;
}
else {
// Other, CannotLookup, BadOrigin, no extra info
console.log('DispatchError:', dispatchError.toString());
return dispatchError.toString();
}
};
// const MAX_PROCESSOR_UPDATES = 100
export class AcurastService {
constructor() {
this.wsProvider$ = new ReplaySubject(1);
this.eventSubs = new Map();
this.wsProvider$.next(new WsProvider(RPC));
// private readonly accounts: AccountService // private readonly network: NetworkService, // private readonly http: HttpClient,
// network.currentNetwork$.subscribe((network) => {
// this.wsProvider$.next(new WsProvider(network.acurast.wsUrl))
// this.api = undefined
// this.connectPromise = undefined
// })
}
connect() {
return __awaiter(this, void 0, void 0, function* () {
if (this.api !== undefined) {
return this.api;
}
if (this.connectPromise !== undefined) {
return yield this.connectPromise;
}
const provider = yield firstValueFrom(this.wsProvider$);
this.connectPromise = ApiPromise.create({
provider,
noInitWarn: true,
types: Object.assign({}, CUSTOM_TYPES),
rpc: {
marketplace: {
filterMatchingSources: {
description: 'Filters possible matches',
params: [
{
name: 'registration',
type: 'PalletAcurastMarketplacePartialJobRegistration',
},
{
name: 'sources',
type: 'Vec<AccountId>',
},
{
name: 'consumer',
type: 'Option<AcurastCommonMultiOrigin<AccountId>>',
},
{
name: 'latest_seen_after',
type: 'Option<u128>',
},
],
type: 'Option<Vec<AccountId>>',
},
},
},
});
this.api = yield this.connectPromise;
this.connectPromise = undefined;
return this.api;
});
}
disconnect() {
return __awaiter(this, void 0, void 0, function* () {
if (this.api) {
yield this.api.disconnect();
this.api = undefined;
}
});
}
// public async accountInfo(account: string): Promise<AccountInfo> {
// const api = await this.connect()
// const info = await api.query.system.account(account)
// return {
// balance: info.data.free,
// nonce: info.nonce,
// }
// }
// public async subscribeAccountInfo(
// account: string,
// sub: (info: AccountInfo) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return api.query.system.account(account, (info) => {
// sub({ balance: info.data.free, nonce: info.nonce })
// })
// }
// public async managerCounter(account: string): Promise<u64> {
// const api = await this.connect()
// const counter = api.createType(
// 'Option<u64>',
// await api.query['acurastProcessorManager']['managerCounter'](account)
// )
// return counter.unwrapOr(api.createType('u64', 0))
// }
// public async onboardingMessage(account: string): Promise<OnboardingMessage> {
// const api = await this.connect()
// const counter = api.createType(
// 'u64',
// (await this.managerCounter(account)).addn(1)
// )
// const counterBytes = counter.toU8a()
// const managerAccount = api.createType('AccountId', account)
// const managerAccountBytes = managerAccount.toU8a()
// const now = Date.now()
// const timestamp = api.createType('u128', now)
// const timestampBytes = timestamp.toU8a()
// const message = new Uint8Array(
// managerAccountBytes.length + timestampBytes.length + counterBytes.length
// )
// message.set(managerAccountBytes)
// message.set(timestampBytes, managerAccount.length)
// message.set(
// counterBytes,
// managerAccountBytes.length + timestampBytes.length
// )
// return {
// message: u8aToHex(message),
// timestamp: {
// scaleEncoded: timestamp.toString(),
// value: now,
// },
// }
// }
// public async onboardingQr(
// account: GetAccount<'substrate'>,
// signature: string,
// timestamp: string,
// apkUrl: string | undefined,
// wifi: { ssid?: string; password?: string; type: string } | undefined
// ): Promise<OnboardingQr> {
// const network = await firstValueFrom(this.network.currentNetwork$)
// const qr: OnboardingQr = {
// 'android.app.extra.PROVISIONING_DEVICE_ADMIN_COMPONENT_NAME':
// network.acurast.deviceAdminComponentName,
// 'android.app.extra.PROVISIONING_DEVICE_ADMIN_PACKAGE_DOWNLOAD_LOCATION':
// apkUrl ?? network.acurast.apkUrl,
// 'android.app.extra.PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM':
// network.acurast.apkChecksum,
// 'android.app.extra.PROVISIONING_ADMIN_EXTRAS_BUNDLE': {
// account: account.address(),
// accountType: account.signatureType,
// timestamp,
// signature,
// },
// }
// if (wifi && wifi.ssid && wifi.password) {
// qr['android.app.extra.PROVISIONING_WIFI_SSID'] = `"${wifi.ssid}"`
// qr['android.app.extra.PROVISIONING_WIFI_PASSWORD'] = wifi.password
// qr['android.app.extra.PROVISIONING_WIFI_SECURITY_TYPE'] =
// wifi.type ?? 'WPA'
// }
// return qr
// }
// public async managerIds(account: string): Promise<u128[] | undefined> {
// const api = await this.connect()
// const tokens = await api.query.uniques.account.entries(account, 0)
// if (tokens.length > 0) {
// return tokens.map((value) => api.createType('u128', value[0].args[2]))
// }
// return undefined
// }
// public async transferProcessorOwnership(
// origin: string,
// newOwnerAccount: string
// ): Promise<Hash> {
// const api = await this.connect()
// const managerIds = await this.managerIds(origin)
// if (managerIds === undefined) {
// throw Error('Cannot find manager id')
// }
// const calls = managerIds.map((managerId) =>
// api.tx.uniques.transfer(
// api.createType('u128', 0),
// managerId,
// api.createType('MultiAddress', newOwnerAccount)
// )
// )
// return this.signAndSend(api, origin, calls)
// }
// public async managedProcessors(account: string): Promise<string[]> {
// const api = await this.connect()
// const managerIds = await this.managerIds(account)
// const processors =
// await api.query['acurastProcessorManager']['managedProcessors'].entries(
// managerIds
// )
// return processors.map(([key, _]) => key.args.at(1)!.toString())
// }
// public async getAllManagers(): Promise<
// { address: string; managerId: number }[]
// > {
// const api = await this.connect()
// const tokens = await api.query.uniques.account.entries()
// console.log(tokens.length)
// return tokens.map(([key, _]) => {
// return {
// address: key.args[0].toString(),
// managerId: key.args[2].toNumber(),
// }
// })
// }
// public async getAllManagerIds(): Promise<
// { accountId: string; managerId: number }[]
// > {
// const api = await this.connect()
// const managerIdIndexEntries =
// await api.query['acurastProcessorManager'][
// 'processorToManagerIdIndex'
// ].entries()
// console.log(managerIdIndexEntries.length)
// return managerIdIndexEntries.map(([key, value]) => {
// return {
// accountId: key.args.at(0)!.toString(),
// managerId: value.toJSON() as number,
// }
// })
// }
// public async getAllProcessors(): Promise<
// { managerId: string; address: string }[]
// > {
// const api = await this.connect()
// const processors =
// await api.query['acurastProcessorManager']['managedProcessors'].entries()
// return processors.map(([key, _]) => ({
// managerId: key.args.at(0)!.toString(),
// address: key.args.at(1)!.toString(),
// }))
// }
// public async getAllHeartbeats(): Promise<
// { address: string; lastSeen: number }[]
// > {
// const api = await this.connect()
// const heartbeats =
// await api.query['acurastProcessorManager']['processorHeartbeat'].entries()
// return heartbeats.map(([key, value]) => {
// const lastSeen = api.createType('Option<u128>', value).unwrap().toNumber()
// return {
// address: key.args.at(0)!.toString(),
// lastSeen: lastSeen,
// }
// })
// }
// public async getAllUpdateInfos(): Promise<
// {
// accountId: string
// updateInfo: { binaryLocation: string; version: Version }
// }[]
// > {
// const api = await this.connect()
// const updateInfoEntries =
// await api.query['acurastProcessorManager'][
// 'processorUpdateInfo'
// ].entries()
// return updateInfoEntries.map(([key, value]) => {
// const updateInfo = api
// .createType('Option<PalletAcurastProcessorManagerUpdateInfo>', value)
// .unwrap()
// return {
// accountId: key.args.at(0)!.toString(),
// updateInfo: codecToUpdateInfo(updateInfo),
// }
// })
// }
// public async getAllVersions(): Promise<
// { accountId: string; version: Version }[]
// > {
// const api = await this.connect()
// const versionEntries =
// await api.query['acurastProcessorManager']['processorVersion'].entries()
// return versionEntries.map(([key, value]) => {
// const version = api
// .createType('Option<PalletAcurastProcessorManagerVersion>', value)
// .unwrap()
// return {
// accountId: key.args.at(0)!.toString(),
// version: codecToVersion(version),
// }
// })
// }
// public async storedReputation(
// processors: string[]
// ): Promise<ReputationInfo[]> {
// const api = await this.connect()
// const reputations =
// await api.query['acurastMarketplace']['storedReputation'].multi(
// processors
// )
// return processReputations(reputations, processors, api)
// }
// public async subscribeStoredReputation(
// processors: string[],
// sub: (reputation: ReputationInfo[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurastMarketplace']['storedReputation'].multi(
// processors,
// (reputations) => {
// sub(processReputations(reputations, processors, api))
// }
// )
// }
// public async storedAdvertisementPricing(
// processor: string
// ): Promise<AdvertisementPricing> {
// const api = await this.connect()
// const pricing = api
// .createType(
// 'Option<PalletAcurastMarketplacePricing>',
// await api.query['acurastMarketplace']['storedAdvertisementPricing'](
// processor
// )
// )
// .unwrap()
// return codecToAdvertisementPricing(pricing)
// }
// public async executionEnvironment(
// jobId: JobId,
// processor: string
// ): Promise<AcurastEnvironment> {
// const api = await this.connect()
// const environment = api
// .createType(
// 'Option<AcurastCommonEnvironment>',
// await api.query['acurast']['executionEnvironment'](jobId, processor)
// )
// .unwrap()
// return codecToAcurastEnvironment(environment)
// }
// public async executionEnvironments(
// jobId: JobId
// ): Promise<AcurastEnvironments> {
// const api = await this.connect()
// const environments =
// await api.query['acurast']['executionEnvironment'].entries(jobId)
// return environments.map(([key, value]) => {
// return {
// processor: key.args.at(1)!.toString(),
// environment: codecToAcurastEnvironment(
// api.createType('Option<AcurastCommonEnvironment>', value).unwrap()
// ),
// }
// })
// }
// public async storedAdvertisementRestriction(
// processor: string
// ): Promise<AdvertisementRestriction> {
// const api = await this.connect()
// const restriction = api
// .createType(
// 'Option<PalletAcurastMarketplaceAdvertisementRestriction>',
// await api.query['acurastMarketplace']['storedAdvertisementRestriction'](
// processor
// )
// )
// .unwrap()
// return codecToAdvertisementRestriction(restriction)
// }
// public async heartbeat(processors: string[]): Promise<HeartbeatInfo[]> {
// const api = await this.connect()
// const heartbeats =
// await api.query['acurastProcessorManager']['processorHeartbeat'].multi(
// processors
// )
// return processHeartbeats(heartbeats, processors, api)
// }
// public async subscribeHeartbeat(
// processors: string[],
// sub: (info: HeartbeatInfo[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurastProcessorManager'][
// 'processorHeartbeat'
// ].multi(processors, (heartbeats) => {
// sub(processHeartbeats(heartbeats, processors, api))
// })
// }
// public async subscribeVersion(
// processors: string[],
// sub: (info: VersionInfo[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurastProcessorManager']['processorVersion'].multi(
// processors,
// (versions) => {
// sub(processVersions(versions, processors, api))
// }
// )
// }
// public async rewardCutPercentage(version: number = 0): Promise<number> {
// const api = await this.connect()
// const percentage =
// await api.query['acurastFeeManager']['feePercentage'](version)
// const value = percentage.toString()
// return Number(value)
// }
// public async fundAccount(
// account: string,
// amount: number = 1000000000000000
// ): Promise<Hash> {
// const api = await this.connect()
// return this.signAndSend(api, this.faucetAccount, [
// api.tx.balances.transfer(account, amount),
// ])
// }
// public async keyAttestationStatus(
// processors: string[]
// ): Promise<KeyAttestationStatus[]> {
// const api = await this.connect()
// const attestations =
// await api.query['acurast']['storedAttestation'].multi(processors)
// return processKeyAttestations(attestations, processors, api)
// }
// public async subscribeKeyAttestationStatus(
// processors: string[],
// sub: (attestations: KeyAttestationStatus[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurast']['storedAttestation'].multi(
// processors,
// (attestations) => {
// sub(processKeyAttestations(attestations, processors, api))
// }
// )
// }
// public async registeredJobs(multiOrigin: MultiOrigin): Promise<Job[]> {
// const api = await this.connect()
// const jobEntries =
// await api.query['acurast']['storedJobRegistration'].entries(multiOrigin)
// return jobEntries.map(([key, value]) => {
// const id = api.createType('u128', key.args.at(1)!)
// const job = api
// .createType('Option<AcurastCommonJobRegistration>', value)
// .unwrap()
// return {
// id: [multiOrigin, id.toNumber()],
// registration: this.codecToJobRegistration(job),
// }
// })
// }
getAllJobs() {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
const jobEntries = yield api.query['acurast']['storedJobRegistration'].entries();
return jobEntries.map(([key, value]) => {
const origin = api.createType('AcurastCommonMultiOrigin', key.args.at(0));
const id = api.createType('u128', key.args.at(1));
const job = api
.createType('Option<AcurastCommonJobRegistration>', value)
.unwrap();
return {
id: [this.codecToMultiOrigin(origin), id.toNumber()],
registration: this.codecToJobRegistration(job),
};
});
});
}
// public async registeredJob(jobId: JobId): Promise<JobRegistration> {
// const api = await this.connect()
// const jobRegistrationCodec = (
// (await api.query['acurast']['storedJobRegistration'](
// api.createType('AcurastCommonMultiOrigin', jobId[0]),
// jobId[1]
// )) as any
// ).unwrapOr(undefined)
// if (jobRegistrationCodec === undefined) {
// throw Error('Cannot fetch job')
// }
// return this.codecToJobRegistration(jobRegistrationCodec)
// }
// public async subscribeToRegisteredJobs(
// multiOrigin: MultiOrigin,
// sub: (job: Job[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return (await api.query['acurast']['storedJobRegistration'].entries(
// multiOrigin,
// (jobEntries: [StorageKey<AnyTuple>, Codec][]) => {
// const jobs = jobEntries.map(([key, value]) => {
// const id = api.createType('u128', key.args.at(1)!)
// const job = api
// .createType('Option<AcurastCommonJobRegistration>', value)
// .unwrap()
// return {
// id: [multiOrigin, id.toNumber()],
// registration: this.codecToJobRegistration(job),
// }
// })
// sub(jobs as Job[])
// }
// )) as any as UnsubscribePromise
// }
subscribeToEvent(eventSub) {
return __awaiter(this, void 0, void 0, function* () {
const subId = Math.random().toString();
this.eventSubs.set(subId, eventSub);
if (this.unsubEvents === undefined) {
const api = yield this.connect();
this.unsubEvents = yield api.query.system.events((events) => {
const subs = Array.from(this.eventSubs.values());
events.forEach((record) => {
const { event } = record;
for (const sub of subs) {
if (sub.filter(event)) {
sub.sub(sub.map(event));
}
}
});
});
}
return () => {
this.eventSubs.delete(subId);
if (this.eventSubs.size === 0 && this.unsubEvents !== undefined) {
this.unsubEvents();
this.unsubEvents = undefined;
}
};
});
}
// public async subscribeToJobRegistrationStored(
// sub: (jobRegistrationStored: [JobRegistration, JobId]) => void
// ): Promise<UnsubEvent> {
// const eventSub: EventSub<[JobRegistration, JobId]> = {
// filter: (event) =>
// event.section === 'acurast' && event.method === 'JobRegistrationStored',
// map: (event) => {
// const jobRegistration = this.codecToJobRegistration(event.data.at(0)!)
// const jobIdJSON = event.data.at(1)!.toJSON() as any
// const jobId: JobId = [
// jobIdJSON[0].acurast
// ? {
// Acurast: jobIdJSON[0].acurast,
// }
// : {
// Tezos: jobIdJSON[0].tezos,
// },
// jobIdJSON[1],
// ]
// return [jobRegistration, jobId] as [JobRegistration, JobId]
// },
// sub,
// }
// return await this.subscribeToEvent(eventSub)
// }
subscribeToJobAssignmentEvents(sub) {
return __awaiter(this, void 0, void 0, function* () {
const eventSub = {
filter: (event) => event.section === 'acurastMarketplace' &&
event.method === 'JobRegistrationAssigned',
map: (event) => ({
id: this.codectToJobId(event.data.at(0)),
processor: event.data.at(1).toString(),
assignment: this.codecToJobAssignment(event.data.at(2)),
}),
sub,
};
return yield this.subscribeToEvent(eventSub);
});
}
// public async subscribeToReportedEvents(
// sub: (assignment: JobAssignmentInfo) => void
// ): Promise<UnsubEvent> {
// const eventSub: EventSub<JobAssignmentInfo> = {
// filter: (event) =>
// event.section === 'acurastMarketplace' && event.method === 'Reported',
// map: (event) => ({
// id: this.codectToJobId(event.data.at(0)!),
// processor: event.data.at(1)!.toString(),
// assignment: this.codecToJobAssignment(event.data.at(2)!),
// }),
// sub,
// }
// return await this.subscribeToEvent(eventSub)
// }
// public async waitForNextBlocks(
// n: number,
// callback: () => void
// ): Promise<void> {
// const api = await this.connect()
// let blockToWaitFor = n
// const unsubscribe = await api.rpc.chain.subscribeFinalizedHeads(
// (_header) => {
// --blockToWaitFor
// if (blockToWaitFor <= 0) {
// unsubscribe()
// callback()
// }
// }
// )
// }
// public async subscribeJobStatus(
// jobIds: JobId[],
// sub: (jobStatuses: JobStatusDetails[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurastMarketplace']['storedJobStatus'].multi(
// jobIds,
// (statuses) => {
// const stat = api.registry.createType(
// 'Vec<Option<PalletAcurastMarketplaceJobStatus>>',
// statuses
// )
// const result = stat
// .map((value, index) => {
// if (value.isSome) {
// const statusValue = value.unwrap() as any
// let status: JobStatus = 'Open'
// if (statusValue.isMatched) {
// status = 'Matched'
// } else if (statusValue.isAssigned) {
// status = { assigned: statusValue.asAssigned.toNumber() }
// }
// return {
// id: jobIds[index],
// status,
// }
// }
// return undefined
// })
// .filter((value) => value !== undefined)
// sub(result as JobStatusDetails[])
// }
// )
// }
assignedProcessors(jobIds) {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
const result = new Map();
const assignedProcessors = (yield Promise.all(jobIds.map((jobId) => api.query['acurastMarketplace']['assignedProcessors'].entries(jobId)))).flat();
assignedProcessors.forEach(([key, _]) => {
var _a, _b;
const jobIdJSON = key.args[0].toJSON();
const jobId = [
jobIdJSON[0].acurast
? {
acurast: jobIdJSON[0].acurast,
}
: {
tezos: jobIdJSON[0].tezos,
},
jobIdJSON[1],
];
const processor = api.createType('AccountId', key.args[1]);
const mapKey = this.jobIdToString(jobId);
const processors = (_b = (_a = result.get(mapKey)) === null || _a === void 0 ? void 0 : _a[1]) !== null && _b !== void 0 ? _b : [];
processors.push(processor.toString());
result.set(mapKey, [jobId, processors]);
});
return result;
});
}
jobIdToString(jobId) {
if (jobId[0].acurast) {
return `Acurast#${jobId[1]}`;
}
return `Tezos#${jobId[1]}`;
}
// public async subscribeJobAssignment(
// keys: [string, JobId][],
// sub: (assignments: JobAssignmentInfo[]) => void
// ): UnsubscribePromise {
// const api = await this.connect()
// return await api.query['acurastMarketplace']['storedMatches'].multi(
// keys,
// (assignments) => {
// const values = api.registry.createType(
// 'Vec<Option<PalletAcurastMarketplaceAssignment>>',
// assignments
// )
// const result: (JobAssignmentInfo | undefined)[] = values
// .map((value, index) => {
// if (value.isSome) {
// const assignment = value.unwrap()
// return {
// id: keys[index][1],
// processor: keys[index][0],
// assignment: this.codecToJobAssignment(assignment),
// }
// }
// return undefined
// })
// .filter((value) => value !== undefined)
// sub(result as JobAssignmentInfo[])
// }
// )
// }
jobAssignments(keys) {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
const assignments = yield api.query['acurastMarketplace']['storedMatches'].multi(keys);
const values = api.registry.createType('Vec<Option<PalletAcurastMarketplaceAssignment>>', assignments);
const result = values
.map((value, index) => {
if (value.isSome) {
const assignment = value.unwrap();
return {
id: keys[index][1],
processor: keys[index][0],
assignment: this.codecToJobAssignment(assignment),
};
}
return undefined;
})
.filter((value) => value !== undefined);
return result;
});
}
// public async subscribeToProcessorJobs(
// processors: string[] = []
// ): Promise<ProcessorJobInfo[]> {
// // TODO: Make reactive
// const api = await this.connect()
// return await Promise.all(
// processors.map(async (processor) => ({
// processor,
// jobs: await api.query['acurastMarketplace']['storedMatches']
// .entries(processor)
// .then((el) => {
// return el.map(([encodedKey, encodedValue]) => {
// const key: [string, JobId] = encodedKey.toHuman() as any
// const decodedValue = api.registry.createType(
// 'Option<PalletAcurastMarketplaceAssignment>',
// encodedValue
// )
// const value = this.codecToJobAssignment(decodedValue.unwrap())
// return { jobId: key[1], assignment: value }
// })
// }),
// }))
// )
// }
jobEnvironmentToCodec(api, jobEnvironment) {
const publicKey = `0x${jobEnvironment.publicKey}`;
const variables = jobEnvironment.variables.map((variable) => {
const key = `0x${Buffer.from(variable.key).toString('hex')}`;
const value = `0x${variable.encryptedValue.iv}${variable.encryptedValue.ciphertext}${variable.encryptedValue.authTag}`;
return [key, value];
});
return api.createType('AcurastCommonEnvironment', {
publicKey: api.createType('Bytes', publicKey),
variables: api.createType('Vec<(Bytes, Bytes)>', variables),
});
}
setEnvironment(keyring, jobId, jobEnvironment) {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
const acurastJobEnvironment = this.jobEnvironmentToCodec(api, jobEnvironment);
return this.signAndSend(api, keyring, [
api.tx['acurast']['setEnvironment'](jobId, keyring.address, acurastJobEnvironment),
]);
});
}
setEnvironments(keyring, jobId, jobEnvironments) {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
const acurastJobEnvironments = jobEnvironments.map((x) => [
x.processor,
this.jobEnvironmentToCodec(api, x.jobEnvironment),
]);
return this.signAndSend(api, keyring, [
api.tx['acurast']['setEnvironments'](jobId, acurastJobEnvironments),
]);
});
}
// public async getLatestProcessorVersion(): Promise<Version | undefined> {
// const api = await this.connect()
// const response =
// await api.query['acurastProcessorManager']['knownBinaryHash'].entries()
// if (response.length === 0) {
// throw new Error('No versions available')
// }
// let selectedVersion: Version | undefined
// response.forEach((element) => {
// const codec = element[0].args.at(0)
// if (!codec) {
// throw new Error('Invalid version encoding')
// }
// const versionInfo = codecToVersion(codec)
// const platformVersions = deviceVersions.get(versionInfo.platform)
// const version = platformVersions?.get(versionInfo.buildNumber)
// if (
// version &&
// (!selectedVersion ||
// selectedVersion.buildNumber < versionInfo.buildNumber)
// ) {
// selectedVersion = versionInfo
// } else {
// console.warn('Ignoring version ', versionInfo)
// }
// })
// return selectedVersion
// }
// public async updateProcessors(
// origin: string,
// processors: string[],
// version: Version
// ): Promise<Hash> {
// const api = await this.connect()
// const network = await firstValueFrom(this.network.currentNetwork$)
// const chunks: string[][] = []
// for (let i = 0; i < processors.length; i += MAX_PROCESSOR_UPDATES) {
// const chunk = processors.slice(i, i + MAX_PROCESSOR_UPDATES)
// chunks.push(chunk)
// }
// const calls = chunks.map((processors) => {
// return api.tx['acurastProcessorManager']['setProcessorUpdateInfo'](
// {
// version,
// binaryLocation: network.acurast.apkUrl,
// },
// processors
// )
// })
// return this.signAndSend(api, origin, calls)
// }
// public async removePairedProcessor(
// origin: string,
// processor: string
// ): Promise<Hash> {
// const api = await this.connect()
// return this.signAndSend(api, origin, [
// api.tx['acurastProcessorManager']['updateProcessorPairings']([
// {
// operation: api.createType(
// 'AcurastCommonListUpdateOperation',
// 'Remove'
// ),
// item: api.createType('AccountId', processor),
// proof: api.createType(
// 'Option<PalletAcurastProcessorManagerProof>',
// undefined
// ),
// },
// ]),
// ])
// }
// public async registerJob(
// origin: string,
// job: JobRegistration
// ): Promise<Hash> {
// const api = await this.connect()
// const jobRegistration = this.jobRegistrationToCodec(api, job)
// return this.signAndSend(api, origin, [
// api.tx['acurast']['register'](jobRegistration),
// ])
// }
deregisterJob(keyring, localJobId) {
return __awaiter(this, void 0, void 0, function* () {
const api = yield this.connect();
return this.signAndSend(api, keyring, [
api.tx['acurast']['deregister'](localJobId),
]);
});
}
// public async finalizeJobs(origin: string, jobIds: JobId[]): Promise<Hash> {
// const api = await this.connect()
// return this.signAndSend(api, origin, [
// api.tx['acurastMarketplace']['finalizeJobs'](
// jobIds.filter((id) => id[0].acurast !== undefined).map((id) => id[1])
// ),
// ])
// }
// public async advertiseFor(
// origin: string,
// processor: string,
// advertisement: Advertisement
// ): Promise<Hash> {
// const api = await this.connect()
// const advertisementCodec = this.advertisementToCodec(api, advertisement)
// return this.signAndSend(api, origin, [
// api.tx['acurastProcessorManager']['advertiseFor'](
// processor,
// advertisementCodec
// ),
// ])
// }
// public async filterMatchingSources(
// job: PartialJobRegistration,
// processors: string[],
// consumer?: string,
// latestSeenAfter?: Date
// ): Promise<string[]> {
// const network = await firstValueFrom(this.network.currentNetwork$)
// const response: any = await firstValueFrom(
// this.http.post(network.acurast.httpUrl, {
// id: 1,
// jsonrpc: '2.0',
// method: 'filterMatchingSources',
// params: [
// this.partialJobRegistrationToJSON(job),
// processors,
// consumer ?? null,
// latestSeenAfter?.getTime() ?? null,
// ],
// })
// )
// return response.result ?? []
// }
// public async properties(): Promise<{
// symbol: string | undefined
// decimals: number | undefined
// }> {
// const api = await this.connect()
// const result = await api.rpc.system.properties()
// const symbol = result.tokenSymbol.unwrapOrDefault().at(0)?.toString()
// const decimals = result.tokenDecimals.unwrapOrDefault().at(0)?.toNumber()
// return {
// symbol,
// decimals,
// }
// }
codecToMultiOrigin(codec) {
const multiOriginJSON = codec.toJSON();
return multiOriginJSON.acurast
? {
acurast: multiOriginJSON.acurast,
}
: {
tezos: multiOriginJSON.tezos,
};
}
signAndSend(api, keyring, calls) {
return __awaiter(this, void 0, void 0, function* () {
let call;
if (calls.length > 1) {
call = api.tx.utility.batch(calls);
}
else {
call = calls[0];
}
return new Promise((resolve, reject) => __awaiter(this, void 0, void 0, function* () {
const unsub = yield call
.signAndSend(keyring, ({ status, events, dispatchError }) => {
if (dispatchError) {
const humanReadableError = getHumanReadableError(api, dispatchError);
if (unsub) {
unsub();
}
reject(new Error(humanReadableError));
return;
}
if (status.isInBlock) {
if (unsub) {
unsub();
}
resolve(status.hash);
return;
}
})
.catch(reject);
}));
});
}
codectToJobId(codec) {
const jobIdJSON = codec.toJSON();
return [
jobIdJSON[0].acurast
? {
acurast: jobIdJSON[0].acurast,
}
: {
tezos: jobIdJSON[0].tezos,
},
jobIdJSON[1],
];
}
// private advertisementToCodec(
// api: ApiPromise,
// advertisement: Advertisement
// ): Codec {
// return api.createType('PalletAcurastMarketplaceAdvertisement', {
// pricing: {
// feePerMillisecond: api.createType(
// 'u128',
// advertisement.pricing.feePerMillisecond.toFixed()
// ),
// feePerStorageByte: api.createType(
// 'u128',
// advertisement.pricing.feePerStorageByte.toFixed()
// ),
// baseFeePerExecution: api.createType(
// 'u128',
// advertisement.pricing.baseFeePerExecution.toFixed()
// ),
// schedulingWindow: {
// end: api.createType(
// 'u64',
// advertisement.pricing.schedulingWindow.end.getTime()
// ),
// },
// },
// maxMemory: api.createType('u32', advertisement.maxMemory),
// networkRequestQuota: api.createType(
// 'u8',
// advertisement.networkRequestQuota
// ),
// storageCapacity: api.createType('u32', advertisement.storageCapacity),
// allowedConsumers: api.createType(
// 'Option<Vec<AcurastCommonMultiOrigin>>',
// advertisement.allowedConsumers
// ),
// availableModules: api.createType(
// 'Vec<AcurastCommonJobModule>',
// advertisement.availableModules
// ),
// })
// }
// private jobRegistrationToCodec(api: ApiPromise, job: JobRegistration): Codec {
// const script = `0x${Buffer.from(new TextEncoder().encode(job.script)).toString('hex')}`
// return api.createType('AcurastCommonJobRegistration', {
// script: api.createType('Bytes', script),
// allowedSources: job.allowedSources
// ? api.createType('Option<Vec<AccountId>>', job.allowedSources)
// : api.createType('Option<Vec<AccountId>>', undefined),
// allowOnlyVerifiedSources: job.allowOnlyVerifiedSources,
// schedule: {
// duration: api.createType('u64', job.schedule.duration),
// startTime: api.createType('u64', job.schedule.startTime.getTime()),
// endTime: api.createType('u64', job.schedule.endTime.getTime()),
// interval: api.createType('u64', job.schedule.interval.toFixed()),
// maxStartDelay: api.createType('u64', job.schedule.maxStartDelay),
// },
// memory: api.createType('u32', job.memory),
// networkRequests: api.createType('u32', job.networkRequests),
// storage: api.createType('u32', job.storage),
// requiredModules: api.createType(
// 'Vec<AcurastCommonJobModule>',
// job.requiredModules ?? []
// ),
// extra: api.createType('PalletAcurastMarketplaceRegistrationExtra', {
// requirements: api.createType(
// 'PalletAcurastMarketplaceJobRequirements',
// {
// assignmentStrategy:
// job.extra.requirements.assignmentStrategy.variant ==
// AssignmentStrategyVariant.Single
// ? api.createType('PalletAcurastMarketplaceAssignmentStrategy', {
// single: job.extra.requirements.assignmentStrategy
// .instantMatch
// ? api.createType(
// 'Option<Vec<PalletAcurastMarketplacePlannedExecution>>',
// job.extra.requirements.assignmentStrategy.instantMatch.map(
// (item) => ({
// source: api.createType('AccountId', item.source),
// startDelay: api.createType(
// 'u64',
// item.startDelay.toFixed()
// ),
// })
// )
// )
// : api.createType('Option<bool>', undefined),
// })
// : api.createType('PalletAcurastMarketplaceAssignmentStrategy', {
// competing: '',
// }),
// slots: api.createType('u8', job.extra.requirements.slots),
// reward: api.createType(
// 'u128',
// job.extra.requirements.reward.toFixed()
// ),
// minReputation: job.extra.requirements.minReputation
// ? api.createType(
// 'Option<u128>',
// job.extra.requirements.minReputation.toFixed()
// )
// : api.createType('Option<u128>', undefined),
// }
// ),
// }),
// })
// }
codecToJobRegistration(codec) {
var _a, _b;
const data = codec;
return {
script: new TextDecoder().decode(Buffer.from(data.script.toHex().slice(2), 'hex')),
allowedSources: (_a = data.allowedSources.unwrapOr(undefined)) === null || _a === void 0 ? void 0 : _a.toJSON(),
allowOnlyVerifiedSources: data.allowOnlyVerifiedSources.toJSON(),
schedule: {
duration: data.schedule.duration.toNumber(),
startTime: new Date(data.schedule.startTime.toNumber()),
endTime: new Date(data.schedule.endTime.toNumber()),
interval: new BigNumber(data.schedule.interval.toBigInt()),
maxStartDelay: data.schedule.maxStartDelay.toNumber(),
},
memory: data.memory.toNumber(),
networkRequests: data.networkRequests.toNumber(),
storage: data.storage.toNumber(),
requiredModules: (_b = data.requiredModules.toJSON()) !== null && _b !== void 0 ? _b : undefined,
extra: {
requirements: {
assignmentStrategy: this.codecToAssignmentStrategy(data.extra.requirements.assignmentStrategy),
slots: data.extra.requirements.slots.toNumber(),
reward: new BigNumber(data.extra.requirements.reward.toBigInt()),
minReputation: (() => {
var _a;
const rep = (_a = data.extra.requirements.minReputation
.unwrapOr(undefined)) === null || _a === void 0 ? void 0 : _a.toBigInt();
if (rep) {
return new BigNumber(rep);
}
return undefined;
})(),
},
},
};
}
codecToAssignmentStrategy(codec) {
var _a;
const data = codec;
if (data.isSingle) {
return {
variant: AssignmentStrategyVariant.Single,
instantMatch: (_a = data.asSingle.toJSON()) === null || _a === void 0 ? void 0 : _a.map((value) => ({
source: value.source,
startDelay: new BigNumber(value.startDelay),
})),
};
}
else if (data.isCompeting) {
return { variant: AssignmentStrategyVariant.Competing };
}
throw new Error(`unsupported AssignmentStrategy variant: ${codec.toString()}`);
}
codecToJobAssignment(codec) {
const json = codec.toJSON();
return {
slot: json.slot,
startDelay: json.startDelay,
feePerExecution: new BigNumber(json.feePerExecution),
acknowledged: json.acknowledged,
sla: {
total: new BigNumber(json.sla.total),
met: new BigNumber(json.sla.met),
},
pubKeys: json.pubKeys.map((value) => ({
SECP256r1: value.secp256r1,
SECP256k1: value.secp256k1,
ED25519: value.ed25519,
SECP256r1Encryption: value.secp256r1Encryption,
SECP256k1Encryption: value.secp256k1Encryption,
})),
execution: {
All: json.execution.all,
Index: json.execution.index,
},
};
}
}
// const processHeartbeats = (
// heartbeats: Codec[],
// processors: string[],
// api: ApiPromise
// ) =>
// heartbeats.map((value, index) => {
// const heartbeat = api.createType('Option<u128>', value)
// return {
// processor: processors[index],
// lastSeen: heartbeat.isSome
// ? new Date(Number(heartbeat.unwrap().toString()))
// : undefined,
// }
// })
// const processVersions = (
// versions: Codec[],
// processors: string[],
// api: ApiPromise
// ) =>
// versions.map((value, index) => {
// const version = api.createType(
// 'Option<PalletAcurastProcessorManagerVersion>',
// value
// )
// return {
// processor: processors[index],
// version: version.isSome ? codecToVersion(version) : undefined,
// }
// })
// const processKeyAttestations = (
// attestations: Codec[],
// processors: string[],
// api: ApiPromise
// ) =>
// attestations.map((value, index) => ({
// processor: processors[index],
// hasKeyAttestation: api.createType(
// 'Option<AcurastCommonBoundedAttestationAttestation>',
// value
// ).isSome,
// }))
// const codecToUpdateInfo = (
// codec: Codec
// ): { binaryLocation: string; version: Version } => {
// const json = codec.toPrimitive() as any
// return {
// binaryLocation: json.binaryLocation,
// version: {
// platform: json.version.platform,
// buildNumber: json.version.buildNumber,
// },
// }
// }
// const codecToVersion = (codec: Codec): Version => {
// const json = codec.toJSON() as any
// return {
// platform: json.platform,
// buildNumber: json.buildNumber,
// }
// }
// const codecToReputation = (codec: Codec): Reputation => {
// const json = codec.toJSON() as any
// return {
// r: new BigNumber(json.r),
// s: new BigNumber(json.s),
// }
// }
// const processReputations = (
// reputations: Codec[],
// processors: string[],
// api: ApiPromise
// ) =>
// reputations.map((params, index) => {
// const reputation = api
// .createType('Option<ReputationBetaParameters>', params)
// .unwrapOr(undefined)
// return {
// processor: processors[index],
// reputation: reputation
// ? codecToReputation(reputation)
// : { r: new BigNumber(0), s: new BigNumber(0) },
// }
// })
// const codecToAdvertisementPricing = (codec: Codec): AdvertisementPricing => {
// const json = codec.toJSON() as any
// return {
// feePerMillisecond: new BigNumber(json.feePerMillisecond),
// feePerStorageByte: new BigNumber(json.feePerStorageByte),
// baseFeePerExecution: new BigNumber(json.baseFeePerExecution),
// schedulingWindow: { end: new Date(json.schedulingWindow.end) },
// }
// }
// const codecToAdvertisementRestriction = (
// codec: Codec
// ): AdvertisementRestriction => {
// const json = codec.toJSON() as any
// return {
// maxMemory: json.maxMemory,
// networkRequestQuota: json.networkRequestQuota,
// storageCapacity: json.storageCapacity,
// allowedConsumers: json.allowedConsumers,
// availableModules: json.availableModules,
// }
// }
// const codecToAcurastEnvironment = (codec: Codec): AcurastEnvironment => {
// const json = codec.toJSON() as any
// return {
// publicKey: json.publicKey,
// variables: json.variables,
// }
// }
//# sourceMappingURL=acurastService.js.map