UNPKG

@cosmology/ast

Version:
452 lines (451 loc) 19 kB
import * as t from "@babel/types"; import { identifier, callExpression, TypeLong, BILLION } from "../../../utils"; import { getInterfaceFromAminoName } from ".."; import { getFieldNames } from "../../types"; import { camel } from "@cosmology/utils"; const setNotUndefinedAndNotNull = (args, value) => { const { propName, origName } = getFieldNames(args.field); return t.ifStatement(t.logicalExpression("&&", t.binaryExpression("!==", t.memberExpression(t.identifier("object"), t.identifier(origName)), t.identifier("undefined")), t.binaryExpression("!==", t.memberExpression(t.identifier("object"), t.identifier(origName)), t.nullLiteral())), t.blockStatement([ t.expressionStatement(t.assignmentExpression("=", t.memberExpression(t.identifier("message"), t.identifier(propName)), value ? value : t.memberExpression(t.identifier("object"), t.identifier(origName)))), ])); }; export const fromAmino = { // message.sender = object.sender ?? ""; string(args) { return setNotUndefinedAndNotNull(args); }, // message.disableMacros = object.disableMacros ?? false; bool(args) { return setNotUndefinedAndNotNull(args); }, // message.doubleValue = object.doubleValue ?? 0; number(args) { return setNotUndefinedAndNotNull(args); }, int32(args) { return fromAmino.number(args); }, uint32(args) { return fromAmino.number(args); }, sint32(args) { return fromAmino.number(args); }, fixed32(args) { return fromAmino.number(args); }, sfixed32(args) { return fromAmino.number(args); }, double(args) { return fromAmino.number(args); }, float(args) { return fromAmino.number(args); }, // if( object.myInt64Value !== undefined && object.myInt64Value !== null ) { message.myInt64Value = Long.fromValue(object.myInt64Value) } long(args) { const { origName } = getFieldNames(args.field); TypeLong.addUtil(args.context); const callExpr = t.callExpression(TypeLong.getFromString(args.context), [ t.memberExpression(t.identifier("object"), t.identifier(origName)), ]); return setNotUndefinedAndNotNull(args, callExpr); }, int64(args) { return fromAmino.long(args); }, uint64(args) { return fromAmino.long(args); }, sint64(args) { return fromAmino.long(args); }, fixed64(args) { return fromAmino.long(args); }, sfixed64(args) { return fromAmino.long(args); }, protoType(args) { const { origName } = getFieldNames(args.field); const name = args.context.getTypeName(args.field); return setNotUndefinedAndNotNull(args, t.callExpression(t.memberExpression(t.identifier(name), t.identifier("fromAmino")), [t.memberExpression(t.identifier("object"), t.identifier(origName))])); }, anyType(args) { const { origName } = getFieldNames(args.field); const interfaceName = args.field.options["(cosmos_proto.accepts_interface)"]; const interfaceFnName = getInterfaceFromAminoName(interfaceName); let aminoFuncExpr = t.identifier(interfaceFnName); const isGlobalRegistry = args.context.options.interfaces?.useGlobalDecoderRegistry; if (isGlobalRegistry) { aminoFuncExpr = t.memberExpression(t.identifier("GlobalDecoderRegistry"), t.identifier("fromAminoMsg")); } return setNotUndefinedAndNotNull(args, t.callExpression(aminoFuncExpr, [ t.memberExpression(t.identifier("object"), t.identifier(origName)), ])); }, type(args) { if (!args.context.options.aminoEncoding.useLegacyInlineEncoding && args.context.options.interfaces.enabled && args.field.type === "google.protobuf.Any" && args.field.options["(cosmos_proto.accepts_interface)"]) { return fromAmino.anyType(args); } return fromAmino.protoType(args); }, enum(args) { return setNotUndefinedAndNotNull(args); }, bytes(args) { // bytes [RawContractMessage] if (args.field.options?.["(gogoproto.casttype)"] === "RawContractMessage") { return fromAmino.rawBytes(args); } // bytes [WASMByteCode] // TODO use a better option for this in proto source // field.options?.["(gogoproto.customname)"] === "WASMByteCode" if (args.field.options?.["(gogoproto.customname)"] === "WASMByteCode") { return fromAmino.wasmByteCode(args); } //default args.context.addUtil("bytesFromBase64"); const { origName } = getFieldNames(args.field); const expr = t.callExpression(t.identifier("bytesFromBase64"), [ t.memberExpression(t.identifier("object"), t.identifier(origName)), ]); return setNotUndefinedAndNotNull(args, expr); }, duration(args) { return fromAmino.type(args); }, durationString(args) { return setNotUndefinedAndNotNull(args, t.identifier("undefined")); }, timestamp(args) { const timestampFormat = args.context.pluginValue("prototypes.typingsFormat.timestamp"); switch (timestampFormat) { case "timestamp": return fromAmino.type(args); case "date": default: return fromAmino.timestampDate(args); } }, timestampDate(args) { const { origName } = getFieldNames(args.field); args.context.addUtil("fromTimestamp"); const expr = t.callExpression(t.identifier("fromTimestamp"), [ t.callExpression(t.memberExpression(t.identifier("Timestamp"), t.identifier("fromAmino")), [t.memberExpression(t.identifier("object"), t.identifier(origName))]), ]); return setNotUndefinedAndNotNull(args, expr); }, // message.referenceMap = Object.entries(object.referenceMap ?? {}).reduce<{ // [key: Long]: Reference; // }>((acc, [key, value]) => { // if (value !== undefined) { // acc[Number(key)] = Reference.fromAmino(value); // } // return acc; // }, {}); // message.labels = Object.entries(object.typeMap ?? {}).reduce<{ // [key: string]: string; // }>((acc, [key, value]) => { // if (value !== undefined) { // acc[key] = String(value); // } // return acc; // }, {}); keyHash(args) { const { propName, origName } = getFieldNames(args.field); const keyType = args.field.keyType; const valueType = args.field.parsedType.name; let fromAminoWithArgs = null; // valueTypeType: string for identifier let valueTypeType = valueType; switch (valueType) { case "string": fromAminoWithArgs = t.callExpression(t.identifier("String"), [ t.identifier("value"), ]); break; case "int32": case "uint32": valueTypeType = "number"; fromAminoWithArgs = t.callExpression(t.identifier("Number"), [ t.identifier("value"), ]); break; case "int64": case "uint64": case "sint64": case "fixed64": case "sfixed64": TypeLong.addUtil(args.context); valueTypeType = TypeLong.getPropType(args.context); fromAminoWithArgs = TypeLong.getFromValueWithArgs(args.context, t.identifier("value")); break; default: fromAminoWithArgs = t.callExpression(t.memberExpression(t.identifier(valueType), t.identifier("fromAmino")), [t.identifier("value")]); } let wrapKey = null; let keyTypeType = null; switch (keyType) { case "string": wrapKey = (a) => a; keyTypeType = t.tsStringKeyword(); break; case "int64": case "uint64": case "sint64": case "fixed64": case "sfixed64": wrapKey = (a) => t.callExpression(t.identifier("Number"), [a]); TypeLong.addUtil(args.context); keyTypeType = t.tsTypeReference(TypeLong.getPropIdentifier(args.context)); break; case "int32": case "uint32": wrapKey = (a) => t.callExpression(t.identifier("Number"), [a]); keyTypeType = t.tsNumberKeyword(); break; default: throw new Error("keyHash requires new type. Ask maintainers."); } return t.expressionStatement(t.assignmentExpression("=", t.memberExpression(t.identifier("message"), t.identifier(propName)), callExpression(t.memberExpression(t.callExpression(t.memberExpression(t.identifier("Object"), t.identifier("entries")), [ t.logicalExpression("??", t.memberExpression(t.identifier("object"), t.identifier(origName)), t.objectExpression([])), ]), t.identifier("reduce")), [ t.arrowFunctionExpression([ t.identifier("acc"), t.arrayPattern([t.identifier("key"), t.identifier("value")]), ], t.blockStatement([ t.ifStatement(t.binaryExpression("!==", t.identifier("value"), t.identifier("undefined")), t.blockStatement([ t.expressionStatement(t.assignmentExpression("=", t.memberExpression(t.identifier("acc"), wrapKey(t.identifier("key")), true), fromAminoWithArgs)), ])), t.returnStatement(t.identifier("acc")), ])), t.objectExpression([]), ], t.tsTypeParameterInstantiation([ t.tsTypeLiteral([ t.tsIndexSignature([identifier("key", t.tsTypeAnnotation(keyTypeType))], t.tsTypeAnnotation(t.tsTypeReference(t.identifier(valueTypeType)))), ]), ])))); }, // message.codeIds = object.codeIds?.map(e => Long.fromValue(e)) || []; array(args, expr) { const { origName, propName } = getFieldNames(args.field); return t.expressionStatement(t.assignmentExpression("=", t.memberExpression(t.identifier("message"), t.identifier(propName)), t.logicalExpression("||", t.optionalCallExpression(t.optionalMemberExpression(t.memberExpression(t.identifier("object"), t.identifier(origName)), t.identifier("map"), false, true), [t.arrowFunctionExpression([t.identifier("e")], expr)], false), t.arrayExpression([])))); }, pubkey(args) { args.context.addUtil("encodePubkey"); const { origName } = getFieldNames(args.field); const callExpr = t.callExpression(t.identifier("encodePubkey"), [ t.memberExpression(t.identifier("object"), t.identifier(origName)), ]); return setNotUndefinedAndNotNull(args, callExpr); }, rawBytes(args) { args.context.addUtil("toUtf8"); const { origName } = getFieldNames(args.field); const expr = t.callExpression(t.identifier("toUtf8"), [ t.callExpression(t.memberExpression(t.identifier("JSON"), t.identifier("stringify")), [t.memberExpression(t.identifier("object"), t.identifier(origName))]), ]); return setNotUndefinedAndNotNull(args, expr); }, wasmByteCode(args) { args.context.addUtil("fromBase64"); const { origName } = getFieldNames(args.field); const expr = t.callExpression(t.identifier("fromBase64"), [ t.memberExpression(t.identifier("object"), t.identifier(origName)), ]); return setNotUndefinedAndNotNull(args, expr); }, }; export const arrayTypes = { // message.overloadId = object.overloadId?.map(e => e) || []; identity() { return t.identifier("e"); }, string() { return arrayTypes.identity(); }, bool() { return arrayTypes.identity(); }, rawBytes(args) { args.context.addUtil("toUtf8"); return t.callExpression(t.identifier("toUtf8"), [ t.callExpression(t.memberExpression(t.identifier("JSON"), t.identifier("stringify")), [t.identifier("e")]), ]); }, wasmByteCode(args) { args.context.addUtil("fromBase64"); const { origName } = getFieldNames(args.field); return t.callExpression(t.identifier("fromBase64"), [t.identifier("e")]); }, bytes(args) { if (args.field.options?.["(gogoproto.casttype)"] === "RawContractMessage") { return arrayTypes.rawBytes(args); } // bytes [WASMByteCode] // field.options?.["(gogoproto.customname)"] === "WASMByteCode" if (args.field.options?.["(gogoproto.customname)"] === "WASMByteCode") { return arrayTypes.wasmByteCode(args); } // default args.context.addUtil("bytesFromBase64"); return t.callExpression(t.identifier("bytesFromBase64"), [ t.identifier("e"), ]); }, double() { return arrayTypes.identity(); }, float() { return arrayTypes.identity(); }, int32() { return arrayTypes.identity(); }, uint32() { return arrayTypes.identity(); }, sint32() { return arrayTypes.identity(); }, fixed32() { return arrayTypes.identity(); }, sfixed32() { return arrayTypes.identity(); }, enum() { return arrayTypes.identity(); }, // message.codeIds = object.codeIds?.map(e => Long.fromValue(e)) || []; long(args) { TypeLong.addUtil(args.context); return TypeLong.getFromStringArray(args.context); }, int64(args) { return arrayTypes.long(args); }, uint64(args) { return arrayTypes.long(args); }, sint64(args) { return arrayTypes.long(args); }, fixed64(args) { return arrayTypes.long(args); }, sfixed64(args) { return arrayTypes.long(args); }, anyType(args) { const interfaceName = args.field.options["(cosmos_proto.accepts_interface)"]; const interfaceFnName = getInterfaceFromAminoName(interfaceName); let aminoFuncExpr = t.identifier(interfaceFnName); const isGlobalRegistry = args.context.options.interfaces?.useGlobalDecoderRegistry; if (isGlobalRegistry) { aminoFuncExpr = t.memberExpression(t.identifier("GlobalDecoderRegistry"), t.identifier("fromAminoMsg")); } return t.callExpression(aminoFuncExpr, [t.identifier("e")]); }, protoType(args) { const name = args.context.getTypeName(args.field); return t.callExpression(t.memberExpression(t.identifier(name), t.identifier("fromAmino")), [t.identifier("e")]); }, type(args) { if (!args.context.options.aminoEncoding.useLegacyInlineEncoding && args.context.options.interfaces.enabled && args.field.type === "google.protobuf.Any" && args.field.options["(cosmos_proto.accepts_interface)"]) { return arrayTypes.anyType(args); } return arrayTypes.protoType(args); }, }; export const fromAminoMessages = { anyType() { return [ t.returnStatement(t.objectExpression([ t.objectProperty(t.identifier("typeUrl"), t.memberExpression(t.identifier("object"), t.identifier("type"))), t.objectProperty(t.identifier("value"), t.memberExpression(t.identifier("object"), t.identifier("value"))), ])), ]; }, timestamp(context, name, proto) { context.addUtil("fromJsonTimestamp"); return [ t.returnStatement(t.callExpression(t.identifier("fromJsonTimestamp"), [ t.identifier("object"), ])), ]; }, height(context, name, proto) { TypeLong.addUtil(context); const keepCase = context.options.prototypes.parser.keepCase; const casing = keepCase ? (str) => str : camel; const makeArgs = (fieldName) => { let args = [ t.logicalExpression("||", t.memberExpression(t.identifier("object"), t.identifier(fieldName)), t.stringLiteral("0")), ]; const longType = TypeLong.getType(context); if (longType == "Long") { args.push(t.booleanLiteral(true)); } return args; }; const makeField = (fieldName) => t.objectProperty(t.identifier(casing(fieldName)), t.callExpression(TypeLong.getFromString(context), makeArgs(fieldName))); return [ // return t.returnStatement(t.objectExpression([ makeField("revision_number"), makeField("revision_height"), ])), ]; }, duration(context, name, proto) { TypeLong.addUtil(context); const longType = TypeLong.getType(context); switch (longType) { case "BigInt": return [ t.variableDeclaration("const", [ t.variableDeclarator(t.identifier("value"), t.callExpression(t.identifier("BigInt"), [t.identifier("object")])), ]), t.returnStatement(t.objectExpression([ t.objectProperty(t.identifier("seconds"), t.binaryExpression("/", t.identifier("value"), t.callExpression(t.identifier("BigInt"), [ t.stringLiteral("1000000000"), ]))), t.objectProperty(t.identifier("nanos"), t.callExpression(t.identifier("Number"), [ t.binaryExpression("%", t.identifier("value"), t.callExpression(t.identifier("BigInt"), [ t.stringLiteral("1000000000"), ])), ])), ])), ]; case "Long": default: return [ t.variableDeclaration("const", [ t.variableDeclarator(t.identifier("value"), t.callExpression(t.identifier("parseInt"), [ t.identifier("object"), ])), ]), // return t.returnStatement(t.objectExpression([ // seconds t.objectProperty(t.identifier("seconds"), t.callExpression(TypeLong.getFromNumber(context), [ t.callExpression(t.memberExpression(t.identifier("Math"), t.identifier("floor")), [t.binaryExpression("/", t.identifier("value"), BILLION)]), ])), // nanos t.objectProperty(t.identifier("nanos"), t.binaryExpression("%", t.identifier("value"), BILLION)), ])), ]; } }, };