UNPKG

wowok_agent

Version:

Agent for WoWok: Unlock Co-Creation, Lighting Transaction, Empower Potential.

204 lines 8.2 kB
import { Entity, Resource, array_unique, TagName, Errors, ERROR, Permission, GuardParser, Passport, TransactionBlock } from 'wowok'; import { query_permission } from '../query/permission.js'; import { Account } from '../local/account.js'; import { query_objects, query_personal, raw2type } from '../query/objects.js'; import { LocalMark } from '../local/local.js'; ; export const GetObjectExisted = (object) => { return (typeof object === 'string') ? object : undefined; }; export const GetObjectMain = (object) => { if (typeof object === 'object' && object !== null && 'type_parameter' in object) { return object; } else if (typeof object === 'object' && object !== null && 'permission' in object) { return object; } else if (typeof object === 'object') { return object; } }; export const GetObjectParam = (object) => { return (typeof object === 'object' && object !== null && 'description' in object) ? object : undefined; }; export const GetAccountOrMark_Address = async (entity) => { if (!entity || !entity.name_or_address) { return (await Account.Instance().get())?.address; } if (entity?.local_mark_first) { const r = await LocalMark.Instance().get_address(entity.name_or_address); if (!r) { return (await Account.Instance().get(entity.name_or_address))?.address; } return r; } else { const r = (await Account.Instance().get(entity.name_or_address))?.address; if (!r) { return await LocalMark.Instance().get_address(entity.name_or_address); } return r; } }; export const GetManyAccountOrMark_Address = async (entities) => { const res = []; for (let i = 0; i < entities.length; ++i) { const addr = await GetAccountOrMark_Address(entities[i]); if (addr) res.push(addr); } return res; }; export const SetWithdrawFee = async (param, treasury) => { if (!treasury) { ERROR(Errors.InvalidParam, 'WithdrawFee: treasury_address invalid'); } const [object, guard] = await LocalMark.Instance().get_many_address([param.for_object, param.for_guard]); return { index: BigInt(param.index), remark: param.remark, for_object: object, for_guard: guard, treasury: treasury }; }; export function ResponseData(response) { const res = []; response?.objectChanges?.forEach(v => { const type_raw = v?.objectType; const type = raw2type(type_raw); if (type) { res.push({ type: type, type_raw: type_raw, object: v?.objectId, version: v?.version, owner: v?.owner, change: v.type }); } }); return res; } export class CallBase { async operate(txb, passport, account) { } ; async prepare() { } ; constructor() { this.traceMarkNew = new Map(); this.content = undefined; } // return WitnessFill to resolve filling witness, and than 'call_with_witness' to complete the call; // return ResponseData when the call has completed; // throw an exception when errors. async call(account) { return undefined; } ; async call_with_witness(info, account) { if (info.guards.length > 0) { // prepare passport const p = await GuardParser.Create([...info.guards]); if (p) { const query = await p.done(info.witness); if (query) { const txb = new TransactionBlock(); const passport = new Passport(txb, query); await this.prepare(); await this.operate(txb, passport?.get_object(), account); passport.destroy(); return await this.sign_and_commit(txb, account); } } else { ERROR(Errors.Fail, 'guard verify'); } } } async check_permission_and_call(permission, permIndex, guards_needed, checkOwner, checkAdmin, account) { var guards = []; if (permIndex.length > 0 || checkOwner) { const p = await query_permission({ permission_object: permission, address: { name_or_address: account } }); if (checkOwner && !p.owner) ERROR(Errors.noPermission, 'owner'); if (checkAdmin && !p.admin) ERROR(Errors.noPermission, 'admin'); permIndex.forEach(v => { const r = Permission.HasPermission(p, v); if (!r?.has) ERROR(Errors.noPermission, v); if (r?.guard) guards.push(r.guard); }); } if (guards_needed.length > 0) { guards = guards.concat(guards_needed); } if (guards.length > 0) { // prepare passport const p = await GuardParser.Create([...guards]); const futures = p ? p.future_fills() : []; if (!p) ERROR(Errors.Fail, 'guard parse'); if (p && futures.length === 0) { const query = await p.done(); if (query) { const txb = new TransactionBlock(); const passport = new Passport(txb, query); await this.operate(txb, passport?.get_object(), account); passport.destroy(); return await this.sign_and_commit(txb, account); } } return { guards: [...guards], witness: p.future_fills() }; } else { // no passport needed return await this.exec(account); } } async exec(account) { const txb = new TransactionBlock(); await this.operate(txb, undefined, account); return await this.sign_and_commit(txb, account); } async new_with_mark(type, txb, object, named_new, account, innerTags = [TagName.Launch]) { const tags = named_new?.tags ? array_unique([...named_new.tags, ...innerTags]) : array_unique([...innerTags]); if (named_new) { named_new.tags = tags; this.traceMarkNew.set(type, named_new); } if (!named_new?.onChain) return; // onchain mark if (!this.resouceObject) { const r = await query_personal({ address: { name_or_address: account } }); if (!r?.mark_object) { this.resouceObject = Entity.From(txb).create_resource2(); // new Resource.From(txb, this.resouceObject).add(object, tags, named_new?.name); } else { Resource.From(txb, r.mark_object).add(object, tags, named_new?.name); } } else { Resource.From(txb, this.resouceObject).add(object, tags, named_new?.name); } } async update_content(type, object) { if (this.content || !object) return; const r = await query_objects({ objects: [object], no_cache: true }); if (r?.objects?.length !== 1 || r?.objects[0]?.type !== type) { ERROR(Errors.Fail, `Fetch ${type} object ${object} failed`); } this.content = r?.objects[0]; } async sign_and_commit(txb, account) { if (this.resouceObject) { Resource.From(txb, this.resouceObject).launch(); //@ resource launch, if created. this.resouceObject = undefined; } const r = await Account.Instance().sign_and_commit(txb, account); if (!r) { ERROR(Errors.Fail, 'sign and commit failed'); } // save the mark locally, anyway const res = ResponseData(r); for (let i = 0; i < res.length; ++i) { const v = res[i]; if (v.type && v.change === 'created') { const namedNew = this.traceMarkNew.get(v.type); if (namedNew) { await LocalMark.Instance().put(namedNew.name, { address: v.object, tags: namedNew?.tags ? [...namedNew?.tags, v.type] : [v.type] }, namedNew?.useAddressIfNameExist); } } } return r; } } //# sourceMappingURL=base.js.map