UNPKG

@waku/rln

Version:

RLN (Rate Limiting Nullifier) implementation for Waku

97 lines (94 loc) 4 kB
import { arrayify } from '../../bytes/lib.esm/index.js'; import { defineReadOnly } from '../../properties/lib.esm/index.js'; import { Logger } from '../../logger/lib.esm/index.js'; import { version } from './_version.js'; import { Reader, Writer } from './coders/abstract-coder.js'; import { AddressCoder } from './coders/address.js'; import { ArrayCoder } from './coders/array.js'; import { BooleanCoder } from './coders/boolean.js'; import { BytesCoder } from './coders/bytes.js'; import { FixedBytesCoder } from './coders/fixed-bytes.js'; import { NullCoder } from './coders/null.js'; import { NumberCoder } from './coders/number.js'; import { StringCoder } from './coders/string.js'; import { TupleCoder } from './coders/tuple.js'; import { ParamType } from './fragments.js'; const logger = new Logger(version); const paramTypeBytes = new RegExp(/^bytes([0-9]*)$/); const paramTypeNumber = new RegExp(/^(u?int)([0-9]*)$/); class AbiCoder { constructor(coerceFunc) { defineReadOnly(this, "coerceFunc", coerceFunc || null); } _getCoder(param) { switch (param.baseType) { case "address": return new AddressCoder(param.name); case "bool": return new BooleanCoder(param.name); case "string": return new StringCoder(param.name); case "bytes": return new BytesCoder(param.name); case "array": return new ArrayCoder(this._getCoder(param.arrayChildren), param.arrayLength, param.name); case "tuple": return new TupleCoder((param.components || []).map((component) => { return this._getCoder(component); }), param.name); case "": return new NullCoder(param.name); } // u?int[0-9]* let match = param.type.match(paramTypeNumber); if (match) { let size = parseInt(match[2] || "256"); if (size === 0 || size > 256 || (size % 8) !== 0) { logger.throwArgumentError("invalid " + match[1] + " bit length", "param", param); } return new NumberCoder(size / 8, (match[1] === "int"), param.name); } // bytes[0-9]+ match = param.type.match(paramTypeBytes); if (match) { let size = parseInt(match[1]); if (size === 0 || size > 32) { logger.throwArgumentError("invalid bytes length", "param", param); } return new FixedBytesCoder(size, param.name); } return logger.throwArgumentError("invalid type", "type", param.type); } _getWordSize() { return 32; } _getReader(data, allowLoose) { return new Reader(data, this._getWordSize(), this.coerceFunc, allowLoose); } _getWriter() { return new Writer(this._getWordSize()); } getDefaultValue(types) { const coders = types.map((type) => this._getCoder(ParamType.from(type))); const coder = new TupleCoder(coders, "_"); return coder.defaultValue(); } encode(types, values) { if (types.length !== values.length) { logger.throwError("types/values length mismatch", Logger.errors.INVALID_ARGUMENT, { count: { types: types.length, values: values.length }, value: { types: types, values: values } }); } const coders = types.map((type) => this._getCoder(ParamType.from(type))); const coder = (new TupleCoder(coders, "_")); const writer = this._getWriter(); coder.encode(writer, values); return writer.data; } decode(types, data, loose) { const coders = types.map((type) => this._getCoder(ParamType.from(type))); const coder = new TupleCoder(coders, "_"); return coder.decode(this._getReader(arrayify(data), loose)); } } const defaultAbiCoder = new AbiCoder(); export { AbiCoder, defaultAbiCoder };