UNPKG

wowok_agent

Version:

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

207 lines (192 loc) 9.62 kB
import { TransactionBlock, PassportObject, Errors, ERROR, Permission, PermissionIndex, PermissionIndexType, Repository, Repository_Policy_Mode, Repository_Value as Wowok_Repository_Value, PermissionObject, uint2address, IsValidU256, ValueType, Repository_Policy, Repository_Value2, } from 'wowok'; import { AccountOrMark_Address, CallBase, CallResult, GetAccountOrMark_Address, GetObjectExisted, GetObjectMain, GetObjectParam, ObjectMain, ObjectsOp, TypeNamedObjectWithPermission} from "./base.js"; import { LocalMark } from '../local/local.js'; import { ObjectRepository } from '../query/objects.js'; // Account name, or local mark name, or address, or u256 number|bigint(eg. time number) that can be converted to address. export type AddressID = AccountOrMark_Address | number | bigint; export const GetAddressID = async(key:AddressID) : Promise<string | undefined> =>{ if (typeof(key) === 'number' || typeof(key) === 'bigint') { if (IsValidU256(key)) { return uint2address(key); } } else { return await GetAccountOrMark_Address(key) } } export interface Repository_Value { address: AddressID; // UID: address or objectid bcsBytes: Uint8Array; // BCS contents. Notice that: First Byte be the Type by caller, or specify type with 'Repository_Policy_Data.value_type' field. } export interface Repository_Policy_Data { key: string; data: Repository_Value[]; value_type?: ValueType; // Specifies a data type prefix; If the data prefix is already included in the data byte stream, there is no need to specify it. } export interface Repository_Policy_Data2 { address: AddressID; data: Repository_Value2[]; value_type?: ValueType; } export interface Repository_Policy_Data_Remove { key: string; address: AddressID; } /// The execution priority is determined by the order in which the object attributes are arranged export interface CallRepository_Data { object?: ObjectMain; description?: string; reference?: ObjectsOp; mode?: Repository_Policy_Mode; // default: 'Relax' (POLICY_MODE_FREE) policy?: {op:'add' | 'set'; data:Repository_Policy[]} | {op:'remove'; keys:string[]} | {op:'removeall'} | {op:'rename'; data:{old:string; new:string}[]}; data?: {op:'add', data: Repository_Policy_Data | Repository_Policy_Data2} | {op:'remove'; data: Repository_Policy_Data_Remove[]}; } export class CallRepository extends CallBase { data: CallRepository_Data; object_address: string | undefined = undefined; permission_address: string | undefined = undefined; constructor(data:CallRepository_Data) { super(); this.data = data; } protected async prepare(): Promise<void> { if (!this.object_address) { this.object_address = (await LocalMark.Instance().get(GetObjectExisted(this.data?.object)))?.address; } if (this.object_address) { await this.update_content('Repository', this.object_address); if (!this.content) ERROR(Errors.InvalidParam, 'CallRepository_Data.data.object:' + this.object_address); this.permission_address = (this.content as ObjectRepository).permission; } else { const n = GetObjectMain(this.data?.object) as TypeNamedObjectWithPermission; this.permission_address = (await LocalMark.Instance().get_address(GetObjectExisted(n?.permission))); } } async call(account?:string) : Promise<CallResult> { var checkOwner = false; const perms : PermissionIndexType[] = []; await this.prepare(); if (this.permission_address) { if (!this.data?.object) { perms.push(PermissionIndex.repository) } if (this.data?.description != null && this.object_address) { perms.push(PermissionIndex.repository_description) } if (this.data?.mode != null && this.object_address) { perms.push(PermissionIndex.repository_mode) } if (this.data?.reference != null) { perms.push(PermissionIndex.repository_reference) } if (this.data?.policy != null) { perms.push(PermissionIndex.repository_policies) } return await this.check_permission_and_call(this.permission_address, perms, [], checkOwner, undefined, account) } return await this.exec(account); } protected async operate(txb:TransactionBlock, passport?:PassportObject, account?:string) { let obj : Repository | undefined ; let perm: Permission | undefined; let permission : PermissionObject | undefined; if (this.object_address) { obj = Repository.From(txb, this.permission_address!, this.object_address); permission = this.permission_address; } else { const n = GetObjectMain(this.data?.object) as TypeNamedObjectWithPermission; permission = await LocalMark.Instance().get_address(GetObjectExisted(n?.permission)); if (!permission) { perm = Permission.New(txb, GetObjectParam(n?.permission)?.description ?? ''); permission = perm.get_object(); } obj = Repository.New(txb, permission, this.data?.description??'', this.data.mode, perm?undefined:passport); } if (!obj) ERROR(Errors.InvalidParam, 'CallRepository_Data.object:' + this.object_address); if (!permission) ERROR(Errors.InvalidParam, 'CallRepository_Data.permission:' + this.permission_address); const pst = perm?undefined:passport; if (this.data?.description != null && this.object_address) { obj?.set_description(this.data.description, pst); } if (this.data?.reference != null) { switch (this.data.reference.op) { case 'set': case 'add': if (this.data.reference.op === 'set') obj?.remove_reference([], true, pst); obj?.add_reference(await LocalMark.Instance().get_many_address2(this.data.reference.objects), pst); break; case 'remove': obj?.remove_reference(await LocalMark.Instance().get_many_address2(this.data.reference.objects), false, pst); break; case 'removeall': obj?.remove_reference([], true, pst); break; } } if (this.data?.mode != null && this.object_address) { //@ priority?? obj?.set_policy_mode(this.data.mode, pst) } if (this.data?.policy != null) { switch(this.data.policy.op) { case 'set': obj?.remove_policies([], true, pst); obj?.add_policies(this.data.policy.data, pst); break; case 'add': obj?.add_policies(this.data.policy.data, pst); break; case 'remove': obj?.remove_policies(this.data.policy.keys, false, pst); break; case 'removeall': obj?.remove_policies([], true, pst); break; case 'rename': this.data.policy.data.forEach((v) => { obj?.rename_policy(v.old, v.new, pst); }) break; } } if (this.data?.data != null) { switch(this.data.data.op) { case 'add': if ((this.data.data?.data as any)?.key != null) { const d = (this.data.data.data as Repository_Policy_Data).data; const add: Wowok_Repository_Value[] = []; for (let i=0; i<d.length; ++i) { const addr = await GetAddressID(d[i].address); if (addr) { add.push({address:addr, bcsBytes:d[i].bcsBytes}); } } obj?.add_data({key:(this.data.data.data as Repository_Policy_Data).key, data:add, value_type:(this.data.data.data as Repository_Policy_Data).value_type}); } else if ((this.data.data?.data as any)?.address != null) { const d = this.data.data.data as Repository_Policy_Data2; const addr = await GetAddressID(d.address); if (addr) { obj?.add_data2({address:addr, data:d.data, value_type:d.value_type}) } } break; case 'remove': for (let i=0; i<this.data.data.data.length; ++i) { const addr = await GetAddressID(this.data.data.data[i].address); if (addr) { obj?.remove(addr, this.data.data.data[i].key); } } break; } } if (perm) { const n = GetObjectMain(this.data?.object) as TypeNamedObjectWithPermission; await this.new_with_mark('Permission', txb, perm.launch(), GetObjectParam(n?.permission), account); } if (!this.object_address) { await this.new_with_mark('Repository', txb, obj.launch(), GetObjectMain(this.data?.object), account); } } }