wowok
Version:
Create, collaborate, and transact on your own terms with the AI-driven web3 collaboration protocol.
1,059 lines • 50 kB
JavaScript
var _a;
import { Inputs } from '@mysten/sui/transactions';
import { Protocol, ContextType, OperatorType, ValueType, SER_VALUE, IsContextWitness, MODULES, WitnessObjectModule, WitnessForModule } from './protocol.js';
import { parse_object_type, array_unique, Bcs, ulebDecode, IsValidAddress, IsValidArray, readOption, readOptionString, deepCopy } from './utils.js';
import { ERROR, Errors } from './exception.js';
import { CMD_CHECK_GUARD, Guard, GUARD_QUERIES, GuardMaker } from './guard.js';
import { bcs } from '@mysten/sui/bcs';
import { Service } from './service.js';
import { Arbitration } from './arbitration.js';
import { Progress } from './progress.js';
export class GuardParser {
constructor(guards) {
this.guard_list = [];
this.guardlist = () => { return this.guard_list; };
this.future_fills = () => {
const ret = [];
this.guard_list.forEach((g) => {
// cmd already in query_list, so filter it out.
//console.log(g.constant); console.log(g.input)
g.constant.filter((i) => i.bWitness).forEach((v) => {
let cited = 0;
g.input.forEach((k) => {
if (k.identifier === v.identifier)
cited++;
});
ret.push({ guard: g.id, witness: undefined, identifier: v.identifier, ..._a.ConstantWitnessModule(v),
type: v.type, cmd: v.cmd, witnessTypes: v.witness, cited: cited }); // module 很重要,需要得到
});
});
return ret;
};
this.fetch_witness = async (fill) => {
if (!fill || fill.length === 0)
return;
// 所有需要查询的witness, 根据module字段获得
const witness = array_unique(fill.filter(v => v.witness_module !== undefined).map(v => v.witness));
if (witness.length === 0)
return;
const res = await Protocol.Instance().query_raw(witness, { showType: true, showContent: true });
//console.log(res);
const witnessObjectInfo = new Map(); // 报错witness 类型信息等
// 查询并填充cmd的witness
for (let i = 0; i < res.length; ++i) {
const v = res[i];
const type_raw = v?.data?.type ?? undefined;
const objectid = v?.data?.objectId ?? undefined;
if (!type_raw || !objectid)
return;
const t = Protocol.Instance().object_name_from_type_repr(type_raw);
switch (t) {
case 'Progress': {
const machine = v?.data?.content?.fields?.machine;
fill.filter(v => v.witness === objectid && v.witness_module === MODULES.progress).forEach(v => {
v.cmd.forEach(i => {
switch (i.witness) {
case ContextType.TYPE_PROGRESS_MACHINE:
i.witness_object = machine;
break;
}
});
});
witnessObjectInfo.set(objectid, { module: MODULES.progress });
break;
}
case 'Order': {
const service = v?.data?.content?.fields?.service;
const machine = v?.data?.content?.fields?.machine;
const progress = v?.data?.content?.fields?.progress;
fill.filter(v => v.witness === objectid && v.witness_module === MODULES.order).forEach(v => {
v.cmd.forEach(i => {
switch (i.witness) {
case ContextType.TYPE_ORDER_MACHINE:
i.witness_object = machine;
break;
case ContextType.TYPE_ORDER_PROGRESS:
i.witness_object = progress;
break;
case ContextType.TYPE_ORDER_SERVICE:
i.witness_object = service;
break;
}
});
});
witnessObjectInfo.set(objectid, { module: MODULES.order, type: Service.parseOrderObjectType(type_raw) });
break;
}
case 'Arb': {
const arbitration = v?.data?.content?.fields?.arbitration;
const order = v?.data?.content?.fields?.order;
const order_res = await Protocol.Instance().query_raw([order], { showType: true, showContent: true });
const service = order_res[0]?.data?.content?.fields?.service;
const machine = order_res[0]?.data?.content?.fields?.machine;
const progress = order_res[0]?.data?.content?.fields?.progress;
const order_type = order_res[0]?.data?.type ?? undefined;
fill.filter(v => v.witness === objectid && v.witness_module === MODULES.arb).forEach(v => {
v.cmd.forEach(i => {
switch (i.witness) {
case ContextType.TYPE_ARB_MACHINE:
i.witness_object = machine;
break;
case ContextType.TYPE_ARB_PROGRESS:
i.witness_object = progress;
break;
case ContextType.TYPE_ARB_SERVICE:
i.witness_object = service;
break;
case ContextType.TYPE_ARB_ORDER:
i.witness_object = order;
break;
case ContextType.TYPE_ARB_ARBITRATION:
i.witness_object = arbitration;
break;
}
});
});
witnessObjectInfo.set(objectid, { module: MODULES.arb, type: Arbitration.parseArbObjectType(type_raw),
order: order, order_type: order_type
});
break;
}
}
}
;
// 检查结果的完整性
fill.filter(v => v.witness_module !== undefined).forEach(v => {
v.cmd.forEach(i => {
if (i.witness && !i.witness_object) {
ERROR(Errors.Fail, `fetch_witness : ${i}`);
}
});
});
return witnessObjectInfo;
};
this.done = async (fill, onPassportQueryReady) => {
let objects = [];
// 填充所有的witness object
const witnessObjectInfo = await this.fetch_witness(fill);
// check all witness and get all objects to query.
this.guard_list.forEach((g) => {
g.constant.forEach((v) => {
if (v.bWitness) {
const value = fill?.find((i) => i.identifier === v.identifier && i.guard === g.id);
if (!value) {
ERROR(Errors.Fail, 'done: invalid witness ' + v.identifier);
}
else {
v.value = value.witness; // 写witness
}
}
});
g.input.filter((v) => v.cmd !== undefined).forEach((i) => {
if (i.identifier !== undefined) {
if (IsContextWitness(i.value)) { //是否是 type witness
const value = fill?.find(c => c.guard === g.id && c.identifier === i.identifier);
const cmd = value?.cmd.find(c => c.cmd === i.cmd);
if (!value || !cmd || !IsValidAddress(cmd.witness_object))
ERROR(Errors.Fail, `witness invalid or not found: ${i}`);
objects.push(cmd.witness_object); // 将witness查询对象地址加入
}
else { // self witness
const value = g.constant.find((c) => c.identifier === i.identifier && c.type === ValueType.TYPE_ADDRESS);
if (!value || !IsValidAddress(value.value))
ERROR(Errors.Fail, 'done: invalid identifier ' + i.identifier);
objects.push(value.value); // const address(witness or not)
}
}
else {
objects.push(i.value); //@ address
}
});
});
if (onPassportQueryReady) {
if (objects.length === 0) {
onPassportQueryReady(this.done_helper([], fill, witnessObjectInfo));
return;
}
Protocol.Instance().query_raw(array_unique(objects), { showType: true }).then((res) => {
onPassportQueryReady(this.done_helper(res, fill, witnessObjectInfo));
}).catch(e => {
console.log(e);
onPassportQueryReady(undefined);
});
return;
}
else {
let res = [];
if (objects.length > 0) {
res = await Protocol.Instance().query_raw(array_unique(objects), { showType: true });
}
return this.done_helper(res, fill, witnessObjectInfo);
}
};
// create onchain query for objects : object, movecall-types, id
this.object_query = (data, method = 'guard_query') => {
for (let k = 0; k < Protocol.Instance().WOWOK_OBJECTS_TYPE().length; k++) {
if (data.type.includes(Protocol.Instance().WOWOK_OBJECTS_TYPE()[k])) { // type: pack::m::Object<...>
return { target: Protocol.Instance().WOWOK_OBJECTS_PREFIX_TYPE()[k] + method,
object: Inputs.SharedObjectRef({
objectId: data.objectId,
mutable: false,
initialSharedVersion: data.version,
}),
types: parse_object_type(data.type),
id: data.objectId, };
}
}
};
this.guards = guards;
}
// ============================================
static Parse_Guard_Helper(guards, res) {
const protocol = Protocol.Instance();
const me = new _a(guards);
res.forEach((r) => {
const c = r.data?.content;
if (!c)
ERROR(Errors.Fail, 'Parse_Guard_Helper invalid content');
const index = protocol.WOWOK_OBJECTS_TYPE().findIndex(v => { return v.includes('guard::Guard') && v == c.type; });
if (index === -1)
ERROR(Errors.Fail, 'Parse_Guard_Helper invalid type: ' + c.type);
if (c.fields.input.type === (protocol.package('base') + '::bcs::BCS')) {
const constants = _a.parse_constant(c.fields.constants); // MUST first
const inputs = _a.parse_bcs(constants, Uint8Array.from(c.fields.input.fields.bytes));
me.guard_list.push({ id: c.fields.id.id, input: [...inputs], constant: [...constants], digest: r.data?.digest ?? '', version: r.data?.version ?? '' });
}
else {
ERROR(Errors.Fail, 'Parse_Guard_Helper invalid package: ' + c.fields.input.type);
}
});
return me;
}
// 检查cmd(含非witness)和witness的模块一致性,并返回模块
static ConstantWitnessModule(constant) {
let module;
let witness_module;
for (let i = 0; i < constant.cmd.length; ++i) {
if (constant.cmd[i].witness !== undefined) { // witness cmd
if (!IsContextWitness(constant.cmd[i].witness)) {
ERROR(Errors.Fail, `ConstantWitnessModule witness type invalid on identifier ${constant}`);
}
const m = WitnessObjectModule(constant.cmd[i].witness);
if (!witness_module) {
witness_module = m;
}
else {
if (witness_module !== m) {
ERROR(Errors.Fail, `ConstantWitnessModule wintesses modules are different on identifier ${constant}`);
}
}
}
else {
const q = GUARD_QUERIES.find((q) => q.query_id == constant.cmd[i].cmd);
if (q) {
if (!module) {
module = q.module;
}
else {
if (module !== q.module) {
ERROR(Errors.Fail, `ConstantWitnessModule modules are different on identifier ${constant}`);
}
}
}
else {
ERROR(Errors.Fail, `ConstantWitnessModule. cmd not found on identifier ${constant}`);
}
}
}
for (let i = 0; i < constant.witness.length; ++i) {
const m = WitnessObjectModule(constant.witness[i]);
if (!witness_module) {
witness_module = m;
}
else {
if (witness_module !== m) {
ERROR(Errors.Fail, `ConstantWitnessModule modules are different on identifier ${constant}`);
}
}
}
return { module: module, witness_module: witness_module };
}
static AddConstantWitness(constants, identifier, type) {
const c = constants.find(i => i.bWitness && i.identifier === identifier);
if (!c)
ERROR(Errors.Fail, `AddConstantWitness identifier ${identifier} with witness not found`);
const module = _a.ConstantWitnessModule(c);
const m = WitnessObjectModule(type);
if (module.witness_module && m !== module.witness_module) {
ERROR(Errors.Fail, `AddConstantWitness.type module not matach ${type}`);
}
const n = c.witness.find(v => v === type);
c.info = { module: m };
if (!n)
c.witness.push(type);
}
static AddConstantCmd(constants, identifier, cmd) {
let c;
if (cmd.witness !== undefined) {
c = constants.find(i => i.bWitness && i.identifier === identifier);
if (!c)
ERROR(Errors.Fail, `AddConstantCmd identifier ${identifier} with witness not found`);
const module = _a.ConstantWitnessModule(c);
GuardMaker.checkCmdWitness(cmd.cmd, cmd.witness);
const m = WitnessForModule(cmd.witness);
if (module.witness_module && m !== module.witness_module) { // 使用module_witness字段
ERROR(Errors.WitnessTypeInvalid, `AddConstantCmd module not match ${identifier}`);
}
c.info = { module: m };
}
else {
c = constants.find(i => i.identifier === identifier);
if (!c)
ERROR(Errors.Fail, `AddConstantCmd identifier ${identifier} with witness not found`);
const module = _a.ConstantWitnessModule(c);
const m = GUARD_QUERIES.find(v => v.query_id === cmd.cmd);
if (!m) {
ERROR(Errors.Fail, `AddConstantCmd.cmd not found ${cmd}`);
}
if (module.module && m?.module !== module.module) { // 使用module字段
ERROR(Errors.Fail, `AddConstantCmd module not match ${identifier}`);
}
}
c.cmd.push(cmd); //@ 每个命令都添加进去,不考虑重复
}
done_helper(res, fill, info) {
let query = [];
let guards = [];
this.guard_list.forEach(g => {
guards.push(g.id);
let object_id;
g.input.filter((v) => v.cmd !== undefined).forEach(q => {
if (q.identifier !== undefined) {
if (IsContextWitness(q.value)) { //是否是 type witness
const value = fill?.find(c => c.guard === g.id && c.identifier === q.identifier);
object_id = value?.cmd.find(c => c.cmd === q.cmd)?.witness_object;
}
else { // self witness
const value = g.constant.find((c) => c.identifier === q.identifier && c.type === ValueType.TYPE_ADDRESS);
if (!value || !IsValidAddress(value.value)) {
ERROR(Errors.Fail, `done_helper: invalid identifier ${q.identifier}`);
}
object_id = value?.value;
}
}
else {
object_id = q.value; //@ address
}
let r = res.find(r => r.data?.objectId == object_id);
if (!r) {
ERROR(Errors.Fail, 'query object not match');
}
let object = this.object_query(r.data); // build passport query objects
if (!object) {
ERROR(Errors.Fail, 'query object fail');
}
query.push(object);
});
});
return { query: query, info: this.guard_list, witnessObjectInfo: info };
}
}
_a = GuardParser;
// 解析一个Guard的数据,生成树结构和表结构
GuardParser.DeGuardObject_FromData = (guard_constants, guard_input_bytes) => {
let constants = _a.parse_constant(guard_constants);
// console.log(constants)
let inputs = _a.parse_bcs(constants, guard_input_bytes);
if (!inputs || inputs.length == 0)
ERROR(Errors.Fail, 'GuardObject: data parsed error');
let stack = [];
inputs.forEach((d) => {
_a.ResolveData(constants, stack, { ...d, child: [] });
});
if (stack.length != 1) {
ERROR(Errors.Fail, 'GuardObject: parse error');
}
return { object: stack.pop(), constant: constants };
};
/// 解析一个Guard地址,生成树结构(通过ResolveData)和表结构。 用于UI对单个guard作图
GuardParser.DeGuardObject = async (protocol, guard) => {
if (!IsValidAddress(guard)) {
ERROR(Errors.IsValidAddress, 'GuardObject guard');
}
let res = await protocol.query_raw([guard]);
if (res.length == 0 || !res[0].data || res[0].data?.objectId != guard) {
ERROR(Errors.Fail, 'GuardObject query error');
}
// console.log(res[0].data?.content);
let content = res[0].data.content;
if (content?.type != protocol.package('base') + '::guard::Guard') {
ERROR(Errors.Fail, 'GuardObject object invalid');
}
return _a.DeGuardObject_FromData(content.fields.constants, content.fields.input.fields.bytes);
};
GuardParser.ResolveData = (constants, stack, current) => {
switch (current.type) {
case OperatorType.TYPE_LOGIC_NOT:
current.ret_type = ValueType.TYPE_BOOL;
if (stack.length < 1)
ERROR(Errors.Fail, `ResolveData: TYPE_LOGIC_NOT`);
var param = stack.pop();
if (!param.ret_type || param.ret_type != ValueType.TYPE_BOOL) {
ERROR(Errors.Fail, 'ResolveData: TYPE_LOGIC_NOT type invalid');
}
current.child.push(param);
stack.push(current);
return;
case OperatorType.TYPE_NUMBER_ADDRESS:
current.ret_type = ValueType.TYPE_ADDRESS;
if (stack.length < 1)
ERROR(Errors.Fail, 'ResolveData: TYPE_NUMBER_ADDRESS');
var param = stack.pop();
if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) {
ERROR(Errors.Fail, 'ResolveData: TYPE_NUMBER_ADDRESS type invalid');
}
current.child.push(param);
stack.push(current);
return;
case OperatorType.TYPE_SAFE_U8:
current.ret_type = ValueType.TYPE_U8;
if (stack.length < 1)
ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U8');
var param = stack.pop();
if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) {
ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U8 type invalid');
}
current.child.push(param);
stack.push(current);
return;
case OperatorType.TYPE_SAFE_U64:
current.ret_type = ValueType.TYPE_U64;
if (stack.length < 1)
ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U64');
var param = stack.pop();
if (!param.ret_type || !GuardMaker.match_u256(param.ret_type)) {
ERROR(Errors.Fail, 'ResolveData: TYPE_SAFE_U64 type invalid');
}
current.child.push(param);
stack.push(current);
return;
case OperatorType.TYPE_STRING_LOWERCASE:
current.ret_type = ValueType.TYPE_STRING;
if (stack.length < 1)
ERROR(Errors.Fail, 'ResolveData: TYPE_STRING_LOWERCASE');
var param = stack.pop();
if (!param.ret_type || param.ret_type !== ValueType.TYPE_STRING) {
ERROR(Errors.Fail, 'ResolveData: TYPE_STRING_LOWERCASE type invalid');
}
current.child.push(param);
stack.push(current);
return;
case OperatorType.TYPE_LOGIC_AS_U256_GREATER:
case OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL:
case OperatorType.TYPE_LOGIC_AS_U256_LESSER:
case OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL:
case OperatorType.TYPE_LOGIC_AS_U256_EQUAL:
case OperatorType.TYPE_NUMBER_ADD:
case OperatorType.TYPE_NUMBER_DEVIDE:
case OperatorType.TYPE_NUMBER_MOD:
case OperatorType.TYPE_NUMBER_MULTIPLY:
case OperatorType.TYPE_NUMBER_SUBTRACT:
if (current.type === OperatorType.TYPE_LOGIC_AS_U256_GREATER || current.type === OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL ||
current.type === OperatorType.TYPE_LOGIC_AS_U256_LESSER || current.type === OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL ||
current.type === OperatorType.TYPE_LOGIC_AS_U256_EQUAL) {
current.ret_type = ValueType.TYPE_BOOL;
}
else {
current.ret_type = ValueType.TYPE_U256;
}
if (stack.length < current.value || current.value < 2)
ERROR(Errors.Fail, 'ResolveData: ' + current.type);
for (let i = 0; i < current.value; ++i) {
var p = stack.pop();
if (!p.ret_type || !GuardMaker.match_u256(p.ret_type))
ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type');
current.child.push(p);
}
stack.push(current);
return;
case OperatorType.TYPE_LOGIC_EQUAL:
current.ret_type = ValueType.TYPE_BOOL;
if (stack.length < current.value || current.value < 2)
ERROR(Errors.Fail, 'ResolveData: ' + current.type);
var p0 = stack.pop();
current.child.push(p0);
for (let i = 1; i < current.value; ++i) {
var p = stack.pop();
if (!p.ret_type || (p.ret_type != p0.ret_type))
ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type');
current.child.push(p);
}
stack.push(current);
return;
case OperatorType.TYPE_LOGIC_HAS_SUBSTRING:
current.ret_type = ValueType.TYPE_BOOL;
if (stack.length < current.value || current.value < 2)
ERROR(Errors.Fail, 'ResolveData: ' + current.type);
for (let i = 0; i < current.value; ++i) {
var p = stack.pop();
if (!p.ret_type || (p.ret_type != ValueType.TYPE_STRING))
ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type');
current.child.push(p);
}
stack.push(current);
return;
case OperatorType.TYPE_LOGIC_AND:
case OperatorType.TYPE_LOGIC_OR:
current.ret_type = ValueType.TYPE_BOOL;
if (stack.length < current.value || current.value < 2)
ERROR(Errors.Fail, 'ResolveData: ' + current.type);
for (let i = 0; i < current.value; ++i) {
var p = stack.pop();
if (!p.ret_type || (p.ret_type != ValueType.TYPE_BOOL))
ERROR(Errors.Fail, 'ResolveData: ' + current.type + ' INVALID param type');
current.child.push(p);
}
stack.push(current);
return;
case OperatorType.TYPE_QUERY:
if (!current?.cmd)
ERROR(Errors.Fail, 'ResolveData: cmd invalid ' + current.type);
let r = Guard.GetCmd(current.cmd);
if (!r)
ERROR(Errors.Fail, 'ResolveData: cmd not supported ' + current.type);
current.ret_type = r?.return;
if (stack.length < r.parameters.length)
ERROR(Errors.Fail, 'ResolveData: cmd param lost ' + current.type);
r.parameters.forEach((e) => {
let d = stack.pop();
if (!d?.ret_type || d.ret_type != e) {
ERROR(Errors.Fail, 'ResolveData: cmd param not match ' + current.type);
}
current.child.push(d);
});
stack.push(current);
return;
case ValueType.TYPE_ADDRESS:
case ValueType.TYPE_BOOL:
case ValueType.TYPE_U128:
case ValueType.TYPE_U256:
case ValueType.TYPE_U64:
case ValueType.TYPE_U8:
case ValueType.TYPE_VEC_ADDRESS:
case ValueType.TYPE_VEC_BOOL:
case ValueType.TYPE_VEC_U128:
case ValueType.TYPE_VEC_U256:
case ValueType.TYPE_VEC_U64:
case ValueType.TYPE_VEC_U8:
case ValueType.TYPE_VEC_VEC_U8:
case ValueType.TYPE_OPTION_ADDRESS:
case ValueType.TYPE_OPTION_BOOL:
case ValueType.TYPE_OPTION_U128:
case ValueType.TYPE_OPTION_U256:
case ValueType.TYPE_OPTION_U64:
case ValueType.TYPE_OPTION_U8:
case ValueType.TYPE_STRING:
current.ret_type = current.type;
stack.push(current);
return;
case ContextType.TYPE_CLOCK:
current.ret_type = ValueType.TYPE_U64;
stack.push(current);
return;
case ContextType.TYPE_SIGNER:
current.ret_type = ValueType.TYPE_ADDRESS;
stack.push(current);
return;
case ContextType.TYPE_GUARD:
current.ret_type = ValueType.TYPE_ADDRESS;
stack.push(current);
return;
case ContextType.TYPE_CONSTANT:
let v = constants.find((e) => e.identifier == current?.identifier);
if (!v)
ERROR(Errors.Fail, 'ResolveData: identifier invalid ' + current.type);
current.ret_type = v?.type;
stack.push(current);
return;
case ContextType.TYPE_ARB_ARBITRATION:
case ContextType.TYPE_ARB_MACHINE:
case ContextType.TYPE_ARB_ORDER:
case ContextType.TYPE_ARB_PROGRESS:
case ContextType.TYPE_ARB_SERVICE:
case ContextType.TYPE_ORDER_MACHINE:
case ContextType.TYPE_ORDER_PROGRESS:
case ContextType.TYPE_ORDER_SERVICE:
case ContextType.TYPE_PROGRESS_MACHINE: {
current.ret_type = ValueType.TYPE_ADDRESS;
stack.push(current);
return;
}
}
ERROR(Errors.Fail, 'ResolveData: type invalid ' + current.type);
};
// 解析一些Guards,生成parser结构。用于生成fill数据或进行passport验证。
GuardParser.Create = async (guards) => {
if (!IsValidArray(guards, IsValidAddress)) {
ERROR(Errors.InvalidParam, 'GuardParser.Create: guards invalid');
}
let guard_list = array_unique(guards);
let check_guards = [...guard_list];
let i = 0;
const parsers = [];
for (; i < _a.MAX_REPOSITORY_DEPTH; ++i) {
const res = await Protocol.Instance().query_raw(check_guards);
const p = _a.Parse_Guard_Helper(guards, res);
const repositories = [];
p.guardlist().forEach((g) => {
g.input.forEach((i) => {
if (i.cmd !== undefined && CMD_CHECK_GUARD.includes(i.cmd)) {
if (i.identifier !== undefined) {
const id = g.constant.find((c) => c.identifier === i.identifier);
if (id && id.value) {
repositories.push(id.value);
}
}
else if (i.value) {
repositories.push(i.value);
}
}
});
});
parsers.push(p);
if (repositories.length === 0) {
break;
}
check_guards = await _a.RepositoryGuards(repositories);
if (check_guards.length === 0) {
break;
}
}
if (i >= _a.MAX_REPOSITORY_DEPTH) {
ERROR(Errors.Fail, `GuardParser.Create: Retrieve guards from the Repository with a maximum depth of more than ${_a.MAX_REPOSITORY_DEPTH} levels.`);
}
// concatenate all parsers
for (let i = 1; i < parsers.length; ++i) {
parsers[0].guard_list = parsers[0].guard_list.concat(deepCopy(parsers[i].guard_list));
parsers[0].guards = parsers[0].guards.concat(parsers[i].guards);
}
if (parsers.length > 0) {
return parsers[0];
}
};
// fetch repository guards
GuardParser.RepositoryGuards = async (repositories) => {
const res = await Protocol.Instance().query_raw(repositories);
const guards = [];
for (let i = 0; i < res.length; ++i) {
if (res[i].data?.content?.fields?.guard) {
guards.push((res[i].data?.content).fields.guard);
}
}
return guards;
};
GuardParser.parse_constant = (constants) => {
let ret = [];
constants.forEach((c) => {
let v = c?.fields ?? c; // graphql dosnot 'fields', but rpcall has.
const data = Uint8Array.from(v.value);
const type = data.slice(0, 1)[0];
if (v.bWitness) { //@ witness
ret.push({ identifier: v.identifier, type: type, bWitness: v.bWitness, value: undefined, cmd: [], witness: [] });
return;
}
var value = data.slice(1);
switch (type) {
case ValueType.TYPE_ADDRESS:
value = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(value)).toString();
break;
case ValueType.TYPE_BOOL:
case ValueType.TYPE_U8:
case ValueType.TYPE_U64:
case ValueType.TYPE_U128:
case ValueType.TYPE_U256:
case ValueType.TYPE_VEC_U8:
case ValueType.TYPE_VEC_U64:
case ValueType.TYPE_VEC_U128:
case ValueType.TYPE_VEC_ADDRESS:
case ValueType.TYPE_VEC_BOOL:
case ValueType.TYPE_VEC_VEC_U8:
case ValueType.TYPE_OPTION_ADDRESS:
case ValueType.TYPE_OPTION_BOOL:
case ValueType.TYPE_OPTION_U128:
case ValueType.TYPE_OPTION_U8:
case ValueType.TYPE_OPTION_U64:
case ValueType.TYPE_OPTION_U256:
case ValueType.TYPE_VEC_U256:
case ValueType.TYPE_STRING:
case ValueType.TYPE_OPTION_STRING:
case ValueType.TYPE_OPTION_VEC_U8:
case ValueType.TYPE_VEC_STRING:
let de = SER_VALUE.find(s => s.type == type);
if (!de)
ERROR(Errors.Fail, 'GuardObject de error');
value = Bcs.getInstance().de(type, Uint8Array.from(value));
break;
default:
ERROR(Errors.Fail, 'GuardObject constant type invalid:' + type);
}
ret.push({ identifier: v.identifier, type: type, bWitness: v.bWitness, value: value, witness: [], cmd: [] });
});
return ret;
};
GuardParser.parse_bcs = (constants, chain_bytes) => {
let bytes = Uint8Array.from(chain_bytes);
let arr = [].slice.call(bytes.reverse());
let data = [];
while (arr.length > 0) {
let type = arr.shift();
let value;
let cmd;
let identifier;
switch (type) {
case ContextType.TYPE_SIGNER:
case ContextType.TYPE_CLOCK:
case ContextType.TYPE_GUARD:
case OperatorType.TYPE_LOGIC_NOT:
case OperatorType.TYPE_NUMBER_ADDRESS:
case OperatorType.TYPE_STRING_LOWERCASE:
case OperatorType.TYPE_SAFE_U64:
case OperatorType.TYPE_SAFE_U8:
break;
case OperatorType.TYPE_LOGIC_AS_U256_GREATER:
case OperatorType.TYPE_LOGIC_AS_U256_GREATER_EQUAL:
case OperatorType.TYPE_LOGIC_AS_U256_LESSER:
case OperatorType.TYPE_LOGIC_AS_U256_LESSER_EQUAL:
case OperatorType.TYPE_LOGIC_AS_U256_EQUAL:
case OperatorType.TYPE_LOGIC_EQUAL:
case OperatorType.TYPE_LOGIC_HAS_SUBSTRING:
case OperatorType.TYPE_NUMBER_ADD:
case OperatorType.TYPE_NUMBER_DEVIDE:
case OperatorType.TYPE_NUMBER_MOD:
case OperatorType.TYPE_NUMBER_MULTIPLY:
case OperatorType.TYPE_NUMBER_SUBTRACT:
case OperatorType.TYPE_LOGIC_AND: //@ with logics count
case OperatorType.TYPE_LOGIC_OR:
value = arr.shift();
break;
case ContextType.TYPE_ARB_ARBITRATION:
case ContextType.TYPE_ARB_MACHINE:
case ContextType.TYPE_ARB_ORDER:
case ContextType.TYPE_ARB_PROGRESS:
case ContextType.TYPE_ARB_SERVICE:
case ContextType.TYPE_ORDER_MACHINE:
case ContextType.TYPE_ORDER_PROGRESS:
case ContextType.TYPE_ORDER_SERVICE:
case ContextType.TYPE_PROGRESS_MACHINE:
identifier = arr.shift(); // identifier
let v = constants.find((v) => (v.identifier == identifier) &&
((v.type == ValueType.TYPE_ADDRESS)));
if (!v) {
ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${identifier} with type ${ValueType.TYPE_ADDRESS} not in constant`);
}
value = type; //@ type used
//@ 将witness数据加入到常量中
_a.AddConstantWitness(constants, identifier, type);
break;
case ContextType.TYPE_CONSTANT:
identifier = arr.shift(); // identifier
break;
case ValueType.TYPE_ADDRESS:
value = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(arr)).toString();
arr.splice(0, 32); // address
break;
case ValueType.TYPE_BOOL:
case ValueType.TYPE_U8:
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.shift();
break;
case ValueType.TYPE_U64:
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, 8);
break;
case ValueType.TYPE_U128:
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, 16);
break;
case ValueType.TYPE_U256:
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, 32);
break;
case ValueType.TYPE_VEC_U8:
case ValueType.TYPE_VEC_BOOL:
case ValueType.TYPE_STRING:
let r = ulebDecode(Uint8Array.from(arr));
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, r.value + r.length);
break;
case ValueType.TYPE_VEC_ADDRESS:
r = ulebDecode(Uint8Array.from(arr));
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, r.value * 32 + r.length);
break;
case ValueType.TYPE_VEC_U128:
r = ulebDecode(Uint8Array.from(arr));
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, r.value * 16 + r.length);
break;
case ValueType.TYPE_VEC_U256:
r = ulebDecode(Uint8Array.from(arr));
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, r.value * 32 + r.length);
break;
case ValueType.TYPE_VEC_U64:
r = ulebDecode(Uint8Array.from(arr));
value = Bcs.getInstance().de(type, Uint8Array.from(arr));
arr.splice(0, r.value * 8 + r.length);
break;
case ValueType.TYPE_VEC_VEC_U8:
case ValueType.TYPE_VEC_STRING:
r = ulebDecode(Uint8Array.from(arr));
arr.splice(0, r.length);
let res = [];
for (let i = 0; i < r.value; i++) {
let r2 = ulebDecode(Uint8Array.from(arr));
res.push(Bcs.getInstance().de(ValueType.TYPE_VEC_U8, Uint8Array.from(arr)));
arr.splice(0, r2.length + r2.value);
}
value = res;
break;
case OperatorType.TYPE_QUERY:
let t = arr.splice(0, 1); // data-type
switch (t[0]) {
case ValueType.TYPE_ADDRESS: {
let addr = Bcs.getInstance().de(ValueType.TYPE_ADDRESS, Uint8Array.from(arr)).toString();
arr.splice(0, 32); // address
value = addr;
cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16)
break;
}
case ContextType.TYPE_CONSTANT: {
let id = arr.splice(0, 1); // key
let v = constants.find((v) => (v.identifier == id[0]) &&
((v.type == ValueType.TYPE_ADDRESS)));
if (!v) {
ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${id[0]} with type ${ValueType.TYPE_ADDRESS} not in constant`);
}
identifier = id[0];
cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16)
_a.AddConstantCmd(constants, identifier, { cmd: cmd }); //@ witness的cmd都添加(Self类型)
break;
}
case ContextType.TYPE_ARB_ARBITRATION:
case ContextType.TYPE_ARB_MACHINE:
case ContextType.TYPE_ARB_ORDER:
case ContextType.TYPE_ARB_PROGRESS:
case ContextType.TYPE_ARB_SERVICE:
case ContextType.TYPE_ORDER_MACHINE:
case ContextType.TYPE_ORDER_PROGRESS:
case ContextType.TYPE_ORDER_SERVICE:
case ContextType.TYPE_PROGRESS_MACHINE: {
let id = arr.splice(0, 1); // key
let v = constants.find((v) => (v.identifier == id[0]) && v.bWitness &&
((v.type == ValueType.TYPE_ADDRESS))); // witness, address type
if (!v) {
ERROR(Errors.Fail, `GuardParser.parse_bcs: indentifier ${id[0]} with type ${ValueType.TYPE_ADDRESS} not in constant`);
}
identifier = id[0];
cmd = bcs.u16().parse(Uint8Array.from(arr.splice(0, 2))); // cmd(u16)
value = t[0]; //@ value used
// 添加witness cmd(witness类型)
_a.AddConstantCmd(constants, identifier, { witness: t[0], cmd: cmd });
break;
}
default:
ERROR(Errors.Fail, 'GuardObject: type invalid');
}
break;
case ValueType.TYPE_OPTION_ADDRESS:
let read = readOption(arr, ValueType.TYPE_ADDRESS);
value = read.value;
if (!read.bNone)
arr.splice(0, 32);
break;
case ValueType.TYPE_OPTION_BOOL:
read = readOption(arr, ValueType.TYPE_BOOL);
value = read.value;
if (!read.bNone)
arr.splice(0, 1);
break;
case ValueType.TYPE_OPTION_U8:
read = readOption(arr, ValueType.TYPE_U8);
value = read.value;
if (!read.bNone)
arr.splice(0, 1);
break;
case ValueType.TYPE_OPTION_U128:
read = readOption(arr, ValueType.TYPE_U128);
value = read.value;
if (!read.bNone)
arr.splice(0, 16);
break;
case ValueType.TYPE_OPTION_U256:
read = readOption(arr, ValueType.TYPE_U256);
value = read.value;
if (!read.bNone)
arr.splice(0, 32);
break;
case ValueType.TYPE_OPTION_U64:
read = readOption(arr, ValueType.TYPE_U64);
value = read.value;
if (!read.bNone)
arr.splice(0, 8);
break;
case ValueType.TYPE_OPTION_STRING:
read = readOptionString(arr); // splice in it
value = read.value;
break;
default:
ERROR(Errors.Fail, 'GuardObject: parse_bcs types ' + type);
}
data.push({ type: type, value: value, cmd: cmd, identifier: identifier });
}
return data;
};
GuardParser.MAX_REPOSITORY_DEPTH = 3;
export class Passport {
get_object() { return this.passport; }
// return passport object used
// bObject(true) in cmd env; (false) in service env
constructor(txb, query) {
this.query_result_async = async (sender) => {
this.txb.moveCall({
target: Protocol.Instance().passportFn('query_result'),
arguments: [this.passport]
});
const res = await Protocol.Client().devInspectTransactionBlock({ sender: sender, transactionBlock: this.txb });
return Passport.ResolveQueryRes(this.txb, res);
};
if (query.info.length > Passport.MAX_GUARD_COUNT) {
ERROR(Errors.InvalidParam, `Passport: guards count max ${Passport.MAX_GUARD_COUNT}`);
}
this.txb = txb; //console.log(query)
this.passport = this.txb.moveCall({
target: Protocol.Instance().passportFn('new'),
arguments: []
});
// add others guards, if any
query.info.forEach((g, guard_index) => {
const ids = g.constant.filter((i) => i.bWitness).map((v) => v.identifier);
const values = g.constant.filter((i) => i.bWitness).map((v) => {
const bcs = Bcs.getInstance().ser(v.type, v.value);
let r = new Uint8Array(bcs.length + 1);
r.set([v.type], 0);
r.set(bcs, 1);
return [].slice.call(r);
});
const guard = g.version !== undefined && g.digest !== undefined ?
txb.objectRef({ objectId: g.id, version: g.version, digest: g.digest }) :
txb.object(g.id);
//console.log(ids); console.log(values)
this.txb.moveCall({
target: Protocol.Instance().passportFn('guard_add'),
arguments: [this.passport, guard, this.txb.pure.vector('u8', [].slice.call(ids)),
this.txb.pure(bcs.vector(bcs.vector(bcs.u8())).serialize([...values]).toBytes())]
});
// 对每个witness object处理所有的witness类型请求
const witness_objects = new Map();
g.constant.forEach(v => {
const types = [];
v.cmd.forEach(i => {
if (i.witness && IsContextWitness(i.witness) && !types.includes(i.witness)) {
types.push(i.witness);
}
});
v.witness.forEach(i => {
if (i && IsContextWitness(i) && !types.includes(i)) {
types.push(i);
}
});
if (types.length > 0) {
let obj = witness_objects.get(v.value); // 用户提供的witness地址
if (obj) {
obj.types = array_unique(types.concat(obj.types));
obj.identifier.push(v.identifier); // identifier加入
}
else {
witness_objects.set(v.value, { types: types, identifier: [v.identifier] });
}
}
});
// 调用witness object的witness
witness_objects.forEach((v, k) => {
const r = query.witnessObjectInfo?.get(k);
if (!r) {
ERROR(Errors.Fail, `Passport: witness not found ${k}`);
}
switch (r?.module) {
case MODULES.progress:
Progress.witness(txb, k, guard_index, v.identifier, this.passport);
break;
case MODULES.order:
Service.witness(txb, k, r.type, guard_index, v.identifier, v.types, this.passport);
break;
case MODULES.arb:
Arbitration.witness(txb, k, r.type, guard_index, v.identifier, v.types, r.order, r.order_type, this.passport);
break;
default:
ERROR(Errors.Fail, `Passport: witness type invalid ${r?.module}`);
}
});
});
const clock = this.txb.sharedObjectRef(Protocol.CLOCK_OBJECT);
// rules: 'verify' & 'query' in turns; 'verify' at final end.
query?.query.forEach((q) => {
this.txb.moveCall({
target: Protocol.Instance().passportFn('passport_verify'),
arguments: [this.passport, this.txb.object(clock)]
});
this.txb.moveCall({
target: q.target,
arguments: [this.txb.object(q.id), this.passport],
typeArguments: q.types,
});
});
this.txb.moveCall({
target: Protocol.Instance().passportFn('passport_verify'),
arguments: [this.passport, this.txb.object(clock)]
});
}
destroy() {
this.txb.moveCall({
target: Protocol.Instance().passportFn('destroy'),
arguments: [this.passport]
});
}
freeze() {
this.txb.moveCall({
target: Protocol.Instance().passportFn('freezen'),
arguments: [this.passport]
});
}
query_result(sender, handleResult) {
this.txb.moveCall({
target: Protocol.Instance().passportFn('query_result'),
arguments: [this.passport]
});
Protocol.Client().devInspectTransactionBlock({ sender: sender, transactionBlock: this.txb }).then((res) => {
const r = Passport.ResolveQueryRes(this.txb, res);
if (r)
handleResult(r);
}).catch(e => {
console.log(e);
});
}
static ResolveQueryRes(txb, res) {
for (let i = 0; i < res.results?.length; ++i) {
const v = res.results[i];
if (v?.returnValues && v.returnValues.length === 2 &&
v.returnValues[0][1] === 'bool' && v.returnValues[1][1] === 'vector<address>') { // (bool, vector<address>)
const result = bcs.bool().parse(Uint8Array.from(v.returnValues[0][0]));
const guards = bcs.vector(bcs.Address).parse(Uint8Array.from(v.returnValues[1][0])).map((v) => '0x' + v);
return { txb: txb, result: result, guards: guards };
}
}
return undefined;
}
}
Passport.MAX_GUARD_COUNT = 8;
//# sourceMappingURL=passport.js.map