UNPKG

@algofi/js-sdk

Version:

The official Algofi JavaScript SDK

10,977 lines 469 kB
import algosdk, { LogicSigAccount, assignGroupID, encodeAddress, getApplicationAddress, encodeUint64, decodeUint64, bytesToBigInt, makePaymentTxnWithSuggestedParamsFromObject, makeApplicationOptInTxnFromObject, makeApplicationNoOpTxnFromObject, makeAssetTransferTxnWithSuggestedParamsFromObject, decodeAddress } from 'algosdk';
import request from 'superagent';

var Base64Encoder = {
  _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

  /**
   * Function to encode an arbitrary string
   *
   * @param   string  e   String to be encoded
   * @return  string  t   Encoded string e
   */
  encode: function encode(e) {
    var t = "";
    var n, r, i, s, o, u, a;
    var f = 0;
    e = Base64Encoder._utf8_encode(e);

    while (f < e.length) {
      n = e.charCodeAt(f++);
      r = e.charCodeAt(f++);
      i = e.charCodeAt(f++);
      s = n >> 2;
      o = (n & 3) << 4 | r >> 4;
      u = (r & 15) << 2 | i >> 6;
      a = i & 63;

      if (isNaN(r)) {
        u = a = 64;
      } else if (isNaN(i)) {
        a = 64;
      }

      t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a);
    }

    return t;
  },

  /**
   * Function to decode a string encoded by Base64Encoder.encode
   *
   * @param   string  e   String to be decoded
   * @return  string  t   Decoded string e
   */
  decode: function decode(e) {
    var t = "";
    var n, r, i;
    var s, o, u, a;
    var f = 0;
    e = e.replace(/[^A-Za-z0-9\+\/\=]/g, "");

    while (f < e.length) {
      s = this._keyStr.indexOf(e.charAt(f++));
      o = this._keyStr.indexOf(e.charAt(f++));
      u = this._keyStr.indexOf(e.charAt(f++));
      a = this._keyStr.indexOf(e.charAt(f++));
      n = s << 2 | o >> 4;
      r = (o & 15) << 4 | u >> 2;
      i = (u & 3) << 6 | a;
      t = t + String.fromCharCode(n);

      if (u != 64) {
        t = t + String.fromCharCode(r);
      }

      if (a != 64) {
        t = t + String.fromCharCode(i);
      }
    }

    t = Base64Encoder._utf8_decode(t);
    return t;
  },

  /**
   * Function to perfom utf8 encoding on an arbitrary string
   *
   * @param   string  e   String to be utf8 encoded
   * @return  string  t   Encoded string e
   */
  _utf8_encode: function _utf8_encode(e) {
    e = e.replace(/\r\n/g, "\n");
    var t = "";

    for (var n = 0; n < e.length; n++) {
      var r = e.charCodeAt(n);

      if (r < 128) {
        t += String.fromCharCode(r);
      } else if (r > 127 && r < 2048) {
        t += String.fromCharCode(r >> 6 | 192);
        t += String.fromCharCode(r & 63 | 128);
      } else {
        t += String.fromCharCode(r >> 12 | 224);
        t += String.fromCharCode(r >> 6 & 63 | 128);
        t += String.fromCharCode(r & 63 | 128);
      }
    }

    return t;
  },

  /**
   * Function to decode a string encoded by Base64Encoder._utf8_encode
   *
   * @param   string  e   String to be utf8 decoded
   * @return  string  t   Decoded string e
   */
  _utf8_decode: function _utf8_decode(e) {
    var t = "";
    var n = 0;
    var r = 0;
    var c2 = 0;
    var c3 = 0;

    while (n < e.length) {
      r = e.charCodeAt(n);

      if (r < 128) {
        t += String.fromCharCode(r);
        n++;
      } else if (r > 191 && r < 224) {
        c2 = e.charCodeAt(n + 1);
        t += String.fromCharCode((r & 31) << 6 | c2 & 63);
        n += 2;
      } else {
        c2 = e.charCodeAt(n + 1);
        c3 = e.charCodeAt(n + 2);
        t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
        n += 3;
      }
    }

    return t;
  }
};

// external imports

var FIXED_3_SCALE_FACTOR = 1000;
var FIXED_6_SCALE_FACTOR = 1000000;
var FIXED_12_SCALE_FACTOR = 1000000000000;
var FIXED_18_SCALE_FACTOR = /*#__PURE__*/BigInt(1000000000000000000);
var ALGO_ASSET_ID = 1;
var BANK_ASSET_ID = 900652777;
var SECONDS_PER_DAY = 86400;
var SECONDS_PER_YEAR = SECONDS_PER_DAY * 365; // requires NoOp, ApplicationCall, No Rekey, No CloseRemainderTo (assits ledger users)

var PERMISSIONLESS_SENDER_LOGIC_SIG = /*#__PURE__*/new LogicSigAccount( /*#__PURE__*/new Uint8Array([6, 49, 16, 129, 6, 18, 68, 49, 25, 129, 0, 18, 68, 49, 9, 50, 3, 18, 68, 49, 32, 50, 3, 18, 68, 129, 1, 67]));
var TEXT_ENCODER = /*#__PURE__*/new TextEncoder();
var MAINNET_ANALYTICS_ENDPOINT = "https://api.algofi.org";
var TESTNET_ANALYTICS_ENDPOINT = "https://api-dev.algofi.org";
function getAnalyticsEndpoint(network) {
  if (network == Network.MAINNET) {
    return MAINNET_ANALYTICS_ENDPOINT;
  } else {
    return TESTNET_ANALYTICS_ENDPOINT;
  }
} // ENUMS

var Network;

(function (Network) {
  Network[Network["MAINNET"] = 0] = "MAINNET";
  Network[Network["TESTNET"] = 1] = "TESTNET";
})(Network || (Network = {}));

function getNetworkName(network) {
  if (network == Network.MAINNET) {
    return "mainnet";
  } else if (network == Network.TESTNET) {
    return "testnet";
  } else {
    throw "bad network";
  }
}

function _regeneratorRuntime() {
  /*! regenerator-runtime -- Copyright (c) 2014-present, Facebook, Inc. -- license (MIT): https://github.com/facebook/regenerator/blob/main/LICENSE */

  _regeneratorRuntime = function () {
    return exports;
  };

  var exports = {},
      Op = Object.prototype,
      hasOwn = Op.hasOwnProperty,
      $Symbol = "function" == typeof Symbol ? Symbol : {},
      iteratorSymbol = $Symbol.iterator || "@@iterator",
      asyncIteratorSymbol = $Symbol.asyncIterator || "@@asyncIterator",
      toStringTagSymbol = $Symbol.toStringTag || "@@toStringTag";

  function define(obj, key, value) {
    return Object.defineProperty(obj, key, {
      value: value,
      enumerable: !0,
      configurable: !0,
      writable: !0
    }), obj[key];
  }

  try {
    define({}, "");
  } catch (err) {
    define = function (obj, key, value) {
      return obj[key] = value;
    };
  }

  function wrap(innerFn, outerFn, self, tryLocsList) {
    var protoGenerator = outerFn && outerFn.prototype instanceof Generator ? outerFn : Generator,
        generator = Object.create(protoGenerator.prototype),
        context = new Context(tryLocsList || []);
    return generator._invoke = function (innerFn, self, context) {
      var state = "suspendedStart";
      return function (method, arg) {
        if ("executing" === state) throw new Error("Generator is already running");

        if ("completed" === state) {
          if ("throw" === method) throw arg;
          return doneResult();
        }

        for (context.method = method, context.arg = arg;;) {
          var delegate = context.delegate;

          if (delegate) {
            var delegateResult = maybeInvokeDelegate(delegate, context);

            if (delegateResult) {
              if (delegateResult === ContinueSentinel) continue;
              return delegateResult;
            }
          }

          if ("next" === context.method) context.sent = context._sent = context.arg;else if ("throw" === context.method) {
            if ("suspendedStart" === state) throw state = "completed", context.arg;
            context.dispatchException(context.arg);
          } else "return" === context.method && context.abrupt("return", context.arg);
          state = "executing";
          var record = tryCatch(innerFn, self, context);

          if ("normal" === record.type) {
            if (state = context.done ? "completed" : "suspendedYield", record.arg === ContinueSentinel) continue;
            return {
              value: record.arg,
              done: context.done
            };
          }

          "throw" === record.type && (state = "completed", context.method = "throw", context.arg = record.arg);
        }
      };
    }(innerFn, self, context), generator;
  }

  function tryCatch(fn, obj, arg) {
    try {
      return {
        type: "normal",
        arg: fn.call(obj, arg)
      };
    } catch (err) {
      return {
        type: "throw",
        arg: err
      };
    }
  }

  exports.wrap = wrap;
  var ContinueSentinel = {};

  function Generator() {}

  function GeneratorFunction() {}

  function GeneratorFunctionPrototype() {}

  var IteratorPrototype = {};
  define(IteratorPrototype, iteratorSymbol, function () {
    return this;
  });
  var getProto = Object.getPrototypeOf,
      NativeIteratorPrototype = getProto && getProto(getProto(values([])));
  NativeIteratorPrototype && NativeIteratorPrototype !== Op && hasOwn.call(NativeIteratorPrototype, iteratorSymbol) && (IteratorPrototype = NativeIteratorPrototype);
  var Gp = GeneratorFunctionPrototype.prototype = Generator.prototype = Object.create(IteratorPrototype);

  function defineIteratorMethods(prototype) {
    ["next", "throw", "return"].forEach(function (method) {
      define(prototype, method, function (arg) {
        return this._invoke(method, arg);
      });
    });
  }

  function AsyncIterator(generator, PromiseImpl) {
    function invoke(method, arg, resolve, reject) {
      var record = tryCatch(generator[method], generator, arg);

      if ("throw" !== record.type) {
        var result = record.arg,
            value = result.value;
        return value && "object" == typeof value && hasOwn.call(value, "__await") ? PromiseImpl.resolve(value.__await).then(function (value) {
          invoke("next", value, resolve, reject);
        }, function (err) {
          invoke("throw", err, resolve, reject);
        }) : PromiseImpl.resolve(value).then(function (unwrapped) {
          result.value = unwrapped, resolve(result);
        }, function (error) {
          return invoke("throw", error, resolve, reject);
        });
      }

      reject(record.arg);
    }

    var previousPromise;

    this._invoke = function (method, arg) {
      function callInvokeWithMethodAndArg() {
        return new PromiseImpl(function (resolve, reject) {
          invoke(method, arg, resolve, reject);
        });
      }

      return previousPromise = previousPromise ? previousPromise.then(callInvokeWithMethodAndArg, callInvokeWithMethodAndArg) : callInvokeWithMethodAndArg();
    };
  }

  function maybeInvokeDelegate(delegate, context) {
    var method = delegate.iterator[context.method];

    if (undefined === method) {
      if (context.delegate = null, "throw" === context.method) {
        if (delegate.iterator.return && (context.method = "return", context.arg = undefined, maybeInvokeDelegate(delegate, context), "throw" === context.method)) return ContinueSentinel;
        context.method = "throw", context.arg = new TypeError("The iterator does not provide a 'throw' method");
      }

      return ContinueSentinel;
    }

    var record = tryCatch(method, delegate.iterator, context.arg);
    if ("throw" === record.type) return context.method = "throw", context.arg = record.arg, context.delegate = null, ContinueSentinel;
    var info = record.arg;
    return info ? info.done ? (context[delegate.resultName] = info.value, context.next = delegate.nextLoc, "return" !== context.method && (context.method = "next", context.arg = undefined), context.delegate = null, ContinueSentinel) : info : (context.method = "throw", context.arg = new TypeError("iterator result is not an object"), context.delegate = null, ContinueSentinel);
  }

  function pushTryEntry(locs) {
    var entry = {
      tryLoc: locs[0]
    };
    1 in locs && (entry.catchLoc = locs[1]), 2 in locs && (entry.finallyLoc = locs[2], entry.afterLoc = locs[3]), this.tryEntries.push(entry);
  }

  function resetTryEntry(entry) {
    var record = entry.completion || {};
    record.type = "normal", delete record.arg, entry.completion = record;
  }

  function Context(tryLocsList) {
    this.tryEntries = [{
      tryLoc: "root"
    }], tryLocsList.forEach(pushTryEntry, this), this.reset(!0);
  }

  function values(iterable) {
    if (iterable) {
      var iteratorMethod = iterable[iteratorSymbol];
      if (iteratorMethod) return iteratorMethod.call(iterable);
      if ("function" == typeof iterable.next) return iterable;

      if (!isNaN(iterable.length)) {
        var i = -1,
            next = function next() {
          for (; ++i < iterable.length;) if (hasOwn.call(iterable, i)) return next.value = iterable[i], next.done = !1, next;

          return next.value = undefined, next.done = !0, next;
        };

        return next.next = next;
      }
    }

    return {
      next: doneResult
    };
  }

  function doneResult() {
    return {
      value: undefined,
      done: !0
    };
  }

  return GeneratorFunction.prototype = GeneratorFunctionPrototype, define(Gp, "constructor", GeneratorFunctionPrototype), define(GeneratorFunctionPrototype, "constructor", GeneratorFunction), GeneratorFunction.displayName = define(GeneratorFunctionPrototype, toStringTagSymbol, "GeneratorFunction"), exports.isGeneratorFunction = function (genFun) {
    var ctor = "function" == typeof genFun && genFun.constructor;
    return !!ctor && (ctor === GeneratorFunction || "GeneratorFunction" === (ctor.displayName || ctor.name));
  }, exports.mark = function (genFun) {
    return Object.setPrototypeOf ? Object.setPrototypeOf(genFun, GeneratorFunctionPrototype) : (genFun.__proto__ = GeneratorFunctionPrototype, define(genFun, toStringTagSymbol, "GeneratorFunction")), genFun.prototype = Object.create(Gp), genFun;
  }, exports.awrap = function (arg) {
    return {
      __await: arg
    };
  }, defineIteratorMethods(AsyncIterator.prototype), define(AsyncIterator.prototype, asyncIteratorSymbol, function () {
    return this;
  }), exports.AsyncIterator = AsyncIterator, exports.async = function (innerFn, outerFn, self, tryLocsList, PromiseImpl) {
    void 0 === PromiseImpl && (PromiseImpl = Promise);
    var iter = new AsyncIterator(wrap(innerFn, outerFn, self, tryLocsList), PromiseImpl);
    return exports.isGeneratorFunction(outerFn) ? iter : iter.next().then(function (result) {
      return result.done ? result.value : iter.next();
    });
  }, defineIteratorMethods(Gp), define(Gp, toStringTagSymbol, "Generator"), define(Gp, iteratorSymbol, function () {
    return this;
  }), define(Gp, "toString", function () {
    return "[object Generator]";
  }), exports.keys = function (object) {
    var keys = [];

    for (var key in object) keys.push(key);

    return keys.reverse(), function next() {
      for (; keys.length;) {
        var key = keys.pop();
        if (key in object) return next.value = key, next.done = !1, next;
      }

      return next.done = !0, next;
    };
  }, exports.values = values, Context.prototype = {
    constructor: Context,
    reset: function (skipTempReset) {
      if (this.prev = 0, this.next = 0, this.sent = this._sent = undefined, this.done = !1, this.delegate = null, this.method = "next", this.arg = undefined, this.tryEntries.forEach(resetTryEntry), !skipTempReset) for (var name in this) "t" === name.charAt(0) && hasOwn.call(this, name) && !isNaN(+name.slice(1)) && (this[name] = undefined);
    },
    stop: function () {
      this.done = !0;
      var rootRecord = this.tryEntries[0].completion;
      if ("throw" === rootRecord.type) throw rootRecord.arg;
      return this.rval;
    },
    dispatchException: function (exception) {
      if (this.done) throw exception;
      var context = this;

      function handle(loc, caught) {
        return record.type = "throw", record.arg = exception, context.next = loc, caught && (context.method = "next", context.arg = undefined), !!caught;
      }

      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i],
            record = entry.completion;
        if ("root" === entry.tryLoc) return handle("end");

        if (entry.tryLoc <= this.prev) {
          var hasCatch = hasOwn.call(entry, "catchLoc"),
              hasFinally = hasOwn.call(entry, "finallyLoc");

          if (hasCatch && hasFinally) {
            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
          } else if (hasCatch) {
            if (this.prev < entry.catchLoc) return handle(entry.catchLoc, !0);
          } else {
            if (!hasFinally) throw new Error("try statement without catch or finally");
            if (this.prev < entry.finallyLoc) return handle(entry.finallyLoc);
          }
        }
      }
    },
    abrupt: function (type, arg) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];

        if (entry.tryLoc <= this.prev && hasOwn.call(entry, "finallyLoc") && this.prev < entry.finallyLoc) {
          var finallyEntry = entry;
          break;
        }
      }

      finallyEntry && ("break" === type || "continue" === type) && finallyEntry.tryLoc <= arg && arg <= finallyEntry.finallyLoc && (finallyEntry = null);
      var record = finallyEntry ? finallyEntry.completion : {};
      return record.type = type, record.arg = arg, finallyEntry ? (this.method = "next", this.next = finallyEntry.finallyLoc, ContinueSentinel) : this.complete(record);
    },
    complete: function (record, afterLoc) {
      if ("throw" === record.type) throw record.arg;
      return "break" === record.type || "continue" === record.type ? this.next = record.arg : "return" === record.type ? (this.rval = this.arg = record.arg, this.method = "return", this.next = "end") : "normal" === record.type && afterLoc && (this.next = afterLoc), ContinueSentinel;
    },
    finish: function (finallyLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];
        if (entry.finallyLoc === finallyLoc) return this.complete(entry.completion, entry.afterLoc), resetTryEntry(entry), ContinueSentinel;
      }
    },
    catch: function (tryLoc) {
      for (var i = this.tryEntries.length - 1; i >= 0; --i) {
        var entry = this.tryEntries[i];

        if (entry.tryLoc === tryLoc) {
          var record = entry.completion;

          if ("throw" === record.type) {
            var thrown = record.arg;
            resetTryEntry(entry);
          }

          return thrown;
        }
      }

      throw new Error("illegal catch attempt");
    },
    delegateYield: function (iterable, resultName, nextLoc) {
      return this.delegate = {
        iterator: values(iterable),
        resultName: resultName,
        nextLoc: nextLoc
      }, "next" === this.method && (this.arg = undefined), ContinueSentinel;
    }
  }, exports;
}

function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
  try {
    var info = gen[key](arg);
    var value = info.value;
  } catch (error) {
    reject(error);
    return;
  }

  if (info.done) {
    resolve(value);
  } else {
    Promise.resolve(value).then(_next, _throw);
  }
}

function _asyncToGenerator(fn) {
  return function () {
    var self = this,
        args = arguments;
    return new Promise(function (resolve, reject) {
      var gen = fn.apply(self, args);

      function _next(value) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "next", value);
      }

      function _throw(err) {
        asyncGeneratorStep(gen, resolve, reject, _next, _throw, "throw", err);
      }

      _next(undefined);
    });
  };
}

function _unsupportedIterableToArray(o, minLen) {
  if (!o) return;
  if (typeof o === "string") return _arrayLikeToArray(o, minLen);
  var n = Object.prototype.toString.call(o).slice(8, -1);
  if (n === "Object" && o.constructor) n = o.constructor.name;
  if (n === "Map" || n === "Set") return Array.from(o);
  if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen);
}

function _arrayLikeToArray(arr, len) {
  if (len == null || len > arr.length) len = arr.length;

  for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];

  return arr2;
}

function _createForOfIteratorHelperLoose(o, allowArrayLike) {
  var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"];
  if (it) return (it = it.call(o)).next.bind(it);

  if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") {
    if (it) o = it;
    var i = 0;
    return function () {
      if (i >= o.length) return {
        done: true
      };
      return {
        done: false,
        value: o[i++]
      };
    };
  }

  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
}

function roundDown(amount, decimals) {
  return Math.floor(amount * Math.pow(10, decimals)) / Math.pow(10, decimals);
}
function roundUp(amount, decimals) {
  return Math.ceil(amount * Math.pow(10, decimals)) / Math.pow(10, decimals);
} // FUNCTIONS

function concatArrays(arrays) {
  // sum of individual array lengths
  var totalLength = arrays.reduce(function (acc, value) {
    return acc + value.length;
  }, 0);
  if (!arrays.length) return null;
  var result = new Uint8Array(totalLength); // for each array - copy it over result
  // next array is copied right after the previous one

  var length = 0;

  for (var _iterator = _createForOfIteratorHelperLoose(arrays), _step; !(_step = _iterator()).done;) {
    var array = _step.value;
    result.set(array, length);
    length += array.length;
  }

  return result;
}
function formatPrefixState(state) {
  var formattedState = {};

  for (var _i = 0, _Object$entries = Object.entries(state); _i < _Object$entries.length; _i++) {
    var _Object$entries$_i = _Object$entries[_i],
        key = _Object$entries$_i[0],
        value = _Object$entries$_i[1];
    var indexUnderScore = key.indexOf("_"); // case when it is a prefix term

    if (indexUnderScore > 0) {
      var prefix = key.substring(0, indexUnderScore + 1);
      var hex = key.substring(indexUnderScore + 1);
      var formatted = Uint8Array.from(hex, function (e) {
        return e.charCodeAt(0);
      });
      var number = formatted[7];
      formattedState[prefix + number.toString()] = value;
    } else {
      formattedState[key] = value;
    }
  }

  return formattedState;
}
function parseAddressBytes(bytes) {
  return encodeAddress(Buffer.from(bytes, "base64"));
}
function decodeBytes(bytes) {
  var result = new Uint8Array(bytes.length);

  for (var i = 0; i < bytes.length; ++i) {
    result[i] = bytes.charCodeAt(i);
  }

  return result;
}
function addressEquals(a, b) {
  return a.publicKey.length == b.publicKey.length && a.publicKey.every(function (val, index) {
    return val == b.publicKey[index];
  }) && a.checksum.length == b.checksum.length && a.checksum.every(function (val, index) {
    return val == b.checksum[index];
  });
}
function composeTransactions(txnsToCompose) {
  var txns = [];

  for (var _iterator2 = _createForOfIteratorHelperLoose(txnsToCompose), _step2; !(_step2 = _iterator2()).done;) {
    var txnGroup = _step2.value;

    for (var _iterator3 = _createForOfIteratorHelperLoose(txnGroup), _step3; !(_step3 = _iterator3()).done;) {
      var _txn = _step3.value;
      txns.push(_txn);
    }
  }

  for (var _i2 = 0, _txns = txns; _i2 < _txns.length; _i2++) {
    var txn = _txns[_i2];
    txn.group = undefined;
  }

  return assignGroupID(txns);
}

// INTERFACE
var TxnLoadMode;

(function (TxnLoadMode) {
  TxnLoadMode[TxnLoadMode["REFRESH"] = 0] = "REFRESH";
  TxnLoadMode[TxnLoadMode["REVERSE"] = 1] = "REVERSE";
})(TxnLoadMode || (TxnLoadMode = {}));

var ParsedTransaction = function ParsedTransaction(transaction, protocol, app, action, params, assetsIn, assetsOut) {
  this.transactionId = transaction['id'];
  this.groupId = transaction['group'];
  this.block = transaction['confirmed-round'];
  this.time = transaction['round-time'];
  this.protocol = protocol;
  this.app = app;
  this.action = action;
  this.params = params; // flatten assets

  for (var _i = 0, _Object$entries = Object.entries(assetsIn); _i < _Object$entries.length; _i++) {
    var _Object$entries$_i = _Object$entries[_i],
        assetId = _Object$entries$_i[0],
        amount = _Object$entries$_i[1];

    if (assetId in assetsOut && amount > assetsOut[assetId]) {
      assetsIn[assetId] -= assetsOut[assetId];
      delete assetsOut[assetId];
    }
  }

  this.assetsIn = assetsIn;
  this.assetsOut = assetsOut;
};

/**
 * Function to get global state of an application
 *
 * @param   {Algodv2}           algodClient
 *
 * @return  {dict<string,any>}  dictionary of global state
 */

function getApplicationGlobalState(_x, _x2) {
  return _getApplicationGlobalState.apply(this, arguments);
}
/**
 * Function to get local state for an account info object
 *
 * @param   {AccountInformation}           accountInfo
 *
 * @return  {dict<number,dict{string:any}>}  dictionary of user local states
 */

function _getApplicationGlobalState() {
  _getApplicationGlobalState = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(algodClient, applicationId) {
    var response, results;
    return _regeneratorRuntime().wrap(function _callee2$(_context2) {
      while (1) {
        switch (_context2.prev = _context2.next) {
          case 0:
            _context2.next = 2;
            return algodClient.getApplicationByID(applicationId)["do"]();

          case 2:
            response = _context2.sent;
            results = {};
            _context2.next = 6;
            return Promise.all(response.params["global-state"].map( /*#__PURE__*/function () {
              var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(x) {
                return _regeneratorRuntime().wrap(function _callee$(_context) {
                  while (1) {
                    switch (_context.prev = _context.next) {
                      case 0:
                        if (x.value.type == 1) {
                          results[Base64Encoder.decode(x.key)] = x.value.bytes;
                        } else {
                          results[Base64Encoder.decode(x.key)] = x.value.uint;
                        }

                      case 1:
                      case "end":
                        return _context.stop();
                    }
                  }
                }, _callee);
              }));

              return function (_x12) {
                return _ref.apply(this, arguments);
              };
            }()));

          case 6:
            return _context2.abrupt("return", results);

          case 7:
          case "end":
            return _context2.stop();
        }
      }
    }, _callee2);
  }));
  return _getApplicationGlobalState.apply(this, arguments);
}

function getLocalStatesFromAccountInfo(_x3) {
  return _getLocalStatesFromAccountInfo.apply(this, arguments);
}
/**
 * Function to get local state for a given address and application
 *
 * @param   {Algodv2}           algodClient
 * @param   {string}            address
 *
 * @return  {dict<number,dict{string:any}>}  dictionary of user local states
 */

function _getLocalStatesFromAccountInfo() {
  _getLocalStatesFromAccountInfo = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(accountInfo) {
    var results;
    return _regeneratorRuntime().wrap(function _callee5$(_context5) {
      while (1) {
        switch (_context5.prev = _context5.next) {
          case 0:
            results = {};
            _context5.next = 3;
            return Promise.all(accountInfo["apps-local-state"].map( /*#__PURE__*/function () {
              var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(appLocalState) {
                var localState;
                return _regeneratorRuntime().wrap(function _callee4$(_context4) {
                  while (1) {
                    switch (_context4.prev = _context4.next) {
                      case 0:
                        if (!appLocalState["key-value"]) {
                          _context4.next = 7;
                          break;
                        }

                        localState = {};
                        _context4.next = 4;
                        return Promise.all(appLocalState["key-value"].map( /*#__PURE__*/function () {
                          var _ref3 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(x) {
                            var key;
                            return _regeneratorRuntime().wrap(function _callee3$(_context3) {
                              while (1) {
                                switch (_context3.prev = _context3.next) {
                                  case 0:
                                    key = Base64Encoder.decode(x.key);

                                    if (x.value.type == 1) {
                                      localState[key] = x.value.bytes;
                                    } else {
                                      localState[key] = x.value.uint;
                                    }

                                  case 2:
                                  case "end":
                                    return _context3.stop();
                                }
                              }
                            }, _callee3);
                          }));

                          return function (_x14) {
                            return _ref3.apply(this, arguments);
                          };
                        }()));

                      case 4:
                        results[appLocalState.id] = localState;
                        _context4.next = 8;
                        break;

                      case 7:
                        results[appLocalState.id] = {};

                      case 8:
                      case "end":
                        return _context4.stop();
                    }
                  }
                }, _callee4);
              }));

              return function (_x13) {
                return _ref2.apply(this, arguments);
              };
            }()));

          case 3:
            return _context5.abrupt("return", results);

          case 4:
          case "end":
            return _context5.stop();
        }
      }
    }, _callee5);
  }));
  return _getLocalStatesFromAccountInfo.apply(this, arguments);
}

function getLocalStates(_x4, _x5) {
  return _getLocalStates.apply(this, arguments);
}
/**
 * Function to get balances given an account info object
 *
 * @param   {AccountInformation}           accountInfo
 *
 * @return  {dict<string,int>}  dictionary of assets to amounts
 */

function _getLocalStates() {
  _getLocalStates = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(algodClient, address) {
    var results, accountInfo;
    return _regeneratorRuntime().wrap(function _callee8$(_context8) {
      while (1) {
        switch (_context8.prev = _context8.next) {
          case 0:
            results = {};
            _context8.next = 3;
            return algodClient.accountInformation(address)["do"]();

          case 3:
            accountInfo = _context8.sent;
            _context8.next = 6;
            return Promise.all(accountInfo["apps-local-state"].map( /*#__PURE__*/function () {
              var _ref4 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(appLocalState) {
                var localState;
                return _regeneratorRuntime().wrap(function _callee7$(_context7) {
                  while (1) {
                    switch (_context7.prev = _context7.next) {
                      case 0:
                        if (!appLocalState["key-value"]) {
                          _context7.next = 7;
                          break;
                        }

                        localState = {};
                        _context7.next = 4;
                        return Promise.all(appLocalState["key-value"].map( /*#__PURE__*/function () {
                          var _ref5 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(x) {
                            var key;
                            return _regeneratorRuntime().wrap(function _callee6$(_context6) {
                              while (1) {
                                switch (_context6.prev = _context6.next) {
                                  case 0:
                                    key = Base64Encoder.decode(x.key);

                                    if (x.value.type == 1) {
                                      localState[key] = x.value.bytes;
                                    } else {
                                      localState[key] = x.value.uint;
                                    }

                                  case 2:
                                  case "end":
                                    return _context6.stop();
                                }
                              }
                            }, _callee6);
                          }));

                          return function (_x16) {
                            return _ref5.apply(this, arguments);
                          };
                        }()));

                      case 4:
                        results[appLocalState.id] = localState;
                        _context7.next = 8;
                        break;

                      case 7:
                        results[appLocalState.id] = {};

                      case 8:
                      case "end":
                        return _context7.stop();
                    }
                  }
                }, _callee7);
              }));

              return function (_x15) {
                return _ref4.apply(this, arguments);
              };
            }()));

          case 6:
            return _context8.abrupt("return", results);

          case 7:
          case "end":
            return _context8.stop();
        }
      }
    }, _callee8);
  }));
  return _getLocalStates.apply(this, arguments);
}

function getAccountBalancesFromAccountInfo(_x6) {
  return _getAccountBalancesFromAccountInfo.apply(this, arguments);
}
/**
 * Function to get balances for an account
 *
 * @param   {Algodv2}           algodClient
 * @param   {string}            address
 *
 * @return  {dict<string,int>}  dictionary of assets to amounts
 */

function _getAccountBalancesFromAccountInfo() {
  _getAccountBalancesFromAccountInfo = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(accountInfo) {
    var results;
    return _regeneratorRuntime().wrap(function _callee10$(_context10) {
      while (1) {
        switch (_context10.prev = _context10.next) {
          case 0:
            results = {};
            results[1] = accountInfo["amount"];
            _context10.next = 4;
            return Promise.all(accountInfo["assets"].map( /*#__PURE__*/function () {
              var _ref6 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(x) {
                return _regeneratorRuntime().wrap(function _callee9$(_context9) {
                  while (1) {
                    switch (_context9.prev = _context9.next) {
                      case 0:
                        results[x["asset-id"]] = x["amount"];

                      case 1:
                      case "end":
                        return _context9.stop();
                    }
                  }
                }, _callee9);
              }));

              return function (_x17) {
                return _ref6.apply(this, arguments);
              };
            }()));

          case 4:
            return _context10.abrupt("return", results);

          case 5:
          case "end":
            return _context10.stop();
        }
      }
    }, _callee10);
  }));
  return _getAccountBalancesFromAccountInfo.apply(this, arguments);
}

function getAccountBalances(_x7, _x8) {
  return _getAccountBalances.apply(this, arguments);
}
/**
 * Function to get min balance from an account info object
 *
 * @param   {AccountInformation}           accountInfo
 *
 * @return  {number}  min algo balance for an account
 */

function _getAccountBalances() {
  _getAccountBalances = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12(algodClient, address) {
    var results, accountInfo;
    return _regeneratorRuntime().wrap(function _callee12$(_context12) {
      while (1) {
        switch (_context12.prev = _context12.next) {
          case 0:
            results = {};
            _context12.next = 3;
            return algodClient.accountInformation(address)["do"]();

          case 3:
            accountInfo = _context12.sent;
            results[1] = accountInfo["amount"];
            _context12.next = 7;
            return Promise.all(accountInfo["assets"].map( /*#__PURE__*/function () {
              var _ref7 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(x) {
                return _regeneratorRuntime().wrap(function _callee11$(_context11) {
                  while (1) {
                    switch (_context11.prev = _context11.next) {
                      case 0:
                        results[x["asset-id"]] = x["amount"];

                      case 1:
                      case "end":
                        return _context11.stop();
                    }
                  }
                }, _callee11);
              }));

              return function (_x18) {
                return _ref7.apply(this, arguments);
              };
            }()));

          case 7:
            return _context12.abrupt("return", results);

          case 8:
          case "end":
            return _context12.stop();
        }
      }
    }, _callee12);
  }));
  return _getAccountBalances.apply(this, arguments);
}

function getAccountMinBalanceFromAccountInfo(_x9) {
  return _getAccountMinBalanceFromAccountInfo.apply(this, arguments);
}
/**
 * Function to get min balance for an account
 *
 * @param   {Algodv2}           algodClient
 * @param   {string}            address
 *
 * @return  {number}  min algo balance for an account
 */

function _getAccountMinBalanceFromAccountInfo() {
  _getAccountMinBalanceFromAccountInfo = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee13(accountInfo) {
    return _regeneratorRuntime().wrap(function _callee13$(_context13) {
      while (1) {
        switch (_context13.prev = _context13.next) {
          case 0:
            return _context13.abrupt("return", accountInfo["min-balance"]);

          case 1:
          case "end":
            return _context13.stop();
        }
      }
    }, _callee13);
  }));
  return _getAccountMinBalanceFromAccountInfo.apply(this, arguments);
}

function getAccountMinBalance(_x10, _x11) {
  return _getAccountMinBalance.apply(this, arguments);
}

function _getAccountMinBalance() {
  _getAccountMinBalance = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee14(algodClient, address) {
    var accountInfo;
    return _regeneratorRuntime().wrap(function _callee14$(_context14) {
      while (1) {
        switch (_context14.prev = _context14.next) {
          case 0:
            _context14.next = 2;
            return algodClient.accountInformation(address)["do"]();

          case 2:
            accountInfo = _context14.sent;
            return _context14.abrupt("return", accountInfo["min-balance"]);

          case 4:
          case "end":
            return _context14.stop();
        }
      }
    }, _callee14);
  }));
  return _getAccountMinBalance.apply(this, arguments);
}
function storeTransferDetails(txn, store) {
  if (txn["tx-type"] == "pay") {
    store[ALGO_ASSET_ID] = txn['payment-transaction']['amount'];
  } else if (txn["tx-type"] == "axfer") {
    store[txn['asset-transfer-transaction']['asset-id']] = txn['asset-transfer-transaction']['amount'];
  }
}

// IMPORTS
// INTERFACE
var BaseLendingUser = /*#__PURE__*/function () {
  function BaseLendingUser(algofiClient, address) {
    this.v2 = algofiClient.lending.v2.getUser(address);
  }

  var _proto = BaseLendingUser.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v2.loadState(userLocalStates);

            case 2:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseLendingUser;
}();

// IMPORTS
// INTERFACE
var BaseStakingUser = /*#__PURE__*/function () {
  function BaseStakingUser(algofiClient, address) {
    this.v1 = algofiClient.staking.v1.getUser(address);
    this.v2 = algofiClient.staking.v2.getUser(address);
  }

  var _proto = BaseStakingUser.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v1.loadState(userLocalStates);

            case 2:
              _context.next = 4;
              return this.v2.loadState(userLocalStates);

            case 4:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseStakingUser;
}();

// IMPORTS
// INTERFACE
var BaseLendingUser$1 = /*#__PURE__*/function () {
  function BaseLendingUser(algofiClient, address) {
    this.v1 = algofiClient.governance.v1.getUser(address);
    this.network = algofiClient.network;
  }

  var _proto = BaseLendingUser.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v1.loadState(userLocalStates);

            case 2:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseLendingUser;
}();

var AlgofiUser = /*#__PURE__*/function () {
  /**
   * Constructor for the algofi client class.
   *
   * @param algofiClient - algofi client
   * @param address - address for user
   */
  function AlgofiUser(algofiClient, address) {
    // account state
    this.balances = {};
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.indexer = this.algofiClient.indexer;
    this.address = address; // lending

    this.lending = new BaseLendingUser(this.algofiClient, this.address); // staking

    this.staking = new BaseStakingUser(this.algofiClient, this.address); // governance

    this.governance = new BaseLendingUser$1(this.algofiClient, this.address);
  }
  /**
   * Function to load the states of all of the sub users on the algofi user
   * class.
   */


  var _proto = AlgofiUser.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var accountInfo, localStates, loadLendingPromise, loadStakingPromise, loadGovernancePromise;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.algod.accountInformation(this.address)["do"]();

            case 2:
              accountInfo = _context.sent;
              _context.next = 5;
              return getLocalStatesFromAccountInfo(accountInfo);

            case 5:
              localStates = _context.sent;
              _context.next = 8;
              return getAccountBalancesFromAccountInfo(accountInfo);

            case 8:
              this.balances = _context.sent;
              _context.next = 11;
              return getAccountMinBalanceFromAccountInfo(accountInfo);

            case 11:
              this.minBalance = _context.sent;
              // update protocol user classes
              loadLendingPromise = this.lending.loadState(localStates); // update user staking state

              loadStakingPromise = this.staking.loadState(localStates); // update user governance state

              loadGovernancePromise = this.governance.loadState(localStates); // await completion

              _context.next = 17;
              return Promise.all([loadLendingPromise, loadStakingPromise, loadGovernancePromise]);

            case 17:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Function to determine whether someone is opted into an asset or not.
   *
   * @param assetId - asset id
   * @returns whether or not the user is opted into the asset id.
   */
  ;

  _proto.isOptedInToAsset = function isOptedInToAsset(assetId) {
    if (assetId in this.balances) {
      return true;
    } else {
      return false;
    }
  };

  _proto.getTransactionHistory = /*#__PURE__*/function () {
    var _getTransactionHistory = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(mode) {
      var accountTxns, txnIdx, txn;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              accountTxns = {};

              if (mode == TxnLoadMode.REFRESH) {
                // clear transactions
                this.transactions = [];
              }

              if (!(mode == TxnLoadMode.REVERSE && this.transactions.length > 0)) {
                _context2.next = 9;
                break;
              }

              _context2.next = 6;
              return this.indexer.lookupAccountTransactions(this.address).maxRound(this.transactions.slice(-1)[0].block).limit(500)["do"]();

            case 6:
              accountTxns = _context2.sent;
              _context2.next = 12;
              break;

            case 9:
              _context2.next = 11;
              return this.indexer.lookupAccountTransactions(this.address).limit(500)["do"]();

            case 11:
              accountTxns = _context2.sent;

            case 12:
              for (txnIdx = 0; txnIdx < accountTxns["transactions"].length; txnIdx++) {
                txn = accountTxns["transactions"][txnIdx];

                if (txn["tx-type"] == "appl") {
                  if (this.algofiClient.lending.v2.isLendingTransaction(txn)) {
                    this.lending.v2.parseTransaction(accountTxns["transactions"], txnIdx, this.transactions);
                  } else if (this.algofiClient.amm.v1.isAMMTransaction(txn)) {
                    this.algofiClient.amm.v1.parseTransaction(accountTxns["transactions"], txnIdx, this.transactions);
                  }
                }
              }

            case 13:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getTransactionHistory(_x) {
      return _getTransactionHistory.apply(this, arguments);
    }

    return getTransactionHistory;
  }();

  return AlgofiUser;
}();

var _AssetConfigs;

var BANK_ASSET_ID$1 = 900652777; // INTERFACE

var AssetConfig =
/**
 * Constructor for the asset config class.
 *
 * @param name - asset name
 * @param assetId - asset id
 * @param decimals - asset decimals
 */
function AssetConfig(name, unitName, assetId, decimals, defaultPrice) {
  this.name = name;
  this.unitName = unitName;
  this.assetId = assetId;
  this.decimals = decimals;
  this.defaultPrice = defaultPrice;
};
var AssetConfigs = (_AssetConfigs = {}, _AssetConfigs[Network.MAINNET] = {
  1: /*#__PURE__*/new AssetConfig("ALGO", "ALGO", 1, 6, undefined),
  818179690: /*#__PURE__*/new AssetConfig("AF-BANK-ALGO-STANDARD", "AF-BANK", 818179690, 6, undefined),
  31566704: /*#__PURE__*/new AssetConfig("USDC", "USDC", 31566704, 6, 1.0),
  818182311: /*#__PURE__*/new AssetConfig("AF-BANK-USDC-STANDARD", "AF-BANK", 818182311, 6, undefined),
  386192725: /*#__PURE__*/new AssetConfig("goBTC", "goBTC", 386192725, 8, undefined),
  818184214: /*#__PURE__*/new AssetConfig("AF-BANK-GOBTC-STANDARD", "AF-BANK", 818184214, 6, undefined),
  386195940: /*#__PURE__*/new AssetConfig("goETH", "goETH", 386195940, 8, undefined),
  818188553: /*#__PURE__*/new AssetConfig("AF-BANK-GOETH-STANDARD", "AF-BANK", 818188553, 6, undefined),
  312769: /*#__PURE__*/new AssetConfig("USDT", "USDT", 312769, 6, 1.0),
  818190568: /*#__PURE__*/new AssetConfig("AF-BANK-USDT-STANDARD", "AF-BANK", 818190568, 6, undefined),
  841126810: /*#__PURE__*/new AssetConfig("STBL2", "STBL2", 841126810, 6, 1.0),
  841157954: /*#__PURE__*/new AssetConfig("AF-BANK_STBL2-STABLE", "AF-BANK", 841157954, 6, undefined),
  // VAULT
  879951266: /*#__PURE__*/new AssetConfig("AF-BANK-ALGO-VAULT", "AF-BANK", 879951266, 6, undefined),
  // BANK
  900652777: /*#__PURE__*/new AssetConfig("BANK", "BANK", 900652777, 6, undefined),
  900919286: /*#__PURE__*/new AssetConfig("AF-BANK-BANK-STANDARD", "AF-BANK", 900919286, 6, undefined),
  // DEPRECATED
  // 842179393: new AssetConfig("wETH", "wETH", 842179393, 8, undefined),
  // 849576890: new AssetConfig("AF-BANK-WETH-STANDARD", "AF-BANK", 849576890, 6, undefined),
  // 846904356: new AssetConfig("wUSDC", "wUSDC", 846904356, 6, undefined),
  // 849581529: new AssetConfig("AF-BANK-wUSDC-STANDARD", "AF-BANK", 849581529, 6, undefined),
  // LP collateral
  841171328: /*#__PURE__*/new AssetConfig("AF-USDC-STBL2-NANO-LP", "AF-POOL", 841171328, 6, undefined),
  841462373: /*#__PURE__*/new AssetConfig("AF-BANK-AF-POOL-LP", "AF-BANK", 841462373, 6, undefined),
  855717054: /*#__PURE__*/new AssetConfig("AF-ALGO-STBL2-0.25%-LP", "AF-POOL", 855717054, 6, undefined),
  856217307: /*#__PURE__*/new AssetConfig("AF-BANK-AF-POOL-LP", "AF-POOL", 856217307, 6, undefined),
  870151164: /*#__PURE__*/new AssetConfig("AF-goBTC-STBL2-0.25%-LP", "AF-POOL", 870151164, 6, undefined),
  870380101: /*#__PURE__*/new AssetConfig("AF-BANK-AF-POOL-LP", "AF-POOL", 870380101, 6, undefined),
  870150187: /*#__PURE__*/new AssetConfig("AF-goETH-STBL2-0.25%-LP", "AF-POOL", 870150187, 6, undefined),
  870391958: /*#__PURE__*/new AssetConfig("AF-BANK-AF-POOL-LP", "AF-POOL", 870391958, 6, undefined),
  // v1 staking assets
  465865291: /*#__PURE__*/new AssetConfig("STBL", "STBL", 465865291, 6, undefined),
  470842789: /*#__PURE__*/new AssetConfig("DEFLY", "DEFLY", 470842789, 6, undefined),
  283820866: /*#__PURE__*/new AssetConfig("XET", "XET", 283820866, 9, undefined),
  287867876: /*#__PURE__*/new AssetConfig("OPUL", "OPUL", 287867876, 10, undefined),
  444035862: /*#__PURE__*/new AssetConfig("ZONE", "ZONE", 444035862, 6, undefined),
  467020179: /*#__PURE__*/new AssetConfig("TM-STBL-USDC-v1-LP", "TM1POOL", 467020179, 6, 1.0),
  552737686: /*#__PURE__*/new AssetConfig("TM-STBL-USDC-v1.1-LP", "TMPOOL11", 552737686, 6, 1.0),
  607645566: /*#__PURE__*/new AssetConfig("AF-STBL-ALGO-0.25%-LP", "AF-BANK", 607645566, 6, undefined),
  609172718: /*#__PURE__*/new AssetConfig("AF-STBL-USDC-0.25%-LP", "AF-BANK", 609172718, 6, undefined),
  658337286: /*#__PURE__*/new AssetConfig("AF-STBL-USDC-NANO-LP", "AF-BANK", 658337286, 6, undefined),
  659678778: /*#__PURE__*/new AssetConfig("AF-USDC-USDT-NANO-LP", "AF-BANK", 659678778, 6, undefined),
  659677515: /*#__PURE__*/new AssetConfig("AF-STBL-USDT-NANO-LP", "AF-BANK", 659677515, 6, undefined),
  635256863: /*#__PURE__*/new AssetConfig("AF-STBL-XET-0.75%-LP", "AF-BANK", 635256863, 6, undefined),
  647801343: /*#__PURE__*/new AssetConfig("AF-STBL-ZONE-0.75%-LP", "AF-BANK", 647801343, 6, undefined),
  624956449: /*#__PURE__*/new AssetConfig("AF-STBL-DEFLY-0.75%-LP", "AF-BANK", 624956449, 6, undefined),
  635846733: /*#__PURE__*/new AssetConfig("AF-STBL-goBTC-0.25%-LP", "AF-BANK", 635846733, 6, undefined),
  635854339: /*#__PURE__*/new AssetConfig("AF-STBL-goETH-0.25%-LP", "AF-BANK", 635854339, 6, undefined),
  637802380: /*#__PURE__*/new AssetConfig("AF-STBL-OPUL-0.75%-LP", "AF-BANK", 637802380, 6, undefined),
  // v2 staking assets
  900924035: /*#__PURE__*/new AssetConfig("AF-STBL2-BANK-0.25%-LP", "AF-BANK", 900924035, 6, undefined),
  919950894: /*#__PURE__*/new AssetConfig("AF-ALGO-USDC-0.25%-LP", "AF-BANK", 919950894, 6, undefined),
  962367827: /*#__PURE__*/new AssetConfig("AF-ALGO-BANK-0.25%-LP", "AF-BANK", 962367827, 6, undefined)
}, _AssetConfigs[Network.TESTNET] = {
  1: /*#__PURE__*/new AssetConfig("ALGO", "ALGO", 1, 6, undefined),
  107212062: /*#__PURE__*/new AssetConfig("BANK", "BANK", 107212062, 6, .20),
  104193939: /*#__PURE__*/new AssetConfig("AF-BANK-ALGO-STANDARD", "AF-BANK", 104193939, 6, undefined),
  104194013: /*#__PURE__*/new AssetConfig("USDC", "USDC", 104194013, 6, undefined),
  104207173: /*#__PURE__*/new AssetConfig("AF-BANK-USDC-STANDARD", "AF-BANK", 104207173, 6, undefined),
  104207287: /*#__PURE__*/new AssetConfig("goBTC", "goBTC", 104207287, 8, undefined),
  104207503: /*#__PURE__*/new AssetConfig("AF-BANK-GOBTC-STANDARD", "AF-BANK", 104207503, 6, undefined),
  104207533: /*#__PURE__*/new AssetConfig("goETH", "goETH", 104207533, 8, undefined),
  104207983: /*#__PURE__*/new AssetConfig("AF-BANK-GOETH-STANDARD", "AF-BANK", 104207983, 6, undefined),
  104208050: /*#__PURE__*/new AssetConfig("USDT", "USDT", 104208050, 6, undefined),
  104222974: /*#__PURE__*/new AssetConfig("AF-BANK-USDT-STANDARD", "AF-BANK", 104222974, 6, undefined),
  104210500: /*#__PURE__*/new AssetConfig("STBL2", "STBL2", 104210500, 6, undefined),
  104217422: /*#__PURE__*/new AssetConfig("AF-BANK-STBL2-STABLE", "AF-BANK", 104217422, 6, undefined),
  104228491: /*#__PURE__*/new AssetConfig("AF-bUSDC-bSTBL2-NANO-LP", "AF-POOL", 104228491, 6, undefined),
  104238470: /*#__PURE__*/new AssetConfig("AF-BANK-AF-bUSDC-bSTBL2-NANO-LP-LP", "AF-BANK", 104238470, 6, undefined)
}, _AssetConfigs);

// INTERFACE
var AssetData = function AssetData(assetId, name, unitName, decimals, price) {
  this.assetId = assetId;
  this.name = name;
  this.unitName = unitName;
  this.decimals = decimals;
  this.price = price;
};

// IMPORTS

var AssetAmount = /*#__PURE__*/function () {
  /**
   * Constructor for the asset class
   *
   * @param amount - quantity of underlying asset
   * @param assetData - assetData object
   */
  function AssetAmount(amount, assetData) {
    this.amount = amount;
    this.assetData = assetData;
  }

  var _proto = AssetAmount.prototype;

  _proto.toUSD = function toUSD() {
    if (!this.assetData.price || this.assetData.price == 0) {
      console.log("Error: unable to get dollarized price for asset:", this.assetData);
      return 0;
    }

    return this.amount * this.assetData.price / Math.pow(10, this.assetData.decimals);
  };

  _proto.toDisplayAmount = function toDisplayAmount(roundResultUp) {
    if (roundResultUp === void 0) {
      roundResultUp = false;
    }

    if (roundResultUp) {
      return roundUp(this.amount / Math.pow(10, this.assetData.decimals), this.assetData.decimals);
    } else {
      return roundDown(this.amount / Math.pow(10, this.assetData.decimals), this.assetData.decimals);
    }
  };

  return AssetAmount;
}();

var AssetDataClient = /*#__PURE__*/function () {
  function AssetDataClient(algofiClient) {
    this.assets = {};
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.assetConfigs = AssetConfigs[this.network];
  }

  var _proto = AssetDataClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var _this = this;

      var _i, _Object$values, assetConfig, endpoint, network, assetsPromise, lpTokensPromise;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              // load configured assets
              for (_i = 0, _Object$values = Object.values(this.assetConfigs); _i < _Object$values.length; _i++) {
                assetConfig = _Object$values[_i];

                if (!(assetConfig.assetId in this.assets)) {
                  // do not overwrite already loaded data
                  this.assets[assetConfig.assetId] = new AssetData(assetConfig.assetId, assetConfig.name, assetConfig.unitName, assetConfig.decimals, assetConfig.defaultPrice);
                }
              }

              endpoint = getAnalyticsEndpoint(this.network);
              network = getNetworkName(this.network); // load prices from amm analytics

              assetsPromise = request.get(endpoint + "/assets?network=" + network).then(function (resp) {
                if (resp.status == 200) {
                  for (var _iterator = _createForOfIteratorHelperLoose(resp.body), _step; !(_step = _iterator()).done;) {
                    var assetInfo = _step.value;
                    _this.assets[assetInfo.asset_id] = new AssetData(assetInfo.asset_id, assetInfo.name, assetInfo.unit_name, assetInfo.decimals, assetInfo.price);
                  }
                } else {
                  console.log("Bad Response");
                }
              })["catch"](function (err) {
                console.log(err.message);
              }); // load lp prices from amm analytics

              lpTokensPromise = request.get(endpoint + "/ammLPTokens?network=" + network).then(function (resp) {
                if (resp.status == 200) {
                  for (var _iterator2 = _createForOfIteratorHelperLoose(resp.body), _step2; !(_step2 = _iterator2()).done;) {
                    var assetInfo = _step2.value;

                    if (!(assetInfo.asset_id in _this.assets)) {
                      _this.assets[assetInfo.asset_id] = new AssetData(assetInfo.asset_id, assetInfo.name, assetInfo.unit_name, assetInfo.decimals, assetInfo.price);
                    } else {
                      _this.assets[assetInfo.asset_id].price = assetInfo.price;
                    }
                  }
                } else {
                  console.log("Bad Response");
                }
              })["catch"](function (err) {
                console.log(err.message);
              });
              _context.next = 7;
              return Promise.all([assetsPromise, lpTokensPromise]);

            case 7:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.loadLendingAssetState = /*#__PURE__*/function () {
    var _loadLendingAssetState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      var _i2, _Object$entries, _Object$entries$_i, market, underlyingAssetConfig, bAssetConfig;

      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              // load prices from oracles (v2 lending)
              for (_i2 = 0, _Object$entries = Object.entries(this.algofiClient.lending.v2.markets); _i2 < _Object$entries.length; _i2++) {
                _Object$entries$_i = _Object$entries[_i2], market = _Object$entries$_i[1];
                // load underlying asset
                underlyingAssetConfig = this.assetConfigs[market.underlyingAssetId]; // skip oracle pricing for BANK

                if (underlyingAssetConfig.assetId != BANK_ASSET_ID$1) {
                  this.assets[underlyingAssetConfig.assetId] = new AssetData(underlyingAssetConfig.assetId, underlyingAssetConfig.name, underlyingAssetConfig.unitName, underlyingAssetConfig.decimals, market.oracle.price);
                } // load b asset


                bAssetConfig = this.assetConfigs[market.bAssetId];
                this.assets[bAssetConfig.assetId] = new AssetData(bAssetConfig.assetId, bAssetConfig.name, bAssetConfig.unitName, bAssetConfig.decimals, market.bAssetToUnderlying(Math.pow(10, bAssetConfig.decimals)).toUSD());
              }

            case 1:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function loadLendingAssetState() {
      return _loadLendingAssetState.apply(this, arguments);
    }

    return loadLendingAssetState;
  }();

  _proto.getAsset = function getAsset(amount, assetId) {
    return new AssetAmount(amount, this.assets[assetId]);
  };

  _proto.getAssetFromDisplayAmount = function getAssetFromDisplayAmount(displayAmount, assetId) {
    var assetData = this.assets[assetId];
    return new AssetAmount(Math.floor(displayAmount * Math.pow(10, assetData.decimals)), assetData);
  };

  _proto.getAssetFromUSDAmount = function getAssetFromUSDAmount(usdAmount, assetId) {
    var assetData = this.assets[assetId];
    return new AssetAmount(Math.floor(usdAmount * Math.pow(10, assetData.decimals) / assetData.price), assetData);
  };

  _proto.loadAsset = /*#__PURE__*/function () {
    var _loadAsset = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(amount, assetId) {
      var asset;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              if (assetId in this.assets) {
                _context3.next = 5;
                break;
              }

              _context3.next = 3;
              return this.algod.getAssetByID(assetId)["do"]();

            case 3:
              asset = _context3.sent;
              this.assets[assetId] = new AssetData(assetId, asset.params.name, asset.params["unit-name"], asset.params.decimals, 0);

            case 5:
              return _context3.abrupt("return", this.getAsset(amount, assetId));

            case 6:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function loadAsset(_x, _x2) {
      return _loadAsset.apply(this, arguments);
    }

    return loadAsset;
  }();

  return AssetDataClient;
}();

var _ManagerConfigs;

var ManagerConfig =
/**
 * Constructor for the manager config class.
 *
 * @param appId - manager app id
 */
function ManagerConfig(appId) {
  this.appId = appId;
};
var ManagerConfigs = (_ManagerConfigs = {}, _ManagerConfigs[Network.MAINNET] = /*#__PURE__*/new ManagerConfig(818176933), _ManagerConfigs[Network.TESTNET] = /*#__PURE__*/new ManagerConfig(104184985), _ManagerConfigs);

// ENUMS
var MarketType;

(function (MarketType) {
  MarketType[MarketType["STANDARD"] = 0] = "STANDARD";
  MarketType[MarketType["STBL"] = 1] = "STBL";
  MarketType[MarketType["VAULT"] = 2] = "VAULT";
  MarketType[MarketType["LP"] = 3] = "LP";
})(MarketType || (MarketType = {})); // STRING CONSTANTS


var MANAGER_STRINGS = {
  // USER STATE
  storage_account: "sa",
  user_account: "ua",
  opted_in_market_count: "omc",
  opted_in_markets_page_prefix: "om_",
  // APPLICATION CALLS
  calculate_user_position: "cup",
  farm_ops: "fo",
  send_governance_txn: "sgt",
  send_keyreg_txn: "skt",
  send_keyreg_offline_txn: "skot",
  set_market_oracle_parameters: "smop",
  storage_account_opt_in: "saoi",
  user_asset_opt_in: "uaoi",
  user_market_close_out: "umco",
  user_market_opt_in: "umoi",
  user_opt_in: "uoi",
  validate_storage_account_txn: "vsat",
  validate_market: "vm"
};
var MARKET_STRINGS = {
  // GLOBAL STATE
  // static
  underlying_asset_id: "uai",
  b_asset_id: "bai",
  market_type: "mt",
  // parameters
  borrow_factor: "bf",
  collateral_factor: "cf",
  flash_loan_fee: "flf",
  flash_loan_protocol_fee: "flpf",
  max_flash_loan_ratio: "mflr",
  liquidation_incentive: "li",
  liquidation_fee: "lf",
  reserve_factor: "rf",
  underlying_supply_cap: "usc",
  underlying_borrow_cap: "ubc",
  // interest rate model
  base_interest_rate: "bir",
  base_interest_slope: "bis",
  quadratic_interest_amplification_factor: "eiaf",
  target_utilization_ratio: "tur",
  // oracle
  oracle_app_id: "oai",
  oracle_price_field_name: "opfn",
  oracle_price_scale_factor: "opsf",
  // balance
  underlying_cash: "uc",
  underlying_borrowed: "ub",
  underlying_reserves: "ur",
  borrow_share_circulation: "bsc",
  b_asset_circulation: "bac",
  active_b_asset_collateral: "ac",
  // interest
  latest_time: "lt",
  borrow_index: "bi",
  implied_borrow_index: "ibi",
  // rewards
  rewards_latest_time: "rlt",
  rewards_admin_prefix: "ra_",
  rewards_program_state_prefix: "rps_",
  rewards_index_prefix: "ri_",
  rewards_escrow_account: "rea",
  // stbl market
  underlying_protocol_reserve: "upr",
  // vault market
  opt_in_enabled: "oie",
  // USER STATE
  user_active_b_asset_collateral: "ubac",
  user_borrow_shares: "ubs",
  user_rewards_program_number_prefix: "urpn_",
  user_latest_rewards_index_prefix: "ulri_",
  user_unclaimed_rewards_prefix: "uur_",
  // APPLICATION CALLS
  farm_ops: "fo",
  flash_loan: "fl",
  mint_b_asset: "mba",
  add_underlying_collateral: "auc",
  add_b_asset_collateral: "abc",
  burn_b_asset: "br",
  remove_underlying_collateral: "ruc",
  remove_b_asset_collateral: "rbc",
  borrow: "b",
  repay_borrow: "rb",
  liquidate: "l",
  seize_collateral: "sc",
  claim_rewards: "cr",
  // vault market
  sync_vault: "sv"
};

var _MarketConfigs;

var MarketConfig =
/**
 * Constructor for the market config class
 *
 * @param appId - market app id
 * @param underlyingAssetId - underlying asset id
 * @param bAssetId - b asset id
 * @param marketType - market type
 */
function MarketConfig(appId, underlyingAssetId, bAssetId, marketType) {
  this.appId = appId;
  this.underlyingAssetId = underlyingAssetId;
  this.bAssetId = bAssetId;
  this.marketType = marketType;
};
var MarketConfigs = (_MarketConfigs = {}, _MarketConfigs[Network.MAINNET] = [/*#__PURE__*/new MarketConfig(818179346, 1, 818179690, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(818182048, 31566704, 818182311, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(818183964, 386192725, 818184214, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(818188286, 386195940, 818188553, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(818190205, 312769, 818190568, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(841145020, 841126810, 841157954, MarketType.STBL), /*#__PURE__*/new MarketConfig(841194726, 841171328, 841462373, MarketType.LP), /*#__PURE__*/new MarketConfig(856183130, 855717054, 856217307, MarketType.LP), /*#__PURE__*/new MarketConfig(870271921, 870151164, 870380101, MarketType.LP), /*#__PURE__*/new MarketConfig(870275741, 870150187, 870391958, MarketType.LP), /*#__PURE__*/new MarketConfig(879935316, 1, 879951266, MarketType.VAULT), /*#__PURE__*/new MarketConfig(900883415, 900652777, 900919286, MarketType.STANDARD)], _MarketConfigs[Network.TESTNET] = [/*#__PURE__*/new MarketConfig(104193717, 1, 104193939, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(104207076, 104194013, 104207173, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(104209685, 104208050, 104222974, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(104207403, 104207287, 104207503, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(104207719, 104207533, 104207983, MarketType.STANDARD), /*#__PURE__*/new MarketConfig(104213311, 104210500, 104217422, MarketType.STBL), /*#__PURE__*/new MarketConfig(104238373, 104228491, 104238470, MarketType.LP) // bUSDC-bSTBL2 LP
], _MarketConfigs);

/**
 * Function that returns standard transaction parameters
 *
 * @param {Algodv2} algodClient
 *
 * @return params
 */

function getParams(_x) {
  return _getParams.apply(this, arguments);
}
/**
 * Function to generate payment or asset transfer transactions
 *
 * @param   {SuggestedParams}   params
 * @param   {string}            sender
 * @param   {string}            receiver
 * @param   {int}               assetId
 * @param   {int}               amount
 *
 * @return  {Payment or AssetTransfer Transaction}
 */

function _getParams() {
  _getParams = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(algodClient) {
    var params;
    return _regeneratorRuntime().wrap(function _callee$(_context) {
      while (1) {
        switch (_context.prev = _context.next) {
          case 0:
            _context.next = 2;
            return algodClient.getTransactionParams()["do"]();

          case 2:
            params = _context.sent;
            params.fee = 1000;
            params.flatFee = true;
            return _context.abrupt("return", params);

          case 6:
          case "end":
            return _context.stop();
        }
      }
    }, _callee);
  }));
  return _getParams.apply(this, arguments);
}

function getPaymentTxn(params, sender, receiver, assetId, amount) {
  if (assetId == 1) {
    // send algos
    var algoPayment = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
      from: sender,
      to: receiver,
      amount: amount,
      suggestedParams: params,
      rekeyTo: undefined
    });
    return algoPayment;
  } else {
    var asaPayment = algosdk.makeAssetTransferTxnWithSuggestedParamsFromObject({
      from: sender,
      to: receiver,
      amount: amount,
      assetIndex: assetId,
      suggestedParams: params,
      rekeyTo: undefined,
      revocationTarget: undefined
    });
    return asaPayment;
  }
}

var Manager = /*#__PURE__*/function () {
  /**
   * Constructor for the manager class.
   *
   * @param algod - an algod client
   * @param appId - app id of the manager
   */
  function Manager(algod, appId) {
    // constants
    this.localMinBalance = 614000;
    this.algod = algod;
    this.appId = appId;
    this.address = getApplicationAddress(this.appId);
  }
  /**
   * Constructs a series of transactions that opt the user into the manager.
   *
   * @param user - algofi user representing the user we want to opt in
   * @param storageAccount - storage account for the user
   * @returns a series of transactions that opt the user into the manager.
   */


  var _proto = Manager.prototype;

  _proto.getOptInTxns =
  /*#__PURE__*/
  function () {
    var _getOptInTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(user, storageAccount) {
      var params, txn0, txn1, txn2;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context.sent;
              // fund storage account
              txn0 = getPaymentTxn(params, user.address, storageAccount.addr, ALGO_ASSET_ID, this.localMinBalance + 101000); // storage account opt in and rekey

              txn1 = algosdk.makeApplicationOptInTxnFromObject({
                from: storageAccount.addr,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.storage_account_opt_in)],
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: this.address
              }); // user opt in

              txn2 = algosdk.makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.user_opt_in)],
                accounts: [storageAccount.addr],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context.abrupt("return", assignGroupID([txn0, txn1, txn2]));

            case 7:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function getOptInTxns(_x, _x2) {
      return _getOptInTxns.apply(this, arguments);
    }

    return getOptInTxns;
  }()
  /**
   * Constructs a series of transactions that opt the user out of the manager.
   *
   * @param user - algofi user representing the user we want to opt in
   * @returns a series of transactions that opt the user out of the manager.
   */
  ;

  _proto.getOptOutTxns =
  /*#__PURE__*/
  function () {
    var _getOptOutTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user) {
      var params, txn0, txn1, txn2;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              // close out
              params.fee = 2000;
              txn0 = algosdk.makeApplicationCloseOutTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: undefined,
                accounts: [user.lending.v2.storageAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              params.fee = 1000;
              txn1 = algosdk.makeApplicationClearStateTxnFromObject({
                from: user.lending.v2.storageAddress,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: undefined,
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              params.fee = 1000;
              txn2 = algosdk.makePaymentTxnWithSuggestedParamsFromObject({
                from: user.lending.v2.storageAddress,
                to: user.lending.v2.storageAddress,
                amount: 0,
                suggestedParams: params,
                rekeyTo: undefined,
                closeRemainderTo: user.address
              });
              return _context2.abrupt("return", assignGroupID([txn0, txn1, txn2]));

            case 10:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getOptOutTxns(_x3) {
      return _getOptOutTxns.apply(this, arguments);
    }

    return getOptOutTxns;
  }()
  /**
   * Constructs a series of transactions that opt the user into a market.
   *
   * @param user - algofi user representing the user we want to opt in
   * @param market - the market we want to opt the user into
   * @returns a series of transactions that opt the user into a market.
   */
  ;

  _proto.getMarketOptInTxns =
  /*#__PURE__*/
  function () {
    var _getMarketOptInTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user, market) {
      var params, txn0, txn1, txn2;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context3.sent;
              // fund storage account
              txn0 = getPaymentTxn(params, user.address, user.lending.v2.storageAddress, ALGO_ASSET_ID, market.localMinBalance); // validate market

              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.validate_market)],
                accounts: [market.address],
                foreignApps: [market.appId],
                foreignAssets: undefined,
                rekeyTo: undefined
              }); // opt into market

              params.fee = 2000;
              txn2 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.user_market_opt_in)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [market.appId],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context3.abrupt("return", assignGroupID([txn0, txn1, txn2]));

            case 8:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getMarketOptInTxns(_x4, _x5) {
      return _getMarketOptInTxns.apply(this, arguments);
    }

    return getMarketOptInTxns;
  }()
  /**
   * Constructs a series of transactions that opt the user out of a market.
   *
   * @param user - algofi user representing the user we want to opt in
   * @param market - the market we want to opt the user out of
   * @returns a series of transactions that opt the user out of a market.
   */
  ;

  _proto.getMarketOptOutTxns =
  /*#__PURE__*/
  function () {
    var _getMarketOptOutTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, market) {
      var params, _user$lending$v2$getM, page, offset, txn0;

      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              _user$lending$v2$getM = user.lending.v2.getMarketPageOffset(market.appId), page = _user$lending$v2$getM[0], offset = _user$lending$v2$getM[1]; // opt out of market

              params.fee = 3000;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.user_market_close_out), concatArrays([encodeUint64(page), encodeUint64(offset)])],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [market.appId],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context4.abrupt("return", [txn0]);

            case 7:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getMarketOptOutTxns(_x6, _x7) {
      return _getMarketOptOutTxns.apply(this, arguments);
    }

    return getMarketOptOutTxns;
  }() // vault

  /**
   * Constructs a series of transactions that sends a governance transaction from the user.
   *
   * @param user - algofi user representing the user we want to opt in
   * @param targetAddress - the target address we are sending the gov transaction to
   * @param note - a note to put in the governance transaction
   * @returns a series of transactions that sends a governance transaction from the user.
   */
  ;

  _proto.getGovernanceTxns =
  /*#__PURE__*/
  function () {
    var _getGovernanceTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, targetAddress, note) {
      var params, txn0;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              // send governance txns
              params.fee = 2000;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.send_governance_txn)],
                accounts: [user.lending.v2.storageAddress, targetAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined,
                note: TEXT_ENCODER.encode(note)
              });
              return _context5.abrupt("return", assignGroupID([txn0]));

            case 6:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getGovernanceTxns(_x8, _x9, _x10) {
      return _getGovernanceTxns.apply(this, arguments);
    }

    return getGovernanceTxns;
  }()
  /**
   * Constructs a series of transactions that send a keyreg transaction for
   * governance from the user.
   *
   * @param user - algofi user representing the user we want to send the keyreg
   * txn on behalf
   * @param votePK -root participation public key
   * @param selectionPK - the VRF public key
   * @param stateProofPK - the 64 byte state proof public key commitment
   * @param voteFirst - the first round that hte participation key is valid
   * @param voteLast - The last round that th eparticipatin key is valid
   * @param voteKeyDilution - The dilution for the 2-level participation key
   * @returns a series of transactions that send a keyreg transaction for
   * governance from the user.
   */
  ;

  _proto.getKeyregTxns =
  /*#__PURE__*/
  function () {
    var _getKeyregTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user, votePK, selectionPK, stateProofPK, voteFirst, voteLast, voteKeyDilution) {
      var params, txn0, txn1;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context6.sent;
              // validate account ownership
              params.fee = 3000;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.validate_storage_account_txn)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }); // opt out of market

              params.fee = 0;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: PERMISSIONLESS_SENDER_LOGIC_SIG.lsig.address(),
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.send_keyreg_txn), new Uint8Array(Buffer.from(votePK, "base64")), new Uint8Array(Buffer.from(selectionPK, "base64")), new Uint8Array(Buffer.from(stateProofPK, "base64")), encodeUint64(voteFirst), encodeUint64(voteLast), encodeUint64(voteKeyDilution)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context6.abrupt("return", assignGroupID([txn0, txn1]));

            case 8:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getKeyregTxns(_x11, _x12, _x13, _x14, _x15, _x16, _x17) {
      return _getKeyregTxns.apply(this, arguments);
    }

    return getKeyregTxns;
  }()
  /**
   * Constructs a series of transactions that send an offlinek eyreg
   * transaction.
   *
   * @param user - algofi user representing the user we want to send the offline
   * keyreg transaction on behalf
   * @returns - a series of transactions that send an offlinek eyreg
   * transaction.
   */
  ;

  _proto.getKeyregOfflineTxns =
  /*#__PURE__*/
  function () {
    var _getKeyregOfflineTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(user) {
      var params, txn0;
      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context7.sent;
              // send keyreg offline txn
              params.fee = 2000;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.send_keyreg_offline_txn)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context7.abrupt("return", assignGroupID([txn0]));

            case 6:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getKeyregOfflineTxns(_x18) {
      return _getKeyregOfflineTxns.apply(this, arguments);
    }

    return getKeyregOfflineTxns;
  }();

  return Manager;
}();

var Oracle = /*#__PURE__*/function () {
  /**
   * Constructor for the oracle object
   *
   * @param algod - algod client
   * @param appId - appid of the oracle
   * @param priceFieldName - price field name
   * @param scaleFactor - scale factor for the asset price
   * @param underlyingAssetDecimals - decimals for the asset
   */
  function Oracle(algod, appId, priceFieldName, scaleFactor, underlyingAssetDecimals) {
    this.algod = algod;
    this.appId = appId;
    this.priceFieldName = priceFieldName;
    this.scaleFactor = scaleFactor;
    this.underlyingAssetDecimals = underlyingAssetDecimals;
  }
  /**
   * Sets raw price after getting global state.
   */


  var _proto = Oracle.prototype;

  _proto.loadPrice =
  /*#__PURE__*/
  function () {
    var _loadPrice = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var state;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.appId);

            case 2:
              state = _context.sent;
              this.rawPrice = state[this.priceFieldName];
              this.price = this.rawPrice * this.underlyingAssetDecimals / (FIXED_3_SCALE_FACTOR * this.scaleFactor);

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadPrice() {
      return _loadPrice.apply(this, arguments);
    }

    return loadPrice;
  }();

  return Oracle;
}();

var CALC_USER_POSITION = true;
var DONT_CALC_USER_POSITION = false; // HELPER CLASSES

var MarketRewardsProgram = /*#__PURE__*/function () {
  /**
   * Constructs a market rewards program class
   *
   * @param state - state of the market rewards program on chain
   * @param programIndex - the index of the rewards program
   */
  function MarketRewardsProgram(market, state, programIndex) {
    this.market = market;
    var rewardsStateBytes = Buffer.from(state[MARKET_STRINGS.rewards_program_state_prefix + String.fromCharCode.apply(null, encodeUint64(programIndex))], "base64").toString("binary");
    this.programNumber = decodeUint64(decodeBytes(rewardsStateBytes.substr(0, 8)), "safe");
    this.rewardsPerSecond = decodeUint64(decodeBytes(rewardsStateBytes.substr(8, 8)), "safe");
    this.assetID = decodeUint64(decodeBytes(rewardsStateBytes.substr(16, 8)), "safe");
    this.issued = decodeUint64(decodeBytes(rewardsStateBytes.substr(24, 8)), "safe");
    this.claimed = decodeUint64(decodeBytes(rewardsStateBytes.substr(32, 8)), "safe");
    var rawRewardsIndexBytes = new Uint8Array(Buffer.from(state[MARKET_STRINGS.rewards_index_prefix + String.fromCharCode.apply(null, encodeUint64(programIndex))], "base64"));
    this.index = bytesToBigInt(rawRewardsIndexBytes);

    if (market.marketType == MarketType.VAULT || market.marketType == MarketType.LP) {
      this.projectedIndex = this.index + (market.activeBAssetCollateral > 0 ? BigInt((Math.floor(Date.now() / 1000) - market.rewardsLatestTime) * this.rewardsPerSecond) * FIXED_18_SCALE_FACTOR / BigInt(market.activeBAssetCollateral) : BigInt(0));
    } else {
      this.projectedIndex = this.index + (market.borrowShareCirculation > 0 ? BigInt((Math.floor(Date.now() / 1000) - market.rewardsLatestTime) * this.rewardsPerSecond) * FIXED_18_SCALE_FACTOR / BigInt(market.borrowShareCirculation) : BigInt(0));
    }
  }

  var _proto = MarketRewardsProgram.prototype;

  _proto.getAnnualRewards = function getAnnualRewards() {
    return this.market.assetDataClient.getAsset(this.rewardsPerSecond * SECONDS_PER_YEAR, this.assetID);
  };

  _proto.getSupplyRewardsAPR = function getSupplyRewardsAPR() {
    if (this.assetID == 0 || this.market.marketType != MarketType.VAULT && this.market.marketType != MarketType.LP) {
      return 0;
    }

    return this.getAnnualRewards().toUSD() / this.market.getTotalSupplied().toUSD();
  };

  _proto.getBorrowRewardsAPR = function getBorrowRewardsAPR() {
    if (this.assetID == 0 || this.market.marketType == MarketType.VAULT || this.market.marketType == MarketType.LP) {
      return 0;
    }

    return this.getAnnualRewards().toUSD() / this.market.getTotalBorrowed().toUSD();
  };

  _proto.getSupplyRewardsPer1k = function getSupplyRewardsPer1k() {
    if (this.assetID == 0 || this.market.marketType != MarketType.VAULT && this.market.marketType != MarketType.LP) {
      return 0;
    }

    return this.getAnnualRewards().toDisplayAmount() / (this.market.getTotalSupplied().toUSD() / 1000);
  };

  _proto.getBorrowRewardsPer1k = function getBorrowRewardsPer1k() {
    if (this.assetID == 0 || this.market.marketType == MarketType.VAULT || this.market.marketType == MarketType.LP) {
      return 0;
    }

    return this.getAnnualRewards().toDisplayAmount() / (this.market.getTotalBorrowed().toUSD() / 1000);
  };

  return MarketRewardsProgram;
}(); // INTERFACE

var Market = /*#__PURE__*/function () {
  /**
   * Constructor for the market class.
   *
   * @param algod - algod client
   * @param lendingClient - lending client
   * @param managerAppId - manager app idd
   * @param marketConfig - market config
   */
  function Market(algod, lendingClient, managerAppId, marketConfig) {
    // constants
    this.localMinBalance = 471000;
    this.rewardsPrograms = [];
    this.algod = algod;
    this.lendingClient = lendingClient;
    this.assetDataClient = lendingClient.algofiClient.assetData;
    this.managerAppId = managerAppId;
    this.appId = marketConfig.appId;
    this.address = getApplicationAddress(this.appId);
    this.marketType = marketConfig.marketType;
    this.underlyingAssetId = marketConfig.underlyingAssetId;
    this.bAssetId = marketConfig.bAssetId;
  }
  /**
   * Function to get the application's global state and load in all of the
   * updated values into the actual object.
   */


  var _proto2 = Market.prototype;

  _proto2.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var state, idx;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.appId);

            case 2:
              state = _context.sent;
              // parameters
              this.borrowFactor = state[MARKET_STRINGS.borrow_factor];
              this.collateralFactor = state[MARKET_STRINGS.collateral_factor];
              this.flashLoanFee = state[MARKET_STRINGS.flash_loan_fee];
              this.flashLoanProtocolFee = state[MARKET_STRINGS.flash_loan_protocol_fee];
              this.maxFlashLoanRatio = state[MARKET_STRINGS.max_flash_loan_ratio];
              this.liquidationIncentive = state[MARKET_STRINGS.liquidation_incentive];
              this.liquidationFee = state[MARKET_STRINGS.liquidation_fee];
              this.reserveFactor = state[MARKET_STRINGS.reserve_factor];
              this.underlyingSupplyCap = state[MARKET_STRINGS.underlying_supply_cap];
              this.underlyingBorrowCap = state[MARKET_STRINGS.underlying_borrow_cap]; // interest rate model

              this.baseInterestRate = state[MARKET_STRINGS.base_interest_rate];
              this.baseInterestSlope = state[MARKET_STRINGS.base_interest_slope];
              this.quadraticInterestAmplificationFactor = state[MARKET_STRINGS.quadratic_interest_amplification_factor];
              this.targetUtilizationRatio = state[MARKET_STRINGS.target_utilization_ratio]; // oracle

              if (!this.oracle) {
                this.oracle = new Oracle(this.algod, state[MARKET_STRINGS.oracle_app_id], Base64Encoder.decode(state[MARKET_STRINGS.oracle_price_field_name]), state[MARKET_STRINGS.oracle_price_scale_factor], Math.pow(10, this.lendingClient.algofiClient.assetData.assetConfigs[this.underlyingAssetId].decimals));
              }

              _context.next = 20;
              return this.oracle.loadPrice();

            case 20:
              // balance
              this.underlyingCash = state[MARKET_STRINGS.underlying_cash];
              this.underlyingBorrowed = state[MARKET_STRINGS.underlying_borrowed];
              this.underlyingReserves = state[MARKET_STRINGS.underlying_reserves];
              this.borrowShareCirculation = state[MARKET_STRINGS.borrow_share_circulation];
              this.bAssetCirculation = state[MARKET_STRINGS.b_asset_circulation];
              this.activeBAssetCollateral = state[MARKET_STRINGS.active_b_asset_collateral];
              this.underlyingProtocolReserve = state[MARKET_STRINGS.underlying_protocol_reserve] || 0; // interest

              this.latestTime = state[MARKET_STRINGS.latest_time];
              this.rewardsLatestTime = state[MARKET_STRINGS.rewards_latest_time];
              this.borrowIndex = state[MARKET_STRINGS.borrow_index];
              this.impliedBorrowIndex = state[MARKET_STRINGS.implied_borrow_index]; // rewards

              this.rewardsPrograms = [];

              for (idx = 0; idx < 2; idx++) {
                this.rewardsPrograms.push(new MarketRewardsProgram(this, state, idx));
              }

              this.rewardsEscrowAccount = parseAddressBytes(state[MARKET_STRINGS.rewards_escrow_account]);

            case 34:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // GETTERS
  ;

  _proto2.getBorrowAPR = function getBorrowAPR(totalSupplied, totalBorrowed) {
    if (totalSupplied === void 0) {
      totalSupplied = this.getUnderlyingSupplied();
    }

    if (totalBorrowed === void 0) {
      totalBorrowed = this.underlyingBorrowed;
    }

    if (this.marketType == MarketType.STBL) {
      return this.baseInterestRate / FIXED_6_SCALE_FACTOR;
    }

    if (this.marketType == MarketType.LP) {
      return 0;
    }

    var borrowUtilization = totalBorrowed / totalSupplied || 0;
    var targetUtilization = this.targetUtilizationRatio / FIXED_6_SCALE_FACTOR;
    var borrowAPR = this.baseInterestRate / FIXED_6_SCALE_FACTOR;

    if (targetUtilization > 0) {
      borrowAPR += this.baseInterestSlope * (borrowUtilization / targetUtilization) / FIXED_6_SCALE_FACTOR;
    }

    if (borrowUtilization > this.targetUtilizationRatio / FIXED_6_SCALE_FACTOR) {
      borrowAPR += this.quadraticInterestAmplificationFactor * Math.pow(borrowUtilization - this.targetUtilizationRatio / FIXED_6_SCALE_FACTOR, 2);
    }

    return borrowAPR;
  };

  _proto2.getSupplyAPR = /*#__PURE__*/function () {
    var _getSupplyAPR = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(totalSupplied, totalBorrowed) {
      var borrowAPR, lendingPool, pool, borrowUtilization, supplyAPR;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (totalSupplied === void 0) {
                totalSupplied = /*#__PURE__*/this.getUnderlyingSupplied();
              }

              if (totalBorrowed === void 0) {
                totalBorrowed = this.underlyingBorrowed;
              }

              borrowAPR = this.getBorrowAPR(totalSupplied, totalBorrowed);

              if (!(this.marketType == MarketType.STBL)) {
                _context2.next = 5;
                break;
              }

              return _context2.abrupt("return", borrowAPR);

            case 5:
              if (!(this.marketType == MarketType.LP)) {
                _context2.next = 23;
                break;
              }

              if (!this.lendingClient.algofiClient.interfaces.hasLendingPoolForLP(this.underlyingAssetId)) {
                _context2.next = 15;
                break;
              }

              _context2.next = 9;
              return this.lendingClient.algofiClient.interfaces.getLendingPoolFromLP(this.underlyingAssetId);

            case 9:
              lendingPool = _context2.sent;
              _context2.next = 12;
              return lendingPool.getAPR();

            case 12:
              return _context2.abrupt("return", _context2.sent);

            case 15:
              if (!this.lendingClient.algofiClient.amm.v1.hasPoolForLPAsset(this.underlyingAssetId)) {
                _context2.next = 22;
                break;
              }

              _context2.next = 18;
              return this.lendingClient.algofiClient.amm.v1.getPoolByAppId(this.underlyingAssetId);

            case 18:
              pool = _context2.sent;
              return _context2.abrupt("return", pool.getAPR());

            case 22:
              return _context2.abrupt("return", 0);

            case 23:
              borrowUtilization = totalBorrowed / totalSupplied || 0;
              supplyAPR = borrowAPR * borrowUtilization * (1 - this.reserveFactor / FIXED_3_SCALE_FACTOR);
              return _context2.abrupt("return", supplyAPR);

            case 26:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getSupplyAPR(_x, _x2) {
      return _getSupplyAPR.apply(this, arguments);
    }

    return getSupplyAPR;
  }()
  /**
  * Gets the underlying supplied for a market.
  *
  * @param isProjected - bool if the underlying supply is projected based on deltaT
  * @returns the underlying supplied for a market.
  */
  ;

  _proto2.getUnderlyingSupplied = function getUnderlyingSupplied(isProjected) {
    if (isProjected === void 0) {
      isProjected = false;
    }

    if (this.marketType == MarketType.STBL) {
      return this.underlyingCash;
    } else {
      if (isProjected) {
        var currentTime = Math.floor(Date.now() / 1000);
        var deltaT = currentTime - this.latestTime;
        var interestTick = Math.floor(deltaT * this.getBorrowAPR() * 1e6 * 1e6 / SECONDS_PER_YEAR);
        var nextBorrowIndexTerm = Math.floor(this.borrowIndex * interestTick / 1e12);
        var newBorrowIndex = this.borrowIndex + nextBorrowIndexTerm;
        var underlyingBorrowWithInterest = Math.floor(this.underlyingBorrowed * newBorrowIndex / this.impliedBorrowIndex);
        var underlyingInterestToReserve = Math.floor((underlyingBorrowWithInterest - this.underlyingBorrowed) * this.reserveFactor / 1e3);
        var newUnderlyingSupplied = this.underlyingCash + underlyingBorrowWithInterest - (this.underlyingReserves + underlyingInterestToReserve);
        return newUnderlyingSupplied;
      } else {
        return this.underlyingBorrowed + this.underlyingCash - this.underlyingReserves;
      }
    }
  } // GETTERS (post asset data load)
  ;

  _proto2.getTotalSupplied = function getTotalSupplied() {
    return this.assetDataClient.getAsset(this.getUnderlyingSupplied(), this.underlyingAssetId);
  };

  _proto2.getTotalBorrowed = function getTotalBorrowed() {
    return this.assetDataClient.getAsset(this.underlyingBorrowed, this.underlyingAssetId);
  };

  _proto2.getSupplyRewardsAPR = function getSupplyRewardsAPR() {
    var supplyRewardsAPR = 0;

    for (var _iterator = _createForOfIteratorHelperLoose(this.rewardsPrograms), _step; !(_step = _iterator()).done;) {
      var rewardsProgram = _step.value;
      supplyRewardsAPR += rewardsProgram.getSupplyRewardsAPR();
    }

    return supplyRewardsAPR;
  };

  _proto2.getBorrowRewardsAPR = function getBorrowRewardsAPR() {
    var borrowRewardsAPR = 0;

    for (var _iterator2 = _createForOfIteratorHelperLoose(this.rewardsPrograms), _step2; !(_step2 = _iterator2()).done;) {
      var rewardsProgram = _step2.value;
      borrowRewardsAPR += rewardsProgram.getBorrowRewardsAPR();
    }

    return borrowRewardsAPR;
  } // CONVERSIONS
  ;

  _proto2.convertUnderlyingToUSD = function convertUnderlyingToUSD(amount) {
    return amount * this.oracle.rawPrice / (this.oracle.scaleFactor * FIXED_3_SCALE_FACTOR);
  }
  /**
   * Converts the b asset to the underlying asset amount
   *
   * @param amount - the amount of the b asset we want to convert
   * @returns the asset amount that corresponds to the b asset amount that we passed in.
   */
  ;

  _proto2.bAssetToUnderlying = function bAssetToUnderlying(amount) {
    var rawUnderlyingAmount = Math.floor(this.bAssetCirculation != 0 ? amount * this.getUnderlyingSupplied() / this.bAssetCirculation : 0);
    return this.assetDataClient.getAsset(rawUnderlyingAmount, this.underlyingAssetId);
  }
  /**
   * Converts the borrow shares to the acutal underlying asset amount those
   * borrow shares represent.
   *
   * @param amount - amount of borrow shares we want to convert
   * @returns the amount of the underlying that is represented by the amount of
   * borrow shares that we passed in.
   */
  ;

  _proto2.borrowSharesToUnderlying = function borrowSharesToUnderlying(amount, roundResultUp) {
    if (roundResultUp === void 0) {
      roundResultUp = false;
    }

    var rawUnderlyingAmount = roundResultUp ? Math.ceil(this.borrowShareCirculation != 0 ? amount * this.underlyingBorrowed / this.borrowShareCirculation : 0) : Math.floor(this.borrowShareCirculation != 0 ? amount * this.underlyingBorrowed / this.borrowShareCirculation : 0);
    return this.assetDataClient.getAsset(rawUnderlyingAmount, this.underlyingAssetId);
  }
  /**
   * Converts the underlying asset to b assets.
   *
   * @param amount - the amount of underlying we want to convert
   * @param isProjected - bool if user wishes to project the b asset to underlying exchange
   * @returns the corresponding amount of the b asset for the underlying that we
   * passed in.
   */
  ;

  _proto2.underlyingToBAsset = function underlyingToBAsset(underlyingAmount, isProjected) {
    if (isProjected === void 0) {
      isProjected = false;
    }

    if (isProjected) {
      var newUnderlyingSupplied = this.getUnderlyingSupplied(isProjected = true);
      return this.assetDataClient.getAsset(Math.floor(underlyingAmount.amount * this.bAssetCirculation / newUnderlyingSupplied), this.bAssetId);
    } else {
      return this.assetDataClient.getAsset(Math.floor(underlyingAmount.amount * this.bAssetCirculation / this.getUnderlyingSupplied()), this.bAssetId);
    }
  } // QUOTES
  ;

  _proto2.getMaximumWithdrawAmount = function getMaximumWithdrawAmount(user, borrowUtilLimit) {
    var _user$lending$v2$user, _user$lending$v2$user2;

    if (borrowUtilLimit === void 0) {
      borrowUtilLimit = 0.9;
    }

    var userExcessScaledCollateral = user.lending.v2.netScaledCollateral - roundUp(user.lending.v2.netScaledBorrow / borrowUtilLimit, 3);
    var maximumWithdrawUSD = userExcessScaledCollateral * FIXED_3_SCALE_FACTOR / this.collateralFactor;
    var maximumWithdrawUnderlying = this.assetDataClient.getAssetFromUSDAmount(maximumWithdrawUSD, this.underlyingAssetId);
    var maximumMarketWithdrawUnderlying = Math.min(maximumWithdrawUnderlying.amount, ((_user$lending$v2$user = user.lending.v2.userMarketStates) == null ? void 0 : (_user$lending$v2$user2 = _user$lending$v2$user[this.appId]) == null ? void 0 : _user$lending$v2$user2.suppliedAmount.amount) || 0); // special handling for final withdraw

    if (user.lending.v2.netScaledBorrow == 0) {
      var _user$lending$v2$user3, _user$lending$v2$user4;

      maximumMarketWithdrawUnderlying = ((_user$lending$v2$user3 = user.lending.v2.userMarketStates) == null ? void 0 : (_user$lending$v2$user4 = _user$lending$v2$user3[this.appId]) == null ? void 0 : _user$lending$v2$user4.suppliedAmount.amount) || 0;
    }

    return this.assetDataClient.getAsset(maximumMarketWithdrawUnderlying, this.underlyingAssetId);
  };

  _proto2.getMaximumWithdrawBAsset = function getMaximumWithdrawBAsset(user, borrowUtilLimit) {
    var _user$lending$v2$user5;

    if (borrowUtilLimit === void 0) {
      borrowUtilLimit = 0.9;
    }

    var userExcessScaledCollateral = user.lending.v2.netScaledCollateral - roundUp(user.lending.v2.netScaledBorrow / borrowUtilLimit, 3);
    var maximumWithdrawUSD = userExcessScaledCollateral * FIXED_3_SCALE_FACTOR / this.collateralFactor;
    var maximumWithdrawBAsset = this.assetDataClient.getAssetFromUSDAmount(maximumWithdrawUSD, this.bAssetId);
    var maximumMarketWithdrawBAsset = Math.min(maximumWithdrawBAsset.amount, ((_user$lending$v2$user5 = user.lending.v2.userMarketStates[this.appId]) == null ? void 0 : _user$lending$v2$user5.bAssetCollateral) || 0);

    if (user.lending.v2.netScaledBorrow == 0) {
      var _user$lending$v2$user6;

      maximumMarketWithdrawBAsset = ((_user$lending$v2$user6 = user.lending.v2.userMarketStates[this.appId]) == null ? void 0 : _user$lending$v2$user6.bAssetCollateral) || 0;
    }

    return this.assetDataClient.getAsset(maximumMarketWithdrawBAsset, this.bAssetId);
  };

  _proto2.getMaximumBorrowAmount = function getMaximumBorrowAmount(user, borrowUtilLimit) {
    var _user$lending$v2$user7;

    if (borrowUtilLimit === void 0) {
      borrowUtilLimit = 0.9;
    }

    var userExcessScaledCollateral = user.lending.v2.netScaledCollateral * borrowUtilLimit - user.lending.v2.netScaledBorrow; // special handling for initial borrow

    if ((_user$lending$v2$user7 = user.lending.v2.userMarketStates[this.appId]) != null && _user$lending$v2$user7.borrowedAmount.amount || 0 == 0) {
      userExcessScaledCollateral -= 0.001;
    }

    var maximumBorrowUSD = userExcessScaledCollateral * FIXED_3_SCALE_FACTOR / this.borrowFactor;
    return this.assetDataClient.getAssetFromUSDAmount(maximumBorrowUSD, this.underlyingAssetId);
  };

  _proto2.getNewBorrowUtilQuote = function getNewBorrowUtilQuote(user, collateralDelta, borrowDelta) {
    var _user$lending$v2$user8, _user$lending$v2$user9;

    var newUserScaledCollateral = user.lending.v2.netScaledCollateral + collateralDelta.toUSD() * this.collateralFactor / FIXED_3_SCALE_FACTOR;
    var newUserScaledBorrow = (user.lending.v2.netScaledBorrow || 0) + borrowDelta.toUSD() * this.borrowFactor / FIXED_3_SCALE_FACTOR; // special handling for initial borrow

    if (borrowDelta.amount > 0 && (((_user$lending$v2$user8 = user.lending.v2.userMarketStates[this.appId]) == null ? void 0 : _user$lending$v2$user8.borrowedAmount.amount) || 0) == 0) {
      newUserScaledBorrow += 0.001;
    } // special handling for final repay


    if ((borrowDelta.amount + ((_user$lending$v2$user9 = user.lending.v2.userMarketStates[this.appId]) == null ? void 0 : _user$lending$v2$user9.borrowedAmount.amount) || 0) <= 0) {
      newUserScaledBorrow -= 0.001;
    }

    if (newUserScaledBorrow <= 0) {
      return 0;
    } else if (newUserScaledCollateral <= 0) {
      return Infinity;
    } else {
      return newUserScaledBorrow / newUserScaledCollateral;
    }
  } // TRANSACTIONS

  /**
   * Constructs a series of transactions that are required for several other
   * transactions in lending.
   *
   * @param params - parameters for the transaction
   * @param user - the user to send the preamble transactions on behalf
   * @returns a series of transactions that are required for several other
   * transactions in lending.
   */
  ;

  _proto2.getPreambleTransactions =
  /*#__PURE__*/
  function () {
    var _getPreambleTransactions = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(params, user, needsUserPosition) {
      var preamble, additionalFee, calcUserPositionTxns, _iterator3, _step3, txn;

      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              preamble = [];

              if (!user.isOptedInToAsset(this.underlyingAssetId)) {
                preamble.push(getPaymentTxn(params, user.address, user.address, this.underlyingAssetId, 0));
              }

              if (!user.isOptedInToAsset(this.bAssetId)) {
                preamble.push(getPaymentTxn(params, user.address, user.address, this.bAssetId, 0));
              }

              additionalFee = 0;

              if (!needsUserPosition) {
                _context3.next = 10;
                break;
              }

              _context3.next = 7;
              return user.lending.v2.getCalcUserPositionTransactions(this.appId);

            case 7:
              calcUserPositionTxns = _context3.sent;
              additionalFee = calcUserPositionTxns.length * 1000;

              for (_iterator3 = _createForOfIteratorHelperLoose(calcUserPositionTxns); !(_step3 = _iterator3()).done;) {
                txn = _step3.value;
                preamble.push(txn);
              }

            case 10:
              return _context3.abrupt("return", [preamble, additionalFee]);

            case 11:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getPreambleTransactions(_x3, _x4, _x5) {
      return _getPreambleTransactions.apply(this, arguments);
    }

    return getPreambleTransactions;
  }()
  /**
   * Constructs a series of transactions that mint b assets for the user.
   *
   * @param user - the user minting b assets
   * @param underlyingAmount - how much of the underlying the user wants to mint
   * @returns a series of transactions that mint b assets for the user.
   */
  ;

  _proto2.getMintTxns =
  /*#__PURE__*/
  function () {
    var _getMintTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, underlyingAmount) {
      var params, _yield$this$getPreamb, preambleTransactions, txn0, txn1;

      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              if (!(this.marketType == MarketType.VAULT)) {
                _context4.next = 2;
                break;
              }

              throw "Mint action not supported by vault market";

            case 2:
              _context4.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context4.sent;
              _context4.next = 8;
              return this.getPreambleTransactions(params, user, DONT_CALC_USER_POSITION);

            case 8:
              _yield$this$getPreamb = _context4.sent;
              preambleTransactions = _yield$this$getPreamb[0];
              // payment
              txn0 = getPaymentTxn(params, user.address, this.address, this.underlyingAssetId, underlyingAmount.amount); // application call

              params.fee = 3000;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.mint_b_asset)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: [this.bAssetId],
                rekeyTo: undefined
              });
              return _context4.abrupt("return", assignGroupID(preambleTransactions.concat([txn0, txn1])));

            case 15:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getMintTxns(_x6, _x7) {
      return _getMintTxns.apply(this, arguments);
    }

    return getMintTxns;
  }()
  /**
   * Constructs a series of transactions that adds underlying collateral for the
   * user.
   *
   * @param user - algofi user who wants to add underlying
   * @param underlyingAmount - the amount of the underlying we want to add
   * @returns a series of transactions that adds underlying collateral for the
   * user.
   */
  ;

  _proto2.getAddUnderlyingCollateralTxns =
  /*#__PURE__*/
  function () {
    var _getAddUnderlyingCollateralTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, underlyingAmount) {
      var params, _yield$this$getPreamb2, preambleTransactions, targetAddress, txn0, txn1;

      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              _context5.next = 6;
              return this.getPreambleTransactions(params, user, DONT_CALC_USER_POSITION);

            case 6:
              _yield$this$getPreamb2 = _context5.sent;
              preambleTransactions = _yield$this$getPreamb2[0];
              // payment
              targetAddress = this.marketType != MarketType.VAULT ? this.address : user.lending.v2.storageAddress;
              txn0 = getPaymentTxn(params, user.address, targetAddress, this.underlyingAssetId, underlyingAmount.amount); // application call

              params.fee = 2000;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.add_underlying_collateral)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context5.abrupt("return", assignGroupID(preambleTransactions.concat([txn0, txn1])));

            case 14:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getAddUnderlyingCollateralTxns(_x8, _x9) {
      return _getAddUnderlyingCollateralTxns.apply(this, arguments);
    }

    return getAddUnderlyingCollateralTxns;
  }()
  /**
   * Constructs a series of transactions that adds b asset collateral for a
   * user.
   *
   * @param user - the user who is adding b assets
   * @param bAssetAmount - the amount of b assets to add
   * @returns a series of transactions that adds b asset collateral for a user.
   */
  ;

  _proto2.getAddBAssetCollateralTxns =
  /*#__PURE__*/
  function () {
    var _getAddBAssetCollateralTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user, bAssetAmount) {
      var params, _yield$this$getPreamb3, preambleTransactions, txn0, txn1;

      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              if (!(this.marketType == MarketType.VAULT)) {
                _context6.next = 2;
                break;
              }

              throw "Add b asset collateral action not supported by vault market";

            case 2:
              _context6.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context6.sent;
              _context6.next = 8;
              return this.getPreambleTransactions(params, user, DONT_CALC_USER_POSITION);

            case 8:
              _yield$this$getPreamb3 = _context6.sent;
              preambleTransactions = _yield$this$getPreamb3[0];
              // payment
              txn0 = getPaymentTxn(params, user.address, this.address, this.bAssetId, bAssetAmount.amount); // application call

              params.fee = 2000;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.add_b_asset_collateral)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context6.abrupt("return", assignGroupID(preambleTransactions.concat([txn0, txn1])));

            case 15:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getAddBAssetCollateralTxns(_x10, _x11) {
      return _getAddBAssetCollateralTxns.apply(this, arguments);
    }

    return getAddBAssetCollateralTxns;
  }()
  /**
   * Constructs a series of transactions that remove underlying collateral for a user.
   *
   * @param user - algofi user representing hte user that wants to remove underlying collateral
   * @param underlyingAmount - algofi user representing the user we want to opt in
   * @param removeMax - whether or not we want to remove the maximum amount
   * @returns a series of transactions that remove underlying collateral for a user.
   */
  ;

  _proto2.getRemoveUnderlyingCollateralTxns =
  /*#__PURE__*/
  function () {
    var _getRemoveUnderlyingCollateralTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(user, underlyingAmount, removeMax) {
      var bAssetAmount, params, _yield$this$getPreamb4, preambleTransactions, additionalFee, txn0;

      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              if (removeMax === void 0) {
                removeMax = false;
              }

              // get b asset amount to remove
              bAssetAmount = Math.min(this.underlyingToBAsset(underlyingAmount).amount, user.lending.v2.userMarketStates[this.appId].bAssetCollateral);

              if (removeMax) {
                bAssetAmount = this.getMaximumWithdrawBAsset(user).amount;
              }

              _context7.next = 5;
              return getParams(this.algod);

            case 5:
              params = _context7.sent;
              _context7.next = 9;
              return this.getPreambleTransactions(params, user, CALC_USER_POSITION);

            case 9:
              _yield$this$getPreamb4 = _context7.sent;
              preambleTransactions = _yield$this$getPreamb4[0];
              additionalFee = _yield$this$getPreamb4[1];
              // application call
              params.fee = this.marketType != MarketType.VAULT ? 3000 + additionalFee : 4000 + additionalFee;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.remove_underlying_collateral), encodeUint64(bAssetAmount)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: [this.underlyingAssetId],
                rekeyTo: undefined
              });
              return _context7.abrupt("return", assignGroupID(preambleTransactions.concat([txn0])));

            case 15:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getRemoveUnderlyingCollateralTxns(_x12, _x13, _x14) {
      return _getRemoveUnderlyingCollateralTxns.apply(this, arguments);
    }

    return getRemoveUnderlyingCollateralTxns;
  }()
  /**
   * Constructs a series of transactions that remove underlying b asset
   * collateral for a user.
   *
   * @param user - algofi user representing the user we want to remove b asset
   * collateral for
   * @param bAssetAmount - the amount of b asset collateral we want to move
   * @returns a series of transactions that remove underlying b asset
   * collateral for a user.
   */
  ;

  _proto2.getRemoveBAssetCollateralTxns =
  /*#__PURE__*/
  function () {
    var _getRemoveBAssetCollateralTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(user, bAssetAmount) {
      var params, _yield$this$getPreamb5, preambleTransactions, additionalFee, txn0;

      return _regeneratorRuntime().wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              if (!(this.marketType == MarketType.VAULT)) {
                _context8.next = 2;
                break;
              }

              throw "Remove b asset collateral action not supported by vault market";

            case 2:
              _context8.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context8.sent;
              _context8.next = 8;
              return this.getPreambleTransactions(params, user, CALC_USER_POSITION);

            case 8:
              _yield$this$getPreamb5 = _context8.sent;
              preambleTransactions = _yield$this$getPreamb5[0];
              additionalFee = _yield$this$getPreamb5[1];
              // application call
              params.fee = 3000 + additionalFee;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.remove_b_asset_collateral), encodeUint64(bAssetAmount.amount)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: [this.bAssetId],
                rekeyTo: undefined
              });
              return _context8.abrupt("return", assignGroupID(preambleTransactions.concat([txn0])));

            case 14:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8, this);
    }));

    function getRemoveBAssetCollateralTxns(_x15, _x16) {
      return _getRemoveBAssetCollateralTxns.apply(this, arguments);
    }

    return getRemoveBAssetCollateralTxns;
  }()
  /**
   * Constructs a series of transactions that represent a burning of b assets.
   *
   * @param user - algofi user representing the user we want to burn the b assets for
   * @param bAssetAmount - the amount of b asset we want to burn
   * @returns a series of transactions that represent a burning of b assets.
   */
  ;

  _proto2.getBurnTxns =
  /*#__PURE__*/
  function () {
    var _getBurnTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(user, bAssetAmount) {
      var params, _yield$this$getPreamb6, preambleTransactions, txn0, txn1;

      return _regeneratorRuntime().wrap(function _callee9$(_context9) {
        while (1) {
          switch (_context9.prev = _context9.next) {
            case 0:
              if (!(this.marketType == MarketType.VAULT)) {
                _context9.next = 2;
                break;
              }

              throw "Burn action not supported by vault market";

            case 2:
              _context9.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context9.sent;
              _context9.next = 8;
              return this.getPreambleTransactions(params, user, DONT_CALC_USER_POSITION);

            case 8:
              _yield$this$getPreamb6 = _context9.sent;
              preambleTransactions = _yield$this$getPreamb6[0];
              // payment
              txn0 = getPaymentTxn(params, user.address, this.address, this.bAssetId, bAssetAmount.amount); // application call

              params.fee = 3000;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.burn_b_asset)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: [this.underlyingAssetId],
                rekeyTo: undefined
              });
              return _context9.abrupt("return", assignGroupID(preambleTransactions.concat([txn0, txn1])));

            case 15:
            case "end":
              return _context9.stop();
          }
        }
      }, _callee9, this);
    }));

    function getBurnTxns(_x17, _x18) {
      return _getBurnTxns.apply(this, arguments);
    }

    return getBurnTxns;
  }()
  /**
   * Constructs a series of transactions that allow a user to borrow some amount
   * of underlying from the market.
   *
   * @param user - algofi user representing the user we want to borrow for
   * @param underlyingAmount - the amount of underlying to borrow
   * @returns a series of transactions that allow a user to borrow some amount
   * of underlying from the market.
   */
  ;

  _proto2.getBorrowTxns =
  /*#__PURE__*/
  function () {
    var _getBorrowTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(user, underlyingAmount) {
      var params, _yield$this$getPreamb7, preambleTransactions, additionalFee, txn0;

      return _regeneratorRuntime().wrap(function _callee10$(_context10) {
        while (1) {
          switch (_context10.prev = _context10.next) {
            case 0:
              if (!(this.marketType == MarketType.VAULT)) {
                _context10.next = 4;
                break;
              }

              throw "Borrow action not supported by vault market";

            case 4:
              if (!(this.marketType == MarketType.LP)) {
                _context10.next = 6;
                break;
              }

              throw "Borrow action not supported by lp market";

            case 6:
              _context10.next = 8;
              return getParams(this.algod);

            case 8:
              params = _context10.sent;
              _context10.next = 12;
              return this.getPreambleTransactions(params, user, CALC_USER_POSITION);

            case 12:
              _yield$this$getPreamb7 = _context10.sent;
              preambleTransactions = _yield$this$getPreamb7[0];
              additionalFee = _yield$this$getPreamb7[1];
              // application call
              params.fee = 3000 + additionalFee;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.borrow), encodeUint64(underlyingAmount.amount)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: [this.underlyingAssetId],
                rekeyTo: undefined
              });
              return _context10.abrupt("return", assignGroupID(preambleTransactions.concat([txn0])));

            case 18:
            case "end":
              return _context10.stop();
          }
        }
      }, _callee10, this);
    }));

    function getBorrowTxns(_x19, _x20) {
      return _getBorrowTxns.apply(this, arguments);
    }

    return getBorrowTxns;
  }()
  /**
   * Constructs a series of transactions that allow a user to repay some of
   * their borrow.
   *
   * @param user - algofi user representing the user we want to borrow for
   * @param underlyingAmount - the amount of underlying to repay
   * @returns a series of transactions that allow a user to repay some of their
   * borrow.
   */
  ;

  _proto2.getRepayBorrowTxns =
  /*#__PURE__*/
  function () {
    var _getRepayBorrowTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(user, underlyingAmount, repayMax) {
      var repayAmount, params, _yield$this$getPreamb8, preambleTransactions, txn0, txn1;

      return _regeneratorRuntime().wrap(function _callee11$(_context11) {
        while (1) {
          switch (_context11.prev = _context11.next) {
            case 0:
              if (repayMax === void 0) {
                repayMax = false;
              }

              if (!(this.marketType == MarketType.VAULT)) {
                _context11.next = 5;
                break;
              }

              throw "Repay borrow action not supported by vault market";

            case 5:
              if (!(this.marketType == MarketType.LP)) {
                _context11.next = 7;
                break;
              }

              throw "Repay borrow action not supported by lp market";

            case 7:
              repayAmount = underlyingAmount.amount;

              if (repayMax) {
                if (this.underlyingAssetId == ALGO_ASSET_ID) {
                  repayAmount = Math.min(Math.ceil(repayAmount * 1.001), user.balances[ALGO_ASSET_ID] - user.minBalance - 100000);
                } else {
                  repayAmount = Math.min(Math.ceil(repayAmount * 1.001), user.balances[this.underlyingAssetId]);
                }
              }

              _context11.next = 11;
              return getParams(this.algod);

            case 11:
              params = _context11.sent;
              _context11.next = 15;
              return this.getPreambleTransactions(params, user, DONT_CALC_USER_POSITION);

            case 15:
              _yield$this$getPreamb8 = _context11.sent;
              preambleTransactions = _yield$this$getPreamb8[0];
              // payment
              txn0 = getPaymentTxn(params, user.address, this.address, this.underlyingAssetId, repayAmount); // application call

              params.fee = 3000;
              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.repay_borrow)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: [this.underlyingAssetId],
                rekeyTo: undefined
              });
              return _context11.abrupt("return", assignGroupID(preambleTransactions.concat([txn0, txn1])));

            case 22:
            case "end":
              return _context11.stop();
          }
        }
      }, _callee11, this);
    }));

    function getRepayBorrowTxns(_x21, _x22, _x23) {
      return _getRepayBorrowTxns.apply(this, arguments);
    }

    return getRepayBorrowTxns;
  }() // claim rewards

  /**
   * Constructs a series of transactions that allow a user to claim their
   * rewards from the market.
   *
   * @param user - algofi user representing the user we want to claim rewards
   * for
   * @returns a series of transactions that allow a user to claim their
   * rewards from the market.
   */
  ;

  _proto2.getClaimRewardsTxns =
  /*#__PURE__*/
  function () {
    var _getClaimRewardsTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee12(user) {
      var params, transactions, i, rewardsAssetID, assetOptInTxn, txn;
      return _regeneratorRuntime().wrap(function _callee12$(_context12) {
        while (1) {
          switch (_context12.prev = _context12.next) {
            case 0:
              _context12.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context12.sent;
              transactions = [];

              for (i = 0; i < 2; ++i) {
                if (user.lending.v2.userMarketStates[this.appId].rewardsProgramStates[i].realUnclaimed > 0) {
                  rewardsAssetID = this.rewardsPrograms[i].assetID;

                  if (rewardsAssetID > 1) {
                    if (!user.isOptedInToAsset(rewardsAssetID)) {
                      params.fee = 1000;
                      assetOptInTxn = getPaymentTxn(params, user.address, user.address, rewardsAssetID, 0);
                      assetOptInTxn.note = TEXT_ENCODER.encode("Asset Opt In " + rewardsAssetID.toString() + " for app " + this.appId.toString());
                      transactions.push(assetOptInTxn);
                    }
                  }

                  params.fee = 3000;
                  txn = algosdk.makeApplicationNoOpTxnFromObject({
                    from: user.address,
                    appIndex: this.appId,
                    suggestedParams: params,
                    appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.claim_rewards), encodeUint64(i)],
                    accounts: [user.lending.v2.storageAddress, this.rewardsEscrowAccount],
                    foreignApps: [this.managerAppId],
                    foreignAssets: [rewardsAssetID],
                    rekeyTo: undefined
                  });
                  transactions.push(txn);
                }
              }

              return _context12.abrupt("return", transactions);

            case 6:
            case "end":
              return _context12.stop();
          }
        }
      }, _callee12, this);
    }));

    function getClaimRewardsTxns(_x24) {
      return _getClaimRewardsTxns.apply(this, arguments);
    }

    return getClaimRewardsTxns;
  }() // vault specific actions

  /**
   * Constructs a series of transactions to sync the vault.
   *
   * @param user - algofi user representing the user we want to sync the vault for
   * @returns a series of transactions to sync the vault.
   */
  ;

  _proto2.getSyncVaultTxns =
  /*#__PURE__*/
  function () {
    var _getSyncVaultTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee13(user) {
      var params, txn0;
      return _regeneratorRuntime().wrap(function _callee13$(_context13) {
        while (1) {
          switch (_context13.prev = _context13.next) {
            case 0:
              if (!(this.marketType != MarketType.VAULT)) {
                _context13.next = 2;
                break;
              }

              throw "Sync vault action only supported by vault market";

            case 2:
              _context13.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context13.sent;

              params.fee = 2000;
              txn0 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(MARKET_STRINGS.sync_vault)],
                accounts: [user.lending.v2.storageAddress],
                foreignApps: [this.managerAppId],
                foreignAssets: [this.underlyingAssetId],
                rekeyTo: undefined
              });
              return _context13.abrupt("return", assignGroupID([txn0]));

            case 9:
            case "end":
              return _context13.stop();
          }
        }
      }, _callee13, this);
    }));

    function getSyncVaultTxns(_x25) {
      return _getSyncVaultTxns.apply(this, arguments);
    }

    return getSyncVaultTxns;
  }();

  return Market;
}();

// IMPORTS

var ROUND_UP = true; // HELPER CLASSES

var UserMarketRewardsState =
/**
 * Constructor for the user's market rewards state.
 *
 * @param marketState - a dictionary representing a users state in a market on chain
 * @param market - the market of interest
 * @param bAssetCollateral - b asset collateral for market
 * @param borrowShares - borrow shares for market
 * @param programIndex - program index we are interested in
 */
function UserMarketRewardsState(marketState, market, bAssetCollateral, borrowShares, programIndex) {
  this.programNumber = (marketState == null ? void 0 : marketState[MARKET_STRINGS.user_rewards_program_number_prefix + String.fromCharCode.apply(null, encodeUint64(programIndex))]) || 0;
  this.assetID = market.rewardsPrograms[programIndex].assetID;

  if (this.programNumber == market.rewardsPrograms[programIndex].programNumber) {
    var rawRewardsIndexBytes = new Uint8Array(Buffer.from(String(marketState[MARKET_STRINGS.user_latest_rewards_index_prefix + String.fromCharCode.apply(null, encodeUint64(programIndex))]), "base64"));
    this.latestIndex = bytesToBigInt(rawRewardsIndexBytes);
    this.unclaimed = marketState[MARKET_STRINGS.user_unclaimed_rewards_prefix + String.fromCharCode.apply(null, encodeUint64(programIndex))];
  } else {
    this.latestIndex = BigInt(0);
    this.unclaimed = 0;
  } // calculate real unclaimed rewards


  this.realUnclaimed = this.unclaimed;
  var userTotal = 0;
  var globalTotal = 0;

  if (market.marketType == MarketType.VAULT || market.marketType == MarketType.LP) {
    userTotal = bAssetCollateral;
    globalTotal = market.bAssetCirculation;
  } else {
    userTotal = borrowShares;
    globalTotal = market.borrowShareCirculation;
  }

  this.realUnclaimed += Number((market.rewardsPrograms[programIndex].projectedIndex - this.latestIndex) * BigInt(userTotal) / FIXED_18_SCALE_FACTOR); // calculate rewards per year at current reate

  this.rewardsPerYear = market.rewardsPrograms[programIndex].rewardsPerSecond * (365 * 24 * 60 * 60) * userTotal / globalTotal;
}; // INTERFACE

var UserMarketState =
/**
 * Constructor for a user market state
 *
 * @param marketState - a dictionary representing the user's state in a market
 * @param market - the market of interest
 */
function UserMarketState(marketState, market) {
  this.rewardsProgramStates = [];
  this.bAssetCollateral = (marketState == null ? void 0 : marketState[MARKET_STRINGS.user_active_b_asset_collateral]) || 0;
  this.borrowShares = (marketState == null ? void 0 : marketState[MARKET_STRINGS.user_borrow_shares]) || 0;
  this.suppliedAmount = market.bAssetToUnderlying(this.bAssetCollateral);
  this.borrowedAmount = market.borrowSharesToUnderlying(this.borrowShares, ROUND_UP);
  this.rewardsProgramStates = [];
  this.rewardsProgramStates.push(new UserMarketRewardsState(marketState, market, this.bAssetCollateral, this.borrowShares, 0));
  this.rewardsProgramStates.push(new UserMarketRewardsState(marketState, market, this.bAssetCollateral, this.borrowShares, 1));
};

var User = /*#__PURE__*/function () {
  /**
   * Constructor for the lending user class.
   *
   * @param lendingClient - lending client
   * @param address - address for user
   */
  function User(lendingClient, address) {
    this.storageBalances = {};
    this.optedInToManager = false;
    this.optedInMarkets = [];
    this.userMarketStates = {};
    this.netUnclaimedRewards = {};
    this.netRewardsPerYear = {};
    this.lendingClient = lendingClient;
    this.algod = this.lendingClient.algod;
    this.address = address;
  }
  /**
   * Functino which updates the lending user object to match the user's actual
   * lending local state.
   *
   * @param userLocalStates - a list of all of the user's local states
   */


  var _proto = User.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      var _this = this;

      var storageLocalStates, managerState, i, pageKey, pageBytes, pageItems, j, dollarTotaledSupplyAPR, dollarTotaledBorrowAPR, _i, _Object$entries, _Object$entries$_i, key, value, market, assetId;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              if (!(this.lendingClient.manager.appId in userLocalStates)) {
                _context.next = 50;
                break;
              }

              this.optedInToManager = true;
              this.storageAddress = parseAddressBytes(userLocalStates[this.lendingClient.manager.appId][MANAGER_STRINGS.storage_account]); // reset state

              this.optedInMarkets = [];
              this.userMarketStates = {}; // load storage balances

              _context.next = 7;
              return getAccountBalances(this.algod, this.storageAddress);

            case 7:
              this.storageBalances = _context.sent;
              _context.next = 10;
              return getAccountMinBalance(this.algod, this.storageAddress);

            case 10:
              this.storageMinBalance = _context.sent;
              _context.next = 13;
              return getLocalStates(this.algod, this.storageAddress);

            case 13:
              storageLocalStates = _context.sent;
              // load manager state
              managerState = storageLocalStates[this.lendingClient.manager.appId];

              for (i = 0; i < 7; ++i) {
                pageKey = MANAGER_STRINGS.opted_in_markets_page_prefix + String.fromCharCode.apply(null, encodeUint64(i));

                if (pageKey in managerState) {
                  pageBytes = Buffer.from(managerState[pageKey], "base64").toString("binary");
                  pageItems = Math.floor(pageBytes.length / 8);

                  for (j = 0; j < pageItems; ++j) {
                    this.optedInMarkets.push(decodeUint64(decodeBytes(pageBytes.substr(j * 8, 8)), "safe"));
                  }
                }
              } // load market states


              this.optedInMarkets.forEach(function (marketAppId) {
                _this.userMarketStates[marketAppId] = new UserMarketState(storageLocalStates[marketAppId], _this.lendingClient.markets[marketAppId]);
              }); // calc net values

              this.netSupplied = 0;
              this.netScaledCollateral = 0;
              this.netBorrowed = 0;
              this.netScaledBorrow = 0;
              this.netUnclaimedRewards = {};
              this.netRewardsPerYear = {};
              this.netSupplyRewardsPerYear = 0;
              this.netBorrowRewardsPerYear = 0;
              dollarTotaledSupplyAPR = 0;
              dollarTotaledBorrowAPR = 0;
              _i = 0, _Object$entries = Object.entries(this.userMarketStates);

            case 28:
              if (!(_i < _Object$entries.length)) {
                _context.next = 46;
                break;
              }

              _Object$entries$_i = _Object$entries[_i], key = _Object$entries$_i[0], value = _Object$entries$_i[1];
              market = this.lendingClient.markets[key]; // TODO improve efficiency

              this.netSupplied += value.suppliedAmount.toUSD();
              this.netBorrowed += value.borrowedAmount.toUSD();
              this.netScaledCollateral += Number((value.suppliedAmount.toUSD() * market.collateralFactor / FIXED_3_SCALE_FACTOR).toFixed(3));

              if (value.borrowShares != 0) {
                // round up unless exactly 0
                this.netScaledBorrow += Number((value.borrowedAmount.toUSD() * market.borrowFactor / FIXED_3_SCALE_FACTOR).toFixed(3)) + 0.001;
              }

              _context.t0 = dollarTotaledSupplyAPR;
              _context.t1 = value.suppliedAmount.toUSD();
              _context.next = 39;
              return market.getSupplyAPR();

            case 39:
              _context.t2 = _context.sent;
              dollarTotaledSupplyAPR = _context.t0 += _context.t1 * _context.t2;
              dollarTotaledBorrowAPR += value.borrowedAmount.toUSD() * market.getBorrowAPR(); // rewards

              for (i = 0; i < 2; i++) {
                assetId = value.rewardsProgramStates[i].assetID;

                if (assetId > 0) {
                  this.netUnclaimedRewards[assetId] = value.rewardsProgramStates[i].realUnclaimed + (this.netUnclaimedRewards[assetId] || 0);
                  this.netRewardsPerYear[assetId] = value.rewardsProgramStates[i].rewardsPerYear + (this.netRewardsPerYear[assetId] || 0);

                  if (market.marketType == MarketType.VAULT || market.marketType == MarketType.LP) {
                    this.netSupplyRewardsPerYear += this.lendingClient.algofiClient.assetData.getAsset(value.rewardsProgramStates[i].rewardsPerYear, assetId).toUSD();
                  } else {
                    this.netBorrowRewardsPerYear += this.lendingClient.algofiClient.assetData.getAsset(value.rewardsProgramStates[i].rewardsPerYear, assetId).toUSD();
                  }
                }
              }

            case 43:
              _i++;
              _context.next = 28;
              break;

            case 46:
              if (this.netSupplied > 0) {
                this.netSupplyAPR = dollarTotaledSupplyAPR / this.netSupplied;
                this.netSupplyRewardsAPR = this.netSupplyRewardsPerYear / this.netSupplied;
              } else {
                this.netSupplyAPR = 0;
                this.netSupplyRewardsAPR = 0;
              }

              if (this.netBorrowed > 0) {
                this.netBorrowAPR = dollarTotaledBorrowAPR / this.netBorrowed;
                this.netBorrowRewardsAPR = this.netBorrowRewardsPerYear / this.netBorrowed;
              } else {
                this.netBorrowAPR = 0;
                this.netBorrowRewardsAPR = 0;
              }

              _context.next = 51;
              break;

            case 50:
              this.optedInToManager = false;

            case 51:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Returns whether or not the user is opted into the market.
   *
   * @param marketAppId - application id of the market
   * @returns whether or not the user is opted into the market.
   */
  ;

  _proto.isUserOptedIntoMarket = function isUserOptedIntoMarket(marketAppId) {
    return marketAppId in this.userMarketStates;
  }
  /**
   * Returns page offset for a market.
   *
   * @param marketAppId - application id of the market
   * @returns an array of the page and offset that the market is stored at.
   */
  ;

  _proto.getMarketPageOffset = function getMarketPageOffset(marketAppId) {
    var marketIndex = this.optedInMarkets.indexOf(marketAppId);
    var page = Math.floor(marketIndex / 3);
    var offset = marketIndex % 3;
    return [page, offset];
  }
  /**
   * Constructs a series of transactions that calculate a user's positions in a market.
   *
   * @param targetMarketAppId - an instance of an algofi client
   * @returns a series of transactions that calculate a user's positions in a market.
   */
  ;

  _proto.getCalcUserPositionTransactions =
  /*#__PURE__*/
  function () {
    var _getCalcUserPositionTransactions = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(targetMarketAppId) {
      var transactions, params, pageCount, page, marketsOnPage, foreignApps, offset, market, txn;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              transactions = [];
              _context2.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context2.sent;
              params.fee = 0;
              pageCount = Math.ceil(this.optedInMarkets.length / 3);

              for (page = 0; page < pageCount; ++page) {
                marketsOnPage = (page + 1) * 3 <= this.optedInMarkets.length ? 3 : this.optedInMarkets.length % 3;
                foreignApps = [];

                for (offset = 0; offset < marketsOnPage; ++offset) {
                  market = this.lendingClient.markets[this.optedInMarkets[page * 3 + offset]];
                  foreignApps.push(market.appId);
                  foreignApps.push(market.oracle.appId);
                }

                txn = algosdk.makeApplicationNoOpTxnFromObject({
                  from: PERMISSIONLESS_SENDER_LOGIC_SIG.lsig.address(),
                  appIndex: this.lendingClient.manager.appId,
                  suggestedParams: params,
                  appArgs: [TEXT_ENCODER.encode(MANAGER_STRINGS.calculate_user_position), encodeUint64(page), encodeUint64(targetMarketAppId)],
                  accounts: [this.storageAddress],
                  foreignApps: foreignApps,
                  foreignAssets: undefined,
                  rekeyTo: undefined
                });
                transactions.push(txn);
              }

              return _context2.abrupt("return", transactions);

            case 8:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getCalcUserPositionTransactions(_x2) {
      return _getCalcUserPositionTransactions.apply(this, arguments);
    }

    return getCalcUserPositionTransactions;
  }();

  _proto.parseTransaction = function parseTransaction(txns, txnIdx, parsedTransactions) {
    var txn = txns[txnIdx];
    var nextTxn = txns[txnIdx + 1];
    var appId = txn['application-transaction']['application-id'];
    var assetsIn = {};
    var assetsOut = {};

    if (appId == this.lendingClient.manager.appId) {
      // manager
      var command = Base64Encoder.decode(txn['application-transaction']['application-args'][0]);

      switch (command) {
        // TODO implement gov and vault functions and manager close out
        case MANAGER_STRINGS.user_opt_in:
          {
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "PROTOCOL OPT IN", [], assetsIn, assetsOut));
            break;
          }

        case MANAGER_STRINGS.user_market_opt_in:
          {
            var marketAppId = txn['application-transaction']['foreign-apps'][0];
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", marketAppId, "MARKET OPT IN", [], assetsIn, assetsOut));
            break;
          }

        case MANAGER_STRINGS.user_market_close_out:
          {
            var _marketAppId = txn['application-transaction']['foreign-apps'][0];
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", _marketAppId, "MARKET OPT OUT", [], assetsIn, assetsOut));
            break;
          }

        default:
          return;
      }
    } else if (appId in this.lendingClient.markets) {
      // markets
      var _command = Base64Encoder.decode(txn['application-transaction']['application-args'][0]);

      switch (_command) {
        // add support for vault txns
        case MARKET_STRINGS.mint_b_asset:
          {
            if (!nextTxn) {
              return;
            }

            storeTransferDetails(nextTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'][1], assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "MINT B ASSET", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.add_underlying_collateral:
          {
            if (!nextTxn) {
              return;
            }

            storeTransferDetails(nextTxn, assetsIn);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "ADD COLLATERAL", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.add_b_asset_collateral:
          {
            if (!nextTxn) {
              return;
            }

            storeTransferDetails(nextTxn, assetsIn);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "ADD B ASSET", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.remove_underlying_collateral:
          {

            if (this.lendingClient.markets[appId].marketType == MarketType.VAULT) {
              storeTransferDetails(txn['inner-txns'][1]['inner-txns'][0], assetsOut);
            } else {
              storeTransferDetails(txn['inner-txns'][1], assetsOut);
            }

            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "REMOVE COLLATERAL", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.remove_b_asset_collateral:
          {
            storeTransferDetails(txn['inner-txns'][1], assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "REMOVE B ASSET", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.burn_b_asset:
          {
            if (!nextTxn) {
              return;
            }

            storeTransferDetails(nextTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'][1], assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "BURN", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.borrow:
          {
            storeTransferDetails(txn['inner-txns'][1], assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "BORROW", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.repay_borrow:
          {
            if (!nextTxn) {
              return;
            }

            storeTransferDetails(nextTxn, assetsIn);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "REPAY BORROW", [], assetsIn, assetsOut));
            break;
          }

        case MARKET_STRINGS.claim_rewards:
          {
            storeTransferDetails(txn['inner-txns'][1], assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "LENDING v2", appId, "CLAIM REWARDS", [], assetsIn, assetsOut));
            break;
          }

        default:
          return;
      }
    }
  };

  return User;
}();

var LendingClient = /*#__PURE__*/function () {
  /**
   * Constructor for the algofi lending client.
   *
   * @param algofiClient - an instance of an algofi client
   */
  function LendingClient(algofiClient) {
    this.markets = {};
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.managerConfig = ManagerConfigs[this.network];
    this.marketConfigs = MarketConfigs[this.network];
    this.manager = new Manager(this.algod, this.managerConfig.appId);
  }
  /**
   * Call load stat eand update all of the user's market and load it into the object.
   */


  var _proto = LendingClient.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return Promise.all(this.marketConfigs.map( /*#__PURE__*/function () {
                var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(config) {
                  return _regeneratorRuntime().wrap(function _callee$(_context) {
                    while (1) {
                      switch (_context.prev = _context.next) {
                        case 0:
                          if (!(config.appId in _this.markets)) {
                            _this.markets[config.appId] = new Market(_this.algod, _this, _this.manager.appId, config);
                          }

                          _context.next = 3;
                          return _this.markets[config.appId].loadState();

                        case 3:
                        case "end":
                          return _context.stop();
                      }
                    }
                  }, _callee);
                }));

                return function (_x) {
                  return _ref.apply(this, arguments);
                };
              }()));

            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Returns a lending user with the given address.
   *
   * @param address - the address that we want to get the lending user for
   */
  ;

  _proto.getUser = function getUser(address) {
    return new User(this, address);
  };

  _proto.getClaimRewardsTxns = /*#__PURE__*/function () {
    var _getClaimRewardsTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user) {
      var transactions, _iterator, _step, market;

      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              transactions = [];
              _iterator = _createForOfIteratorHelperLoose(user.lending.v2.optedInMarkets);

            case 2:
              if ((_step = _iterator()).done) {
                _context3.next = 12;
                break;
              }

              market = _step.value;

              if (!(transactions.length <= 12)) {
                _context3.next = 10;
                break;
              }

              _context3.t0 = transactions;
              _context3.next = 8;
              return this.markets[market].getClaimRewardsTxns(user);

            case 8:
              _context3.t1 = _context3.sent;
              transactions = _context3.t0.concat.call(_context3.t0, _context3.t1);

            case 10:
              _context3.next = 2;
              break;

            case 12:
              return _context3.abrupt("return", assignGroupID(transactions));

            case 13:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getClaimRewardsTxns(_x2) {
      return _getClaimRewardsTxns.apply(this, arguments);
    }

    return getClaimRewardsTxns;
  }();

  _proto.isLendingTransaction = function isLendingTransaction(txn) {
    var appId = txn['application-transaction']['application-id'];
    return appId in this.markets || appId == this.manager.appId;
  };

  _proto.getTotalSupplied = function getTotalSupplied() {
    var totalSupplied = 0;

    for (var _i = 0, _Object$entries = Object.entries(this.markets); _i < _Object$entries.length; _i++) {
      var _Object$entries$_i = _Object$entries[_i],
          market = _Object$entries$_i[1];
      totalSupplied += market.getTotalSupplied().toUSD();
    }

    return totalSupplied;
  };

  _proto.getTotalBorrowed = function getTotalBorrowed() {
    var totalBorrowed = 0;

    for (var _i2 = 0, _Object$entries2 = Object.entries(this.markets); _i2 < _Object$entries2.length; _i2++) {
      var _Object$entries2$_i = _Object$entries2[_i2],
          market = _Object$entries2$_i[1];
      totalBorrowed += market.getTotalBorrowed().toUSD();
    }

    return totalBorrowed;
  };

  return LendingClient;
}();

var BaseLendingClient = /*#__PURE__*/function () {
  function BaseLendingClient(algofiClient) {
    this.v2 = new LendingClient(algofiClient);
  }

  var _proto = BaseLendingClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v2.loadState();

            case 2:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseLendingClient;
}();

var _StakingConfigs;

var StakingConfig =
/**
 * Constructor for the v1 staking config.
 *
 * @param name - name
 * @param managerAppId - manager app id
 * @param marketAppId - market app id
 * @param assetId - asset id
 * @param oracleAppId - oracle app id
 */
function StakingConfig(name, managerAppId, marketAppId, assetId, oracleAppId) {
  this.name = name;
  this.managerAppId = managerAppId;
  this.marketAppId = marketAppId;
  this.assetId = assetId;
  this.oracleAppId = oracleAppId;
};
var StakingConfigs = (_StakingConfigs = {}, _StakingConfigs[Network.MAINNET] = [
/*#__PURE__*/
// Staking
// new StakingConfig("STBL Staking", 482625868, 482608867, 465865291, 451327550),
new StakingConfig("DEFLY Staking", 641500474, 641499935, 470842789, 451327550), /*#__PURE__*/new StakingConfig("OPUL Staking", 674527132, 674526408, 287867876, 451327550),
/*#__PURE__*/
// Tinyman Farming
new StakingConfig("Tinyman v1 STBL-USDC LP Staking", 485247444, 485244022, 467020179, 451327550), /*#__PURE__*/new StakingConfig("Tinyman v1.1 STBL-USDC LP Staking", 553869413, 553866305, 552737686, 451327550),
/*#__PURE__*/
// Algofi Farming
new StakingConfig("Algofi STBL-ALGO LP Staking", 611804624, 611801333, 607645566, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-USDC LP Staking", 611869320, 611867642, 609172718, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-USDC Nano LP Staking", 661193019, 661192413, 658337286, 451327550), /*#__PURE__*/new StakingConfig("Algofi USDC-USDT Nano LP Staking", 661247364, 661207804, 659678778, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-USDT Nano LP Staking", 661204747, 661199805, 659677515, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-XET LP Staking", 635813909, 635812850, 635256863, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-ZONE LP Staking", 647785804, 647785158, 647801343, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-DEFLY LP Staking", 639747739, 639747119, 624956449, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-goBTC LP Staking", 635863793, 635860537, 635846733, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-goETH LP Staking", 635866213, 635864509, 635854339, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-OPUL LP Staking", 637795072, 637793356, 637802380, 451327550), /*#__PURE__*/new StakingConfig("Algofi STBL-goMINT LP Staking", 764407972, 764406975, 764421152, 451327550)], _StakingConfigs[Network.TESTNET] = [], _StakingConfigs);
var STAKING_STRINGS = {
  latest_rewards_time: "lrt",
  rewards_program_number: "nrp",
  user_storage_address: "usa",
  total_staked: "acc",
  user_total_staked: "uac",
  rewards_amount: "ra",
  rewards_asset_id: "rai",
  rewards_per_second: "rp",
  rewards_secondary_asset_id: "rsai",
  rewards_secondary_ratio: "rsr",
  user_pending_rewards: "upr",
  user_secondary_pending_rewards: "us",
  user_rewards_program_number: "urpn",
  rewards_coefficient: "\x00\x00\x00\x00\x00\x00\x00\x01_ci",
  user_rewards_coefficient: "\x00\x00\x00\x00\x00\x00\x00\x01_uc",
  fetch_market_variables: "fmv",
  dummy: "d",
  oracle_app_id: "o",
  update_prices: "up",
  update_protocol_data: "upd",
  update_rewards_program: "urp",
  stake: "mt",
  unstake: "rcu",
  claim_rewards: "cr"
};

var Staking = /*#__PURE__*/function () {
  /**
   * Constructor for the staking object.
   *
   * @param algod - algod client
   * @param stakingClient - staking client
   * @param stakingConfig - stakingConfig object with information on the staking
   * contract
   */
  function Staking(algod, stakingClient, stakingConfig) {
    this.algod = algod;
    this.stakingClient = stakingClient;
    this.assetDataClient = stakingClient.algofiClient.assetData;
    this.managerAppId = stakingConfig.managerAppId;
    this.marketAppId = stakingConfig.marketAppId;
    this.managerAddress = getApplicationAddress(this.managerAppId);
    this.marketAddress = getApplicationAddress(this.marketAppId);
    this.assetId = stakingConfig.assetId;
  }
  /**
   * Function to load in global state into the relevant fields on the class.
   */


  var _proto = Staking.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var managerGlobalState, marketGlobalState;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.managerAppId);

            case 2:
              managerGlobalState = _context.sent;
              _context.next = 5;
              return getApplicationGlobalState(this.algod, this.marketAppId);

            case 5:
              marketGlobalState = _context.sent;
              this.latestTime = managerGlobalState[STAKING_STRINGS.latest_rewards_time];
              this.oracleAppId = marketGlobalState[STAKING_STRINGS.oracle_app_id];
              this.totalStaked = marketGlobalState[STAKING_STRINGS.total_staked];
              this.rewardsProgramNumber = managerGlobalState[STAKING_STRINGS.rewards_program_number];
              this.rewardsCoefficient = managerGlobalState[STAKING_STRINGS.rewards_coefficient];
              this.rewardsAmount = managerGlobalState[STAKING_STRINGS.rewards_amount];
              this.rewardsAssetId = managerGlobalState[STAKING_STRINGS.rewards_asset_id];
              this.rewardsPerSecond = managerGlobalState[STAKING_STRINGS.rewards_per_second];
              this.rewardsSecondaryAssetId = managerGlobalState[STAKING_STRINGS.rewards_secondary_asset_id];
              this.rewardsSecondaryRatio = managerGlobalState[STAKING_STRINGS.rewards_secondary_ratio];
              this.projectedRewardsCoefficient = this.rewardsCoefficient + (Math.floor(Date.now() / 1000) - this.latestTime) * this.rewardsPerSecond * Math.pow(10, 14) / this.totalStaked;

            case 17:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // GETTERS (require assetData to be loaded)
  ;

  _proto.getTotalStaked = function getTotalStaked() {
    return this.assetDataClient.getAsset(this.totalStaked, this.assetId);
  };

  _proto.getRewardsAPR = function getRewardsAPR() {
    if (this.rewardsAssetId == 0) {
      return 0;
    }

    var annualRewards = this.assetDataClient.getAsset(this.rewardsPerSecond * SECONDS_PER_YEAR, this.rewardsAssetId);
    return annualRewards.toUSD() / (this.getTotalStaked().toUSD() || 1);
  };

  _proto.getSecondaryRewardsAPR = function getSecondaryRewardsAPR() {
    if (this.rewardsSecondaryAssetId == 0) {
      return 0;
    }

    var annualSecondaryRewards = this.assetDataClient.getAsset(Math.floor(this.rewardsPerSecond * SECONDS_PER_YEAR * this.rewardsSecondaryRatio / 1000), this.rewardsSecondaryAssetId);
    return annualSecondaryRewards.toUSD() / (this.getTotalStaked().toUSD() || 1);
  }
  /**
   * Constructs a series of transactions to opt a user into the staking
   * contract.
   *
   * @param user - user opting in
   * @param storageAccount - storage account for user opting in
   * @returns a series of transactions to opt a user into the staking
   * contract.
   */
  ;

  _proto.getOptInTxns =
  /*#__PURE__*/
  function () {
    var _getOptInTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user, storageAccount) {
      var params, txns;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              txns = []; // fund storage account

              txns.push(makePaymentTxnWithSuggestedParamsFromObject({
                from: user.address,
                amount: 700000,
                to: storageAccount.addr,
                suggestedParams: params,
                closeRemainderTo: undefined,
                rekeyTo: undefined
              })); // opt in storage account

              txns.push(makeApplicationOptInTxnFromObject({
                from: storageAccount.addr,
                appIndex: this.marketAppId,
                suggestedParams: params,
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              })); // opt user into manager

              txns.push(makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                suggestedParams: params,
                foreignApps: [this.marketAppId],
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              })); // opt storage account into manager

              txns.push(makeApplicationOptInTxnFromObject({
                from: storageAccount.addr,
                appIndex: this.managerAppId,
                suggestedParams: params,
                rekeyTo: this.managerAddress,
                foreignApps: undefined,
                accounts: undefined,
                foreignAssets: undefined
              }));
              return _context2.abrupt("return", assignGroupID(txns));

            case 9:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getOptInTxns(_x, _x2) {
      return _getOptInTxns.apply(this, arguments);
    }

    return getOptInTxns;
  }()
  /**
   * Constructs a series of transactions to put before many of the transactions
   * in staking on the Algofi protocol.
   *
   * @param user - user to get preamble transactions for
   * @returns a series of transactions to put before many of the transactions
   * in staking on the Algofi protocol.
   */
  ;

  _proto.getPreambleTxns =
  /*#__PURE__*/
  function () {
    var _getPreambleTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user) {
      var params, txns, enc, i;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context3.sent;
              txns = [];
              enc = new TextEncoder();
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                foreignApps: [this.marketAppId],
                appArgs: [enc.encode(STAKING_STRINGS.fetch_market_variables)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }));
              params.fee = 2000;
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                foreignApps: [this.oracleAppId],
                appArgs: [enc.encode(STAKING_STRINGS.update_prices)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }));
              params.fee = 1000;
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                foreignApps: [this.marketAppId],
                appArgs: [enc.encode(STAKING_STRINGS.update_protocol_data)],
                accounts: [user.staking.v1.userStakingStates[this.managerAppId].storageAddress],
                suggestedParams: params,
                foreignAssets: undefined,
                rekeyTo: undefined
              }));

              for (i = 0; i < 9; i++) {
                txns.push(makeApplicationNoOpTxnFromObject({
                  from: user.address,
                  appIndex: this.managerAppId,
                  foreignApps: undefined,
                  appArgs: [enc.encode("dummy_" + i.toString())],
                  suggestedParams: params,
                  accounts: undefined,
                  foreignAssets: undefined,
                  rekeyTo: undefined
                }));
              }

              return _context3.abrupt("return", txns);

            case 12:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getPreambleTxns(_x3) {
      return _getPreambleTxns.apply(this, arguments);
    }

    return getPreambleTxns;
  }()
  /**
   * Constructs a series of transactions to stake a certain amount of an asset for
   * a user.
   *
   * @param user - user staking
   * @param amount - amount staking
   * @returns a series of transactions to stake a certain amount of an asset for
   * a user.
   */
  ;

  _proto.getStakeTxns =
  /*#__PURE__*/
  function () {
    var _getStakeTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, amount) {
      var params, enc, txns;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              enc = new TextEncoder();
              _context4.next = 6;
              return this.getPreambleTxns(user);

            case 6:
              txns = _context4.sent;
              txns.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                appArgs: [enc.encode(STAKING_STRINGS.stake)],
                suggestedParams: params,
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }));
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.marketAppId,
                foreignApps: [this.managerAppId],
                appArgs: [enc.encode(STAKING_STRINGS.stake)],
                accounts: [user.staking.v1.userStakingStates[this.managerAppId].storageAddress],
                suggestedParams: params,
                foreignAssets: undefined,
                rekeyTo: undefined
              })); // sending staking asset

              txns.push(makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.address,
                to: this.marketAddress,
                assetIndex: this.assetId,
                amount: amount,
                suggestedParams: params,
                rekeyTo: undefined,
                revocationTarget: undefined
              }));
              return _context4.abrupt("return", assignGroupID(txns));

            case 11:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getStakeTxns(_x4, _x5) {
      return _getStakeTxns.apply(this, arguments);
    }

    return getStakeTxns;
  }()
  /**
   * Constructs a series of transactions to unstake a certain amount for a user on
   * a staking contract.
   *
   * @param user - user to unstake for
   * @param amount - amount to unstake
   * @returns a series of transactions to unstake a certain amount for a user on
   * a staking contract.
   */
  ;

  _proto.getUnstakeTxns =
  /*#__PURE__*/
  function () {
    var _getUnstakeTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, amount) {
      var params, enc, txns;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              enc = new TextEncoder();
              _context5.next = 6;
              return this.getPreambleTxns(user);

            case 6:
              txns = _context5.sent;
              txns.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                appArgs: [enc.encode(STAKING_STRINGS.unstake), encodeUint64(amount)],
                suggestedParams: params,
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }));
              params.fee = 2000;
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.marketAppId,
                foreignApps: [this.managerAppId],
                appArgs: [enc.encode(STAKING_STRINGS.unstake), encodeUint64(amount)],
                accounts: [user.staking.v1.userStakingStates[this.managerAppId].storageAddress],
                suggestedParams: params,
                foreignAssets: [this.assetId],
                rekeyTo: undefined
              }));
              return _context5.abrupt("return", assignGroupID(txns));

            case 11:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getUnstakeTxns(_x6, _x7) {
      return _getUnstakeTxns.apply(this, arguments);
    }

    return getUnstakeTxns;
  }()
  /**
   * Constructs a series of transactions to claim a user's staked assets.
   *
   * @param user - user to claim
   * @returns a series of transactions to claim a user's staked assets.
   */
  ;

  _proto.getClaimTxns =
  /*#__PURE__*/
  function () {
    var _getClaimTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user) {
      var params, enc, txns;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context6.sent;
              enc = new TextEncoder();
              _context6.next = 6;
              return this.getPreambleTxns(user);

            case 6:
              txns = _context6.sent;
              params.fee = 3000;
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.managerAppId,
                foreignApps: [this.marketAppId],
                appArgs: [enc.encode(STAKING_STRINGS.claim_rewards)],
                accounts: [user.staking.v1.userStakingStates[this.managerAppId].storageAddress],
                suggestedParams: params,
                foreignAssets: this.rewardsAssetId != 1 ? [this.rewardsAssetId] : [this.rewardsSecondaryAssetId],
                rekeyTo: undefined
              }));
              return _context6.abrupt("return", assignGroupID(txns));

            case 10:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getClaimTxns(_x8) {
      return _getClaimTxns.apply(this, arguments);
    }

    return getClaimTxns;
  }();

  return Staking;
}();

var UserStakingState = /*#__PURE__*/function () {
  /**
   * Constructor for the v1 user staking state object.
   *
   * @param algod - algod client
   * @param staking - staking
   * @param storageAddress - storage address
   */
  function UserStakingState(algod, staking, storageAddress) {
    this.algod = algod;
    this.staking = staking;
    this.storageAddress = storageAddress;
  }
  /**
   * Function to get the local states of the staking contract and update the
   * information in the object.
   */


  var _proto = UserStakingState.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var storageLocalStates, pendingRewards, pendingSecondaryRewards, unrealizedRewards, unrealizedSecondaryRewards;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getLocalStates(this.algod, this.storageAddress);

            case 2:
              storageLocalStates = _context.sent;
              this.totalStaked = storageLocalStates[this.staking.marketAppId][STAKING_STRINGS.user_total_staked] || 0;
              this.rewardsProgramNumber = storageLocalStates[this.staking.managerAppId][STAKING_STRINGS.user_rewards_program_number] || 0;
              this.rewardsCoefficient = storageLocalStates[this.staking.managerAppId][STAKING_STRINGS.user_rewards_coefficient] || 0;
              pendingRewards = storageLocalStates[this.staking.managerAppId][STAKING_STRINGS.user_pending_rewards] || 0;
              pendingSecondaryRewards = storageLocalStates[this.staking.managerAppId][STAKING_STRINGS.user_secondary_pending_rewards] || 0;
              unrealizedRewards = 0;

              if (this.rewardsProgramNumber == this.staking.rewardsProgramNumber) {
                unrealizedRewards = (this.staking.projectedRewardsCoefficient - this.rewardsCoefficient) * this.totalStaked / Math.pow(10, 14);
              } else {
                unrealizedRewards = this.staking.projectedRewardsCoefficient * this.totalStaked / Math.pow(10, 14);
              }

              unrealizedSecondaryRewards = unrealizedRewards * this.staking.rewardsSecondaryRatio / Math.pow(10, 3);
              this.unclaimedRewards = pendingRewards + unrealizedRewards;
              this.unclaimedSecondaryRewards = pendingSecondaryRewards + unrealizedSecondaryRewards;

              if (this.totalStaked > 0) {
                this.rewardsPerYear = this.staking.rewardsPerSecond * (365 * 24 * 60 * 60) * this.totalStaked / this.staking.totalStaked;
              } else {
                this.rewardsPerYear = 0;
              }

              this.secondaryRewardsPerYear = this.rewardsPerYear * this.staking.rewardsSecondaryRatio / Math.pow(10, 3);

            case 15:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return UserStakingState;
}();

var StakingUser = /*#__PURE__*/function () {
  function StakingUser(stakingClient, address) {
    this.stakingClient = stakingClient;
    this.algod = this.stakingClient.algod;
    this.address = address;
  } // get opted in staking contracts

  /**
   * Function to take the local states of a user and update the data on the
   * object.
   *
   * @param userLocalStates - collection of all of the local states for the user
   */


  var _proto = StakingUser.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      var _i, _Object$entries, _Object$entries$_i, formattedAppId, userLocalState, appId, storageAddress;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              this.optedInStakingContracts = [];
              this.userStakingStates = {};
              _i = 0, _Object$entries = Object.entries(userLocalStates);

            case 3:
              if (!(_i < _Object$entries.length)) {
                _context.next = 15;
                break;
              }

              _Object$entries$_i = _Object$entries[_i], formattedAppId = _Object$entries$_i[0], userLocalState = _Object$entries$_i[1];
              appId = parseInt(formattedAppId);

              if (!(appId in this.stakingClient.stakingContracts)) {
                _context.next = 12;
                break;
              }

              this.optedInStakingContracts.push(appId);
              storageAddress = parseAddressBytes(userLocalState[STAKING_STRINGS.user_storage_address]);

              if (!this.userStakingStates[appId]) {
                this.userStakingStates[appId] = new UserStakingState(this.algod, this.stakingClient.stakingContracts[appId], storageAddress);
              }

              _context.next = 12;
              return this.userStakingStates[appId].loadState();

            case 12:
              _i++;
              _context.next = 3;
              break;

            case 15:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return StakingUser;
}();

var StakingClient = /*#__PURE__*/function () {
  /**
   * Constructor for the staking client.
   *
   * @param algofiClient - algofi client
   */
  function StakingClient(algofiClient) {
    this.stakingContracts = {};
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.stakingConfigs = StakingConfigs[this.network];
  }
  /**
   * Function to load in the staking contracts from the config and update their
   * internal object state with what is represented on chain.
   */


  var _proto = StakingClient.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return Promise.all(this.stakingConfigs.map( /*#__PURE__*/function () {
                var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(config) {
                  return _regeneratorRuntime().wrap(function _callee$(_context) {
                    while (1) {
                      switch (_context.prev = _context.next) {
                        case 0:
                          if (!(config.managerAppId in _this.stakingContracts)) {
                            _this.stakingContracts[config.managerAppId] = new Staking(_this.algod, _this, config);
                          }

                          _context.next = 3;
                          return _this.stakingContracts[config.managerAppId].loadState();

                        case 3:
                        case "end":
                          return _context.stop();
                      }
                    }
                  }, _callee);
                }));

                return function (_x) {
                  return _ref.apply(this, arguments);
                };
              }()));

            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Function to create a v1 staking user from an address.
   *
   * @param address - address of user
   * @returns a constructed v1 staking user.
   */
  ;

  _proto.getUser = function getUser(address) {
    return new StakingUser(this, address);
  };

  return StakingClient;
}();

var _StakingConfigs$1, _rewardsManagerAppId;

var StakingType;

(function (StakingType) {
  StakingType[StakingType["V1"] = 0] = "V1";
  StakingType[StakingType["V2"] = 1] = "V2";
  StakingType[StakingType["BASSET"] = 2] = "BASSET";
  StakingType[StakingType["LENDPOOL"] = 3] = "LENDPOOL";
})(StakingType || (StakingType = {}));

var StakingConfig$1 =
/**
 * Constructor for staking config.
 *
 * @param appId - staking app id
 * @param assetId - staking asset id
 * @param type - type
 */
function StakingConfig(name, appId, assetId, type) {
  this.name = name;
  this.appId = appId;
  this.assetId = assetId;
  this.type = type;
};
var StakingConfigs$1 = (_StakingConfigs$1 = {}, _StakingConfigs$1[Network.MAINNET] = [/*#__PURE__*/new StakingConfig$1("USDC Lend and Earn", 821882730, 818182311, StakingType.BASSET), /*#__PURE__*/new StakingConfig$1("USDT Lend and Earn", 821882927, 818190568, StakingType.BASSET), /*#__PURE__*/new StakingConfig$1("STBL2/BANK LP Staking", 900932886, 900924035, StakingType.LENDPOOL), /*#__PURE__*/new StakingConfig$1("ALGO/USDC LP Staking", 919964086, 919950894, StakingType.LENDPOOL), /*#__PURE__*/new StakingConfig$1("STBL2/ALGO LP Staking", 919964388, 855717054, StakingType.LENDPOOL), /*#__PURE__*/new StakingConfig$1("STBL2/goBTC LP Staking", 919965019, 870151164, StakingType.LENDPOOL), /*#__PURE__*/new StakingConfig$1("STBL2/goETH LP Staking", 919965630, 870150187, StakingType.LENDPOOL), /*#__PURE__*/new StakingConfig$1("ALGO/BANK LP Staking", 962407544, 962367827, StakingType.LENDPOOL)], _StakingConfigs$1[Network.TESTNET] = [/*#__PURE__*/new StakingConfig$1("USDC Lend and Earn", 104267989, 104207173, StakingType.BASSET)], _StakingConfigs$1);
var rewardsManagerAppId = (_rewardsManagerAppId = {}, _rewardsManagerAppId[Network.MAINNET] = 0, _rewardsManagerAppId[Network.TESTNET] = 0, _rewardsManagerAppId);
var STAKING_STRINGS$1 = {
  admin: "a",
  rewards_program_count: "rpc",
  rps_pusher: "rpsp",
  contract_update_delay: "cud",
  contract_update_time: "cut",
  voting_escrow_app_id: "veai",
  rewards_manager_app_id: "rmai",
  external_boost_multiplier: "ebm",
  asset_id: "ai",
  user_total_staked: "uts",
  user_scaled_total_staked: "usts",
  boost_multiplier: "lm",
  user_rewards_program_counter_prefix: "urpc_",
  user_rewards_coefficient_prefix: "urc_",
  user_unclaimed_rewards_prefix: "uur_",
  total_staked: "ts",
  scaled_total_staked: "sts",
  latest_time: "lt",
  rewards_escrow_account: "rea",
  rewards_program_counter_prefix: "rpc_",
  rewards_asset_id_prefix: "rai_",
  rewards_per_second_prefix: "rps_",
  rewards_coefficient_prefix: "rc_",
  rewards_issued_prefix: "ri_",
  rewards_payed_prefix: "rp_",
  schedule_contract_update: "scu",
  increase_contract_update_delay: "icud",
  set_rewards_manager_app_id: "srma",
  set_boost_app_id: "sbai",
  set_rewards_program: "srp",
  update_rewards_program: "urp",
  opt_into_asset: "oia",
  opt_into_rewards_manager: "oirm",
  update_rewards_per_second: "urps",
  farm_ops: "fo",
  stake: "s",
  unstake: "u",
  claim_rewards: "cr",
  update_target_user: "utu",
  update_vebank_data: "update_vebank_data"
};

var RewardsProgramState = /*#__PURE__*/function () {
  /**
   * Constructor for rewards program state
   *
   * @param stakingState - formatted staking state
   * @param rewardsProgramIndex - index of rewards program
   */
  function RewardsProgramState(staking, stakingState, rewardsProgramIndex) {
    this.staking = staking;
    this.rewardsProgramIndex = rewardsProgramIndex;
    this.rewardsProgramCounter = stakingState[STAKING_STRINGS$1.rewards_program_counter_prefix + this.rewardsProgramIndex.toString()] || 0;
    this.rewardsAssetId = stakingState[STAKING_STRINGS$1.rewards_asset_id_prefix + this.rewardsProgramIndex.toString()] || 0;
    this.rewardsPerSecond = stakingState[STAKING_STRINGS$1.rewards_per_second_prefix + this.rewardsProgramIndex.toString()] || 0;
    this.rewardsIssued = stakingState[STAKING_STRINGS$1.rewards_issued_prefix + this.rewardsProgramIndex.toString()] || 0;
    this.rewardsPayed = stakingState[STAKING_STRINGS$1.rewards_payed_prefix + this.rewardsProgramIndex.toString()] || 0;
    var nonFormattedRewardsCoefficient = stakingState[STAKING_STRINGS$1.rewards_coefficient_prefix + this.rewardsProgramIndex.toString()] || 0;

    if (nonFormattedRewardsCoefficient === 0) {
      this.rewardsCoefficient = BigInt(0);
    } else {
      var bytesVer = new Uint8Array(Buffer.from(nonFormattedRewardsCoefficient, "base64"));
      var bigInt = bytesToBigInt(bytesVer);
      this.rewardsCoefficient = bigInt;
    }

    if (staking.scaledTotalStaked > 0) {
      this.projectedRewardsCoefficient = this.rewardsCoefficient + BigInt((Math.floor(Date.now() / 1000) - staking.latestTime) * this.rewardsPerSecond) * FIXED_18_SCALE_FACTOR / BigInt(staking.scaledTotalStaked);
    } else {
      this.projectedRewardsCoefficient = this.rewardsCoefficient;
    }
  }

  var _proto = RewardsProgramState.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var rawRewardsPerYear, rewardsPerYear, rewardsPerYearUSD, totalScaledStakedUSD;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              rawRewardsPerYear = this.staking.assetDataClient.getAsset(this.rewardsPerSecond * SECONDS_PER_YEAR, this.rewardsAssetId);
              rewardsPerYear = rawRewardsPerYear.toDisplayAmount();
              rewardsPerYearUSD = rawRewardsPerYear.toUSD();
              totalScaledStakedUSD = this.staking.getScaledTotalStaked().toUSD();

              if (totalScaledStakedUSD > 0) {
                this.baseAPR = 0.4 * rewardsPerYearUSD / totalScaledStakedUSD;
                this.maxBoostedAPR = rewardsPerYearUSD / totalScaledStakedUSD;
                this.annualBaseRewardsPer1k = 0.4 * rewardsPerYear / (totalScaledStakedUSD / 1000);
                this.maxBoostedAnnualRewardsPer1k = rewardsPerYear / (totalScaledStakedUSD / 1000);
              } else {
                this.baseAPR = 0;
                this.maxBoostedAPR = 0;
                this.annualBaseRewardsPer1k = 0;
                this.maxBoostedAnnualRewardsPer1k = 0;
              }

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // DEPRECATED
  ;

  _proto.getAPR = function getAPR() {
    return this.baseAPR;
  };

  return RewardsProgramState;
}();
var UserRewardsProgramState =
/**
 * Constructor for user rewards program state object
 *
 * @param formattedUserLocalState - local state for the user
 * @param rewardsProgramIndex - index of the rewards program
 * @param staking - staking
 * @param userScaledTotalStaked - scaled user total staked
 */
function UserRewardsProgramState(formattedUserLocalState, rewardsProgramIndex, staking, userScaledTotalStaked, userRewardsBoost) {
  this.staking = staking;
  this.rewardsProgramIndex = rewardsProgramIndex;
  this.userRewardsProgramCounter = formattedUserLocalState[STAKING_STRINGS$1.user_rewards_program_counter_prefix + this.rewardsProgramIndex.toString()] || 0;
  this.userUnclaimedRewards = formattedUserLocalState[STAKING_STRINGS$1.user_unclaimed_rewards_prefix + this.rewardsProgramIndex.toString()] || 0;
  var nonFormattedRewardsCoefficient = formattedUserLocalState[STAKING_STRINGS$1.user_rewards_coefficient_prefix + this.rewardsProgramIndex.toString()] || 0;

  if (nonFormattedRewardsCoefficient === 0) {
    this.userRewardsCoefficient = BigInt(0);
  } else {
    var bytesVer = new Uint8Array(Buffer.from(nonFormattedRewardsCoefficient, "base64"));
    var bigInt = bytesToBigInt(bytesVer);
    this.userRewardsCoefficient = bigInt;
  }

  var rewardsProgram = staking.rewardsProgramStates[this.rewardsProgramIndex];
  this.userRewardsPerDay = staking.assetDataClient.getAsset(rewardsProgram.rewardsPerSecond * 86400 * userScaledTotalStaked / staking.scaledTotalStaked, rewardsProgram.rewardsAssetId); // calc user unrealized rewards (global coefficient on rewards program - user rewards coefficient on rewards program) * userTotalScaledStaked

  this.userUnrealizedRewards = Number((rewardsProgram.projectedRewardsCoefficient - this.userRewardsCoefficient) * BigInt(userScaledTotalStaked) / FIXED_18_SCALE_FACTOR + BigInt(this.userUnclaimedRewards)); // calc user APRs

  this.userAPR = rewardsProgram.baseAPR * userRewardsBoost;
};

var StakingQuote = function StakingQuote(newAPR, newBoost, newAnnualBankPer1k, newTotalAnnualBank) {
  this.newAPR = newAPR;
  this.newBoost = newBoost;
  this.newAnnualBankPer1k = newAnnualBankPer1k;
  this.newTotalAnnualBank = newTotalAnnualBank;
}; // INTERFACE

var Staking$1 = /*#__PURE__*/function () {
  /**
   * Constructor for the staking object.
   *
   * @param algod - algod client
   * @param stakingClient - staking client
   * @param rewardsManagerAppId - rewards manager app id
   * @param stakingConfig - stakingConfig object with information on the staking
   */
  function Staking(algod, stakingClient, rewardsManagerAppId, stakingConfig) {
    this.algod = algod;
    this.stakingClient = stakingClient;
    this.assetDataClient = stakingClient.algofiClient.assetData;
    this.name = stakingConfig.name;
    this.appId = stakingConfig.appId;
    this.address = getApplicationAddress(this.appId);
    this.assetId = stakingConfig.assetId;
    this.rewardsManagerAppId = rewardsManagerAppId;
  }
  /**
   * Loads in the global state of the specific staking contract and sets relevant
   * fields on the class.
   */


  var _proto = Staking.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var globalState, formattedState, loadingRewardProgramStates, i;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.appId);

            case 2:
              globalState = _context.sent;
              this.latestTime = globalState[STAKING_STRINGS$1.latest_time];
              this.rewardsEscrowAccount = parseAddressBytes(globalState[STAKING_STRINGS$1.rewards_escrow_account]);
              this.votingEscrowAppId = globalState[STAKING_STRINGS$1.voting_escrow_app_id];
              this.totalStaked = globalState[STAKING_STRINGS$1.total_staked];
              this.scaledTotalStaked = globalState[STAKING_STRINGS$1.scaled_total_staked];
              this.rewardsManagerAppId = globalState[STAKING_STRINGS$1.rewards_manager_app_id];
              this.rewardsProgramCount = globalState[STAKING_STRINGS$1.rewards_program_count];
              this.rewardsProgramStates = {}; // loading in rewards program specific state

              formattedState = formatPrefixState(globalState);
              this.baseAPR = 0;
              this.annualBankPer1k = 0;
              loadingRewardProgramStates = [];

              for (i = 0; i < this.rewardsProgramCount; ++i) {
                if (!this.rewardsProgramStates[i]) {
                  this.rewardsProgramStates[i] = new RewardsProgramState(this, formattedState, i);
                }

                loadingRewardProgramStates.push(this.rewardsProgramStates[i].loadState());

                if (this.rewardsProgramStates[i].rewardsAssetId == BANK_ASSET_ID) {
                  this.annualBankPer1k += this.rewardsProgramStates[i].annualBaseRewardsPer1k;
                } else {
                  this.baseAPR += this.rewardsProgramStates[i].baseAPR;
                }
              }

              _context.next = 18;
              return Promise.all(loadingRewardProgramStates);

            case 18:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getTotalStaked = function getTotalStaked() {
    return this.assetDataClient.getAsset(this.totalStaked, this.assetId);
  };

  _proto.getScaledTotalStaked = function getScaledTotalStaked() {
    return this.assetDataClient.getAsset(this.scaledTotalStaked, this.assetId);
  };

  _proto.getStakingAPRQuote = function getStakingAPRQuote(user, amountToStake) {
    var userStakingState = user.staking.v2.userStakingStates[this.appId];
    var userVotingState = user.governance.v1.userVotingEscrowState;
    var newUserTotalStaked = userStakingState ? userStakingState.totalStaked + amountToStake : amountToStake;
    var newUserScaledTotalStaked = userVotingState ? Math.min(newUserTotalStaked, 0.4 * newUserTotalStaked + 0.6 * userVotingState.projBoostMultiplier * this.totalStaked / FIXED_12_SCALE_FACTOR) : 0;
    var newBoost = Math.max(1, newUserScaledTotalStaked / (0.4 * newUserTotalStaked)) || 1;
    var newAPR = this.baseAPR * newBoost;
    var newAnnualBankPer1k = this.annualBankPer1k * newBoost;
    var newTotalAnnualBank = this.annualBankPer1k * newBoost * this.assetDataClient.getAsset(newUserTotalStaked, this.assetId).toUSD() / 1000;
    return new StakingQuote(newAPR, newBoost, newAnnualBankPer1k, newTotalAnnualBank);
  };

  _proto.getLockingAPRQuote = function getLockingAPRQuote(user, newBoostMultiplier) {
    var userStakingState = user.staking.v2.userStakingStates[this.appId];
    var userTotalStaked = userStakingState ? userStakingState.totalStaked : 0;
    var newUserScaledTotalStaked = Math.min(userTotalStaked, 0.4 * userTotalStaked + 0.6 * newBoostMultiplier * this.totalStaked / FIXED_12_SCALE_FACTOR);
    var newBoost = newUserScaledTotalStaked / (0.4 * userTotalStaked) || 1;
    var newAPR = this.baseAPR * newBoost;
    var newAnnualBankPer1k = this.annualBankPer1k * newBoost;
    var newTotalAnnualBank = this.annualBankPer1k * newBoost * this.assetDataClient.getAsset(userTotalStaked, this.assetId).toUSD() / 1000;
    return new StakingQuote(newAPR, newBoost, newAnnualBankPer1k, newTotalAnnualBank);
  }
  /**
   * Constructs a series of transactions that opt a user into the staking
   * contract.
   *
   * @param user - user who is opting in
   * @returns a series of transactions that opt a user into the staking
   * contract.
   */
  ;

  _proto.getUserOptInTxns =
  /*#__PURE__*/
  function () {
    var _getUserOptInTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user) {
      var params, enc, txn0;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              enc = new TextEncoder(); // unstake transaction

              txn0 = algosdk.makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: undefined,
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context2.abrupt("return", [txn0]);

            case 6:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getUserOptInTxns(_x) {
      return _getUserOptInTxns.apply(this, arguments);
    }

    return getUserOptInTxns;
  }()
  /**
   * Constructs a series of transactions that opt a user into the staking
   * contract.
   *
   * @param user - user who is opting in
   * @returns a series of transactions that opt a user into the staking
   * contract.
   */
  ;

  _proto.getUserCloseOutTxns =
  /*#__PURE__*/
  function () {
    var _getUserCloseOutTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user) {
      var params, enc, txn0;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context3.sent;
              enc = new TextEncoder(); // unstake transaction

              txn0 = algosdk.makeApplicationCloseOutTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [encodeUint64(0)],
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context3.abrupt("return", [txn0]);

            case 6:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getUserCloseOutTxns(_x2) {
      return _getUserCloseOutTxns.apply(this, arguments);
    }

    return getUserCloseOutTxns;
  }()
  /**
   * Constructs a series of transactions to stake user's assets in the staking
   * contract.
   *
   * @param user - user who is staking
   * @param amount - amount they are staking
   * @returns a series of transactions to stake user's assets in the staking
   * contract.
   */
  ;

  _proto.getStakeTxns =
  /*#__PURE__*/
  function () {
    var _getStakeTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, amount) {
      var params, enc, txn0, txn1, txn2;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              enc = new TextEncoder(); // farm ops

              txn0 = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(STAKING_STRINGS$1.farm_ops)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              }); // sending staking asset

              txn1 = makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.address,
                to: this.address,
                assetIndex: this.assetId,
                amount: amount,
                suggestedParams: params,
                rekeyTo: undefined,
                revocationTarget: undefined
              }); // stake

              params.fee = 2000;
              txn2 = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(STAKING_STRINGS$1.stake)],
                suggestedParams: params,
                foreignApps: [this.votingEscrowAppId || 1],
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context4.abrupt("return", assignGroupID([txn0, txn1, txn2]));

            case 9:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getStakeTxns(_x3, _x4) {
      return _getStakeTxns.apply(this, arguments);
    }

    return getStakeTxns;
  }()
  /**
   * Constructs a series of transactions that unstake a user's current stake
   * from the staking contract.
   *
   * @param user - user who is unstaking
   * @param amount - amount they are unstaking
   * @returns a series of transactions that unstake a user's current stake
   * from the staking contract.
   */
  ;

  _proto.getUnstakeTxns =
  /*#__PURE__*/
  function () {
    var _getUnstakeTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, amount) {
      var params, enc, txn0, txn1;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              enc = new TextEncoder(); // farm ops

              txn0 = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(STAKING_STRINGS$1.farm_ops)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              params.fee = 3000; // unstake

              txn1 = algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(STAKING_STRINGS$1.unstake), encodeUint64(amount)],
                foreignAssets: [this.assetId],
                suggestedParams: params,
                foreignApps: [this.votingEscrowAppId || 1],
                accounts: undefined,
                rekeyTo: undefined
              });
              return _context5.abrupt("return", assignGroupID([txn0, txn1]));

            case 8:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getUnstakeTxns(_x5, _x6) {
      return _getUnstakeTxns.apply(this, arguments);
    }

    return getUnstakeTxns;
  }()
  /**
   * Constructs a series of transactions that claim a user's staked assets.
   *
   * @param user - user who is claiming
   * @returns a series of transactions that claim a user's staked assets.
   */
  ;

  _proto.getClaimTxns =
  /*#__PURE__*/
  function () {
    var _getClaimTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user) {
      var params, enc, txns, i, assetOptInTxn;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context6.sent;
              enc = new TextEncoder();
              txns = []; // iterate over all rewards programs on this contract

              for (i = 0; i < this.rewardsProgramCount; ++i) {
                // skip rewards programs with 0 unrealized rewards
                if (user.staking.v2.userStakingStates[this.appId].userRewardsProgramStates[i].userUnrealizedRewards > 0) {
                  // opt in if needed
                  if (!user.isOptedInToAsset(this.rewardsProgramStates[i].rewardsAssetId)) {
                    params.fee = 1000;
                    assetOptInTxn = getPaymentTxn(params, user.address, user.address, this.rewardsProgramStates[i].rewardsAssetId, 0);
                    assetOptInTxn.note = enc.encode("Asset Opt In " + this.rewardsProgramStates[i].rewardsAssetId.toString() + " for app " + this.appId.toString());
                    txns.push(assetOptInTxn);
                  } // farm ops


                  params.fee = 1000;
                  txns.push(makeApplicationNoOpTxnFromObject({
                    from: user.address,
                    appIndex: this.appId,
                    appArgs: [enc.encode(STAKING_STRINGS$1.farm_ops)],
                    suggestedParams: params,
                    accounts: undefined,
                    foreignAssets: undefined,
                    foreignApps: undefined,
                    rekeyTo: undefined,
                    note: enc.encode("Farm Opts: " + i.toString())
                  })); // claim rewards

                  params.fee = 3000;
                  txns.push(makeApplicationNoOpTxnFromObject({
                    from: user.address,
                    appIndex: this.appId,
                    appArgs: [enc.encode(STAKING_STRINGS$1.claim_rewards), encodeUint64(i)],
                    foreignAssets: [this.rewardsProgramStates[i].rewardsAssetId],
                    accounts: [this.rewardsEscrowAccount],
                    rekeyTo: undefined,
                    foreignApps: [this.votingEscrowAppId || 1],
                    suggestedParams: params
                  }));
                }
              }

              if (!(txns.length == 0)) {
                _context6.next = 10;
                break;
              }

              return _context6.abrupt("return", []);

            case 10:
              if (!(txns.length == 1)) {
                _context6.next = 14;
                break;
              }

              return _context6.abrupt("return", txns);

            case 14:
              return _context6.abrupt("return", assignGroupID(txns));

            case 15:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getClaimTxns(_x7) {
      return _getClaimTxns.apply(this, arguments);
    }

    return getClaimTxns;
  }();

  _proto.getUpdateTargetUserTxn = /*#__PURE__*/function () {
    var _getUpdateTargetUserTxn = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(user) {
      var params, enc;
      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context7.sent;
              enc = new TextEncoder();
              params.fee = 2000;
              return _context7.abrupt("return", makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(STAKING_STRINGS$1.update_target_user)],
                suggestedParams: params,
                accounts: [user.address],
                foreignAssets: undefined,
                foreignApps: [this.votingEscrowAppId],
                rekeyTo: undefined
              }));

            case 6:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getUpdateTargetUserTxn(_x8) {
      return _getUpdateTargetUserTxn.apply(this, arguments);
    }

    return getUpdateTargetUserTxn;
  }();

  return Staking;
}();

// IMPORTS

var UserStakingState$1 =
/**
 * Constructor for the user staking state object.
 *
 * @param userLocalState - user's local state with one staking contract
 * @param staking - staking contract of interest
 */
function UserStakingState(userLocalState, staking) {
  this.totalStaked = userLocalState[STAKING_STRINGS$1.user_total_staked] || 0;
  this.scaledTotalStaked = userLocalState[STAKING_STRINGS$1.user_scaled_total_staked] || 0;
  this.boostMultiplier = userLocalState[STAKING_STRINGS$1.boost_multiplier] || 0;
  this.rewardsBoost = Math.max(1, this.scaledTotalStaked / (0.4 * this.totalStaked));
  this.userRewardsProgramStates = {};
  var rewardsProgramCount = staking.rewardsProgramCount;
  this.totalUserAPR = 0;
  this.totalBankPerYear = 0;

  for (var i = 0; i < rewardsProgramCount; ++i) {
    this.userRewardsProgramStates[i] = new UserRewardsProgramState(formatPrefixState(userLocalState), i, staking, this.scaledTotalStaked, this.rewardsBoost);

    if (staking.rewardsProgramStates[i].rewardsAssetId == BANK_ASSET_ID) {
      this.totalBankPerYear += this.userRewardsProgramStates[i].userRewardsPerDay.toDisplayAmount() * 365;
    } else {
      this.totalUserAPR += this.userRewardsProgramStates[i].userAPR;
    }
  }
};

var stakingUser = /*#__PURE__*/function () {
  /**
   * Constructor for the staking user.
   *
   * @param stakingClient - staking client
   * @param address - address of the user
   */
  function stakingUser(stakingClient, address) {
    this.stakingClient = stakingClient;
    this.algod = this.stakingClient.algod;
    this.address = address;
  } // get opted in staking contracts

  /**
   * Function to take in the user's local states and update their state with the
   * staking contractsw on the staking user object.
   *
   * @param userLocalStates - a list of local states for the user
   */


  var _proto = stakingUser.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      var _this = this;

      var allStakingContracts, _loop, _i, _Object$entries;

      return _regeneratorRuntime().wrap(function _callee$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              allStakingContracts = StakingConfigs$1[this.stakingClient.network].map(function (stakingConfig) {
                return stakingConfig.appId;
              }); // getting the opted in staking contracts

              this.optedInStakingContracts = [];
              this.userStakingStates = {};
              _loop = /*#__PURE__*/_regeneratorRuntime().mark(function _loop() {
                var _Object$entries$_i, key, value, appId, stakingConfig, staking;

                return _regeneratorRuntime().wrap(function _loop$(_context) {
                  while (1) {
                    switch (_context.prev = _context.next) {
                      case 0:
                        _Object$entries$_i = _Object$entries[_i], key = _Object$entries$_i[0], value = _Object$entries$_i[1];
                        appId = parseInt(key);

                        if (!allStakingContracts.includes(appId)) {
                          _context.next = 9;
                          break;
                        }

                        // instantiate dummy staking config
                        stakingConfig = StakingConfigs$1[_this.stakingClient.network].filter(function (stakingConfig) {
                          return stakingConfig.appId === appId;
                        })[0]; // instantiate a staking contract (to get global state)

                        staking = new Staking$1(_this.algod, _this.stakingClient, rewardsManagerAppId[_this.stakingClient.network], stakingConfig); // so we can get the global state

                        _context.next = 7;
                        return staking.loadState();

                      case 7:
                        // set for the key the following
                        _this.userStakingStates[appId] = new UserStakingState$1(value, staking); // first push this to the opted in staking contracts

                        _this.optedInStakingContracts.push(appId);

                      case 9:
                      case "end":
                        return _context.stop();
                    }
                  }
                }, _loop);
              });
              _i = 0, _Object$entries = Object.entries(userLocalStates);

            case 5:
              if (!(_i < _Object$entries.length)) {
                _context2.next = 10;
                break;
              }

              return _context2.delegateYield(_loop(), "t0", 7);

            case 7:
              _i++;
              _context2.next = 5;
              break;

            case 10:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return stakingUser;
}();

var StakingClient$1 = /*#__PURE__*/function () {
  /**
   * Constructor for the staking client.
   *
   * @param algofiClient - algofi client
   */
  function StakingClient(algofiClient) {
    this.stakingContracts = {};
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.stakingConfigs = StakingConfigs$1[this.network];
  }
  /**
   * Function to load in all of the global states from the staking contracts and
   * store their state in the object.
   */


  var _proto = StakingClient.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return Promise.all(this.stakingConfigs.map( /*#__PURE__*/function () {
                var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(config) {
                  return _regeneratorRuntime().wrap(function _callee$(_context) {
                    while (1) {
                      switch (_context.prev = _context.next) {
                        case 0:
                          if (!(config.appId in _this.stakingContracts)) {
                            _this.stakingContracts[config.appId] = new Staking$1(_this.algod, _this, rewardsManagerAppId[_this.network], config);
                          }

                          _context.next = 3;
                          return _this.stakingContracts[config.appId].loadState();

                        case 3:
                        case "end":
                          return _context.stop();
                      }
                    }
                  }, _callee);
                }));

                return function (_x) {
                  return _ref.apply(this, arguments);
                };
              }()));

            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Returns a staking user
   *
   * @param address - the address of the person we are generating the staking
   * user for
   * @returns a new staking user
   */
  ;

  _proto.getUser = function getUser(address) {
    return new stakingUser(this, address);
  };

  _proto.getUpdateUserTxns = /*#__PURE__*/function () {
    var _getUpdateUserTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user) {
      var txns, _i, _Object$entries, _Object$entries$_i, stakingAppId, userStakingState;

      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              txns = [];
              _i = 0, _Object$entries = Object.entries(user.staking.v2.userStakingStates);

            case 2:
              if (!(_i < _Object$entries.length)) {
                _context3.next = 13;
                break;
              }

              _Object$entries$_i = _Object$entries[_i], stakingAppId = _Object$entries$_i[0], userStakingState = _Object$entries$_i[1];

              if (!(userStakingState.totalStaked > 0)) {
                _context3.next = 10;
                break;
              }

              _context3.t0 = txns;
              _context3.next = 8;
              return this.stakingContracts[stakingAppId].getUpdateTargetUserTxn(user);

            case 8:
              _context3.t1 = _context3.sent;

              _context3.t0.push.call(_context3.t0, _context3.t1);

            case 10:
              _i++;
              _context3.next = 2;
              break;

            case 13:
              return _context3.abrupt("return", txns);

            case 14:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getUpdateUserTxns(_x2) {
      return _getUpdateUserTxns.apply(this, arguments);
    }

    return getUpdateUserTxns;
  }();

  return StakingClient;
}();

var BaseStakingClient = /*#__PURE__*/function () {
  function BaseStakingClient(algofiClient) {
    this.v1 = new StakingClient(algofiClient);
    this.v2 = new StakingClient$1(algofiClient);
  }

  var _proto = BaseStakingClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v1.loadState();

            case 2:
              _context.next = 4;
              return this.v2.loadState();

            case 4:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseStakingClient;
}();

var _GovernanceConfigs;

var GovernanceConfig =
/**
 * Constructor for the governance config clas
 *
 * @param adminAppId - admin app id
 * @param votingEscrowAppId - voting escrow app id
 * @param proposalFactoryAppId - proposal factory app id
 * @param rewardsManagerAppId - rewards manager app id
 * @param governanceToken - governance token
 */
function GovernanceConfig(adminAppId, votingEscrowAppId, proposalFactoryAppId, rewardsManagerAppId, governanceToken) {
  this.adminAppId = adminAppId;
  this.votingEscrowAppId = votingEscrowAppId;
  this.proposalFactoryAppId = proposalFactoryAppId;
  this.rewardsManagerAppId = rewardsManagerAppId;
  this.governanceToken = governanceToken; // 4 years

  this.votingEscrowMaxTimeLockSeconds = 60 * 60 * 24 * 365 * 4; // 1 week

  this.votingEscrowMinTimeLockSeconds = 60 * 60 * 24 * 7;
};
var GovernanceConfigs = (_GovernanceConfigs = {}, _GovernanceConfigs[Network.MAINNET] = /*#__PURE__*/new GovernanceConfig(900653388, 900653165, 900653632, 900652834, 900652777), _GovernanceConfigs[Network.TESTNET] = /*#__PURE__*/new GovernanceConfig(107210614, 107210153, 107211052, 107210021, 107212062), _GovernanceConfigs);
var VOTING_ESCROW_STRINGS = {
  admin_contract_app_id: "acid",
  asset_id: "ai",
  claim: "c",
  contract_update_delay: "cud",
  contract_update_approval_hash: "cuah",
  contract_update_clear_hash: "cuch",
  contract_update_time: "cut",
  dao_address: "da",
  emergency_dao_address: "eda",
  extend_lock: "el",
  increase_contract_update_delay: "icud",
  increase_lock_amount: "ila",
  lock: "l",
  total_locked: "tl",
  total_vebank: "tv",
  update_dao_address: "uda",
  update_emergency_dao_address: "ueda",
  update_vebank_data: "uvb",
  user_amount_locked: "aal",
  user_amount_vebank: "aav",
  user_lock_duration: "uld",
  user_lock_start_time: "ulst",
  user_last_update_time: "ulut",
  user_boost_multiplier: "bm",
  rewards_manager_app_id: "rmid",
  schedule_contract_update: "scu",
  set_gov_token_id: "sgti",
  set_rewards_manager_app_id: "srmai",
  set_admin_contract_app_id: "sacai"
};
var ADMIN_STRINGS = {
  admin: "a",
  cancel_proposal: "cp",
  canceled_by_emergency_dao: "cbed",
  contract_update_approval_hash: "cuah",
  contract_update_clear_hash: "cuch",
  contract_update_delay: "cud",
  contract_update_time: "cut",
  close_out_from_proposal: "cofp",
  delegate: "d",
  delegator_count: "dc",
  delegating_to: "dt",
  delegated_vote: "devo",
  emergency_dao_address: "eda",
  emergency_multisig: "em",
  execute: "e",
  executed: "ex",
  execution_time: "ext",
  fast_track_proposal: "ftp",
  increase_contract_update_delay: "icud",
  proposal_duration: "pd",
  num_proposals_opted_into: "npoi",
  open_to_delegation: "otd",
  proposal_app_id: "pai",
  proposal_contract_opt_in: "coi",
  proposal_execution_delay: "ped",
  proposal_factory_address: "pfa",
  quorum_value: "qv",
  schedule_contract_update: "scu",
  set_executed: "sex",
  set_proposal_duration: "spd",
  set_not_open_to_delegation: "snotd",
  set_open_to_delegation: "sotd",
  set_proposal_execution_delay: "sped",
  set_proposal_factory_address: "spfi",
  set_quorum_value: "sqv",
  set_super_majority: "ssm",
  set_voting_escrow_app_id: "sveai",
  super_majority: "sm",
  storage_account: "sa",
  storage_account_close_out: "saco",
  storage_account_opt_in: "saoi",
  undelegate: "ud",
  user_account: "ua",
  user_close_out: "uco",
  user_opt_in: "uoi",
  validate: "va",
  vote: "vo",
  vote_close_time: "vct",
  votes_against: "va",
  votes_for: "vf",
  voting_escrow_app_id: "veai",
  update_user_vebank: "uuv",
  vebank: "vb"
};
var PROPOSAL_FACTORY_STRINGS = {
  admin: "a",
  admin_app_id: "aai",
  contract_update_approval_hash: "cuah",
  contract_update_clear_hash: "cuch",
  contract_update_delay: "cud",
  contract_update_time: "cut",
  create_proposal: "cp",
  dao_address: "da",
  emergency_dao_address: "eda",
  gov_token: "gt",
  increase_contract_update_delay: "icud",
  proposal_template: "pt",
  minimum_ve_bank_to_propose: "mvbtp",
  update_dao_address: "uda",
  update_emergency_dao_address: "ueda",
  set_voting_escrow_app_id: "sveai",
  set_proposal_template: "spt",
  schedule_contract_update: "scu",
  set_admin_app_id: "saai",
  set_minimum_ve_bank_to_propose: "smvbtp",
  validate_user_account: "vua",
  voting_escrow_app_id: "veai"
};
var PROPOSAL_STRINGS = {
  create_transaction: "ct",
  creator_of_proposal: "cop",
  for_or_against: "foa",
  link: "l",
  opt_into_admin: "oia",
  template_id: "ti",
  title: "t",
  user_close_out: "uco",
  user_vote: "uv",
  voting_amount: "vamt"
};
var REWARDS_MANAGER_STRINGS = {
  admin: "a",
  asset_id: "ai",
  contract_opt_in: "coi",
  contract_update_approval_hash: "cuah",
  contract_update_clear_hash: "cuch",
  contract_update_delay: "cud",
  contract_update_time: "cut",
  epoch: "e",
  epoch_start: "es",
  epoch_end: "ee",
  epoch_amount: "ea",
  epoch_rps: "erps",
  epoch_expiration_delay: "eed",
  emitter_app_id: "eaid",
  next_epoch_votes_received: "nevr",
  num_registered_contracts: "nrc",
  staking_contract_to_opt_in: "scoi",
  user_epoch: "ue",
  user_total_votes: "utv",
  user_votes_used: "uvu",
  voting_escrow_app_id: "veid",
  votes_received: "vr",
  set_emitter_app_id: "seai",
  set_voting_escrow_app_id: "sveai",
  set_gov_token_id: "sgti",
  dao_begin_next_epoch: "dbne",
  emitter_begin_next_epoch: "ebne",
  vote: "v",
  sync_staking_contract: "ssc",
  stage_contract_opt_in: "scoi",
  dao_address: "da",
  emergency_dao_address: "eda",
  schedule_contract_update: "scu",
  increase_contract_update_delay: "icud",
  update_dao_address: "uda",
  update_emergency_dao_address: "ueda",
  user_opt_in: "uoi",
  set_epoch_expiration_delay: "seed",
  reclaim_rewards: "rr",
  sync_voter: "su"
};

var VotingEscrow = /*#__PURE__*/function () {
  /**
   * The constructor for the voting escrow object.
   *
   * @param governanceClient - a governance client
   */
  function VotingEscrow(governanceClient) {
    this.governanceClient = governanceClient;
    this.algod = this.governanceClient.algod;
    this.appId = governanceClient.governanceConfig.votingEscrowAppId;
    this.votingEscrowMaxTimeLockSeconds = governanceClient.governanceConfig.votingEscrowMaxTimeLockSeconds;
    this.votingEscrowMinTimeLockSeconds = governanceClient.governanceConfig.votingEscrowMinTimeLockSeconds;
  }
  /**
   * Function which will update the data on the voting escrow object to match
   * that of the global state of the voting escrow contract.
   */


  var _proto = VotingEscrow.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var globalState;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.appId);

            case 2:
              globalState = _context.sent;
              this.totalLocked = globalState[VOTING_ESCROW_STRINGS.total_locked] || 0;
              this.totalVebank = globalState[VOTING_ESCROW_STRINGS.total_vebank] || 0;
              this.assetId = globalState[VOTING_ESCROW_STRINGS.asset_id] || 0;

            case 6:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getLockQuote = function getLockQuote(user, lockAmount, lockEnd) {
    var userVotingEscrowState = user.governance.v1.userVotingEscrowState;
    var newAmountLocked = ((userVotingEscrowState == null ? void 0 : userVotingEscrowState.amountLocked) || 0) + lockAmount;
    var newDurationRemaining = lockEnd - Date.now() / 1000;

    var _userVotingEscrowStat = userVotingEscrowState.getProjValues(newAmountLocked, newDurationRemaining),
        projAmountVeBank = _userVotingEscrowStat[0],
        projBoostMultiplier = _userVotingEscrowStat[1];

    var stakingQuotes = {};

    for (var _i = 0, _Object$entries = Object.entries(this.governanceClient.algofiClient.staking.v2.stakingContracts); _i < _Object$entries.length; _i++) {
      var _Object$entries$_i = _Object$entries[_i],
          key = _Object$entries$_i[0],
          value = _Object$entries$_i[1];
      stakingQuotes[key] = value.getLockingAPRQuote(user, projBoostMultiplier);
    }

    return [projAmountVeBank, stakingQuotes];
  };

  _proto.getAirdropTxns = /*#__PURE__*/function () {
    var _getAirdropTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user) {
      var params, enc, txns;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              enc = new TextEncoder();
              txns = [];
              params.fee = 3000;
              txns.push(getPaymentTxn(params, user.address, user.address, this.assetId, 0));
              params.fee = 0;
              txns.push(makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.governance.v1.userAirdropState.dropLsig.address(),
                to: user.address,
                assetIndex: this.assetId,
                amount: user.governance.v1.userAirdropState.unlockedAirdrop,
                suggestedParams: params,
                closeRemainderTo: user.address,
                rekeyTo: undefined,
                revocationTarget: undefined
              }));
              txns.push(makePaymentTxnWithSuggestedParamsFromObject({
                from: user.governance.v1.userAirdropState.dropLsig.address(),
                to: "RF5KSQEGCGO5WPRU6B7VZHLY7AIOGY2K4ERCVHGWAJ3GG3X5VA5J5V3PRA",
                amount: 200000,
                suggestedParams: params,
                closeRemainderTo: "RF5KSQEGCGO5WPRU6B7VZHLY7AIOGY2K4ERCVHGWAJ3GG3X5VA5J5V3PRA",
                rekeyTo: undefined
              }));
              return _context2.abrupt("return", assignGroupID(txns));

            case 11:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getAirdropTxns(_x) {
      return _getAirdropTxns.apply(this, arguments);
    }

    return getAirdropTxns;
  }();

  _proto.getLockedAirdropTxns = /*#__PURE__*/function () {
    var _getLockedAirdropTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user) {
      var params, enc, txns, update_txns, _iterator, _step, txn;

      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context3.sent;
              enc = new TextEncoder();
              txns = [];
              params.fee = 0;
              txns.push(makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.governance.v1.userAirdropState.lockLsig.address(),
                to: getApplicationAddress(this.appId),
                assetIndex: this.assetId,
                amount: user.governance.v1.userAirdropState.lockedAirdrop,
                suggestedParams: params,
                closeRemainderTo: getApplicationAddress(this.appId),
                rekeyTo: undefined,
                revocationTarget: undefined
              }));
              params.fee = 3000;
              txns.push(makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.lock), encodeUint64(60 * 60 * 24 * 180)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              }));
              params.fee = 0;
              txns.push(makePaymentTxnWithSuggestedParamsFromObject({
                from: user.governance.v1.userAirdropState.lockLsig.address(),
                to: "RF5KSQEGCGO5WPRU6B7VZHLY7AIOGY2K4ERCVHGWAJ3GG3X5VA5J5V3PRA",
                amount: 200000,
                suggestedParams: params,
                closeRemainderTo: "RF5KSQEGCGO5WPRU6B7VZHLY7AIOGY2K4ERCVHGWAJ3GG3X5VA5J5V3PRA",
                rekeyTo: undefined
              }));
              _context3.next = 13;
              return this.governanceClient.algofiClient.staking.v2.getUpdateUserTxns(user);

            case 13:
              update_txns = _context3.sent;

              for (_iterator = _createForOfIteratorHelperLoose(update_txns); !(_step = _iterator()).done;) {
                txn = _step.value;
                txns.push(txn);
              }

              return _context3.abrupt("return", assignGroupID(txns));

            case 16:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getLockedAirdropTxns(_x2) {
      return _getLockedAirdropTxns.apply(this, arguments);
    }

    return getLockedAirdropTxns;
  }()
  /**
   * Constructs a series of transactions to update a target user's vebank.
   *
   * @param userCalling - user who is calling the udpate transaction
   * @param userUpdating - user whose vebank is actually being updated
   * @returns a series of transactions to update a target user's vebank.
   */
  ;

  _proto.getUpdateVeBankDataTxns =
  /*#__PURE__*/
  function () {
    var _getUpdateVeBankDataTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(userCalling, userUpdating) {
      var params, enc, updateUserVebankDataTxn;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              enc = new TextEncoder();
              updateUserVebankDataTxn = makeApplicationNoOpTxnFromObject({
                from: userCalling.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.update_vebank_data)],
                suggestedParams: params,
                accounts: [userUpdating.address],
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              return _context4.abrupt("return", [updateUserVebankDataTxn]);

            case 6:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getUpdateVeBankDataTxns(_x3, _x4) {
      return _getUpdateVeBankDataTxns.apply(this, arguments);
    }

    return getUpdateVeBankDataTxns;
  }()
  /**
   * Constructs a series of transactions that lock a user's BANK.
   *
   * @param user - user who is locking
   * @param amount - amount they are locking
   * @param durationSeconds - amount of time they are locking for
   * @returns a series of transactions that lock a user's BANK.
   */
  ;

  _proto.getLockTxns =
  /*#__PURE__*/
  function () {
    var _getLockTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, amount, durationSeconds) {
      var params, enc, txns, govTokenTxn, lockTxn, update_txns, _iterator2, _step2, txn;

      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              enc = new TextEncoder();
              txns = [];

              if (!(user.governance.v1.userAirdropState.lockedAirdrop > 0)) {
                _context5.next = 7;
                break;
              }

              throw 'User has airdrop to claim!';

            case 7:
              govTokenTxn = makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.address,
                to: getApplicationAddress(this.appId),
                assetIndex: this.governanceClient.governanceConfig.governanceToken,
                amount: amount,
                suggestedParams: params,
                rekeyTo: undefined,
                revocationTarget: undefined
              });
              lockTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.lock), encodeUint64(durationSeconds)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              txns.push(govTokenTxn, lockTxn);
              _context5.next = 12;
              return this.governanceClient.algofiClient.staking.v2.getUpdateUserTxns(user);

            case 12:
              update_txns = _context5.sent;

              for (_iterator2 = _createForOfIteratorHelperLoose(update_txns); !(_step2 = _iterator2()).done;) {
                txn = _step2.value;
                txns.push(txn);
              }

              return _context5.abrupt("return", assignGroupID(txns));

            case 15:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getLockTxns(_x5, _x6, _x7) {
      return _getLockTxns.apply(this, arguments);
    }

    return getLockTxns;
  }()
  /**
   * Constructs a series of transactions that extend a user's lock.
   *
   * @param user - user who is locking
   * @param durationSeconds - amount of time they are extending for
   * @returns a series of transactions that extend a user's lock.
   */
  ;

  _proto.getExtendLockTxns =
  /*#__PURE__*/
  function () {
    var _getExtendLockTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user, durationSeconds) {
      var params, enc, txns, extendLockTxn, update_txns, _iterator3, _step3, txn;

      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context6.sent;
              enc = new TextEncoder();
              txns = [];
              extendLockTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.extend_lock), encodeUint64(durationSeconds)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              txns.push(extendLockTxn);
              _context6.next = 9;
              return this.governanceClient.algofiClient.staking.v2.getUpdateUserTxns(user);

            case 9:
              update_txns = _context6.sent;

              for (_iterator3 = _createForOfIteratorHelperLoose(update_txns); !(_step3 = _iterator3()).done;) {
                txn = _step3.value;
                txns.push(txn);
              }

              return _context6.abrupt("return", assignGroupID(txns));

            case 12:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getExtendLockTxns(_x8, _x9) {
      return _getExtendLockTxns.apply(this, arguments);
    }

    return getExtendLockTxns;
  }()
  /**
   * Constructs a series of transactions that increase a user's lock amount.
   *
   * @param user - user who is locking
   * @param amount - amount they are increasing their lock for
   * @returns a series of transactions that increase a user's lock amount.
   */
  ;

  _proto.getIncreaseLockAmountTxns =
  /*#__PURE__*/
  function () {
    var _getIncreaseLockAmountTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(user, amount) {
      var params, enc, txns, govTokenTxn, increaseLockAmountTxns, update_txns, _iterator4, _step4, txn;

      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context7.sent;
              enc = new TextEncoder();
              txns = [];
              govTokenTxn = makeAssetTransferTxnWithSuggestedParamsFromObject({
                from: user.address,
                to: getApplicationAddress(this.appId),
                assetIndex: this.governanceClient.governanceConfig.governanceToken,
                amount: amount,
                suggestedParams: params,
                rekeyTo: undefined,
                revocationTarget: undefined
              });
              increaseLockAmountTxns = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.increase_lock_amount)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              txns.push(govTokenTxn, increaseLockAmountTxns);
              _context7.next = 10;
              return this.governanceClient.algofiClient.staking.v2.getUpdateUserTxns(user);

            case 10:
              update_txns = _context7.sent;

              for (_iterator4 = _createForOfIteratorHelperLoose(update_txns); !(_step4 = _iterator4()).done;) {
                txn = _step4.value;
                txns.push(txn);
              }

              return _context7.abrupt("return", assignGroupID(txns));

            case 13:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getIncreaseLockAmountTxns(_x10, _x11) {
      return _getIncreaseLockAmountTxns.apply(this, arguments);
    }

    return getIncreaseLockAmountTxns;
  }();

  _proto.getClaimTxns = /*#__PURE__*/function () {
    var _getClaimTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(user) {
      var params, enc, claimTxn;
      return _regeneratorRuntime().wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              _context8.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context8.sent;
              enc = new TextEncoder();
              params.fee = 2000;
              claimTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                appArgs: [enc.encode(VOTING_ESCROW_STRINGS.claim)],
                suggestedParams: params,
                foreignAssets: [this.governanceClient.governanceConfig.governanceToken],
                accounts: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              return _context8.abrupt("return", [claimTxn]);

            case 7:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8, this);
    }));

    function getClaimTxns(_x12) {
      return _getClaimTxns.apply(this, arguments);
    }

    return getClaimTxns;
  }();

  return VotingEscrow;
}();

// IMPORTS

var UserAdminState =
/**
 * Constructor for the user admin state class.
 *
 * @param storageAddress - the address of the storage account for the user
 * @param userStorageLocalStates - list of local states for the user's storage account
 * @param governanceClient - a governance client
 */
function UserAdminState(storageAddress, userStorageLocalStates, governanceClient) {
  this.userProposalStates = {};
  var proposals = Object.keys(governanceClient.admin.proposals).map(function (appId) {
    return parseInt(appId);
  });
  this.storageAddress = storageAddress; // Loop through to get storage account's local state on admin

  for (var _i = 0, _Object$entries = Object.entries(userStorageLocalStates); _i < _Object$entries.length; _i++) {
    var _Object$entries$_i = _Object$entries[_i],
        key = _Object$entries$_i[0],
        value = _Object$entries$_i[1];
    var appId = parseInt(key); // Case when we have the storage account's local state with admin contract

    if (appId == governanceClient.admin.adminAppId) {
      this.openToDelegation = value[ADMIN_STRINGS.open_to_delegation];
      this.delegatorCount = value[ADMIN_STRINGS.delegator_count];
      this.delegatingTo = parseAddressBytes(value[ADMIN_STRINGS.delegating_to]);
    } // If we have a proposal that the storage account is opted into


    if (proposals.includes(appId)) {
      this.userProposalStates[appId] = new UserProposalState(value);
    }
  }
};
var UserProposalState =
/**
 * Constructor for the user proposal state object.
 *
 * @param storageProposalLocalState - an dictionary representing the local
 * state of the proposal contract with the admin contract.
 */
function UserProposalState(storageProposalLocalState) {
  this.forOrAgainst = storageProposalLocalState[PROPOSAL_STRINGS.for_or_against];
  this.votingAmount = storageProposalLocalState[PROPOSAL_STRINGS.voting_amount];
};

var UserRewardsManagerState = function UserRewardsManagerState() {};

// IMPORTS

var UserVotingEscrowState = /*#__PURE__*/function () {
  /**
   * Constructor for the user voting escrow class.
   *
   * @param userLocalState - a dictionary representing a user's local state with
   * the voting escrow contract.
   */
  function UserVotingEscrowState(userLocalState, votingEscrow) {
    this.votingEscrow = votingEscrow;
    this.amountLocked = userLocalState[VOTING_ESCROW_STRINGS.user_amount_locked];
    this.lockStartTime = userLocalState[VOTING_ESCROW_STRINGS.user_lock_start_time];
    this.lockDuration = userLocalState[VOTING_ESCROW_STRINGS.user_lock_duration];
    this.lockEndTime = this.lockStartTime + this.lockDuration;
    this.lockDurationRemaining = Math.max(0, this.lockEndTime - Date.now() / 1000);
    this.lockDurationRemainingYears = this.lockDurationRemaining / SECONDS_PER_YEAR;
    this.amountVeBank = userLocalState[VOTING_ESCROW_STRINGS.user_amount_vebank];
    this.boostMultiplier = userLocalState[VOTING_ESCROW_STRINGS.user_boost_multiplier]; // projected values

    var _this$getProjValues = this.getProjValues(this.amountLocked, this.lockDurationRemaining),
        projAmountVeBank = _this$getProjValues[0],
        projBoostMultiplier = _this$getProjValues[1];

    this.projAmountVeBank = projAmountVeBank;
    this.projBoostMultiplier = projBoostMultiplier;
  }

  var _proto = UserVotingEscrowState.prototype;

  _proto.getProjValues = function getProjValues(amountLocked, durationRemaining) {
    // TODO fix denom
    var projAmountVeBank = Math.max(0, amountLocked * durationRemaining / SECONDS_PER_YEAR);
    var projBoostMultiplier = Math.max(0, projAmountVeBank * FIXED_12_SCALE_FACTOR / this.votingEscrow.totalVebank || 0);
    return [projAmountVeBank, projBoostMultiplier];
  };

  return UserVotingEscrowState;
}();

function concatArrays$1(arrays) {
  // sum of individual array lengths
  var totalLength = arrays.reduce(function (acc, value) {
    return acc + value.length;
  }, 0);
  if (!arrays.length) return null;
  var result = new Uint8Array(totalLength); // for each array - copy it over result
  // next array is copied right after the previous one

  var length = 0;

  for (var _iterator = _createForOfIteratorHelperLoose(arrays), _step; !(_step = _iterator()).done;) {
    var array = _step.value;
    result.set(array, length);
    length += array.length;
  }

  return result;
}

var UserAirdropState = /*#__PURE__*/function () {
  function UserAirdropState(address, govAssetId) {
    this.address = address;
    this.govAssetId = govAssetId;
    this.decodedAddress = decodeAddress(this.address).publicKey;
    this.dropLsig = this.getDropLogicSig();
    this.lockLsig = this.getLockLogicSig();
  }

  var _proto = UserAirdropState.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(algod) {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.prev = 0;
              _context.next = 3;
              return algod.accountAssetInformation(this.dropLsig.address(), this.govAssetId)["do"]();

            case 3:
              this.unlockedAirdrop = _context.sent["asset-holding"].amount;
              _context.next = 9;
              break;

            case 6:
              _context.prev = 6;
              _context.t0 = _context["catch"](0);
              this.unlockedAirdrop = 0;

            case 9:
              _context.prev = 9;
              _context.next = 12;
              return algod.accountAssetInformation(this.lockLsig.address(), this.govAssetId)["do"]();

            case 12:
              this.lockedAirdrop = _context.sent["asset-holding"].amount;
              _context.next = 18;
              break;

            case 15:
              _context.prev = 15;
              _context.t1 = _context["catch"](9);
              this.lockedAirdrop = 0;

            case 18:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this, [[0, 6], [9, 15]]);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getDropLogicSig = function getDropLogicSig() {
    var lsigPart1 = new Uint8Array([6, 32, 1, 1, 38, 2, 32]);
    var lsigPart2 = new Uint8Array([32, 137, 122, 169, 64, 134, 17, 157, 219, 62, 52, 240, 127, 92, 157, 120, 248, 16, 227, 99, 74, 225, 34, 42, 156, 214, 2, 118, 99, 110, 253, 168, 58, 49, 32, 50, 3, 18, 68, 49, 16, 34, 18, 64, 0, 49, 49, 16, 129, 4, 18, 64, 0, 1, 0, 49, 32, 50, 3, 18, 68, 49, 20, 49, 0, 18, 49, 20, 40, 18, 17, 68, 49, 20, 40, 18, 64, 0, 8, 49, 21, 50, 3, 18, 68, 34, 67, 49, 21, 40, 18, 68, 66, 255, 246, 49, 9, 41, 18, 68, 49, 7, 41, 18, 68, 34, 67]);
    var lsigBytes = concatArrays$1([lsigPart1, this.decodedAddress, lsigPart2]);
    return new LogicSigAccount(lsigBytes);
  };

  _proto.getLockLogicSig = function getLockLogicSig() {
    var lsigPart1 = new Uint8Array([6, 32, 1, 1, 38, 2, 32, 199, 236, 238, 162, 167, 166, 41, 228, 253, 192, 209, 28, 184, 221, 184, 171, 137, 164, 82, 233, 16, 35, 65, 58, 200, 114, 122, 22, 9, 11, 245, 115, 32, 137, 122, 169, 64, 134, 17, 157, 219, 62, 52, 240, 127, 92, 157, 120, 248, 16, 227, 99, 74, 225, 34, 42, 156, 214, 2, 118, 99, 110, 253, 168, 58, 49, 32, 50, 3, 18, 68, 49, 16, 34, 18, 64, 0, 152, 49, 16, 129, 4, 18, 64, 0, 1, 0, 49, 32, 50, 3, 18, 68, 49, 20, 49, 0, 18, 49, 20, 40, 18, 17, 68, 49, 20, 40, 18, 64, 0, 8, 49, 21, 50, 3, 18, 68, 34, 67, 49, 21, 40, 18, 68, 49, 22, 34, 8, 56, 0, 128, 32]);
    var lsigPart2 = new Uint8Array([18, 68, 49, 22, 34, 8, 56, 16, 129, 6, 18, 68, 49, 22, 34, 8, 56, 24, 129, 237, 192, 187, 173, 3, 18, 68, 49, 22, 34, 8, 56, 25, 129, 0, 18, 68, 49, 22, 34, 8, 57, 26, 0, 128, 1, 108, 18, 68, 49, 22, 34, 8, 57, 26, 1, 23, 129, 128, 156, 181, 7, 18, 68, 66, 255, 143, 49, 9, 41, 18, 68, 49, 7, 41, 18, 68, 34, 67]);
    var lsigBytes = concatArrays$1([lsigPart1, this.decodedAddress, lsigPart2]);
    return new LogicSigAccount(lsigBytes);
  };

  return UserAirdropState;
}();

var governanceUser = /*#__PURE__*/function () {
  /**
   * Constructor for the governance user class.
   *
   * @param governanceClient - a governance client
   * @param address - address of the user
   */
  function governanceUser(governanceClient, address) {
    this.optedInToGovernance = false;
    this.governanceClient = governanceClient;
    this.algod = this.governanceClient.algod;
    this.address = address;
  }
  /**
   * A function which will load in all of the state for a governance user
   * including their admin state, voting escrow state, and rewards manager
   * state into the governance user object.
   *
   * @param userLocalStates - a list of all of the local states for the
   * particular user with the admin, voting escrow, and rewards manager
   * contracts.
   */


  var _proto = governanceUser.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(userLocalStates) {
      var _i, _Object$entries, _Object$entries$_i, key, value, appId, storageAddress, userStorageLocalStates;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _i = 0, _Object$entries = Object.entries(userLocalStates);

            case 1:
              if (!(_i < _Object$entries.length)) {
                _context.next = 16;
                break;
              }

              _Object$entries$_i = _Object$entries[_i], key = _Object$entries$_i[0], value = _Object$entries$_i[1];
              appId = parseInt(key); // Case when we have the local state of the user with the admin contract

              if (!(appId == this.governanceClient.admin.adminAppId)) {
                _context.next = 11;
                break;
              }

              // Get storage account
              storageAddress = parseAddressBytes(value[ADMIN_STRINGS.storage_account]); // Get storage account local states

              _context.next = 8;
              return getLocalStates(this.algod, storageAddress);

            case 8:
              userStorageLocalStates = _context.sent;
              this.userAdminState = new UserAdminState(storageAddress, userStorageLocalStates, this.governanceClient);
              this.optedInToGovernance = true;

            case 11:
              // Case when we have the local state of the user with the voting escrow contract
              if (appId == this.governanceClient.votingEscrow.appId) {
                this.userVotingEscrowState = new UserVotingEscrowState(value, this.governanceClient.votingEscrow);
              } // Setting rewards manager


              if (appId == this.governanceClient.rewardsManager.appId) {
                this.userRewardsManagerState = new UserRewardsManagerState();
              }

            case 13:
              _i++;
              _context.next = 1;
              break;

            case 16:
              this.userAirdropState = new UserAirdropState(this.address, this.governanceClient.governanceConfig.governanceToken);
              _context.next = 19;
              return this.userAirdropState.loadState(this.algod);

            case 19:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState(_x) {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return governanceUser;
}();

var Proposal = /*#__PURE__*/function () {
  /**
   * Constructor for the proposal class.
   *
   * @param governanceClient - a governance client
   * @param proposalAppId - the app id of the proposal
   */
  function Proposal(governanceClient, proposalAppId) {
    this.governanceClient = governanceClient;
    this.algod = this.governanceClient.algod;
    this.appId = proposalAppId;
    this.adminAppId = governanceClient.governanceConfig.adminAppId;
    this.address = getApplicationAddress(this.appId);
  }
  /**
   * Function that will update the data on the proposal object with the global
   * and local data of the proposal contract on chain.
   */


  var _proto = Proposal.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var proposalLocalStates, _i, _Object$entries, _Object$entries$_i, key, value, appId, globalState;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getLocalStates(this.algod, this.address);

            case 2:
              proposalLocalStates = _context.sent;

              for (_i = 0, _Object$entries = Object.entries(proposalLocalStates); _i < _Object$entries.length; _i++) {
                _Object$entries$_i = _Object$entries[_i], key = _Object$entries$_i[0], value = _Object$entries$_i[1];
                appId = parseInt(key);

                if (appId == this.governanceClient.admin.adminAppId) {
                  this.votesFor = value[ADMIN_STRINGS.votes_for] || 0;
                  this.votesAgainst = value[ADMIN_STRINGS.votes_against] || 0;
                  this.voteCloseTime = value[ADMIN_STRINGS.vote_close_time] || 0;
                  this.executionTime = value[ADMIN_STRINGS.execution_time] || 0;
                  this.executed = value[ADMIN_STRINGS.executed] || 0;
                  this.canceledByEmergencyDao = value[ADMIN_STRINGS.canceled_by_emergency_dao] || 0;
                }
              } // Set proposal global state


              _context.next = 6;
              return getApplicationGlobalState(this.algod, this.appId);

            case 6:
              globalState = _context.sent;
              this.title = atob(globalState[PROPOSAL_STRINGS.title]);
              this.link = atob(globalState[PROPOSAL_STRINGS.link]);

            case 9:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getData = /*#__PURE__*/function () {
    var _getData = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(topicId) {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return request.get(getAnalyticsEndpoint(this.governanceClient.network) + "/getDiscourseTopic?topic_id=" + topicId).then(function (resp) {
                if (resp.status == 200) {
                  _this.summary = resp.body.post_stream.posts[0].cooked;
                  _this.categoryId = resp.body.category_id;
                } else {
                  _this.summary = "Link not Found";
                }
              })["catch"](function (err) {
                console.log(err.message);
                _this.summary = "Link not Found";
              });

            case 2:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getData(_x) {
      return _getData.apply(this, arguments);
    }

    return getData;
  }();

  return Proposal;
}();

var Admin = /*#__PURE__*/function () {
  /**
   * Constructor for the Admin class.
   *
   * @param governanceClient - algofi governance client
   */
  function Admin(governanceClient) {
    this.proposals = {};
    this.governanceClient = governanceClient;
    this.algod = this.governanceClient.algod;
    this.adminAppId = governanceClient.governanceConfig.adminAppId;
    this.proposalFactoryAppId = governanceClient.governanceConfig.proposalFactoryAppId;
    this.proposalFactoryAddress = getApplicationAddress(this.proposalFactoryAppId);
    this.adminAddress = getApplicationAddress(this.adminAppId);
  }
  /**
   * Function to refresh and load all of the global and local state we need to
   * keep track of on the admin, including all of the proposals that have been
   * created.
   */


  var _proto = Admin.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var globalStateAdmin, globalStateProposalFactory, proposalFactoryAddressInfo, _iterator, _step, appObject;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getApplicationGlobalState(this.algod, this.adminAppId);

            case 2:
              globalStateAdmin = _context.sent;
              this.quorumValue = globalStateAdmin[ADMIN_STRINGS.quorum_value] || 0;
              this.superMajority = globalStateAdmin[ADMIN_STRINGS.super_majority] || 0;
              this.proposalDuration = globalStateAdmin[ADMIN_STRINGS.proposal_duration] || 0;
              this.proposalExecutionDelay = globalStateAdmin[ADMIN_STRINGS.proposal_execution_delay] || 0; // Setting state for proposal factory

              _context.next = 9;
              return getApplicationGlobalState(this.algod, this.proposalFactoryAppId);

            case 9:
              globalStateProposalFactory = _context.sent;
              // Put this in config (fixed)
              this.govToken = globalStateProposalFactory[PROPOSAL_FACTORY_STRINGS.gov_token] || 0;
              this.proposalTemplateId = globalStateProposalFactory[PROPOSAL_FACTORY_STRINGS.proposal_template] || 0;
              this.minimumVeBankToPropose = globalStateProposalFactory[PROPOSAL_FACTORY_STRINGS.minimum_ve_bank_to_propose] || 0; // Creating the proposal dictionary

              _context.next = 15;
              return this.algod.accountInformation(this.proposalFactoryAddress)["do"]();

            case 15:
              proposalFactoryAddressInfo = _context.sent;
              _iterator = _createForOfIteratorHelperLoose(proposalFactoryAddressInfo["created-apps"]);

            case 17:
              if ((_step = _iterator()).done) {
                _context.next = 24;
                break;
              }

              appObject = _step.value;

              if (!(appObject["id"] in this.proposals)) {
                this.proposals[appObject["id"]] = new Proposal(this.governanceClient, appObject["id"]);
              }

              _context.next = 22;
              return this.proposals[appObject["id"]].loadState();

            case 22:
              _context.next = 17;
              break;

            case 24:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Constructs a series of transactions to update a target user's vebank.
   *
   * @param userCalling - the user who is calling the transaction
   * @param userUpdating - the user who is being updated
   * @returns a series of transactions to update a target user's vebank.
   */
  ;

  _proto.getUpdateUserVeBankDataTxns =
  /*#__PURE__*/
  function () {
    var _getUpdateUserVeBankDataTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(userCalling, userUpdating) {
      var params, enc, updateUserVebankDataTxn;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              enc = new TextEncoder(); // TODO figure out correct amount

              params.fee = 5000;
              updateUserVebankDataTxn = makeApplicationNoOpTxnFromObject({
                from: userCalling.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.update_user_vebank)],
                foreignApps: [this.governanceClient.votingEscrow.appId],
                suggestedParams: params,
                accounts: [userUpdating.address, userUpdating.governance.v1.userAdminState.storageAddress],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context2.abrupt("return", [updateUserVebankDataTxn]);

            case 7:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getUpdateUserVeBankDataTxns(_x, _x2) {
      return _getUpdateUserVeBankDataTxns.apply(this, arguments);
    }

    return getUpdateUserVeBankDataTxns;
  }()
  /**
   * Constructs a series of transactions to vote on a proposal.
   *
   * @param user - user who is voting
   * @param proposal - proposal being voted on
   * @returns a series of transactions to vote on a proposal.
   */
  ;

  _proto.getVoteTxns =
  /*#__PURE__*/
  function () {
    var _getVoteTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user, proposal, forOrAgainst) {
      var params, enc, updateUserVebankDataTxn, voteTxn;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context3.sent;
              enc = new TextEncoder();

              _context3.next = 7;
              return this.getUpdateUserVeBankDataTxns(user, user);

            case 7:
              updateUserVebankDataTxn = _context3.sent;
              params.fee = 2000;
              voteTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.vote), encodeUint64(forOrAgainst)],
                foreignApps: [proposal.appId],
                suggestedParams: params,
                accounts: [user.governance.v1.userAdminState.storageAddress, getApplicationAddress(proposal.appId)],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context3.abrupt("return", assignGroupID([].concat(updateUserVebankDataTxn, [voteTxn])));

            case 11:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getVoteTxns(_x3, _x4, _x5) {
      return _getVoteTxns.apply(this, arguments);
    }

    return getVoteTxns;
  }()
  /**
   * Constructs a series of transactions to delegate a user's votes to another
   * user.
   *
   * @param user - user who is delegating
   * @param delegatee - user who is being delegated to
   * @returns a series of transactions to delegate a user's votes to another
   * user.
   */
  ;

  _proto.getDelegateTxns =
  /*#__PURE__*/
  function () {
    var _getDelegateTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, delegatee) {
      var params, enc, delegateTxn;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              enc = new TextEncoder();

              delegateTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.delegate)],
                suggestedParams: params,
                accounts: [user.governance.v1.userAdminState.storageAddress, delegatee.governance.v1.userAdminState.storageAddress],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context4.abrupt("return", [delegateTxn]);

            case 7:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getDelegateTxns(_x6, _x7) {
      return _getDelegateTxns.apply(this, arguments);
    }

    return getDelegateTxns;
  }()
  /**
   * Constructs a series of transactions that will validate a specific proposal.
   *
   * @param user - user who is trying to validate a proposal
   * @param proposal - the proposal to validate
   * @returns a series of transactions that will validate a specific proposal.
   */
  ;

  _proto.getValidateTxns =
  /*#__PURE__*/
  function () {
    var _getValidateTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, proposal) {
      var params, enc, validateTxn;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              enc = new TextEncoder();
              validateTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.validate)],
                foreignApps: [proposal.appId],
                suggestedParams: params,
                accounts: [getApplicationAddress(proposal.appId)],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context5.abrupt("return", [validateTxn]);

            case 7:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getValidateTxns(_x8, _x9) {
      return _getValidateTxns.apply(this, arguments);
    }

    return getValidateTxns;
  }()
  /**
   * Constructs a series of transactions that will undelegate a user from their
   * current delegatee.
   *
   * @param user - user who is undelegating
   * @returns a series of transactions that will undelegate a user from their
   * current delegatee.
   */
  ;

  _proto.getUndelegateTxns =
  /*#__PURE__*/
  function () {
    var _getUndelegateTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user) {
      var params, enc, undelegateTxn;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context6.sent;
              enc = new TextEncoder();
              undelegateTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.undelegate)],
                suggestedParams: params,
                accounts: [user.governance.v1.userAdminState.storageAddress, user.governance.v1.userAdminState.delegatingTo],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context6.abrupt("return", [undelegateTxn]);

            case 7:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getUndelegateTxns(_x10) {
      return _getUndelegateTxns.apply(this, arguments);
    }

    return getUndelegateTxns;
  }()
  /**
   * Constructs a series of transactions that will make a user vote on a
   * proposal as their delegatee has.
   *
   * @param callingUser - user who is calling the delegated vote transaction
   * @param votingUser - user who is voting
   * @param proposal - proposal being voted on
   * @returns a series of transactions that will make a user vote on a proposal
   * as their delegatee has.
   */
  ;

  _proto.getDelegatedVoteTxns =
  /*#__PURE__*/
  function () {
    var _getDelegatedVoteTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(callingUser, votingUser, proposal) {
      var params, enc, updateUserVebankDataTxn, delegatedVoteTxn;
      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context7.sent;
              enc = new TextEncoder();
              _context7.next = 7;
              return this.getUpdateUserVeBankDataTxns(callingUser, votingUser);

            case 7:
              updateUserVebankDataTxn = _context7.sent;
              delegatedVoteTxn = makeApplicationNoOpTxnFromObject({
                from: callingUser.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.delegated_vote)],
                foreignApps: [proposal.appId, this.governanceClient.votingEscrow.appId],
                suggestedParams: params,
                accounts: [votingUser.address, votingUser.governance.v1.userAdminState.storageAddress, votingUser.governance.v1.userAdminState.delegatingTo, getApplicationAddress(proposal.appId)],
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              return _context7.abrupt("return", assignGroupID([].concat(updateUserVebankDataTxn, [delegatedVoteTxn])));

            case 10:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getDelegatedVoteTxns(_x11, _x12, _x13) {
      return _getDelegatedVoteTxns.apply(this, arguments);
    }

    return getDelegatedVoteTxns;
  }()
  /**
   * Constructs a series of transactions which will close out a target user from a proposal.
   *
   * @param userCalling - user who is calling the transaction
   * @param userClosingOut - user who is closing out
   * @param proposal - proposal being closed out of
   * @returns a series of transactions which will close out a target user from a proposal.
   */
  ;

  _proto.getCloseOutFromProposalTxns =
  /*#__PURE__*/
  function () {
    var _getCloseOutFromProposalTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(userCalling, userClosingOut, proposal) {
      var params, enc, closeOutFromProposalTxn;
      return _regeneratorRuntime().wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              _context8.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context8.sent;
              enc = new TextEncoder();
              params.fee = 3000;
              _context8.next = 7;
              return makeApplicationNoOpTxnFromObject({
                from: userCalling.address,
                appIndex: this.adminAppId,
                suggestedParams: params,
                appArgs: [enc.encode(ADMIN_STRINGS.close_out_from_proposal)],
                accounts: [getApplicationAddress(proposal.appId), userClosingOut.governance.v1.userAdminState.storageAddress],
                foreignApps: [proposal.appId],
                foreignAssets: undefined,
                rekeyTo: undefined
              });

            case 7:
              closeOutFromProposalTxn = _context8.sent;
              return _context8.abrupt("return", [closeOutFromProposalTxn]);

            case 9:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8, this);
    }));

    function getCloseOutFromProposalTxns(_x14, _x15, _x16) {
      return _getCloseOutFromProposalTxns.apply(this, arguments);
    }

    return getCloseOutFromProposalTxns;
  }()
  /**
   * Constructs a series of tranactions to set a user open to delegation.
   *
   * @param user - user who is setting themselves open to delegation
   * @returns a series of tranactions to set a user open to delegation.
   */
  ;

  _proto.getSetOpenToDelegationTxns =
  /*#__PURE__*/
  function () {
    var _getSetOpenToDelegationTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee9(user) {
      var params, enc, setOpenToDelegationTxn;
      return _regeneratorRuntime().wrap(function _callee9$(_context9) {
        while (1) {
          switch (_context9.prev = _context9.next) {
            case 0:
              _context9.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context9.sent;
              enc = new TextEncoder();
              setOpenToDelegationTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.set_open_to_delegation)],
                suggestedParams: params,
                accounts: [user.governance.v1.userAdminState.storageAddress],
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              return _context9.abrupt("return", [setOpenToDelegationTxn]);

            case 7:
            case "end":
              return _context9.stop();
          }
        }
      }, _callee9, this);
    }));

    function getSetOpenToDelegationTxns(_x17) {
      return _getSetOpenToDelegationTxns.apply(this, arguments);
    }

    return getSetOpenToDelegationTxns;
  }()
  /**
   * Constructs a series of tranactions to set a user not open to delegation.
   *
   * @param user - user who is setting themselves not open to delegation
   * @returns a series of tranactions to set a user not open to delegation.
   */
  ;

  _proto.getSetNotOpenToDelegationTxns =
  /*#__PURE__*/
  function () {
    var _getSetNotOpenToDelegationTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee10(user) {
      var params, enc, setNotOpenToDelegationTxn;
      return _regeneratorRuntime().wrap(function _callee10$(_context10) {
        while (1) {
          switch (_context10.prev = _context10.next) {
            case 0:
              _context10.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context10.sent;
              enc = new TextEncoder();
              setNotOpenToDelegationTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.adminAppId,
                appArgs: [enc.encode(ADMIN_STRINGS.set_not_open_to_delegation)],
                suggestedParams: params,
                accounts: [user.governance.v1.userAdminState.storageAddress],
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              });
              return _context10.abrupt("return", [setNotOpenToDelegationTxn]);

            case 7:
            case "end":
              return _context10.stop();
          }
        }
      }, _callee10, this);
    }));

    function getSetNotOpenToDelegationTxns(_x18) {
      return _getSetNotOpenToDelegationTxns.apply(this, arguments);
    }

    return getSetNotOpenToDelegationTxns;
  }()
  /**
   * Constructs a series of transactions to create a proposal.
   *
   * @param user - user who is trying to create the transaction
   * @param title - title of the proposal to be created
   * @param link - link of the proposal to be created
   * @returns a series of transactions to create a proposal.
   */
  ;

  _proto.getCreateProposalTxns =
  /*#__PURE__*/
  function () {
    var _getCreateProposalTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee11(user, title, link) {
      var params, txns, enc, fundAppTxn, validateUserAccountsTxn, proposalCreationTxn;
      return _regeneratorRuntime().wrap(function _callee11$(_context11) {
        while (1) {
          switch (_context11.prev = _context11.next) {
            case 0:
              _context11.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context11.sent;
              txns = [];
              enc = new TextEncoder(); // TODO figure out correct funding

              fundAppTxn = makePaymentTxnWithSuggestedParamsFromObject({
                from: user.address,
                amount: 4000000,
                to: this.proposalFactoryAddress,
                suggestedParams: params,
                closeRemainderTo: undefined,
                rekeyTo: undefined
              });
              validateUserAccountsTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.proposalFactoryAppId,
                appArgs: [enc.encode(PROPOSAL_FACTORY_STRINGS.validate_user_account)],
                suggestedParams: params,
                accounts: undefined,
                foreignAssets: undefined,
                foreignApps: undefined,
                rekeyTo: undefined
              }); // TODO figure out if this fee is correct

              params.fee = 6000;
              proposalCreationTxn = makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.proposalFactoryAppId,
                appArgs: [enc.encode(PROPOSAL_FACTORY_STRINGS.create_proposal), enc.encode(title), enc.encode(link)],
                suggestedParams: params,
                accounts: [user.address, user.governance.v1.userAdminState.storageAddress],
                foreignAssets: undefined,
                foreignApps: [this.governanceClient.votingEscrow.appId, this.proposalTemplateId, this.adminAppId],
                rekeyTo: undefined
              });
              txns.push(fundAppTxn, validateUserAccountsTxn, proposalCreationTxn);
              return _context11.abrupt("return", assignGroupID(txns));

            case 11:
            case "end":
              return _context11.stop();
          }
        }
      }, _callee11, this);
    }));

    function getCreateProposalTxns(_x19, _x20, _x21) {
      return _getCreateProposalTxns.apply(this, arguments);
    }

    return getCreateProposalTxns;
  }();

  return Admin;
}();

// IMPORTS
var RewardsManager =
/**
 * Constructor for the rewardsManager object.
 *
 * @param governanceClient - governance client
 * @param governanceConfig - governance config
 */
function RewardsManager(governanceClient, governanceConfig) {
  this.governanceClient = governanceClient;
  this.algod = this.governanceClient.algod;
  this.appId = governanceConfig.rewardsManagerAppId;
};

var GovernanceClient = /*#__PURE__*/function () {
  /**
   * Constructor for the algofi governance client.
   *
   * @param algofiClient - an instance of an algofi client
   */
  function GovernanceClient(algofiClient) {
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.governanceConfig = GovernanceConfigs[this.network];
  }
  /**
   * Creates new admin, voting escrow, and rewards managers on the algofi client
   * object and loads their state.
   */


  var _proto = GovernanceClient.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              // Creating new Admin + Proposal Factory and filling in state
              if (!this.admin) {
                this.admin = new Admin(this);
              }

              _context.next = 3;
              return this.admin.loadState();

            case 3:
              // Creating new Voting Escrow and filling in state
              if (!this.votingEscrow) {
                this.votingEscrow = new VotingEscrow(this);
              }

              _context.next = 6;
              return this.votingEscrow.loadState();

            case 6:
              // Put in empty load state function
              this.rewardsManager = new RewardsManager(this, this.governanceConfig);

            case 7:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Gets an algofi governance user given an address.
   *
   * @param address - the address of the user we are interested in.
   * @returns an algofi governance user.
   */
  ;

  _proto.getUser = function getUser(address) {
    return new governanceUser(this, address);
  }
  /**
   * Constructs a series of transactions to opt the user and their storage
   * account into all of the necessary applications for governance including the
   * admin, the voting escrow, and the rewards manager.
   *
   * @param user - user we are opting into the contracts
   * @param storageAccount - a newly created account that will serve as the
   * storage account for the user on the protocol
   * @returns a series of transactions to opt the user and their storage
   * account into all of the necessary applications for governance including the
   * admin, the voting escrow, and the rewards manager.
   */
  ;

  _proto.getOptInTxns =
  /*#__PURE__*/
  function () {
    var _getOptInTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user, storageAccount) {
      var params, txns, enc, fundStorageAccountTxn, optStorageAccountIntoAdminTxn, optPrimaryAccountIntoAdminTxn, optPrimaryAccountIntoVotingEscrowTxn, optPrimaryAccountIntoRewardsManager;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              txns = [];
              enc = new TextEncoder(); // Fund storage account

              fundStorageAccountTxn = makePaymentTxnWithSuggestedParamsFromObject({
                from: user.address,
                // TODO figure out exact amount
                amount: 607500,
                to: storageAccount.addr,
                suggestedParams: params,
                closeRemainderTo: undefined,
                rekeyTo: undefined
              }); // Opt storage account into admin

              optStorageAccountIntoAdminTxn = makeApplicationOptInTxnFromObject({
                from: storageAccount.addr,
                appIndex: this.admin.adminAppId,
                suggestedParams: params,
                appArgs: [enc.encode(ADMIN_STRINGS.storage_account_opt_in)],
                accounts: [user.address],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: this.admin.adminAddress
              }); // Opt the primary account into the admin contract

              optPrimaryAccountIntoAdminTxn = makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.admin.adminAppId,
                suggestedParams: params,
                appArgs: [enc.encode(ADMIN_STRINGS.user_opt_in)],
                accounts: [storageAccount.addr],
                foreignApps: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }); // Opt primary account into voting escrow

              optPrimaryAccountIntoVotingEscrowTxn = makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.votingEscrow.appId,
                suggestedParams: params,
                foreignApps: [this.rewardsManager.appId],
                appArgs: undefined,
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              }); // Opt primary account into rewards manager

              optPrimaryAccountIntoRewardsManager = makeApplicationOptInTxnFromObject({
                from: user.address,
                appIndex: this.rewardsManager.appId,
                suggestedParams: params,
                foreignApps: [this.votingEscrow.appId],
                appArgs: [enc.encode(REWARDS_MANAGER_STRINGS.user_opt_in)],
                accounts: undefined,
                foreignAssets: undefined,
                rekeyTo: undefined
              });
              txns.push(fundStorageAccountTxn, optStorageAccountIntoAdminTxn, optPrimaryAccountIntoAdminTxn, optPrimaryAccountIntoVotingEscrowTxn, optPrimaryAccountIntoRewardsManager);
              return _context2.abrupt("return", assignGroupID(txns));

            case 12:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getOptInTxns(_x, _x2) {
      return _getOptInTxns.apply(this, arguments);
    }

    return getOptInTxns;
  }();

  return GovernanceClient;
}();

var BaseLendingClient$1 = /*#__PURE__*/function () {
  function BaseLendingClient(algofiClient) {
    this.v1 = new GovernanceClient(algofiClient);
    this.network = algofiClient.network;
  }

  var _proto = BaseLendingClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v1.loadState();

            case 2:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseLendingClient;
}();

var MAINNET_APPROVAL_PROGRAM_LOW_FEE_CONSTANT_PRODUCT = /*#__PURE__*/new Uint8Array([5, 32, 11, 1, 0, 2, 6, 192, 132, 61, 188, 160, 236, 160, 2, 4, 128, 148, 235, 220, 3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 232, 7, 196, 19, 38, 34, 2, 98, 49, 2, 98, 50, 2, 97, 49, 2, 97, 50, 2, 108, 99, 2, 114, 102, 3, 97, 49, 114, 3, 97, 50, 114, 4, 109, 102, 108, 114, 1, 97, 3, 102, 108, 102, 3, 99, 117, 116, 3, 99, 117, 100, 3, 99, 102, 49, 3, 99, 102, 50, 1, 105, 1, 108, 2, 108, 116, 3, 115, 102, 101, 4, 99, 116, 49, 50, 4, 99, 116, 50, 49, 3, 99, 118, 49, 3, 99, 118, 50, 4, 99, 118, 49, 50, 4, 99, 118, 50, 49, 1, 112, 8, 65, 70, 45, 80, 79, 79, 76, 45, 1, 45, 7, 45, 50, 53, 46, 48, 66, 80, 5, 114, 112, 97, 49, 114, 5, 114, 112, 97, 50, 114, 4, 98, 97, 49, 111, 4, 98, 97, 50, 111, 3, 114, 115, 114, 49, 24, 35, 18, 64, 12, 240, 49, 25, 129, 5, 18, 64, 12, 228, 49, 25, 34, 18, 64, 12, 217, 49, 25, 36, 18, 64, 12, 206, 39, 15, 100, 34, 18, 64, 1, 111, 54, 26, 0, 128, 2, 105, 112, 18, 64, 0, 1, 0, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 39, 15, 100, 20, 68, 42, 100, 34, 13, 64, 1, 69, 43, 100, 34, 13, 64, 1, 54, 42, 100, 34, 18, 64, 1, 13, 42, 100, 113, 3, 53, 39, 53, 40, 43, 100, 113, 3, 53, 41, 53, 42, 52, 39, 68, 52, 41, 68, 39, 26, 52, 40, 80, 39, 27, 80, 52, 42, 80, 39, 28, 80, 53, 27, 177, 129, 3, 178, 16, 52, 27, 178, 38, 128, 7, 65, 70, 45, 80, 79, 79, 76, 178, 37, 33, 8, 178, 34, 37, 178, 35, 128, 18, 104, 116, 116, 112, 115, 58, 47, 47, 97, 108, 103, 111, 102, 105, 46, 111, 114, 103, 178, 39, 50, 10, 178, 41, 50, 10, 178, 42, 179, 39, 16, 180, 60, 103, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 33, 5, 39, 10, 101, 53, 35, 53, 36, 52, 35, 68, 52, 36, 33, 4, 14, 68, 39, 10, 52, 36, 103, 33, 5, 39, 8, 101, 53, 37, 53, 38, 52, 37, 68, 52, 38, 33, 4, 14, 68, 39, 8, 52, 38, 103, 39, 11, 35, 103, 33, 5, 39, 12, 101, 53, 33, 53, 34, 52, 33, 68, 39, 12, 52, 34, 103, 39, 17, 50, 7, 103, 40, 35, 103, 41, 35, 103, 39, 4, 35, 103, 39, 6, 35, 103, 39, 7, 35, 103, 39, 19, 35, 103, 39, 20, 35, 103, 39, 21, 35, 103, 39, 22, 35, 103, 39, 23, 35, 103, 39, 24, 35, 103, 39, 13, 35, 103, 39, 14, 35, 103, 128, 2, 109, 97, 33, 5, 103, 128, 3, 115, 102, 112, 33, 10, 103, 39, 15, 34, 103, 34, 66, 11, 228, 43, 100, 113, 3, 53, 41, 53, 42, 52, 41, 68, 39, 26, 128, 4, 65, 76, 71, 79, 80, 39, 27, 80, 52, 42, 80, 39, 28, 80, 53, 27, 66, 254, 247, 43, 100, 136, 11, 222, 66, 254, 194, 42, 100, 136, 11, 214, 66, 254, 179, 49, 0, 39, 9, 100, 18, 64, 10, 171, 49, 25, 35, 18, 49, 16, 37, 18, 16, 64, 0, 1, 0, 54, 26, 0, 128, 5, 100, 117, 109, 109, 121, 18, 64, 10, 140, 54, 26, 0, 39, 25, 18, 64, 8, 30, 54, 26, 0, 39, 29, 18, 64, 7, 162, 54, 26, 0, 39, 30, 18, 64, 7, 38, 54, 26, 0, 39, 31, 18, 64, 6, 111, 54, 26, 0, 39, 32, 18, 64, 5, 186, 54, 26, 0, 39, 18, 18, 54, 26, 0, 128, 3, 115, 101, 102, 18, 17, 64, 2, 122, 54, 26, 0, 39, 33, 18, 64, 1, 249, 54, 26, 0, 128, 2, 102, 108, 18, 64, 0, 1, 0, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 33, 5, 39, 10, 101, 53, 35, 53, 36, 52, 35, 68, 52, 36, 33, 4, 14, 68, 39, 10, 52, 36, 103, 33, 5, 39, 8, 101, 53, 37, 53, 38, 52, 37, 68, 52, 38, 33, 4, 14, 68, 39, 8, 52, 38, 103, 54, 26, 2, 23, 39, 10, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 34, 8, 53, 22, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 35, 18, 68, 54, 26, 1, 23, 42, 100, 18, 54, 26, 1, 23, 43, 100, 18, 17, 68, 54, 26, 2, 23, 35, 13, 68, 54, 26, 1, 23, 42, 100, 18, 64, 1, 75, 54, 26, 2, 23, 41, 100, 39, 8, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 14, 68, 54, 26, 1, 23, 34, 18, 64, 0, 255, 50, 4, 34, 9, 56, 16, 33, 6, 18, 68, 50, 4, 34, 9, 56, 17, 54, 26, 1, 23, 18, 68, 50, 4, 34, 9, 56, 20, 50, 10, 18, 68, 50, 4, 34, 9, 56, 18, 35, 13, 68, 50, 4, 34, 9, 56, 18, 54, 26, 2, 23, 52, 22, 8, 18, 68, 54, 26, 1, 23, 42, 100, 18, 64, 0, 160, 43, 100, 54, 26, 2, 23, 136, 10, 126, 54, 26, 1, 23, 42, 100, 18, 64, 0, 131, 41, 41, 100, 52, 22, 8, 103, 52, 22, 39, 5, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 53, 23, 54, 26, 1, 23, 42, 100, 18, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 22, 52, 23, 9, 136, 9, 254, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 9, 218, 40, 40, 100, 52, 23, 9, 103, 39, 6, 39, 6, 100, 52, 23, 8, 103, 39, 13, 39, 13, 100, 52, 22, 52, 23, 9, 136, 9, 190, 103, 66, 255, 189, 40, 40, 100, 52, 22, 8, 103, 66, 255, 122, 42, 100, 34, 18, 64, 0, 12, 42, 100, 54, 26, 2, 23, 136, 9, 215, 66, 255, 86, 54, 26, 2, 23, 136, 9, 231, 66, 255, 76, 50, 4, 34, 9, 56, 16, 34, 18, 68, 50, 4, 34, 9, 56, 7, 50, 10, 18, 68, 50, 4, 34, 9, 56, 8, 35, 13, 68, 50, 4, 34, 9, 56, 8, 54, 26, 2, 23, 52, 22, 8, 18, 68, 66, 255, 11, 54, 26, 2, 23, 40, 100, 39, 8, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 14, 68, 66, 254, 178, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 18, 18, 68, 49, 22, 34, 9, 59, 14, 35, 13, 64, 0, 4, 34, 66, 9, 12, 49, 22, 34, 9, 59, 8, 64, 0, 14, 43, 100, 49, 22, 34, 9, 59, 14, 136, 9, 48, 66, 255, 229, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 14, 136, 9, 27, 66, 255, 208, 49, 22, 34, 9, 59, 14, 136, 9, 41, 66, 255, 196, 50, 7, 39, 17, 100, 9, 53, 24, 39, 17, 50, 7, 103, 41, 100, 33, 7, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 25, 40, 100, 33, 7, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 26, 33, 8, 52, 25, 10, 52, 24, 13, 64, 2, 228, 33, 8, 52, 26, 10, 52, 24, 13, 64, 2, 200, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 49, 22, 34, 9, 56, 16, 34, 18, 64, 2, 119, 49, 22, 34, 9, 56, 17, 42, 100, 18, 49, 22, 34, 9, 56, 17, 43, 100, 18, 17, 68, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 49, 22, 34, 9, 56, 17, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 9, 49, 22, 34, 9, 56, 17, 42, 100, 18, 64, 2, 32, 35, 53, 8, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 54, 26, 0, 39, 18, 18, 64, 1, 224, 54, 26, 0, 39, 18, 18, 64, 1, 23, 52, 9, 33, 10, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 34, 8, 53, 3, 52, 9, 52, 3, 9, 53, 10, 52, 10, 35, 13, 68, 52, 8, 64, 0, 194, 40, 100, 52, 10, 29, 35, 41, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 2, 9, 103, 41, 41, 100, 52, 9, 8, 103, 42, 100, 34, 18, 64, 0, 146, 42, 100, 52, 2, 136, 7, 227, 52, 2, 52, 10, 136, 8, 19, 52, 2, 35, 13, 68, 52, 2, 54, 26, 1, 23, 15, 68, 52, 3, 39, 5, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 53, 23, 52, 8, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 3, 52, 23, 9, 136, 7, 101, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 7, 65, 40, 40, 100, 52, 23, 9, 103, 39, 6, 39, 6, 100, 52, 23, 8, 103, 39, 13, 39, 13, 100, 52, 3, 52, 23, 9, 136, 7, 37, 103, 66, 255, 189, 52, 2, 136, 7, 109, 66, 255, 109, 41, 100, 52, 10, 29, 35, 40, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 9, 8, 103, 41, 41, 100, 52, 2, 9, 103, 43, 100, 52, 2, 136, 7, 40, 52, 10, 52, 2, 136, 7, 88, 66, 255, 66, 54, 26, 1, 23, 53, 11, 52, 11, 35, 13, 68, 52, 8, 64, 0, 152, 41, 100, 52, 11, 29, 35, 40, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 52, 12, 35, 13, 68, 52, 12, 33, 4, 29, 35, 33, 4, 33, 10, 9, 31, 72, 72, 76, 20, 68, 34, 8, 52, 12, 9, 53, 3, 52, 12, 52, 3, 8, 53, 13, 52, 9, 52, 13, 15, 68, 52, 8, 64, 0, 53, 40, 40, 100, 52, 11, 9, 103, 41, 41, 100, 52, 13, 8, 103, 42, 100, 34, 18, 64, 0, 24, 42, 100, 52, 11, 136, 6, 174, 52, 11, 52, 12, 136, 6, 222, 52, 9, 52, 13, 9, 53, 14, 66, 254, 206, 52, 11, 136, 6, 178, 66, 255, 231, 40, 40, 100, 52, 13, 8, 103, 41, 41, 100, 52, 11, 9, 103, 43, 100, 52, 11, 136, 6, 128, 52, 12, 52, 11, 136, 6, 176, 66, 255, 207, 40, 100, 52, 11, 29, 35, 41, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 66, 255, 101, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 33, 18, 68, 66, 253, 246, 34, 66, 253, 221, 42, 100, 34, 18, 68, 49, 22, 34, 9, 56, 16, 34, 18, 68, 49, 22, 34, 9, 56, 7, 50, 10, 18, 68, 49, 22, 34, 9, 56, 8, 35, 13, 68, 49, 22, 34, 9, 56, 8, 53, 9, 34, 53, 8, 66, 253, 176, 39, 20, 39, 20, 100, 52, 26, 52, 24, 11, 136, 5, 189, 103, 66, 253, 39, 39, 19, 39, 19, 100, 52, 25, 52, 24, 11, 136, 5, 172, 103, 66, 253, 11, 49, 22, 36, 9, 56, 16, 33, 6, 18, 68, 49, 22, 36, 9, 56, 17, 39, 16, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 31, 18, 68, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 36, 9, 56, 18, 39, 4, 100, 18, 64, 0, 63, 49, 22, 36, 9, 56, 18, 41, 100, 29, 35, 39, 4, 100, 31, 72, 72, 76, 20, 68, 53, 7, 52, 7, 35, 13, 68, 52, 7, 41, 100, 14, 68, 41, 41, 100, 52, 7, 9, 103, 39, 4, 39, 4, 100, 49, 22, 36, 9, 56, 18, 9, 103, 43, 100, 52, 7, 136, 5, 62, 34, 66, 5, 2, 41, 100, 53, 7, 66, 255, 207, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 39, 16, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 32, 18, 68, 49, 22, 34, 9, 56, 18, 39, 4, 100, 18, 64, 0, 65, 49, 22, 34, 9, 56, 18, 40, 100, 29, 35, 39, 4, 100, 31, 72, 72, 76, 20, 68, 53, 6, 52, 6, 35, 13, 68, 52, 6, 40, 100, 14, 68, 40, 40, 100, 52, 6, 9, 103, 42, 100, 34, 18, 64, 0, 11, 42, 100, 52, 6, 136, 4, 152, 34, 66, 4, 92, 52, 6, 136, 4, 169, 66, 255, 244, 40, 100, 53, 6, 66, 255, 205, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 36, 9, 56, 25, 35, 18, 68, 49, 22, 36, 9, 56, 16, 37, 18, 68, 49, 22, 36, 9, 56, 24, 50, 8, 18, 68, 49, 22, 36, 9, 57, 26, 0, 39, 25, 18, 68, 49, 22, 36, 9, 59, 20, 35, 13, 64, 0, 4, 34, 66, 4, 13, 35, 64, 0, 14, 43, 100, 49, 22, 36, 9, 59, 20, 136, 4, 54, 66, 255, 234, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 36, 9, 59, 20, 136, 4, 33, 66, 255, 213, 49, 22, 36, 9, 59, 20, 136, 4, 47, 66, 255, 201, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 25, 18, 68, 49, 22, 34, 9, 59, 19, 35, 13, 64, 0, 4, 34, 66, 3, 154, 34, 64, 0, 14, 43, 100, 49, 22, 34, 9, 59, 19, 136, 3, 195, 66, 255, 234, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 19, 136, 3, 174, 66, 255, 213, 49, 22, 34, 9, 59, 19, 136, 3, 188, 66, 255, 201, 42, 100, 34, 18, 64, 2, 55, 49, 22, 36, 9, 56, 16, 33, 6, 18, 68, 49, 22, 36, 9, 56, 17, 42, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 36, 9, 56, 18, 53, 4, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 43, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 5, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 29, 18, 68, 49, 22, 36, 8, 56, 25, 35, 18, 68, 49, 22, 36, 8, 56, 16, 37, 18, 68, 49, 22, 36, 8, 56, 24, 50, 8, 18, 68, 49, 22, 36, 8, 57, 26, 0, 39, 30, 18, 68, 40, 100, 41, 100, 8, 35, 18, 64, 1, 108, 40, 100, 33, 7, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 15, 52, 4, 33, 7, 29, 35, 52, 5, 31, 72, 72, 76, 20, 68, 53, 16, 52, 15, 33, 4, 29, 35, 52, 16, 31, 72, 72, 76, 20, 68, 53, 21, 52, 21, 33, 4, 54, 26, 1, 23, 9, 13, 52, 21, 33, 4, 54, 26, 1, 23, 8, 12, 16, 68, 52, 16, 52, 15, 13, 64, 0, 251, 52, 16, 52, 15, 12, 64, 0, 208, 52, 16, 52, 15, 18, 64, 0, 1, 0, 52, 4, 53, 17, 52, 5, 53, 18, 35, 53, 19, 35, 53, 20, 40, 100, 41, 100, 8, 35, 18, 64, 0, 141, 52, 17, 39, 4, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 28, 52, 18, 39, 4, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 29, 52, 28, 52, 29, 13, 64, 0, 92, 52, 28, 53, 0, 52, 0, 35, 13, 68, 40, 100, 41, 100, 8, 35, 18, 64, 0, 65, 40, 40, 100, 52, 17, 8, 103, 41, 41, 100, 52, 18, 8, 103, 39, 4, 39, 4, 100, 52, 0, 8, 103, 39, 16, 100, 52, 0, 136, 2, 5, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 1, 171, 39, 17, 50, 7, 103, 66, 255, 183, 52, 29, 53, 0, 66, 255, 161, 33, 8, 52, 17, 10, 52, 18, 13, 64, 0, 12, 52, 17, 146, 52, 18, 146, 11, 53, 0, 66, 255, 138, 52, 17, 52, 18, 11, 146, 53, 0, 66, 255, 127, 52, 4, 53, 17, 52, 4, 41, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 18, 35, 53, 19, 52, 5, 52, 18, 9, 53, 20, 66, 255, 36, 52, 5, 40, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 17, 52, 5, 53, 18, 52, 4, 52, 17, 9, 53, 19, 35, 53, 20, 66, 255, 1, 52, 4, 53, 17, 52, 5, 53, 18, 66, 254, 246, 49, 22, 36, 9, 56, 16, 34, 18, 68, 49, 22, 36, 9, 56, 7, 50, 10, 18, 68, 49, 22, 36, 9, 56, 8, 35, 13, 68, 49, 22, 36, 9, 56, 8, 53, 4, 66, 253, 209, 34, 66, 0, 254, 49, 25, 33, 6, 18, 64, 0, 127, 54, 26, 0, 128, 3, 115, 99, 117, 18, 64, 0, 63, 54, 26, 0, 128, 2, 114, 114, 18, 64, 0, 1, 0, 49, 0, 39, 9, 100, 18, 68, 42, 100, 34, 18, 64, 0, 28, 42, 100, 39, 6, 100, 136, 1, 0, 43, 100, 39, 7, 100, 136, 0, 248, 39, 6, 35, 103, 39, 7, 35, 103, 34, 66, 0, 180, 39, 6, 100, 136, 1, 0, 66, 255, 227, 49, 0, 39, 9, 100, 18, 68, 33, 5, 39, 12, 101, 53, 33, 53, 34, 52, 33, 64, 0, 23, 54, 26, 1, 23, 50, 7, 39, 12, 100, 8, 15, 68, 39, 11, 54, 26, 1, 23, 103, 34, 66, 0, 127, 39, 12, 52, 34, 103, 66, 255, 225, 49, 0, 39, 9, 100, 18, 68, 39, 11, 100, 35, 19, 68, 39, 11, 100, 50, 7, 14, 68, 39, 11, 35, 103, 34, 66, 0, 91, 35, 66, 0, 87, 35, 66, 0, 83, 35, 66, 0, 79, 49, 53, 33, 6, 15, 68, 49, 52, 129, 32, 15, 68, 33, 5, 39, 9, 101, 53, 1, 53, 30, 52, 1, 68, 39, 9, 52, 30, 103, 54, 26, 0, 23, 35, 19, 54, 26, 1, 23, 35, 19, 16, 68, 54, 26, 0, 23, 54, 26, 1, 23, 12, 68, 42, 54, 26, 0, 23, 103, 43, 54, 26, 1, 23, 103, 128, 2, 118, 105, 54, 26, 2, 23, 103, 39, 15, 35, 103, 34, 67, 53, 44, 53, 43, 52, 44, 33, 8, 52, 43, 9, 13, 64, 0, 6, 52, 43, 52, 44, 8, 137, 52, 44, 33, 8, 52, 43, 9, 9, 34, 9, 137, 53, 45, 177, 33, 6, 178, 16, 52, 45, 178, 17, 35, 178, 18, 50, 10, 178, 20, 35, 178, 1, 179, 137, 53, 47, 53, 46, 177, 33, 6, 178, 16, 52, 46, 178, 17, 52, 47, 178, 18, 49, 0, 178, 20, 35, 178, 1, 179, 137, 53, 48, 50, 10, 96, 52, 48, 50, 1, 8, 15, 68, 177, 34, 178, 16, 52, 48, 178, 8, 49, 0, 178, 7, 35, 178, 1, 179, 137, 53, 50, 53, 49, 39, 21, 39, 21, 100, 52, 49, 136, 255, 132, 103, 39, 22, 39, 22, 100, 52, 50, 136, 255, 121, 103, 33, 8, 52, 50, 10, 52, 25, 13, 64, 0, 28, 33, 8, 52, 49, 10, 52, 26, 13, 65, 0, 34, 39, 24, 39, 24, 100, 52, 49, 52, 26, 11, 136, 255, 85, 103, 66, 0, 17, 39, 23, 39, 23, 100, 52, 50, 52, 25, 11, 136, 255, 68, 103, 66, 255, 211, 137]);
var MAINNET_APPROVAL_PROGRAM_HIGH_FEE_CONSTANT_PRODUCT = /*#__PURE__*/new Uint8Array([5, 32, 11, 1, 0, 2, 6, 192, 132, 61, 188, 160, 236, 160, 2, 4, 128, 148, 235, 220, 3, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 232, 7, 204, 58, 38, 34, 2, 98, 49, 2, 98, 50, 2, 97, 49, 2, 97, 50, 2, 108, 99, 2, 114, 102, 3, 97, 49, 114, 3, 97, 50, 114, 4, 109, 102, 108, 114, 1, 97, 3, 102, 108, 102, 3, 99, 117, 116, 3, 99, 117, 100, 3, 99, 102, 49, 3, 99, 102, 50, 1, 105, 1, 108, 2, 108, 116, 3, 115, 102, 101, 4, 99, 116, 49, 50, 4, 99, 116, 50, 49, 3, 99, 118, 49, 3, 99, 118, 50, 4, 99, 118, 49, 50, 4, 99, 118, 50, 49, 1, 112, 8, 65, 70, 45, 80, 79, 79, 76, 45, 1, 45, 7, 45, 55, 53, 46, 48, 66, 80, 5, 114, 112, 97, 49, 114, 5, 114, 112, 97, 50, 114, 4, 98, 97, 49, 111, 4, 98, 97, 50, 111, 3, 114, 115, 114, 49, 24, 35, 18, 64, 12, 240, 49, 25, 129, 5, 18, 64, 12, 228, 49, 25, 34, 18, 64, 12, 217, 49, 25, 36, 18, 64, 12, 206, 39, 15, 100, 34, 18, 64, 1, 111, 54, 26, 0, 128, 2, 105, 112, 18, 64, 0, 1, 0, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 39, 15, 100, 20, 68, 42, 100, 34, 13, 64, 1, 69, 43, 100, 34, 13, 64, 1, 54, 42, 100, 34, 18, 64, 1, 13, 42, 100, 113, 3, 53, 39, 53, 40, 43, 100, 113, 3, 53, 41, 53, 42, 52, 39, 68, 52, 41, 68, 39, 26, 52, 40, 80, 39, 27, 80, 52, 42, 80, 39, 28, 80, 53, 27, 177, 129, 3, 178, 16, 52, 27, 178, 38, 128, 7, 65, 70, 45, 80, 79, 79, 76, 178, 37, 33, 8, 178, 34, 37, 178, 35, 128, 18, 104, 116, 116, 112, 115, 58, 47, 47, 97, 108, 103, 111, 102, 105, 46, 111, 114, 103, 178, 39, 50, 10, 178, 41, 50, 10, 178, 42, 179, 39, 16, 180, 60, 103, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 33, 5, 39, 10, 101, 53, 35, 53, 36, 52, 35, 68, 52, 36, 33, 4, 14, 68, 39, 10, 52, 36, 103, 33, 5, 39, 8, 101, 53, 37, 53, 38, 52, 37, 68, 52, 38, 33, 4, 14, 68, 39, 8, 52, 38, 103, 39, 11, 35, 103, 33, 5, 39, 12, 101, 53, 33, 53, 34, 52, 33, 68, 39, 12, 52, 34, 103, 39, 17, 50, 7, 103, 40, 35, 103, 41, 35, 103, 39, 4, 35, 103, 39, 6, 35, 103, 39, 7, 35, 103, 39, 19, 35, 103, 39, 20, 35, 103, 39, 21, 35, 103, 39, 22, 35, 103, 39, 23, 35, 103, 39, 24, 35, 103, 39, 13, 35, 103, 39, 14, 35, 103, 128, 2, 109, 97, 33, 5, 103, 128, 3, 115, 102, 112, 33, 10, 103, 39, 15, 34, 103, 34, 66, 11, 228, 43, 100, 113, 3, 53, 41, 53, 42, 52, 41, 68, 39, 26, 128, 4, 65, 76, 71, 79, 80, 39, 27, 80, 52, 42, 80, 39, 28, 80, 53, 27, 66, 254, 247, 43, 100, 136, 11, 222, 66, 254, 194, 42, 100, 136, 11, 214, 66, 254, 179, 49, 0, 39, 9, 100, 18, 64, 10, 171, 49, 25, 35, 18, 49, 16, 37, 18, 16, 64, 0, 1, 0, 54, 26, 0, 128, 5, 100, 117, 109, 109, 121, 18, 64, 10, 140, 54, 26, 0, 39, 25, 18, 64, 8, 30, 54, 26, 0, 39, 29, 18, 64, 7, 162, 54, 26, 0, 39, 30, 18, 64, 7, 38, 54, 26, 0, 39, 31, 18, 64, 6, 111, 54, 26, 0, 39, 32, 18, 64, 5, 186, 54, 26, 0, 39, 18, 18, 54, 26, 0, 128, 3, 115, 101, 102, 18, 17, 64, 2, 122, 54, 26, 0, 39, 33, 18, 64, 1, 249, 54, 26, 0, 128, 2, 102, 108, 18, 64, 0, 1, 0, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 33, 5, 39, 10, 101, 53, 35, 53, 36, 52, 35, 68, 52, 36, 33, 4, 14, 68, 39, 10, 52, 36, 103, 33, 5, 39, 8, 101, 53, 37, 53, 38, 52, 37, 68, 52, 38, 33, 4, 14, 68, 39, 8, 52, 38, 103, 54, 26, 2, 23, 39, 10, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 34, 8, 53, 22, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 35, 18, 68, 54, 26, 1, 23, 42, 100, 18, 54, 26, 1, 23, 43, 100, 18, 17, 68, 54, 26, 2, 23, 35, 13, 68, 54, 26, 1, 23, 42, 100, 18, 64, 1, 75, 54, 26, 2, 23, 41, 100, 39, 8, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 14, 68, 54, 26, 1, 23, 34, 18, 64, 0, 255, 50, 4, 34, 9, 56, 16, 33, 6, 18, 68, 50, 4, 34, 9, 56, 17, 54, 26, 1, 23, 18, 68, 50, 4, 34, 9, 56, 20, 50, 10, 18, 68, 50, 4, 34, 9, 56, 18, 35, 13, 68, 50, 4, 34, 9, 56, 18, 54, 26, 2, 23, 52, 22, 8, 18, 68, 54, 26, 1, 23, 42, 100, 18, 64, 0, 160, 43, 100, 54, 26, 2, 23, 136, 10, 126, 54, 26, 1, 23, 42, 100, 18, 64, 0, 131, 41, 41, 100, 52, 22, 8, 103, 52, 22, 39, 5, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 53, 23, 54, 26, 1, 23, 42, 100, 18, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 22, 52, 23, 9, 136, 9, 254, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 9, 218, 40, 40, 100, 52, 23, 9, 103, 39, 6, 39, 6, 100, 52, 23, 8, 103, 39, 13, 39, 13, 100, 52, 22, 52, 23, 9, 136, 9, 190, 103, 66, 255, 189, 40, 40, 100, 52, 22, 8, 103, 66, 255, 122, 42, 100, 34, 18, 64, 0, 12, 42, 100, 54, 26, 2, 23, 136, 9, 215, 66, 255, 86, 54, 26, 2, 23, 136, 9, 231, 66, 255, 76, 50, 4, 34, 9, 56, 16, 34, 18, 68, 50, 4, 34, 9, 56, 7, 50, 10, 18, 68, 50, 4, 34, 9, 56, 8, 35, 13, 68, 50, 4, 34, 9, 56, 8, 54, 26, 2, 23, 52, 22, 8, 18, 68, 66, 255, 11, 54, 26, 2, 23, 40, 100, 39, 8, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 14, 68, 66, 254, 178, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 18, 18, 68, 49, 22, 34, 9, 59, 14, 35, 13, 64, 0, 4, 34, 66, 9, 12, 49, 22, 34, 9, 59, 8, 64, 0, 14, 43, 100, 49, 22, 34, 9, 59, 14, 136, 9, 48, 66, 255, 229, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 14, 136, 9, 27, 66, 255, 208, 49, 22, 34, 9, 59, 14, 136, 9, 41, 66, 255, 196, 50, 7, 39, 17, 100, 9, 53, 24, 39, 17, 50, 7, 103, 41, 100, 33, 7, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 25, 40, 100, 33, 7, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 26, 33, 8, 52, 25, 10, 52, 24, 13, 64, 2, 228, 33, 8, 52, 26, 10, 52, 24, 13, 64, 2, 200, 33, 5, 39, 5, 101, 53, 31, 53, 32, 52, 31, 68, 52, 32, 33, 4, 14, 68, 39, 5, 52, 32, 103, 49, 22, 34, 9, 56, 16, 34, 18, 64, 2, 119, 49, 22, 34, 9, 56, 17, 42, 100, 18, 49, 22, 34, 9, 56, 17, 43, 100, 18, 17, 68, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 49, 22, 34, 9, 56, 17, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 9, 49, 22, 34, 9, 56, 17, 42, 100, 18, 64, 2, 32, 35, 53, 8, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 54, 26, 0, 39, 18, 18, 64, 1, 224, 54, 26, 0, 39, 18, 18, 64, 1, 23, 52, 9, 33, 10, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 34, 8, 53, 3, 52, 9, 52, 3, 9, 53, 10, 52, 10, 35, 13, 68, 52, 8, 64, 0, 194, 40, 100, 52, 10, 29, 35, 41, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 2, 9, 103, 41, 41, 100, 52, 9, 8, 103, 42, 100, 34, 18, 64, 0, 146, 42, 100, 52, 2, 136, 7, 227, 52, 2, 52, 10, 136, 8, 19, 52, 2, 35, 13, 68, 52, 2, 54, 26, 1, 23, 15, 68, 52, 3, 39, 5, 100, 29, 35, 33, 4, 31, 72, 72, 76, 20, 68, 53, 23, 52, 8, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 3, 52, 23, 9, 136, 7, 101, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 7, 65, 40, 40, 100, 52, 23, 9, 103, 39, 6, 39, 6, 100, 52, 23, 8, 103, 39, 13, 39, 13, 100, 52, 3, 52, 23, 9, 136, 7, 37, 103, 66, 255, 189, 52, 2, 136, 7, 109, 66, 255, 109, 41, 100, 52, 10, 29, 35, 40, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 9, 8, 103, 41, 41, 100, 52, 2, 9, 103, 43, 100, 52, 2, 136, 7, 40, 52, 10, 52, 2, 136, 7, 88, 66, 255, 66, 54, 26, 1, 23, 53, 11, 52, 11, 35, 13, 68, 52, 8, 64, 0, 152, 41, 100, 52, 11, 29, 35, 40, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 52, 12, 35, 13, 68, 52, 12, 33, 4, 29, 35, 33, 4, 33, 10, 9, 31, 72, 72, 76, 20, 68, 34, 8, 52, 12, 9, 53, 3, 52, 12, 52, 3, 8, 53, 13, 52, 9, 52, 13, 15, 68, 52, 8, 64, 0, 53, 40, 40, 100, 52, 11, 9, 103, 41, 41, 100, 52, 13, 8, 103, 42, 100, 34, 18, 64, 0, 24, 42, 100, 52, 11, 136, 6, 174, 52, 11, 52, 12, 136, 6, 222, 52, 9, 52, 13, 9, 53, 14, 66, 254, 206, 52, 11, 136, 6, 178, 66, 255, 231, 40, 40, 100, 52, 13, 8, 103, 41, 41, 100, 52, 11, 9, 103, 43, 100, 52, 11, 136, 6, 128, 52, 12, 52, 11, 136, 6, 176, 66, 255, 207, 40, 100, 52, 11, 29, 35, 41, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 66, 255, 101, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 33, 18, 68, 66, 253, 246, 34, 66, 253, 221, 42, 100, 34, 18, 68, 49, 22, 34, 9, 56, 16, 34, 18, 68, 49, 22, 34, 9, 56, 7, 50, 10, 18, 68, 49, 22, 34, 9, 56, 8, 35, 13, 68, 49, 22, 34, 9, 56, 8, 53, 9, 34, 53, 8, 66, 253, 176, 39, 20, 39, 20, 100, 52, 26, 52, 24, 11, 136, 5, 189, 103, 66, 253, 39, 39, 19, 39, 19, 100, 52, 25, 52, 24, 11, 136, 5, 172, 103, 66, 253, 11, 49, 22, 36, 9, 56, 16, 33, 6, 18, 68, 49, 22, 36, 9, 56, 17, 39, 16, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 31, 18, 68, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 36, 9, 56, 18, 39, 4, 100, 18, 64, 0, 63, 49, 22, 36, 9, 56, 18, 41, 100, 29, 35, 39, 4, 100, 31, 72, 72, 76, 20, 68, 53, 7, 52, 7, 35, 13, 68, 52, 7, 41, 100, 14, 68, 41, 41, 100, 52, 7, 9, 103, 39, 4, 39, 4, 100, 49, 22, 36, 9, 56, 18, 9, 103, 43, 100, 52, 7, 136, 5, 62, 34, 66, 5, 2, 41, 100, 53, 7, 66, 255, 207, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 39, 16, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 32, 18, 68, 49, 22, 34, 9, 56, 18, 39, 4, 100, 18, 64, 0, 65, 49, 22, 34, 9, 56, 18, 40, 100, 29, 35, 39, 4, 100, 31, 72, 72, 76, 20, 68, 53, 6, 52, 6, 35, 13, 68, 52, 6, 40, 100, 14, 68, 40, 40, 100, 52, 6, 9, 103, 42, 100, 34, 18, 64, 0, 11, 42, 100, 52, 6, 136, 4, 152, 34, 66, 4, 92, 52, 6, 136, 4, 169, 66, 255, 244, 40, 100, 53, 6, 66, 255, 205, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 36, 9, 56, 25, 35, 18, 68, 49, 22, 36, 9, 56, 16, 37, 18, 68, 49, 22, 36, 9, 56, 24, 50, 8, 18, 68, 49, 22, 36, 9, 57, 26, 0, 39, 25, 18, 68, 49, 22, 36, 9, 59, 20, 35, 13, 64, 0, 4, 34, 66, 4, 13, 35, 64, 0, 14, 43, 100, 49, 22, 36, 9, 59, 20, 136, 4, 54, 66, 255, 234, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 36, 9, 59, 20, 136, 4, 33, 66, 255, 213, 49, 22, 36, 9, 59, 20, 136, 4, 47, 66, 255, 201, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 37, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 25, 18, 68, 49, 22, 34, 9, 59, 19, 35, 13, 64, 0, 4, 34, 66, 3, 154, 34, 64, 0, 14, 43, 100, 49, 22, 34, 9, 59, 19, 136, 3, 195, 66, 255, 234, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 19, 136, 3, 174, 66, 255, 213, 49, 22, 34, 9, 59, 19, 136, 3, 188, 66, 255, 201, 42, 100, 34, 18, 64, 2, 55, 49, 22, 36, 9, 56, 16, 33, 6, 18, 68, 49, 22, 36, 9, 56, 17, 42, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 36, 9, 56, 18, 53, 4, 49, 22, 34, 9, 56, 16, 33, 6, 18, 68, 49, 22, 34, 9, 56, 17, 43, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 5, 49, 25, 35, 18, 68, 49, 16, 37, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 37, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 29, 18, 68, 49, 22, 36, 8, 56, 25, 35, 18, 68, 49, 22, 36, 8, 56, 16, 37, 18, 68, 49, 22, 36, 8, 56, 24, 50, 8, 18, 68, 49, 22, 36, 8, 57, 26, 0, 39, 30, 18, 68, 40, 100, 41, 100, 8, 35, 18, 64, 1, 108, 40, 100, 33, 7, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 15, 52, 4, 33, 7, 29, 35, 52, 5, 31, 72, 72, 76, 20, 68, 53, 16, 52, 15, 33, 4, 29, 35, 52, 16, 31, 72, 72, 76, 20, 68, 53, 21, 52, 21, 33, 4, 54, 26, 1, 23, 9, 13, 52, 21, 33, 4, 54, 26, 1, 23, 8, 12, 16, 68, 52, 16, 52, 15, 13, 64, 0, 251, 52, 16, 52, 15, 12, 64, 0, 208, 52, 16, 52, 15, 18, 64, 0, 1, 0, 52, 4, 53, 17, 52, 5, 53, 18, 35, 53, 19, 35, 53, 20, 40, 100, 41, 100, 8, 35, 18, 64, 0, 141, 52, 17, 39, 4, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 28, 52, 18, 39, 4, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 29, 52, 28, 52, 29, 13, 64, 0, 92, 52, 28, 53, 0, 52, 0, 35, 13, 68, 40, 100, 41, 100, 8, 35, 18, 64, 0, 65, 40, 40, 100, 52, 17, 8, 103, 41, 41, 100, 52, 18, 8, 103, 39, 4, 39, 4, 100, 52, 0, 8, 103, 39, 16, 100, 52, 0, 136, 2, 5, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 7, 12, 68, 41, 100, 40, 100, 10, 33, 7, 12, 68, 34, 66, 1, 171, 39, 17, 50, 7, 103, 66, 255, 183, 52, 29, 53, 0, 66, 255, 161, 33, 8, 52, 17, 10, 52, 18, 13, 64, 0, 12, 52, 17, 146, 52, 18, 146, 11, 53, 0, 66, 255, 138, 52, 17, 52, 18, 11, 146, 53, 0, 66, 255, 127, 52, 4, 53, 17, 52, 4, 41, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 18, 35, 53, 19, 52, 5, 52, 18, 9, 53, 20, 66, 255, 36, 52, 5, 40, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 17, 52, 5, 53, 18, 52, 4, 52, 17, 9, 53, 19, 35, 53, 20, 66, 255, 1, 52, 4, 53, 17, 52, 5, 53, 18, 66, 254, 246, 49, 22, 36, 9, 56, 16, 34, 18, 68, 49, 22, 36, 9, 56, 7, 50, 10, 18, 68, 49, 22, 36, 9, 56, 8, 35, 13, 68, 49, 22, 36, 9, 56, 8, 53, 4, 66, 253, 209, 34, 66, 0, 254, 49, 25, 33, 6, 18, 64, 0, 127, 54, 26, 0, 128, 3, 115, 99, 117, 18, 64, 0, 63, 54, 26, 0, 128, 2, 114, 114, 18, 64, 0, 1, 0, 49, 0, 39, 9, 100, 18, 68, 42, 100, 34, 18, 64, 0, 28, 42, 100, 39, 6, 100, 136, 1, 0, 43, 100, 39, 7, 100, 136, 0, 248, 39, 6, 35, 103, 39, 7, 35, 103, 34, 66, 0, 180, 39, 6, 100, 136, 1, 0, 66, 255, 227, 49, 0, 39, 9, 100, 18, 68, 33, 5, 39, 12, 101, 53, 33, 53, 34, 52, 33, 64, 0, 23, 54, 26, 1, 23, 50, 7, 39, 12, 100, 8, 15, 68, 39, 11, 54, 26, 1, 23, 103, 34, 66, 0, 127, 39, 12, 52, 34, 103, 66, 255, 225, 49, 0, 39, 9, 100, 18, 68, 39, 11, 100, 35, 19, 68, 39, 11, 100, 50, 7, 14, 68, 39, 11, 35, 103, 34, 66, 0, 91, 35, 66, 0, 87, 35, 66, 0, 83, 35, 66, 0, 79, 49, 53, 33, 6, 15, 68, 49, 52, 129, 32, 15, 68, 33, 5, 39, 9, 101, 53, 1, 53, 30, 52, 1, 68, 39, 9, 52, 30, 103, 54, 26, 0, 23, 35, 19, 54, 26, 1, 23, 35, 19, 16, 68, 54, 26, 0, 23, 54, 26, 1, 23, 12, 68, 42, 54, 26, 0, 23, 103, 43, 54, 26, 1, 23, 103, 128, 2, 118, 105, 54, 26, 2, 23, 103, 39, 15, 35, 103, 34, 67, 53, 44, 53, 43, 52, 44, 33, 8, 52, 43, 9, 13, 64, 0, 6, 52, 43, 52, 44, 8, 137, 52, 44, 33, 8, 52, 43, 9, 9, 34, 9, 137, 53, 45, 177, 33, 6, 178, 16, 52, 45, 178, 17, 35, 178, 18, 50, 10, 178, 20, 35, 178, 1, 179, 137, 53, 47, 53, 46, 177, 33, 6, 178, 16, 52, 46, 178, 17, 52, 47, 178, 18, 49, 0, 178, 20, 35, 178, 1, 179, 137, 53, 48, 50, 10, 96, 52, 48, 50, 1, 8, 15, 68, 177, 34, 178, 16, 52, 48, 178, 8, 49, 0, 178, 7, 35, 178, 1, 179, 137, 53, 50, 53, 49, 39, 21, 39, 21, 100, 52, 49, 136, 255, 132, 103, 39, 22, 39, 22, 100, 52, 50, 136, 255, 121, 103, 33, 8, 52, 50, 10, 52, 25, 13, 64, 0, 28, 33, 8, 52, 49, 10, 52, 26, 13, 65, 0, 34, 39, 24, 39, 24, 100, 52, 49, 52, 26, 11, 136, 255, 85, 103, 66, 0, 17, 39, 23, 39, 23, 100, 52, 50, 52, 25, 11, 136, 255, 68, 103, 66, 255, 211, 137]);
var MAINNET_CLEAR_STATE_PROGRAM = /*#__PURE__*/new Uint8Array([5, 129, 1, 67]);
var TESTNET_APPROVAL_PROGRAM_LOW_FEE_CONSTANT_PRODUCT = /*#__PURE__*/new Uint8Array([6, 32, 10, 1, 0, 2, 192, 132, 61, 6, 128, 148, 235, 220, 3, 185, 184, 217, 49, 4, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 232, 7, 38, 35, 2, 98, 49, 2, 98, 50, 2, 97, 49, 5, 108, 49, 116, 50, 112, 2, 97, 50, 2, 108, 99, 2, 114, 102, 3, 97, 49, 114, 3, 97, 50, 114, 4, 109, 102, 108, 114, 1, 97, 3, 102, 108, 102, 3, 99, 117, 116, 3, 99, 117, 100, 3, 99, 102, 49, 3, 99, 102, 50, 1, 105, 1, 108, 2, 108, 116, 3, 115, 102, 101, 4, 99, 116, 49, 50, 4, 99, 116, 50, 49, 3, 99, 118, 49, 3, 99, 118, 50, 4, 99, 118, 49, 50, 4, 99, 118, 50, 49, 3, 115, 102, 112, 1, 112, 8, 65, 70, 45, 80, 79, 79, 76, 45, 1, 45, 5, 114, 112, 97, 49, 114, 5, 114, 112, 97, 50, 114, 4, 98, 97, 49, 111, 4, 98, 97, 50, 111, 3, 114, 115, 114, 49, 24, 35, 18, 64, 13, 138, 49, 25, 129, 5, 18, 64, 13, 126, 49, 25, 34, 18, 64, 13, 115, 49, 25, 36, 18, 64, 13, 104, 39, 16, 100, 34, 18, 64, 1, 112, 54, 26, 0, 128, 2, 105, 112, 18, 64, 0, 1, 0, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 39, 16, 100, 20, 68, 42, 100, 34, 13, 64, 1, 69, 39, 4, 100, 34, 13, 64, 1, 52, 42, 100, 34, 18, 64, 1, 13, 42, 100, 113, 3, 53, 38, 53, 37, 39, 4, 100, 113, 3, 53, 40, 53, 39, 52, 38, 68, 52, 40, 68, 39, 28, 52, 37, 39, 29, 52, 39, 80, 80, 80, 53, 27, 177, 129, 3, 178, 16, 52, 27, 178, 38, 128, 7, 65, 70, 45, 80, 79, 79, 76, 178, 37, 33, 8, 178, 34, 33, 4, 178, 35, 128, 18, 104, 116, 116, 112, 115, 58, 47, 47, 97, 108, 103, 111, 102, 105, 46, 111, 114, 103, 178, 39, 50, 10, 178, 41, 50, 10, 178, 42, 179, 39, 17, 180, 60, 103, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 33, 6, 39, 11, 101, 53, 34, 53, 33, 52, 34, 68, 52, 33, 37, 14, 68, 39, 11, 52, 33, 103, 33, 6, 39, 9, 101, 53, 36, 53, 35, 52, 36, 68, 52, 35, 37, 14, 68, 39, 9, 52, 35, 103, 39, 12, 35, 103, 33, 6, 39, 13, 101, 53, 32, 53, 31, 52, 32, 68, 39, 13, 52, 31, 103, 39, 18, 50, 7, 103, 40, 35, 103, 41, 35, 103, 39, 5, 35, 103, 39, 7, 35, 103, 39, 8, 35, 103, 39, 20, 35, 103, 39, 21, 35, 103, 39, 22, 35, 103, 39, 23, 35, 103, 39, 24, 35, 103, 39, 25, 35, 103, 39, 14, 35, 103, 39, 15, 35, 103, 43, 34, 103, 43, 34, 103, 128, 2, 109, 97, 33, 6, 103, 39, 26, 129, 196, 19, 103, 39, 16, 34, 103, 34, 66, 12, 125, 39, 4, 100, 113, 3, 53, 40, 53, 39, 52, 40, 68, 39, 28, 128, 4, 65, 76, 71, 79, 39, 29, 52, 39, 80, 80, 80, 53, 27, 66, 254, 247, 39, 4, 100, 136, 12, 120, 66, 254, 195, 42, 100, 136, 12, 112, 66, 254, 179, 49, 0, 39, 10, 100, 18, 64, 11, 67, 49, 25, 35, 18, 49, 16, 33, 4, 18, 16, 64, 0, 1, 0, 54, 26, 0, 39, 27, 18, 64, 8, 198, 54, 26, 0, 39, 30, 18, 64, 8, 71, 54, 26, 0, 39, 31, 18, 64, 7, 200, 54, 26, 0, 39, 32, 18, 64, 7, 15, 54, 26, 0, 39, 33, 18, 64, 6, 87, 54, 26, 0, 39, 19, 18, 54, 26, 0, 128, 3, 115, 101, 102, 18, 17, 64, 2, 121, 54, 26, 0, 39, 34, 18, 64, 1, 245, 54, 26, 0, 128, 2, 102, 108, 18, 64, 0, 1, 0, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 33, 6, 39, 11, 101, 53, 34, 53, 33, 52, 34, 68, 52, 33, 37, 14, 68, 39, 11, 52, 33, 103, 33, 6, 39, 9, 101, 53, 36, 53, 35, 52, 36, 68, 52, 35, 37, 14, 68, 39, 9, 52, 35, 103, 54, 26, 2, 23, 39, 11, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 34, 8, 53, 22, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 35, 18, 68, 54, 26, 1, 23, 42, 100, 18, 54, 26, 1, 23, 39, 4, 100, 18, 17, 68, 54, 26, 2, 23, 35, 13, 68, 54, 26, 1, 23, 42, 100, 18, 64, 1, 74, 54, 26, 2, 23, 41, 100, 39, 9, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 14, 68, 54, 26, 1, 23, 34, 18, 64, 0, 255, 50, 4, 34, 9, 56, 16, 33, 7, 18, 68, 50, 4, 34, 9, 56, 17, 54, 26, 1, 23, 18, 68, 50, 4, 34, 9, 56, 20, 50, 10, 18, 68, 50, 4, 34, 9, 56, 18, 35, 13, 68, 50, 4, 34, 9, 56, 18, 54, 26, 2, 23, 52, 22, 8, 18, 68, 54, 26, 1, 23, 42, 100, 18, 64, 0, 160, 39, 4, 100, 54, 26, 2, 23, 136, 11, 39, 54, 26, 1, 23, 42, 100, 18, 64, 0, 130, 41, 41, 100, 52, 22, 8, 103, 52, 22, 39, 6, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 53, 23, 54, 26, 1, 23, 42, 100, 18, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 8, 39, 8, 100, 52, 23, 8, 103, 39, 15, 39, 15, 100, 52, 22, 52, 23, 9, 136, 10, 168, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 10, 132, 40, 40, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 22, 52, 23, 9, 136, 10, 104, 103, 66, 255, 189, 40, 40, 100, 52, 22, 8, 103, 66, 255, 123, 42, 100, 34, 18, 64, 0, 12, 42, 100, 54, 26, 2, 23, 136, 10, 129, 66, 255, 87, 54, 26, 2, 23, 136, 10, 145, 66, 255, 77, 50, 4, 34, 9, 56, 16, 34, 18, 68, 50, 4, 34, 9, 56, 7, 50, 10, 18, 68, 50, 4, 34, 9, 56, 8, 35, 13, 68, 50, 4, 34, 9, 56, 8, 54, 26, 2, 23, 52, 22, 8, 18, 68, 66, 255, 11, 54, 26, 2, 23, 40, 100, 39, 9, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 14, 68, 66, 254, 179, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 19, 18, 68, 49, 22, 34, 9, 59, 14, 35, 13, 64, 0, 4, 34, 66, 9, 181, 49, 22, 34, 9, 59, 8, 64, 0, 15, 39, 4, 100, 49, 22, 34, 9, 59, 14, 136, 9, 216, 66, 255, 228, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 14, 136, 9, 195, 66, 255, 207, 49, 22, 34, 9, 59, 14, 136, 9, 209, 66, 255, 195, 50, 7, 39, 18, 100, 9, 53, 24, 39, 18, 50, 7, 103, 33, 8, 43, 100, 10, 52, 24, 13, 64, 3, 162, 33, 8, 43, 100, 10, 52, 24, 13, 64, 3, 134, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 49, 22, 34, 9, 56, 16, 34, 18, 64, 3, 54, 49, 22, 34, 9, 56, 17, 42, 100, 18, 49, 22, 34, 9, 56, 17, 39, 4, 100, 18, 17, 68, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 49, 22, 34, 9, 56, 17, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 9, 49, 22, 34, 9, 56, 17, 42, 100, 18, 64, 2, 222, 35, 53, 8, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 54, 26, 0, 39, 19, 18, 64, 2, 156, 54, 26, 0, 39, 19, 18, 64, 1, 117, 52, 9, 39, 26, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 34, 8, 53, 3, 52, 9, 52, 3, 9, 53, 10, 52, 10, 35, 13, 68, 52, 8, 64, 0, 240, 40, 100, 52, 10, 29, 35, 41, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 2, 9, 103, 41, 41, 100, 52, 9, 8, 103, 42, 100, 34, 18, 64, 0, 192, 42, 100, 52, 2, 136, 8, 170, 52, 2, 37, 13, 52, 10, 37, 13, 16, 64, 0, 138, 52, 2, 52, 10, 136, 8, 206, 52, 2, 35, 13, 68, 52, 2, 54, 26, 1, 23, 15, 68, 52, 3, 39, 6, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 53, 23, 52, 8, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 8, 39, 8, 100, 52, 23, 8, 103, 39, 15, 39, 15, 100, 52, 3, 52, 23, 9, 136, 8, 33, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 7, 253, 40, 40, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 3, 52, 23, 9, 136, 7, 225, 103, 66, 255, 189, 43, 52, 2, 33, 5, 29, 35, 52, 10, 31, 72, 72, 76, 20, 68, 103, 43, 52, 10, 33, 5, 29, 35, 52, 2, 31, 72, 72, 76, 20, 68, 103, 66, 255, 83, 52, 2, 136, 8, 6, 66, 255, 63, 41, 100, 52, 10, 29, 35, 40, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 9, 8, 103, 41, 41, 100, 52, 2, 9, 103, 39, 4, 100, 52, 2, 136, 7, 192, 52, 10, 37, 13, 52, 2, 37, 13, 16, 64, 0, 10, 52, 10, 52, 2, 136, 7, 228, 66, 255, 19, 43, 52, 10, 33, 5, 29, 35, 52, 2, 31, 72, 72, 76, 20, 68, 103, 43, 52, 2, 33, 5, 29, 35, 52, 10, 31, 72, 72, 76, 20, 68, 103, 66, 255, 211, 54, 26, 1, 23, 53, 11, 52, 11, 35, 13, 68, 52, 8, 64, 0, 246, 41, 100, 52, 11, 29, 35, 40, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 52, 12, 35, 13, 68, 52, 12, 37, 29, 35, 37, 39, 26, 100, 9, 31, 72, 72, 76, 20, 68, 34, 8, 52, 12, 9, 53, 3, 52, 12, 52, 3, 8, 53, 13, 52, 9, 52, 13, 15, 68, 52, 8, 64, 0, 100, 40, 40, 100, 52, 11, 9, 103, 41, 41, 100, 52, 13, 8, 103, 42, 100, 34, 18, 64, 0, 71, 42, 100, 52, 11, 136, 7, 24, 52, 11, 37, 13, 52, 12, 37, 13, 16, 64, 0, 17, 52, 11, 52, 12, 136, 7, 60, 52, 9, 52, 13, 9, 53, 14, 66, 254, 113, 43, 52, 11, 33, 5, 29, 35, 52, 12, 31, 72, 72, 76, 20, 68, 103, 43, 52, 12, 33, 5, 29, 35, 52, 11, 31, 72, 72, 76, 20, 68, 103, 66, 255, 204, 52, 11, 136, 6, 237, 66, 255, 184, 40, 40, 100, 52, 13, 8, 103, 41, 41, 100, 52, 11, 9, 103, 39, 4, 100, 52, 11, 136, 6, 186, 52, 12, 37, 13, 52, 11, 37, 13, 16, 64, 0, 10, 52, 12, 52, 11, 136, 6, 222, 66, 255, 159, 43, 52, 12, 33, 5, 29, 35, 52, 11, 31, 72, 72, 76, 20, 68, 103, 43, 52, 11, 33, 5, 29, 35, 52, 12, 31, 72, 72, 76, 20, 68, 103, 66, 255, 211, 40, 100, 52, 11, 29, 35, 41, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 66, 255, 7, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 34, 18, 68, 66, 253, 57, 34, 66, 253, 31, 42, 100, 34, 18, 68, 49, 22, 34, 9, 56, 16, 34, 18, 68, 49, 22, 34, 9, 56, 7, 50, 10, 18, 68, 49, 22, 34, 9, 56, 8, 35, 13, 68, 49, 22, 34, 9, 56, 8, 53, 9, 34, 53, 8, 66, 252, 242, 39, 21, 39, 21, 100, 43, 100, 52, 24, 11, 136, 5, 199, 103, 66, 252, 105, 39, 20, 39, 20, 100, 43, 100, 52, 24, 11, 136, 5, 182, 103, 66, 252, 77, 49, 22, 36, 9, 56, 16, 33, 7, 18, 68, 49, 22, 36, 9, 56, 17, 39, 17, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 32, 18, 68, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 18, 39, 5, 100, 18, 64, 0, 64, 49, 22, 36, 9, 56, 18, 41, 100, 29, 35, 39, 5, 100, 31, 72, 72, 76, 20, 68, 53, 7, 52, 7, 35, 13, 68, 52, 7, 41, 100, 14, 68, 41, 41, 100, 52, 7, 9, 103, 39, 5, 39, 5, 100, 49, 22, 36, 9, 56, 18, 9, 103, 39, 4, 100, 52, 7, 136, 5, 69, 34, 66, 5, 9, 41, 100, 53, 7, 66, 255, 206, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 39, 17, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 33, 18, 68, 49, 22, 34, 9, 56, 18, 39, 5, 100, 18, 64, 0, 65, 49, 22, 34, 9, 56, 18, 40, 100, 29, 35, 39, 5, 100, 31, 72, 72, 76, 20, 68, 53, 6, 52, 6, 35, 13, 68, 52, 6, 40, 100, 14, 68, 40, 40, 100, 52, 6, 9, 103, 42, 100, 34, 18, 64, 0, 11, 42, 100, 52, 6, 136, 4, 157, 34, 66, 4, 97, 52, 6, 136, 4, 174, 66, 255, 244, 40, 100, 53, 6, 66, 255, 205, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 25, 35, 18, 68, 49, 22, 36, 9, 56, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 24, 50, 8, 18, 68, 49, 22, 36, 9, 57, 26, 0, 39, 27, 18, 68, 49, 22, 36, 9, 59, 20, 35, 13, 64, 0, 4, 34, 66, 4, 16, 35, 64, 0, 15, 39, 4, 100, 49, 22, 36, 9, 59, 20, 136, 4, 56, 66, 255, 233, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 36, 9, 59, 20, 136, 4, 35, 66, 255, 212, 49, 22, 36, 9, 59, 20, 136, 4, 49, 66, 255, 200, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 27, 18, 68, 49, 22, 34, 9, 59, 19, 35, 13, 64, 0, 4, 34, 66, 3, 154, 34, 64, 0, 15, 39, 4, 100, 49, 22, 34, 9, 59, 19, 136, 3, 194, 66, 255, 233, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 19, 136, 3, 173, 66, 255, 212, 49, 22, 34, 9, 59, 19, 136, 3, 187, 66, 255, 200, 42, 100, 34, 18, 64, 2, 56, 49, 22, 36, 9, 56, 16, 33, 7, 18, 68, 49, 22, 36, 9, 56, 17, 42, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 36, 9, 56, 18, 53, 4, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 39, 4, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 5, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 30, 18, 68, 49, 22, 36, 8, 56, 25, 35, 18, 68, 49, 22, 36, 8, 56, 16, 33, 4, 18, 68, 49, 22, 36, 8, 56, 24, 50, 8, 18, 68, 49, 22, 36, 8, 57, 26, 0, 39, 31, 18, 68, 40, 100, 41, 100, 8, 35, 18, 64, 1, 105, 40, 100, 33, 5, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 15, 52, 4, 33, 5, 29, 35, 52, 5, 31, 72, 72, 76, 20, 68, 53, 16, 52, 15, 37, 29, 35, 52, 16, 31, 72, 72, 76, 20, 68, 53, 21, 52, 21, 37, 54, 26, 1, 23, 9, 13, 52, 21, 37, 54, 26, 1, 23, 8, 12, 16, 68, 52, 16, 52, 15, 13, 64, 0, 251, 52, 16, 52, 15, 12, 64, 0, 208, 52, 16, 52, 15, 18, 64, 0, 1, 0, 52, 4, 53, 17, 52, 5, 53, 18, 35, 53, 19, 35, 53, 20, 40, 100, 41, 100, 8, 35, 18, 64, 0, 141, 52, 17, 39, 5, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 28, 52, 18, 39, 5, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 29, 52, 28, 52, 29, 13, 64, 0, 92, 52, 28, 53, 0, 52, 0, 35, 13, 68, 40, 100, 41, 100, 8, 35, 18, 64, 0, 65, 40, 40, 100, 52, 17, 8, 103, 41, 41, 100, 52, 18, 8, 103, 39, 5, 39, 5, 100, 52, 0, 8, 103, 39, 17, 100, 52, 0, 136, 2, 3, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 1, 169, 39, 18, 50, 7, 103, 66, 255, 183, 52, 29, 53, 0, 66, 255, 161, 33, 8, 52, 17, 10, 52, 18, 13, 64, 0, 12, 52, 17, 146, 52, 18, 146, 11, 53, 0, 66, 255, 138, 52, 17, 52, 18, 11, 146, 53, 0, 66, 255, 127, 52, 4, 53, 17, 52, 4, 41, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 18, 35, 53, 19, 52, 5, 52, 18, 9, 53, 20, 66, 255, 36, 52, 5, 40, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 17, 52, 5, 53, 18, 52, 4, 52, 17, 9, 53, 19, 35, 53, 20, 66, 255, 1, 52, 4, 53, 17, 52, 5, 53, 18, 66, 254, 246, 49, 22, 36, 9, 56, 16, 34, 18, 68, 49, 22, 36, 9, 56, 7, 50, 10, 18, 68, 49, 22, 36, 9, 56, 8, 35, 13, 68, 49, 22, 36, 9, 56, 8, 53, 4, 66, 253, 208, 49, 25, 33, 7, 18, 64, 0, 128, 54, 26, 0, 128, 3, 115, 99, 117, 18, 64, 0, 64, 54, 26, 0, 128, 2, 114, 114, 18, 64, 0, 1, 0, 49, 0, 39, 10, 100, 18, 68, 42, 100, 34, 18, 64, 0, 29, 42, 100, 39, 7, 100, 136, 1, 2, 39, 4, 100, 39, 8, 100, 136, 0, 249, 39, 7, 35, 103, 39, 8, 35, 103, 34, 66, 0, 181, 39, 7, 100, 136, 1, 1, 66, 255, 226, 49, 0, 39, 10, 100, 18, 68, 33, 6, 39, 13, 101, 53, 32, 53, 31, 52, 32, 64, 0, 23, 54, 26, 1, 23, 50, 7, 39, 13, 100, 8, 15, 68, 39, 12, 54, 26, 1, 23, 103, 34, 66, 0, 128, 39, 13, 52, 31, 103, 66, 255, 225, 49, 0, 39, 10, 100, 18, 68, 39, 12, 100, 35, 19, 68, 39, 12, 100, 50, 7, 14, 68, 39, 12, 35, 103, 34, 66, 0, 92, 35, 66, 0, 88, 35, 66, 0, 84, 35, 66, 0, 80, 49, 53, 33, 7, 15, 68, 49, 52, 129, 32, 15, 68, 33, 6, 39, 10, 101, 53, 25, 53, 1, 52, 25, 68, 39, 10, 52, 1, 103, 54, 26, 0, 23, 35, 19, 54, 26, 1, 23, 35, 19, 16, 68, 54, 26, 0, 23, 54, 26, 1, 23, 12, 68, 42, 54, 26, 0, 23, 103, 39, 4, 54, 26, 1, 23, 103, 128, 2, 118, 105, 54, 26, 2, 23, 103, 39, 16, 35, 103, 34, 67, 53, 42, 53, 41, 52, 42, 33, 8, 52, 41, 9, 13, 64, 0, 6, 52, 41, 52, 42, 8, 137, 52, 42, 33, 8, 52, 41, 9, 9, 34, 9, 137, 53, 43, 177, 33, 7, 178, 16, 52, 43, 178, 17, 35, 178, 18, 50, 10, 178, 20, 35, 178, 1, 179, 137, 53, 45, 53, 44, 177, 33, 7, 178, 16, 52, 44, 178, 17, 52, 45, 178, 18, 49, 0, 178, 20, 35, 178, 1, 179, 137, 53, 46, 50, 10, 96, 52, 46, 50, 1, 8, 15, 68, 177, 34, 178, 16, 52, 46, 178, 8, 49, 0, 178, 7, 35, 178, 1, 179, 137, 53, 48, 53, 47, 39, 22, 39, 22, 100, 52, 47, 136, 255, 132, 103, 39, 23, 39, 23, 100, 52, 48, 136, 255, 121, 103, 33, 8, 52, 48, 10, 43, 100, 13, 64, 0, 28, 33, 8, 52, 47, 10, 43, 100, 13, 65, 0, 34, 39, 25, 39, 25, 100, 52, 47, 43, 100, 11, 136, 255, 85, 103, 66, 0, 17, 39, 24, 39, 24, 100, 52, 48, 43, 100, 11, 136, 255, 68, 103, 66, 255, 211, 137]);
var TESTNET_APPROVAL_PROGRAM_HIGH_FEE_CONSTANT_PRODUCT = /*#__PURE__*/new Uint8Array([6, 32, 10, 1, 0, 2, 192, 132, 61, 6, 128, 148, 235, 220, 3, 185, 184, 217, 49, 4, 255, 255, 255, 255, 255, 255, 255, 255, 255, 1, 232, 7, 38, 35, 2, 98, 49, 2, 98, 50, 2, 97, 49, 5, 108, 49, 116, 50, 112, 2, 97, 50, 2, 108, 99, 2, 114, 102, 3, 97, 49, 114, 3, 97, 50, 114, 4, 109, 102, 108, 114, 1, 97, 3, 102, 108, 102, 3, 99, 117, 116, 3, 99, 117, 100, 3, 99, 102, 49, 3, 99, 102, 50, 1, 105, 1, 108, 2, 108, 116, 3, 115, 102, 101, 4, 99, 116, 49, 50, 4, 99, 116, 50, 49, 3, 99, 118, 49, 3, 99, 118, 50, 4, 99, 118, 49, 50, 4, 99, 118, 50, 49, 3, 115, 102, 112, 1, 112, 8, 65, 70, 45, 80, 79, 79, 76, 45, 1, 45, 5, 114, 112, 97, 49, 114, 5, 114, 112, 97, 50, 114, 4, 98, 97, 49, 111, 4, 98, 97, 50, 111, 3, 114, 115, 114, 49, 24, 35, 18, 64, 13, 138, 49, 25, 129, 5, 18, 64, 13, 126, 49, 25, 34, 18, 64, 13, 115, 49, 25, 36, 18, 64, 13, 104, 39, 16, 100, 34, 18, 64, 1, 112, 54, 26, 0, 128, 2, 105, 112, 18, 64, 0, 1, 0, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 39, 16, 100, 20, 68, 42, 100, 34, 13, 64, 1, 69, 39, 4, 100, 34, 13, 64, 1, 52, 42, 100, 34, 18, 64, 1, 13, 42, 100, 113, 3, 53, 44, 53, 43, 39, 4, 100, 113, 3, 53, 46, 53, 45, 52, 44, 68, 52, 46, 68, 39, 28, 52, 43, 39, 29, 52, 45, 80, 80, 80, 53, 27, 177, 129, 3, 178, 16, 52, 27, 178, 38, 128, 7, 65, 70, 45, 80, 79, 79, 76, 178, 37, 33, 8, 178, 34, 33, 4, 178, 35, 128, 18, 104, 116, 116, 112, 115, 58, 47, 47, 97, 108, 103, 111, 102, 105, 46, 111, 114, 103, 178, 39, 50, 10, 178, 41, 50, 10, 178, 42, 179, 39, 17, 180, 60, 103, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 33, 6, 39, 11, 101, 53, 34, 53, 33, 52, 34, 68, 52, 33, 37, 14, 68, 39, 11, 52, 33, 103, 33, 6, 39, 9, 101, 53, 36, 53, 35, 52, 36, 68, 52, 35, 37, 14, 68, 39, 9, 52, 35, 103, 39, 12, 35, 103, 33, 6, 39, 13, 101, 53, 32, 53, 31, 52, 32, 68, 39, 13, 52, 31, 103, 39, 18, 50, 7, 103, 40, 35, 103, 41, 35, 103, 39, 5, 35, 103, 39, 7, 35, 103, 39, 8, 35, 103, 39, 20, 35, 103, 39, 21, 35, 103, 39, 22, 35, 103, 39, 23, 35, 103, 39, 24, 35, 103, 39, 25, 35, 103, 39, 14, 35, 103, 39, 15, 35, 103, 43, 34, 103, 43, 34, 103, 128, 2, 109, 97, 33, 6, 103, 39, 26, 129, 204, 58, 103, 39, 16, 34, 103, 34, 66, 12, 125, 39, 4, 100, 113, 3, 53, 46, 53, 45, 52, 46, 68, 39, 28, 128, 4, 65, 76, 71, 79, 39, 29, 52, 45, 80, 80, 80, 53, 27, 66, 254, 247, 39, 4, 100, 136, 12, 120, 66, 254, 195, 42, 100, 136, 12, 112, 66, 254, 179, 49, 0, 39, 10, 100, 18, 64, 11, 67, 49, 25, 35, 18, 49, 16, 33, 4, 18, 16, 64, 0, 1, 0, 54, 26, 0, 39, 27, 18, 64, 8, 198, 54, 26, 0, 39, 30, 18, 64, 8, 71, 54, 26, 0, 39, 31, 18, 64, 7, 200, 54, 26, 0, 39, 32, 18, 64, 7, 15, 54, 26, 0, 39, 33, 18, 64, 6, 87, 54, 26, 0, 39, 19, 18, 54, 26, 0, 128, 3, 115, 101, 102, 18, 17, 64, 2, 121, 54, 26, 0, 39, 34, 18, 64, 1, 245, 54, 26, 0, 128, 2, 102, 108, 18, 64, 0, 1, 0, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 33, 6, 39, 11, 101, 53, 34, 53, 33, 52, 34, 68, 52, 33, 37, 14, 68, 39, 11, 52, 33, 103, 33, 6, 39, 9, 101, 53, 36, 53, 35, 52, 36, 68, 52, 35, 37, 14, 68, 39, 9, 52, 35, 103, 54, 26, 2, 23, 39, 11, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 34, 8, 53, 22, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 35, 18, 68, 54, 26, 1, 23, 42, 100, 18, 54, 26, 1, 23, 39, 4, 100, 18, 17, 68, 54, 26, 2, 23, 35, 13, 68, 54, 26, 1, 23, 42, 100, 18, 64, 1, 74, 54, 26, 2, 23, 41, 100, 39, 9, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 14, 68, 54, 26, 1, 23, 34, 18, 64, 0, 255, 50, 4, 34, 9, 56, 16, 33, 7, 18, 68, 50, 4, 34, 9, 56, 17, 54, 26, 1, 23, 18, 68, 50, 4, 34, 9, 56, 20, 50, 10, 18, 68, 50, 4, 34, 9, 56, 18, 35, 13, 68, 50, 4, 34, 9, 56, 18, 54, 26, 2, 23, 52, 22, 8, 18, 68, 54, 26, 1, 23, 42, 100, 18, 64, 0, 160, 39, 4, 100, 54, 26, 2, 23, 136, 11, 39, 54, 26, 1, 23, 42, 100, 18, 64, 0, 130, 41, 41, 100, 52, 22, 8, 103, 52, 22, 39, 6, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 53, 23, 54, 26, 1, 23, 42, 100, 18, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 8, 39, 8, 100, 52, 23, 8, 103, 39, 15, 39, 15, 100, 52, 22, 52, 23, 9, 136, 10, 168, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 10, 132, 40, 40, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 22, 52, 23, 9, 136, 10, 104, 103, 66, 255, 189, 40, 40, 100, 52, 22, 8, 103, 66, 255, 123, 42, 100, 34, 18, 64, 0, 12, 42, 100, 54, 26, 2, 23, 136, 10, 129, 66, 255, 87, 54, 26, 2, 23, 136, 10, 145, 66, 255, 77, 50, 4, 34, 9, 56, 16, 34, 18, 68, 50, 4, 34, 9, 56, 7, 50, 10, 18, 68, 50, 4, 34, 9, 56, 8, 35, 13, 68, 50, 4, 34, 9, 56, 8, 54, 26, 2, 23, 52, 22, 8, 18, 68, 66, 255, 11, 54, 26, 2, 23, 40, 100, 39, 9, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 14, 68, 66, 254, 179, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 19, 18, 68, 49, 22, 34, 9, 59, 14, 35, 13, 64, 0, 4, 34, 66, 9, 181, 49, 22, 34, 9, 59, 8, 64, 0, 15, 39, 4, 100, 49, 22, 34, 9, 59, 14, 136, 9, 216, 66, 255, 228, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 14, 136, 9, 195, 66, 255, 207, 49, 22, 34, 9, 59, 14, 136, 9, 209, 66, 255, 195, 50, 7, 39, 18, 100, 9, 53, 24, 39, 18, 50, 7, 103, 33, 8, 43, 100, 10, 52, 24, 13, 64, 3, 162, 33, 8, 43, 100, 10, 52, 24, 13, 64, 3, 134, 33, 6, 39, 6, 101, 53, 30, 53, 26, 52, 30, 68, 52, 26, 37, 14, 68, 39, 6, 52, 26, 103, 49, 22, 34, 9, 56, 16, 34, 18, 64, 3, 54, 49, 22, 34, 9, 56, 17, 42, 100, 18, 49, 22, 34, 9, 56, 17, 39, 4, 100, 18, 17, 68, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 49, 22, 34, 9, 56, 17, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 9, 49, 22, 34, 9, 56, 17, 42, 100, 18, 64, 2, 222, 35, 53, 8, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 54, 26, 0, 39, 19, 18, 64, 2, 156, 54, 26, 0, 39, 19, 18, 64, 1, 117, 52, 9, 39, 26, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 34, 8, 53, 3, 52, 9, 52, 3, 9, 53, 10, 52, 10, 35, 13, 68, 52, 8, 64, 0, 240, 40, 100, 52, 10, 29, 35, 41, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 2, 9, 103, 41, 41, 100, 52, 9, 8, 103, 42, 100, 34, 18, 64, 0, 192, 42, 100, 52, 2, 136, 8, 170, 52, 2, 37, 13, 52, 10, 37, 13, 16, 64, 0, 138, 52, 2, 52, 10, 136, 8, 206, 52, 2, 35, 13, 68, 52, 2, 54, 26, 1, 23, 15, 68, 52, 3, 39, 6, 100, 29, 35, 37, 31, 72, 72, 76, 20, 68, 53, 23, 52, 8, 64, 0, 64, 41, 41, 100, 52, 23, 9, 103, 39, 8, 39, 8, 100, 52, 23, 8, 103, 39, 15, 39, 15, 100, 52, 3, 52, 23, 9, 136, 8, 33, 103, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 7, 253, 40, 40, 100, 52, 23, 9, 103, 39, 7, 39, 7, 100, 52, 23, 8, 103, 39, 14, 39, 14, 100, 52, 3, 52, 23, 9, 136, 7, 225, 103, 66, 255, 189, 43, 52, 2, 33, 5, 29, 35, 52, 10, 31, 72, 72, 76, 20, 68, 103, 43, 52, 10, 33, 5, 29, 35, 52, 2, 31, 72, 72, 76, 20, 68, 103, 66, 255, 83, 52, 2, 136, 8, 6, 66, 255, 63, 41, 100, 52, 10, 29, 35, 40, 100, 52, 10, 8, 31, 72, 72, 76, 20, 68, 53, 2, 40, 40, 100, 52, 9, 8, 103, 41, 41, 100, 52, 2, 9, 103, 39, 4, 100, 52, 2, 136, 7, 192, 52, 10, 37, 13, 52, 2, 37, 13, 16, 64, 0, 10, 52, 10, 52, 2, 136, 7, 228, 66, 255, 19, 43, 52, 10, 33, 5, 29, 35, 52, 2, 31, 72, 72, 76, 20, 68, 103, 43, 52, 2, 33, 5, 29, 35, 52, 10, 31, 72, 72, 76, 20, 68, 103, 66, 255, 211, 54, 26, 1, 23, 53, 11, 52, 11, 35, 13, 68, 52, 8, 64, 0, 246, 41, 100, 52, 11, 29, 35, 40, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 52, 12, 35, 13, 68, 52, 12, 37, 29, 35, 37, 39, 26, 100, 9, 31, 72, 72, 76, 20, 68, 34, 8, 52, 12, 9, 53, 3, 52, 12, 52, 3, 8, 53, 13, 52, 9, 52, 13, 15, 68, 52, 8, 64, 0, 100, 40, 40, 100, 52, 11, 9, 103, 41, 41, 100, 52, 13, 8, 103, 42, 100, 34, 18, 64, 0, 71, 42, 100, 52, 11, 136, 7, 24, 52, 11, 37, 13, 52, 12, 37, 13, 16, 64, 0, 17, 52, 11, 52, 12, 136, 7, 60, 52, 9, 52, 13, 9, 53, 14, 66, 254, 113, 43, 52, 11, 33, 5, 29, 35, 52, 12, 31, 72, 72, 76, 20, 68, 103, 43, 52, 12, 33, 5, 29, 35, 52, 11, 31, 72, 72, 76, 20, 68, 103, 66, 255, 204, 52, 11, 136, 6, 237, 66, 255, 184, 40, 40, 100, 52, 13, 8, 103, 41, 41, 100, 52, 11, 9, 103, 39, 4, 100, 52, 11, 136, 6, 186, 52, 12, 37, 13, 52, 11, 37, 13, 16, 64, 0, 10, 52, 12, 52, 11, 136, 6, 222, 66, 255, 159, 43, 52, 12, 33, 5, 29, 35, 52, 11, 31, 72, 72, 76, 20, 68, 103, 43, 52, 11, 33, 5, 29, 35, 52, 12, 31, 72, 72, 76, 20, 68, 103, 66, 255, 211, 40, 100, 52, 11, 29, 35, 41, 100, 52, 11, 9, 31, 72, 72, 76, 20, 68, 34, 8, 53, 12, 66, 255, 7, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 34, 18, 68, 66, 253, 57, 34, 66, 253, 31, 42, 100, 34, 18, 68, 49, 22, 34, 9, 56, 16, 34, 18, 68, 49, 22, 34, 9, 56, 7, 50, 10, 18, 68, 49, 22, 34, 9, 56, 8, 35, 13, 68, 49, 22, 34, 9, 56, 8, 53, 9, 34, 53, 8, 66, 252, 242, 39, 21, 39, 21, 100, 43, 100, 52, 24, 11, 136, 5, 199, 103, 66, 252, 105, 39, 20, 39, 20, 100, 43, 100, 52, 24, 11, 136, 5, 182, 103, 66, 252, 77, 49, 22, 36, 9, 56, 16, 33, 7, 18, 68, 49, 22, 36, 9, 56, 17, 39, 17, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 32, 18, 68, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 18, 39, 5, 100, 18, 64, 0, 64, 49, 22, 36, 9, 56, 18, 41, 100, 29, 35, 39, 5, 100, 31, 72, 72, 76, 20, 68, 53, 7, 52, 7, 35, 13, 68, 52, 7, 41, 100, 14, 68, 41, 41, 100, 52, 7, 9, 103, 39, 5, 39, 5, 100, 49, 22, 36, 9, 56, 18, 9, 103, 39, 4, 100, 52, 7, 136, 5, 69, 34, 66, 5, 9, 41, 100, 53, 7, 66, 255, 206, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 39, 17, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 33, 18, 68, 49, 22, 34, 9, 56, 18, 39, 5, 100, 18, 64, 0, 65, 49, 22, 34, 9, 56, 18, 40, 100, 29, 35, 39, 5, 100, 31, 72, 72, 76, 20, 68, 53, 6, 52, 6, 35, 13, 68, 52, 6, 40, 100, 14, 68, 40, 40, 100, 52, 6, 9, 103, 42, 100, 34, 18, 64, 0, 11, 42, 100, 52, 6, 136, 4, 157, 34, 66, 4, 97, 52, 6, 136, 4, 174, 66, 255, 244, 40, 100, 53, 6, 66, 255, 205, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 25, 35, 18, 68, 49, 22, 36, 9, 56, 16, 33, 4, 18, 68, 49, 22, 36, 9, 56, 24, 50, 8, 18, 68, 49, 22, 36, 9, 57, 26, 0, 39, 27, 18, 68, 49, 22, 36, 9, 59, 20, 35, 13, 64, 0, 4, 34, 66, 4, 16, 35, 64, 0, 15, 39, 4, 100, 49, 22, 36, 9, 59, 20, 136, 4, 56, 66, 255, 233, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 36, 9, 59, 20, 136, 4, 35, 66, 255, 212, 49, 22, 36, 9, 59, 20, 136, 4, 49, 66, 255, 200, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 25, 35, 18, 68, 49, 22, 34, 9, 56, 16, 33, 4, 18, 68, 49, 22, 34, 9, 56, 24, 50, 8, 18, 68, 49, 22, 34, 9, 57, 26, 0, 39, 27, 18, 68, 49, 22, 34, 9, 59, 19, 35, 13, 64, 0, 4, 34, 66, 3, 154, 34, 64, 0, 15, 39, 4, 100, 49, 22, 34, 9, 59, 19, 136, 3, 194, 66, 255, 233, 42, 100, 34, 18, 64, 0, 14, 42, 100, 49, 22, 34, 9, 59, 19, 136, 3, 173, 66, 255, 212, 49, 22, 34, 9, 59, 19, 136, 3, 187, 66, 255, 200, 42, 100, 34, 18, 64, 2, 56, 49, 22, 36, 9, 56, 16, 33, 7, 18, 68, 49, 22, 36, 9, 56, 17, 42, 100, 18, 68, 49, 22, 36, 9, 56, 20, 50, 10, 18, 68, 49, 22, 36, 9, 56, 18, 35, 13, 68, 49, 22, 36, 9, 56, 18, 53, 4, 49, 22, 34, 9, 56, 16, 33, 7, 18, 68, 49, 22, 34, 9, 56, 17, 39, 4, 100, 18, 68, 49, 22, 34, 9, 56, 20, 50, 10, 18, 68, 49, 22, 34, 9, 56, 18, 35, 13, 68, 49, 22, 34, 9, 56, 18, 53, 5, 49, 25, 35, 18, 68, 49, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 25, 35, 18, 68, 49, 22, 34, 8, 56, 16, 33, 4, 18, 68, 49, 22, 34, 8, 56, 24, 50, 8, 18, 68, 49, 22, 34, 8, 57, 26, 0, 39, 30, 18, 68, 49, 22, 36, 8, 56, 25, 35, 18, 68, 49, 22, 36, 8, 56, 16, 33, 4, 18, 68, 49, 22, 36, 8, 56, 24, 50, 8, 18, 68, 49, 22, 36, 8, 57, 26, 0, 39, 31, 18, 68, 40, 100, 41, 100, 8, 35, 18, 64, 1, 105, 40, 100, 33, 5, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 15, 52, 4, 33, 5, 29, 35, 52, 5, 31, 72, 72, 76, 20, 68, 53, 16, 52, 15, 37, 29, 35, 52, 16, 31, 72, 72, 76, 20, 68, 53, 21, 52, 21, 37, 54, 26, 1, 23, 9, 13, 52, 21, 37, 54, 26, 1, 23, 8, 12, 16, 68, 52, 16, 52, 15, 13, 64, 0, 251, 52, 16, 52, 15, 12, 64, 0, 208, 52, 16, 52, 15, 18, 64, 0, 1, 0, 52, 4, 53, 17, 52, 5, 53, 18, 35, 53, 19, 35, 53, 20, 40, 100, 41, 100, 8, 35, 18, 64, 0, 141, 52, 17, 39, 5, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 53, 28, 52, 18, 39, 5, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 53, 29, 52, 28, 52, 29, 13, 64, 0, 92, 52, 28, 53, 0, 52, 0, 35, 13, 68, 40, 100, 41, 100, 8, 35, 18, 64, 0, 65, 40, 40, 100, 52, 17, 8, 103, 41, 41, 100, 52, 18, 8, 103, 39, 5, 39, 5, 100, 52, 0, 8, 103, 39, 17, 100, 52, 0, 136, 2, 3, 40, 100, 33, 9, 15, 68, 41, 100, 33, 9, 15, 68, 40, 100, 41, 100, 10, 33, 5, 12, 68, 41, 100, 40, 100, 10, 33, 5, 12, 68, 34, 66, 1, 169, 39, 18, 50, 7, 103, 66, 255, 183, 52, 29, 53, 0, 66, 255, 161, 33, 8, 52, 17, 10, 52, 18, 13, 64, 0, 12, 52, 17, 146, 52, 18, 146, 11, 53, 0, 66, 255, 138, 52, 17, 52, 18, 11, 146, 53, 0, 66, 255, 127, 52, 4, 53, 17, 52, 4, 41, 100, 29, 35, 40, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 18, 35, 53, 19, 52, 5, 52, 18, 9, 53, 20, 66, 255, 36, 52, 5, 40, 100, 29, 35, 41, 100, 31, 72, 72, 76, 20, 68, 34, 8, 53, 17, 52, 5, 53, 18, 52, 4, 52, 17, 9, 53, 19, 35, 53, 20, 66, 255, 1, 52, 4, 53, 17, 52, 5, 53, 18, 66, 254, 246, 49, 22, 36, 9, 56, 16, 34, 18, 68, 49, 22, 36, 9, 56, 7, 50, 10, 18, 68, 49, 22, 36, 9, 56, 8, 35, 13, 68, 49, 22, 36, 9, 56, 8, 53, 4, 66, 253, 208, 49, 25, 33, 7, 18, 64, 0, 128, 54, 26, 0, 128, 3, 115, 99, 117, 18, 64, 0, 64, 54, 26, 0, 128, 2, 114, 114, 18, 64, 0, 1, 0, 49, 0, 39, 10, 100, 18, 68, 42, 100, 34, 18, 64, 0, 29, 42, 100, 39, 7, 100, 136, 1, 2, 39, 4, 100, 39, 8, 100, 136, 0, 249, 39, 7, 35, 103, 39, 8, 35, 103, 34, 66, 0, 181, 39, 7, 100, 136, 1, 1, 66, 255, 226, 49, 0, 39, 10, 100, 18, 68, 33, 6, 39, 13, 101, 53, 32, 53, 31, 52, 32, 64, 0, 23, 54, 26, 1, 23, 50, 7, 39, 13, 100, 8, 15, 68, 39, 12, 54, 26, 1, 23, 103, 34, 66, 0, 128, 39, 13, 52, 31, 103, 66, 255, 225, 49, 0, 39, 10, 100, 18, 68, 39, 12, 100, 35, 19, 68, 39, 12, 100, 50, 7, 14, 68, 39, 12, 35, 103, 34, 66, 0, 92, 35, 66, 0, 88, 35, 66, 0, 84, 35, 66, 0, 80, 49, 53, 33, 7, 15, 68, 49, 52, 129, 32, 15, 68, 33, 6, 39, 10, 101, 53, 25, 53, 1, 52, 25, 68, 39, 10, 52, 1, 103, 54, 26, 0, 23, 35, 19, 54, 26, 1, 23, 35, 19, 16, 68, 54, 26, 0, 23, 54, 26, 1, 23, 12, 68, 42, 54, 26, 0, 23, 103, 39, 4, 54, 26, 1, 23, 103, 128, 2, 118, 105, 54, 26, 2, 23, 103, 39, 16, 35, 103, 34, 67, 53, 38, 53, 37, 52, 38, 33, 8, 52, 37, 9, 13, 64, 0, 6, 52, 37, 52, 38, 8, 137, 52, 38, 33, 8, 52, 37, 9, 9, 34, 9, 137, 53, 39, 177, 33, 7, 178, 16, 52, 39, 178, 17, 35, 178, 18, 50, 10, 178, 20, 35, 178, 1, 179, 137, 53, 41, 53, 40, 177, 33, 7, 178, 16, 52, 40, 178, 17, 52, 41, 178, 18, 49, 0, 178, 20, 35, 178, 1, 179, 137, 53, 42, 50, 10, 96, 52, 42, 50, 1, 8, 15, 68, 177, 34, 178, 16, 52, 42, 178, 8, 49, 0, 178, 7, 35, 178, 1, 179, 137, 53, 48, 53, 47, 39, 22, 39, 22, 100, 52, 47, 136, 255, 132, 103, 39, 23, 39, 23, 100, 52, 48, 136, 255, 121, 103, 33, 8, 52, 48, 10, 43, 100, 13, 64, 0, 28, 33, 8, 52, 47, 10, 43, 100, 13, 65, 0, 34, 39, 25, 39, 25, 100, 52, 47, 43, 100, 11, 136, 255, 85, 103, 66, 0, 17, 39, 24, 39, 24, 100, 52, 48, 43, 100, 11, 136, 255, 68, 103, 66, 255, 211, 137]);
var TESTNET_CLEAR_STATE_PROGRAM = /*#__PURE__*/new Uint8Array([6, 129, 1, 67]);

// IMPORTS

var PoolType;

(function (PoolType) {
  PoolType[PoolType["LOW_FEE"] = 0] = "LOW_FEE";
  PoolType[PoolType["HIGH_FEE"] = 1] = "HIGH_FEE";
  PoolType[PoolType["NANO"] = 2] = "NANO";
  PoolType[PoolType["MOVING_RATIO_NANO"] = 3] = "MOVING_RATIO_NANO";
  PoolType[PoolType["LOW_FEE_LENDING"] = 4] = "LOW_FEE_LENDING";
})(PoolType || (PoolType = {})); // SWAP FEES


function getSwapFee(poolType) {
  if (poolType == PoolType.LOW_FEE || poolType == PoolType.LOW_FEE_LENDING) {
    return 0.0025;
  } else if (poolType == PoolType.HIGH_FEE) {
    return 0.0075;
  } else {
    return 0.001;
  }
} // VALIDATOR INDECIES

function getValidatorIndex(poolType) {
  if (poolType == PoolType.LOW_FEE || poolType == PoolType.LOW_FEE_LENDING) {
    return 0;
  } else if (poolType == PoolType.HIGH_FEE) {
    return 1;
  } else {
    throw new Error("bad pool type");
  }
} // APPROVAL PROGRAMS

function getPoolApprovalProgram(network, poolType) {
  if (poolType == PoolType.LOW_FEE) {
    return network == Network.MAINNET ? MAINNET_APPROVAL_PROGRAM_LOW_FEE_CONSTANT_PRODUCT : TESTNET_APPROVAL_PROGRAM_LOW_FEE_CONSTANT_PRODUCT;
  } else if (poolType == PoolType.HIGH_FEE) {
    return network == Network.MAINNET ? MAINNET_APPROVAL_PROGRAM_HIGH_FEE_CONSTANT_PRODUCT : TESTNET_APPROVAL_PROGRAM_HIGH_FEE_CONSTANT_PRODUCT;
  } else {
    throw new Error("bad pool type");
  }
} // CLEAR STATE PROGRAMS

function getPoolClearStateProgram(network) {
  return network == Network.MAINNET ? MAINNET_CLEAR_STATE_PROGRAM : TESTNET_CLEAR_STATE_PROGRAM;
} // STRING CONSTANTS

var POOL_STRINGS = {
  manager_app_id: "ma",
  asset1_id: "a1",
  asset2_id: "a2",
  lp_id: "l",
  asset1_reserve: "a1r",
  asset2_reserve: "a2r",
  balance_1: "b1",
  balance_2: "b2",
  lp_circulation: "lc",
  pool: "p",
  redeem_pool_asset1_residual: "rpa1r",
  redeem_pool_asset2_residual: "rpa2r",
  burn_asset1_out: "ba1o",
  burn_asset2_out: "ba2o",
  swap_exact_for: "sef",
  swap_for_exact: "sfe",
  redeem_swap_residual: "rsr",
  registered_pool_id: "p",
  initialize_pool: "ip",
  // nano
  initial_amplification_factor: "iaf",
  future_amplification_factor: "faf",
  initial_amplification_factor_time: "iat",
  future_amplification_factor_time: "fat",
  ramp_amplification_factor: "raf",
  // moving ration nano
  target_ratio_adjustment_start_time: "trast",
  target_ratio_adjustment_end_time: "traet",
  initial_target_asset1_to_asset2_ratio: "it1t2r",
  current_target_asset1_to_asset2_ratio: "ct1t2r",
  goal_target_asset1_to_asset2_ratio: "gt1t2r"
};

var _ManagerConfigs$1;

var ManagerConfig$1 = function ManagerConfig(appId) {
  this.appId = appId;
};
var ManagerConfigs$1 = (_ManagerConfigs$1 = {}, _ManagerConfigs$1[Network.MAINNET] = /*#__PURE__*/new ManagerConfig$1(605753404), _ManagerConfigs$1[Network.TESTNET] = /*#__PURE__*/new ManagerConfig$1(104225849), _ManagerConfigs$1);

// IMPORTS
// INTERFACE
var PoolConfig = function PoolConfig(appId, asset1Id, asset2Id, lpAssetId, poolType) {
  this.appId = appId;
  this.asset1Id = asset1Id;
  this.asset2Id = asset2Id;
  this.lpAssetId = lpAssetId;
  this.poolType = poolType;
};

// pool factory logic sig template and indexes
var POOL_FACTORY_LOGIC_SIG_TEMPLATE_1 = /*#__PURE__*/new Uint8Array([5, 32, 3]);
var POOL_FACTORY_LOGIC_SIG_TEMPLATE_2 = /*#__PURE__*/new Uint8Array([1, 34, 35, 12, 68, 49, 16, 129, 6, 18, 68, 49, 25, 36, 18, 68, 49, 24, 129]);
var POOL_FACTORY_LOGIC_SIG_TEMPLATE_3 = /*#__PURE__*/new Uint8Array([18, 68, 54, 26, 0, 23, 34, 18, 68, 54, 26, 1, 23, 35, 18, 68, 54, 26, 2, 23, 129]);
var POOL_FACTORY_LOGIC_SIG_TEMPLATE_4 = /*#__PURE__*/new Uint8Array([18, 68, 49, 32, 50, 3, 18, 68, 36, 67]);
/**
 * Function to concatinate uint8arrays
 *
 * @param   {Uint8Array[]}  arrays
 *
 * @returns {Uint8Array}
 */

function concatArrays$2(arrays) {
  // sum of individual array lengths
  var totalLength = arrays.reduce(function (acc, value) {
    return acc + value.length;
  }, 0);
  if (!arrays.length) return null;
  var result = new Uint8Array(totalLength); // for each array - copy it over result
  // next array is copied right after the previous one

  var length = 0;

  for (var _iterator = _createForOfIteratorHelperLoose(arrays), _step; !(_step = _iterator()).done;) {
    var array = _step.value;
    result.set(array, length);
    length += array.length;
  }

  return result;
}
/**
 * Function to generate approval program bytes from integer
 *
 * @param   {int} value
 *
 * @return  {Uint8Array} bytes to use in approval program
 */


function encodeInt(value) {
  var result = new Uint8Array(8);
  var idx = 0;

  while (true) {
    var next_byte = value & 127;
    value >>= 7;

    if (value) {
      result.set([next_byte | 128], idx);
    } else {
      result.set([next_byte], idx);
      break;
    }

    idx += 1;
  }

  return result.slice(0, idx + 1);
}
/**
 * Funtion to generate an algofi amm logic sig for a given set of inputs
 *
 * @param   {int}     manager_app_id
 * @param   {int}     asset1_id
 * @param   {int}     asset2_id
 * @param   {int}     validator_index
 *
 * @return  {string} logic sig for provided args
 */


function generateLogicSig(asset1_id, asset2_id, manager_app_id, validator_index) {
  var arrays = [POOL_FACTORY_LOGIC_SIG_TEMPLATE_1, encodeInt(asset1_id), encodeInt(asset2_id), POOL_FACTORY_LOGIC_SIG_TEMPLATE_2, encodeInt(manager_app_id), POOL_FACTORY_LOGIC_SIG_TEMPLATE_3, encodeInt(validator_index), POOL_FACTORY_LOGIC_SIG_TEMPLATE_4];
  return concatArrays$2(arrays);
}

var A_PRECISION = /*#__PURE__*/BigInt(1000000);
function getD(tokenAmounts, amplificationFactor) {
  var N_COINS = tokenAmounts.length;
  var S = BigInt(0);
  var Dprev = BigInt(0);

  for (var _i2 = 0, _Array$from = Array.from(tokenAmounts); _i2 < _Array$from.length; _i2++) {
    var _x = _Array$from[_i2];
    S += BigInt(_x);
  }

  if (S == BigInt(0)) {
    return [0, 0];
  }

  var D = S;
  var Ann = BigInt(amplificationFactor * Math.pow(N_COINS, N_COINS));

  for (var _i = 0; _i < 255; _i++) {
    var D_P = D;

    for (var _i3 = 0, _Array$from2 = Array.from(tokenAmounts); _i3 < _Array$from2.length; _i3++) {
      var _x = _Array$from2[_i3];
      D_P = D_P * D / (BigInt(_x) * BigInt(N_COINS));
    }

    Dprev = D;
    D = (Ann * S / A_PRECISION + D_P * BigInt(N_COINS)) * D / ((Ann - A_PRECISION) * D / A_PRECISION + BigInt(N_COINS + 1) * D_P);

    if (D > Dprev) {
      if (D - Dprev <= BigInt(1)) {
        return [Number(D), _i];
      }
    } else {
      if (Dprev - D <= BigInt(1)) {
        return [Number(D), _i];
      }
    }
  }
}
function getY(i, j, x, tokenAmounts, D, amplificationFactor) {
  var N_COINS = tokenAmounts.length;
  var Ann = BigInt(amplificationFactor * Math.pow(N_COINS, N_COINS));
  var c = BigInt(D);
  var S = BigInt(0);

  var _x = BigInt(0);

  var y_prev = BigInt(0);

  for (var _i = 0; _i < N_COINS; _i++) {
    if (_i == i) {
      _x = BigInt(x);
    } else if (_i != j) {
      _x = BigInt(tokenAmounts[_i]);
    } else {
      continue;
    }

    S += _x;
    c = c * BigInt(D) / (BigInt(_x) * BigInt(N_COINS));
  }

  c = c * BigInt(D) * A_PRECISION / (Ann * BigInt(N_COINS));
  var b = S + BigInt(D) * A_PRECISION / Ann;
  var y = BigInt(D);

  for (var _i = 0; _i < 255; _i++) {
    y_prev = y;
    y = (y * y + c) / (BigInt(2) * y + b - BigInt(D));

    if (y > y_prev) {
      if (y - y_prev <= BigInt(1)) {
        return [Number(y), _i];
      }
    } else {
      if (y_prev - y <= BigInt(1)) {
        return [Number(y), _i];
      }
    }
  }
}

var PoolQuoteType;

(function (PoolQuoteType) {
  PoolQuoteType[PoolQuoteType["EMPTY_POOL"] = 0] = "EMPTY_POOL";
  PoolQuoteType[PoolQuoteType["POOL"] = 1] = "POOL";
  PoolQuoteType[PoolQuoteType["BURN"] = 2] = "BURN";
  PoolQuoteType[PoolQuoteType["SWAP_EXACT_FOR"] = 3] = "SWAP_EXACT_FOR";
  PoolQuoteType[PoolQuoteType["SWAP_FOR_EXACT"] = 4] = "SWAP_FOR_EXACT";
  PoolQuoteType[PoolQuoteType["ZAP"] = 5] = "ZAP";
})(PoolQuoteType || (PoolQuoteType = {}));

var PoolQuote = function PoolQuote(quoteType, asset1Delta, asset2Delta, lpDelta, iterations, zapAsset1Swap, zapAsset2Swap, zapBonus) {
  if (zapAsset1Swap === void 0) {
    zapAsset1Swap = 0;
  }

  if (zapAsset2Swap === void 0) {
    zapAsset2Swap = 0;
  }

  if (zapBonus === void 0) {
    zapBonus = 0;
  }

  this.quoteType = quoteType;
  this.asset1Delta = asset1Delta;
  this.asset2Delta = asset2Delta;
  this.lpDelta = lpDelta;
  this.iterations = iterations;
  this.zapAsset1Swap = zapAsset1Swap;
  this.zapAsset2Swap = zapAsset2Swap;
  this.zapBonus = zapBonus;
}; // INTERFACE

var Pool = /*#__PURE__*/function () {
  function Pool(algod, ammClient, poolConfig, tvl, apr) {
    if (tvl === void 0) {
      tvl = 0;
    }

    if (apr === void 0) {
      apr = 0;
    }

    this.algod = algod;
    this.indexer = ammClient.algofiClient.indexer;
    this.ammClient = ammClient;
    this.assetDataClient = ammClient.algofiClient.assetData;
    this.appId = poolConfig.appId;
    this.asset1Id = poolConfig.asset1Id;
    this.asset2Id = poolConfig.asset2Id;
    this.poolType = poolConfig.poolType;
    this.tvl = tvl;
    this.apr = apr;
  }

  var _proto = Pool.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var managerAppId, logicSigStates, state;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              if (!(this.appId == 0)) {
                _context.next = 9;
                break;
              }

              managerAppId = this.ammClient.managerAppId;
              this.logicSig = new LogicSigAccount(generateLogicSig(this.asset1Id, this.asset2Id, managerAppId, getValidatorIndex(this.poolType)));
              logicSigStates = getLocalStates(this.algod, this.logicSig.address());

              if (!(managerAppId in logicSigStates)) {
                _context.next = 8;
                break;
              }

              this.appId = logicSigStates[managerAppId][POOL_STRINGS.registered_pool_id];
              _context.next = 9;
              break;

            case 8:
              return _context.abrupt("return");

            case 9:
              this.address = getApplicationAddress(this.appId);
              _context.next = 12;
              return getApplicationGlobalState(this.algod, this.appId);

            case 12:
              state = _context.sent;
              // parameters
              this.managerAppId = state[POOL_STRINGS.manager_app_id];
              this.lpAssetId = state[POOL_STRINGS.lp_id];
              this.balance1 = state[POOL_STRINGS.balance_1];
              this.balance2 = state[POOL_STRINGS.balance_2];
              this.lpCirculation = state[POOL_STRINGS.lp_circulation];

              if (this.poolType == PoolType.NANO || this.poolType == PoolType.MOVING_RATIO_NANO) {
                this.initialAmplificationFactor = state[POOL_STRINGS.initial_amplification_factor];
                this.futureAmplificationFactor = state[POOL_STRINGS.future_amplification_factor];
                this.initialAmplificationFactorTime = state[POOL_STRINGS.initial_amplification_factor_time];
                this.futureAmplificationFactorTime = state[POOL_STRINGS.future_amplification_factor_time];
                this.ramp_amplification_factor = state[POOL_STRINGS.ramp_amplification_factor];
              }

              if (this.poolType == PoolType.MOVING_RATIO_NANO) {
                this.targetRatioAdjustmentStartTime = state[POOL_STRINGS.target_ratio_adjustment_start_time];
                this.targetRatioAdjustmentEndTime = state[POOL_STRINGS.target_ratio_adjustment_end_time];
                this.initialTargetAsset1ToAsset2Ratio = state[POOL_STRINGS.initial_target_asset1_to_asset2_ratio];
                this.currentTargetAsset1ToAsset2Ratio = state[POOL_STRINGS.current_target_asset1_to_asset2_ratio];
                this.goalTargetAsset1ToAsset2Ratio = state[POOL_STRINGS.goal_target_asset1_to_asset2_ratio];
              }

              this.swapFee = getSwapFee(this.poolType); // special handling for STBL pools// TODO this is gross

              if (this.poolType == PoolType.LOW_FEE_LENDING && (this.asset1Id == 841157954 || this.asset2Id == 841157954)) {
                this.swapFee = 0.00125;
              }

            case 22:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // GETTERS
  ;

  _proto.getTVL = function getTVL() {
    return this.tvl;
  };

  _proto.getAPR = function getAPR() {
    return this.apr;
  } // HELPER FUNCTIONS
  ;

  _proto.isCreated = function isCreated() {
    return this.appId != 0;
  };

  _proto.getAmplificationFactor = function getAmplificationFactor() {
    var now = Math.floor(Date.now() / 1000);

    if (now < this.futureAmplificationFactorTime) {
      return Math.floor(this.initialAmplificationFactor + (this.futureAmplificationFactor - this.initialAmplificationFactor) * (now - this.initialAmplificationFactor) / (this.futureAmplificationFactorTime - this.initialAmplificationFactorTime));
    }

    return this.futureAmplificationFactor;
  };

  _proto.getTargetRatio = function getTargetRatio() {
    var now = Math.floor(Date.now() / 1000);

    if (now < this.targetRatioAdjustmentEndTime) {
      return this.initialTargetAsset1ToAsset2Ratio + (this.goalTargetAsset1ToAsset2Ratio - this.initialTargetAsset1ToAsset2Ratio) * (now - this.targetRatioAdjustmentStartTime) / (this.targetRatioAdjustmentEndTime - this.targetRatioAdjustmentStartTime);
    }

    return this.currentTargetAsset1ToAsset2Ratio;
  };

  _proto.isNanoPool = function isNanoPool() {
    return this.poolType == PoolType.NANO || this.poolType == PoolType.MOVING_RATIO_NANO;
  };

  _proto.scaleAsset1 = function scaleAsset1(input) {
    if (this.poolType == PoolType.MOVING_RATIO_NANO) {
      return Math.floor(input * this.getTargetRatio() / FIXED_12_SCALE_FACTOR);
    } else {
      return input;
    }
  };

  _proto.unscaleAsset1 = function unscaleAsset1(input) {
    if (this.poolType == PoolType.MOVING_RATIO_NANO) {
      return Math.floor(input * FIXED_12_SCALE_FACTOR / this.getTargetRatio());
    } else {
      return input;
    }
  };

  _proto.binarySearch = function binarySearch(lower, upper, objective) {
    if (lower > upper) return lower;
    var mid = Math.floor(lower + (upper - lower) / 2);
    var midVal = objective(mid);
    var upperVal = objective(upper);
    var lowerVal = objective(lower);

    if (midVal < 0) {
      return this.binarySearch(mid + 1, upper, objective);
    } else if (midVal > 0) {
      return this.binarySearch(lower, mid - 1, objective);
    } else {
      return mid;
    }
  } // QUOTE FUNCTIONS
  ;

  _proto.getEmptyPoolQuote = function getEmptyPoolQuote(asset1PooledAmount, asset2PooledAmount) {
    var lpsIssued = 0;
    var numIter = 0;

    if (this.isNanoPool()) {
      var _getD = getD([this.scaleAsset1(asset1PooledAmount), asset2PooledAmount], this.getAmplificationFactor());

      lpsIssued = _getD[0];
      numIter = _getD[1];
    } else if (asset1PooledAmount * asset2PooledAmount > Math.pow(2, 64) - 1) {
      lpsIssued = Math.sqrt(asset1PooledAmount) * Math.sqrt(asset2PooledAmount);
      numIter = 0;
    } else {
      var _ref = [Math.sqrt(asset1PooledAmount * asset2PooledAmount), 0];
      lpsIssued = _ref[0];
      numIter = _ref[1];
    }

    return new PoolQuote(PoolQuoteType.EMPTY_POOL, -1 * asset1PooledAmount, -1 * asset2PooledAmount, Number(lpsIssued), numIter);
  };

  _proto.getPoolQuote = function getPoolQuote(assetId, assetAmount) {
    if (this.lpCirculation === 0) {
      throw new Error("Error: pool is empty");
    }

    var asset1PooledAmount = 0;
    var asset2PooledAmount = 0;
    var lpsIssued = 0;
    var numIter = 0;

    if (assetId == this.asset1Id) {
      asset1PooledAmount = assetAmount;
      asset2PooledAmount = Math.ceil(asset1PooledAmount * this.balance2 / this.balance1);
    } else {
      asset2PooledAmount = assetAmount;
      asset1PooledAmount = Math.ceil(asset2PooledAmount * this.balance1 / this.balance2);
    }

    if (this.isNanoPool()) {
      var _getD2 = getD([this.scaleAsset1(this.balance1), this.balance2], this.getAmplificationFactor()),
          D0 = _getD2[0],
          numIterD0 = _getD2[1];

      var _getD3 = getD([this.scaleAsset1(asset1PooledAmount + this.balance1), asset2PooledAmount + this.balance2], this.getAmplificationFactor()),
          D1 = _getD3[0],
          numIterD1 = _getD3[1];

      lpsIssued = Math.floor(this.lpCirculation * Number((D1 - D0) / D0));
      numIter = numIterD0 + numIterD1;
    } else {
      lpsIssued = Math.floor(asset1PooledAmount * this.lpCirculation / this.balance1);
    }

    return new PoolQuote(PoolQuoteType.POOL, -1 * asset1PooledAmount, -1 * asset2PooledAmount, lpsIssued, numIter);
  } // burn quote
  ;

  _proto.getBurnQuote = function getBurnQuote(lpAmount) {
    if (this.lpCirculation === 0) {
      throw new Error("Error: pool is empty");
    }

    if (this.lpCirculation < lpAmount) {
      throw new Error("Error: cannot burn more lp tokens than are in circulation");
    }

    var asset1Amount = Math.floor(lpAmount * this.balance1 / this.lpCirculation);
    var asset2Amount = Math.floor(lpAmount * this.balance2 / this.lpCirculation);
    return new PoolQuote(PoolQuoteType.BURN, asset1Amount, asset2Amount, -1 * lpAmount, 0);
  } // swap_exact_for quote
  ;

  _proto.getSwapExactForQuote = function getSwapExactForQuote(swapInAssetId, swapInAmount) {
    if (this.lpCirculation === 0) {
      throw new Error("Error: pool is empty");
    }

    var swapInAmountLessFees = swapInAmount - (Math.floor(swapInAmount * this.swapFee) + 1);
    var swapOutAmount = 0;
    var numIter = 0;

    if (swapInAssetId === this.asset1Id) {
      if (this.isNanoPool()) {
        var _getD4 = getD([this.scaleAsset1(this.balance1), this.balance2], this.getAmplificationFactor()),
            D = _getD4[0],
            numIterD = _getD4[1];

        var _getY = getY(0, 1, this.scaleAsset1(this.balance1 + swapInAmountLessFees), [this.scaleAsset1(this.balance1), this.balance2], D, this.getAmplificationFactor()),
            y = _getY[0],
            numIterY = _getY[1];

        swapOutAmount = this.balance2 - Number(y) - 1;
        numIter = numIterD + numIterY;
      } else {
        swapOutAmount = Math.floor(this.balance2 * swapInAmountLessFees / (this.balance1 + swapInAmountLessFees));
      }

      return new PoolQuote(PoolQuoteType.SWAP_EXACT_FOR, -1 * swapInAmount, swapOutAmount, 0, numIter);
    } else {
      if (this.isNanoPool()) {
        var _getD5 = getD([this.scaleAsset1(this.balance1), this.balance2], this.getAmplificationFactor()),
            _D = _getD5[0],
            _numIterD = _getD5[1];

        var _getY2 = getY(1, 0, this.balance2 + swapInAmountLessFees, [this.scaleAsset1(this.balance1), this.balance2], _D, this.getAmplificationFactor()),
            _y = _getY2[0],
            _numIterY = _getY2[1];

        swapOutAmount = this.balance1 - this.unscaleAsset1(_y) - 1;
        numIter = _numIterD + _numIterY;
      } else {
        swapOutAmount = Math.floor(this.balance1 * swapInAmountLessFees / (this.balance2 + swapInAmountLessFees));
      }

      return new PoolQuote(PoolQuoteType.SWAP_EXACT_FOR, swapOutAmount, -1 * swapInAmount, 0, numIter);
    }
  };

  _proto.getSwapForExactQuote = function getSwapForExactQuote(swapOutAssetId, swapOutAmount) {
    if (this.lpCirculation === 0) {
      throw new Error("Error: pool is empty");
    }

    var swapInAmountLessFees = 0;
    var numIter = 0;

    if (swapOutAssetId === this.asset1Id) {
      if (this.isNanoPool()) {
        var _getD6 = getD([this.scaleAsset1(this.balance1), this.balance2], this.getAmplificationFactor()),
            D = _getD6[0],
            numIterD = _getD6[1];

        var _getY3 = getY(1, 0, this.scaleAsset1(this.balance1 - swapOutAmount), [this.scaleAsset1(this.balance1), this.balance2], D, this.getAmplificationFactor()),
            y = _getY3[0],
            numIterY = _getY3[1];

        swapInAmountLessFees = y - this.balance2 + 1;
        numIter = numIterD + numIterY;
      } else {
        swapInAmountLessFees = Math.floor(this.balance2 * swapOutAmount / (this.balance1 - swapOutAmount)) - 1;
      }
    } else {
      if (this.isNanoPool()) {
        var _getD7 = getD([this.scaleAsset1(this.balance1), this.balance2], this.getAmplificationFactor()),
            _D2 = _getD7[0],
            _numIterD2 = _getD7[1];

        var _getY4 = getY(0, 1, this.balance2 - swapOutAmount, [this.scaleAsset1(this.balance1), this.balance2], _D2, this.getAmplificationFactor()),
            _y2 = _getY4[0],
            _numIterY2 = _getY4[1];

        swapInAmountLessFees = this.unscaleAsset1(_y2) - this.balance1 + 1;
        numIter = _numIterD2 + _numIterY2;
      } else {
        swapInAmountLessFees = Math.floor(this.balance1 * swapOutAmount / (this.balance2 - swapOutAmount)) - 1;
      }
    }

    var swapInAmount = Math.ceil(swapInAmountLessFees / (1 - this.swapFee));

    if (swapOutAssetId === this.asset1Id) {
      return new PoolQuote(PoolQuoteType.SWAP_FOR_EXACT, swapOutAmount, -1 * swapInAmount, 0, numIter);
    } else {
      return new PoolQuote(PoolQuoteType.SWAP_FOR_EXACT, -1 * swapInAmount, swapOutAmount, 0, numIter);
    }
  };

  _proto.getZapQuote = function getZapQuote(assetAID, assetAAmount, assetBAmount) {
    if (assetBAmount === void 0) {
      assetBAmount = 0;
    }

    var asset1Amount = Math.floor((assetAID == this.asset1Id ? assetAAmount : assetBAmount) * 0.995);
    var asset2Amount = Math.floor((assetAID == this.asset1Id ? assetBAmount : assetAAmount) * 0.995);

    if (asset1Amount == 0 && asset2Amount == 0) {
      return new PoolQuote(PoolQuoteType.ZAP, 0, 0, 0, 0);
    }

    var asset1ImpliedLPTokens = Math.floor(asset1Amount * this.lpCirculation / this.balance1);
    var asset2ImpliedLPTokens = Math.floor(asset2Amount * this.lpCirculation / this.balance2); // calculate swap amounts

    if (asset1ImpliedLPTokens > asset2ImpliedLPTokens) {
      var objective = function (dy) {
        var dx = -1 * this.getSwapForExactQuote(this.asset2Id, dy).asset1Delta;
        return (asset2Amount + dy) / (this.balance2 - dy) - (asset1Amount - dx) / (this.balance1 + dx); // new ratio must equal new input ratio
      }.bind(this);

      var swapOutAmt = this.binarySearch(0, Math.min(Math.floor(asset1Amount * this.balance2 / this.balance1), this.balance2), objective);
      var swapQuote = this.getSwapForExactQuote(this.asset2Id, swapOutAmt);
      var swapInAmt = swapQuote.asset1Delta;
      var asset1PoolQuote = this.getPoolQuote(this.asset1Id, asset1Amount - -1 * swapInAmt - 10);
      var asset2PoolQuote = this.getPoolQuote(this.asset2Id, asset2Amount + swapOutAmt - 10);
      var poolQuote = asset1PoolQuote.lpDelta < asset2PoolQuote.lpDelta ? asset1PoolQuote : asset2PoolQuote;
      poolQuote.quoteType = PoolQuoteType.ZAP;
      poolQuote.zapAsset1Swap = swapInAmt;
      poolQuote.zapAsset2Swap = swapOutAmt;
      poolQuote.iterations += swapQuote.iterations;

      if (this.poolType === PoolType.NANO || this.poolType == PoolType.MOVING_RATIO_NANO) {
        var initialLPPrice = (this.balance1 + this.balance2) / this.lpCirculation;
        var actualLPPrice = (asset1Amount + asset2Amount) / poolQuote.lpDelta;
        poolQuote.zapBonus = (initialLPPrice - actualLPPrice) / initialLPPrice;
      }

      return poolQuote;
    } else {
      var _objective = function (dx) {
        var dy = -1 * this.getSwapForExactQuote(this.asset1Id, dx).asset2Delta;
        return (asset1Amount + dx) / (this.balance1 - dx) - (asset2Amount - dy) / (this.balance2 + dy); // new ratio must equal new input ratio
      }.bind(this);

      var _swapOutAmt = this.binarySearch(0, Math.min(Math.floor(asset2Amount * this.balance1 / this.balance2), this.balance1), _objective);

      var _swapQuote = this.getSwapForExactQuote(this.asset1Id, _swapOutAmt);

      var _swapInAmt = _swapQuote.asset2Delta;

      var _asset1PoolQuote = this.getPoolQuote(this.asset1Id, asset1Amount + _swapOutAmt - 10);

      var _asset2PoolQuote = this.getPoolQuote(this.asset2Id, asset2Amount - -1 * _swapInAmt - 10);

      var _poolQuote = _asset1PoolQuote.lpDelta < _asset2PoolQuote.lpDelta ? _asset1PoolQuote : _asset2PoolQuote;

      _poolQuote.quoteType = PoolQuoteType.ZAP;
      _poolQuote.zapAsset2Swap = _swapInAmt;
      _poolQuote.zapAsset1Swap = _swapOutAmt;
      _poolQuote.iterations += _swapQuote.iterations;

      if (this.poolType === PoolType.NANO || this.poolType == PoolType.MOVING_RATIO_NANO) {
        var _initialLPPrice = (this.balance1 + this.balance2) / this.lpCirculation;

        var _actualLPPrice = (asset1Amount + asset2Amount) / _poolQuote.lpDelta;

        _poolQuote.zapBonus = (_initialLPPrice - _actualLPPrice) / _initialLPPrice;
      }

      return _poolQuote;
    }
  } // TRANSACTION GETTERS
  ;

  _proto.getCreatePoolTxns =
  /*#__PURE__*/
  function () {
    var _getCreatePoolTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user) {
      var params, transactions, approvalProgram, clearStateProgram;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (!this.isCreated()) {
                _context2.next = 2;
                break;
              }

              throw new Error("Pool already active cannot generate create pool txn");

            case 2:
              if (!(this.poolType === PoolType.NANO || this.poolType == PoolType.MOVING_RATIO_NANO || this.poolType == PoolType.LOW_FEE_LENDING)) {
                _context2.next = 4;
                break;
              }

              throw new Error("Nanoswap or Lending pool cannot generate create pool txn");

            case 4:
              _context2.next = 6;
              return getParams(this.algod);

            case 6:
              params = _context2.sent;
              transactions = [];
              approvalProgram = getPoolApprovalProgram(this.ammClient.network, this.poolType);
              clearStateProgram = getPoolClearStateProgram(this.ammClient.network);
              transactions.push(algosdk.makeApplicationCreateTxnFromObject({
                from: user.address,
                suggestedParams: params,
                approvalProgram: approvalProgram,
                clearProgram: clearStateProgram,
                numLocalInts: 0,
                numLocalByteSlices: 0,
                numGlobalInts: 60,
                numGlobalByteSlices: 4,
                extraPages: 3,
                onComplete: algosdk.OnApplicationComplete.NoOpOC,
                appArgs: [encodeUint64(this.asset1Id), encodeUint64(this.asset2Id), encodeUint64(getValidatorIndex(this.poolType))],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: undefined,
                rekeyTo: undefined
              }));
              return _context2.abrupt("return", assignGroupID(transactions));

            case 12:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getCreatePoolTxns(_x) {
      return _getCreatePoolTxns.apply(this, arguments);
    }

    return getCreatePoolTxns;
  }();

  _proto.getInitializePoolTxns = /*#__PURE__*/function () {
    var _getInitializePoolTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user, poolAppId) {
      var params, transactions;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              if (!this.isCreated()) {
                _context3.next = 2;
                break;
              }

              throw new Error("Pool already active cannot generate initialize pool txn");

            case 2:
              _context3.next = 4;
              return getParams(this.algod);

            case 4:
              params = _context3.sent;
              transactions = []; // fund manager

              transactions.push(getPaymentTxn(params, user.address, getApplicationAddress(this.managerAppId), ALGO_ASSET_ID, 400000)); // fund logic sig

              transactions.push(getPaymentTxn(params, user.address, this.logicSig.address(), ALGO_ASSET_ID, 450000)); // opt logic sig into manager

              params.fee = 2000;
              transactions.push(algosdk.makeApplicationOptInTxnFromObject({
                from: this.logicSig.address(),
                appIndex: this.managerAppId,
                suggestedParams: params,
                appArgs: [encodeUint64(this.asset1Id), encodeUint64(this.asset2Id), encodeUint64(getValidatorIndex(this.poolType))],
                accounts: [getApplicationAddress(poolAppId)],
                foreignApps: [poolAppId],
                foreignAssets: undefined,
                rekeyTo: undefined
              })); // initialize pool

              params.fee = 4000;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: poolAppId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.initialize_pool)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: this.asset1Id === 1 ? [this.asset2Id] : [this.asset1Id, this.asset2Id],
                rekeyTo: undefined
              }));
              return _context3.abrupt("return", assignGroupID(transactions));

            case 13:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getInitializePoolTxns(_x2, _x3) {
      return _getInitializePoolTxns.apply(this, arguments);
    }

    return getInitializePoolTxns;
  }();

  _proto.getPoolTxns = /*#__PURE__*/function () {
    var _getPoolTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, quote, maximumSlippage, addToUserCollateral) {
      var params, transactions;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:

              _context4.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context4.sent;
              transactions = [];

              if (!user.isOptedInToAsset(this.lpAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.lpAssetId, 0));
              }

              transactions.push(getPaymentTxn(params, user.address, this.address, this.asset1Id, -1 * quote.asset1Delta));
              transactions.push(getPaymentTxn(params, user.address, this.address, this.asset2Id, -1 * quote.asset2Delta));
              params.fee = 3000 + 1000 * quote.iterations;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.pool), encodeUint64(maximumSlippage)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: [this.lpAssetId],
                rekeyTo: undefined
              }));
              params.fee = 1000;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.redeem_pool_asset1_residual)],
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: [this.asset1Id],
                rekeyTo: undefined
              }));
              params.fee = 1000;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.redeem_pool_asset2_residual)],
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: [this.asset2Id],
                rekeyTo: undefined
              }));
              return _context4.abrupt("return", assignGroupID(transactions));

            case 15:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getPoolTxns(_x4, _x5, _x6, _x7) {
      return _getPoolTxns.apply(this, arguments);
    }

    return getPoolTxns;
  }();

  _proto.getBurnTxns = /*#__PURE__*/function () {
    var _getBurnTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, quote) {
      var params, transactions;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              _context5.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context5.sent;
              transactions = [];

              if (!user.isOptedInToAsset(this.asset1Id)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.asset1Id, 0));
              }

              if (!user.isOptedInToAsset(this.asset2Id)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.asset2Id, 0));
              }

              transactions.push(getPaymentTxn(params, user.address, this.address, this.lpAssetId, -1 * quote.lpDelta));
              params.fee = 2000 + 1000 * quote.iterations;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.burn_asset1_out)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: [this.asset1Id],
                rekeyTo: undefined
              }));
              params.fee = 2000;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.burn_asset2_out)],
                accounts: undefined,
                foreignApps: undefined,
                foreignAssets: [this.asset2Id],
                rekeyTo: undefined
              }));
              return _context5.abrupt("return", assignGroupID(transactions));

            case 12:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getBurnTxns(_x8, _x9) {
      return _getBurnTxns.apply(this, arguments);
    }

    return getBurnTxns;
  }();

  _proto.getSwapTxns = /*#__PURE__*/function () {
    var _getSwapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user, quote, maxSlippage) {
      var params, transactions, inputIsAsset1, inputAmount, inputAssetId, outputAssetId, minOutputAmount;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              if (maxSlippage === void 0) {
                maxSlippage = 0.005;
              }

              _context6.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context6.sent;
              transactions = [];
              inputIsAsset1 = quote.asset1Delta < 0;
              inputAmount = inputIsAsset1 ? quote.asset1Delta : quote.asset2Delta;
              inputAssetId = inputIsAsset1 ? this.asset1Id : this.asset2Id;
              outputAssetId = inputIsAsset1 ? this.asset2Id : this.asset1Id;
              minOutputAmount = inputIsAsset1 ? quote.asset2Delta : quote.asset1Delta;

              if (quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR) {
                minOutputAmount = Math.floor(minOutputAmount * (1 - maxSlippage));
              } else {
                inputAmount = Math.ceil(inputAmount * (1 + maxSlippage));
              }

              if (!user.isOptedInToAsset(outputAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, outputAssetId, 0));
              }

              transactions.push(getPaymentTxn(params, user.address, this.address, inputAssetId, -1 * inputAmount));
              params.fee = 2000 + 1000 * quote.iterations;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR ? TEXT_ENCODER.encode(POOL_STRINGS.swap_exact_for) : TEXT_ENCODER.encode(POOL_STRINGS.swap_for_exact), encodeUint64(minOutputAmount)],
                accounts: undefined,
                foreignApps: [this.managerAppId],
                foreignAssets: [outputAssetId],
                rekeyTo: undefined
              }));

              if (quote.quoteType == PoolQuoteType.SWAP_FOR_EXACT) {
                params.fee = 2000;
                transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                  from: user.address,
                  appIndex: this.appId,
                  suggestedParams: params,
                  appArgs: [TEXT_ENCODER.encode(POOL_STRINGS.redeem_swap_residual)],
                  accounts: undefined,
                  foreignApps: undefined,
                  foreignAssets: [inputAssetId],
                  rekeyTo: undefined
                }));
              }

              return _context6.abrupt("return", assignGroupID(transactions));

            case 17:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getSwapTxns(_x10, _x11, _x12) {
      return _getSwapTxns.apply(this, arguments);
    }

    return getSwapTxns;
  }();

  _proto.getZapTxns = /*#__PURE__*/function () {
    var _getZapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(user, quote, maxSlippage, addToUserCollateral) {
      var swapQuote, swapTxns, poolQuote, poolMaxSlippage, poolTxns;
      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              if (maxSlippage === void 0) {
                maxSlippage = 0.005;
              }

              if (addToUserCollateral === void 0) {
                addToUserCollateral = false;
              }

              swapQuote = new PoolQuote(PoolQuoteType.SWAP_FOR_EXACT, quote.zapAsset1Swap, quote.zapAsset2Swap, 0, Math.ceil(quote.iterations / 2));
              _context7.next = 5;
              return this.getSwapTxns(user, swapQuote, maxSlippage);

            case 5:
              swapTxns = _context7.sent;
              poolQuote = new PoolQuote(PoolQuoteType.POOL, quote.asset1Delta, quote.asset2Delta, quote.lpDelta, Math.floor(quote.iterations / 2));
              poolMaxSlippage = Math.floor(1000000 * maxSlippage);
              _context7.next = 10;
              return this.getPoolTxns(user, poolQuote, poolMaxSlippage, addToUserCollateral);

            case 10:
              poolTxns = _context7.sent;
              return _context7.abrupt("return", composeTransactions([swapTxns, poolTxns]));

            case 12:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getZapTxns(_x13, _x14, _x15, _x16) {
      return _getZapTxns.apply(this, arguments);
    }

    return getZapTxns;
  }() // TXN HISTORY
  ;

  _proto.getTransactionHistory =
  /*#__PURE__*/
  function () {
    var _getTransactionHistory = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(mode) {
      var accountTxns, txnIdx, txn;
      return _regeneratorRuntime().wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              accountTxns = {};

              if (mode == TxnLoadMode.REFRESH) {
                // clear transactions
                this.transactions = [];
              }

              if (!(mode == TxnLoadMode.REVERSE && this.transactions.length > 0)) {
                _context8.next = 9;
                break;
              }

              _context8.next = 6;
              return this.indexer.searchForTransactions().address(this.address).maxRound(this.transactions.slice(-1)[0].block).limit(500)["do"]();

            case 6:
              accountTxns = _context8.sent;
              _context8.next = 12;
              break;

            case 9:
              _context8.next = 11;
              return this.indexer.searchForTransactions().address(this.address).limit(500)["do"]();

            case 11:
              accountTxns = _context8.sent;

            case 12:
              for (txnIdx = 0; txnIdx < accountTxns["transactions"].length; txnIdx++) {
                txn = accountTxns["transactions"][txnIdx];

                if (txn["tx-type"] == "appl") {
                  if (this.ammClient.isAMMTransaction(txn)) {
                    this.ammClient.parseTransaction(accountTxns["transactions"], txnIdx, this.transactions);
                  }
                }
              }

            case 13:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8, this);
    }));

    function getTransactionHistory(_x17) {
      return _getTransactionHistory.apply(this, arguments);
    }

    return getTransactionHistory;
  }();

  return Pool;
}();

var LINEAR_SWAP_LOGIC_SIG = /*#__PURE__*/new Uint8Array([6, 32, 5, 1, 0, 4, 240, 214, 134, 15, 203, 148, 146, 222, 1, 35, 56, 0, 128, 32, 77, 24, 114, 157, 193, 118, 18, 150, 182, 193, 27, 233, 232, 217, 123, 152, 46, 141, 228, 36, 93, 37, 113, 111, 45, 242, 225, 182, 55, 176, 180, 25, 18, 65, 0, 2, 34, 67, 50, 4, 129, 2, 18, 129, 17, 16, 68, 49, 22, 34, 18, 129, 18, 16, 68, 49, 1, 35, 18, 129, 20, 16, 68, 49, 16, 36, 18, 129, 22, 16, 68, 49, 32, 50, 3, 18, 129, 23, 16, 68, 49, 21, 50, 3, 18, 129, 24, 16, 68, 49, 22, 34, 9, 56, 16, 36, 18, 129, 26, 16, 68, 49, 22, 34, 9, 56, 20, 49, 0, 18, 129, 27, 16, 68, 49, 22, 34, 9, 56, 18, 49, 18, 18, 129, 29, 16, 68, 49, 17, 37, 18, 49, 22, 34, 9, 56, 17, 33, 4, 18, 16, 49, 17, 33, 4, 18, 49, 22, 34, 9, 56, 17, 37, 18, 16, 17, 129, 31, 16, 68, 34, 67]);
var USDC_ASSET_ID = 31566704;
var STBL_ASSET_ID = 465865291; // INTERFACE

var LinearPool = /*#__PURE__*/function () {
  function LinearPool(algod) {
    this.algod = algod;
    this.logicSig = new LogicSigAccount(LINEAR_SWAP_LOGIC_SIG);
  }

  var _proto = LinearPool.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var balances;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return getAccountBalances(this.algod, this.logicSig.address());

            case 2:
              balances = _context.sent;
              this.usdcBalance = balances[USDC_ASSET_ID];
              this.stblBalace = balances[STBL_ASSET_ID];

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // TRANSACTION GETTERS
  ;

  _proto.getSwapTxns =
  /*#__PURE__*/
  function () {
    var _getSwapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user, inputAssetId, amount) {
      var params, transactions, outputAssetId;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context2.sent;
              transactions = [];
              outputAssetId = inputAssetId == USDC_ASSET_ID ? STBL_ASSET_ID : USDC_ASSET_ID;
              params.fee = 2000;
              transactions.push(getPaymentTxn(params, user.address, this.logicSig.address(), inputAssetId, amount));
              params.fee = 0;
              transactions.push(getPaymentTxn(params, this.logicSig.address(), user.address, outputAssetId, amount));
              return _context2.abrupt("return", assignGroupID(transactions));

            case 10:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getSwapTxns(_x, _x2, _x3) {
      return _getSwapTxns.apply(this, arguments);
    }

    return getSwapTxns;
  }();

  return LinearPool;
}();

var AMMClient = /*#__PURE__*/function () {
  function AMMClient(algofiClient) {
    this.pools = {}; // appId -> pool

    this.assetPoolMap = {}; // asset -> pools

    this.poolMap = {}; // asset1, asset2, type -> pool

    this.lpPoolMap = {}; // lp asset id -> pool

    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.network = this.algofiClient.network;
    this.managerAppId = ManagerConfigs$1[this.network].appId; // special linear pool for usdc/stbl

    this.linearPool = new LinearPool(this.algod);
  }

  var _proto = AMMClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.linearPool.loadState();

            case 2:
              _context.next = 4;
              return request.get(getAnalyticsEndpoint(this.network) + "/pools?network=" + getNetworkName(this.network)).then(function (resp) {
                if (resp.status == 200) {
                  for (var _iterator = _createForOfIteratorHelperLoose(resp.body), _step; !(_step = _iterator()).done;) {
                    var poolInfo = _step.value;

                    if (!(poolInfo.appId in _this.pools)) {
                      var config = new PoolConfig(poolInfo.app_id, poolInfo.asset1_id, poolInfo.asset2_id, poolInfo.lp_asset_id, PoolType[poolInfo.type]); // pools

                      _this.pools[config.appId] = new Pool(_this.algod, _this, config, poolInfo.tvl, poolInfo.apr_data.week); // assetPoolMap

                      if (!(config.asset1Id in _this.assetPoolMap)) {
                        _this.assetPoolMap[config.asset1Id] = [];
                      }

                      if (!(config.asset2Id in _this.assetPoolMap)) {
                        _this.assetPoolMap[config.asset2Id] = [];
                      }

                      _this.assetPoolMap[config.asset1Id].push(_this.pools[config.appId]);

                      _this.assetPoolMap[config.asset2Id].push(_this.pools[config.appId]); // poolMap


                      if (!(config.asset1Id in _this.poolMap)) {
                        _this.poolMap[config.asset1Id] = {};
                      }

                      if (!(config.asset2Id in _this.poolMap[config.asset1Id])) {
                        _this.poolMap[config.asset1Id][config.asset2Id] = {};
                      }

                      _this.poolMap[config.asset1Id][config.asset2Id][config.poolType] = _this.pools[config.appId]; // lpPoolMap

                      _this.lpPoolMap[config.lpAssetId] = _this.pools[config.appId];
                    }
                  }
                } else {
                  console.log("Bad Response");
                }
              })["catch"](function (err) {
                console.log(err.message);
              });

            case 4:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getPool = /*#__PURE__*/function () {
    var _getPool = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(assetAId, assetBId, poolType) {
      var _this$poolMap, _this$poolMap$asset1I, _this$poolMap$asset1I2;

      var asset1Id, asset2Id, pool;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (!(assetAId == assetBId)) {
                _context2.next = 2;
                break;
              }

              throw new Error("Asset IDs must differ");

            case 2:
              // normalize asset order
              asset1Id = assetAId < assetBId ? assetAId : assetBId;
              asset2Id = assetAId < assetBId ? assetBId : assetAId;

              if (!((_this$poolMap = this.poolMap) != null && (_this$poolMap$asset1I = _this$poolMap[asset1Id]) != null && (_this$poolMap$asset1I2 = _this$poolMap$asset1I[asset2Id]) != null && _this$poolMap$asset1I2[poolType])) {
                _context2.next = 8;
                break;
              }

              _context2.next = 7;
              return this.poolMap[asset1Id][asset2Id][poolType].loadState();

            case 7:
              return _context2.abrupt("return", this.poolMap[asset1Id][asset2Id][poolType]);

            case 8:
              if (!(poolType == PoolType.NANO || poolType == PoolType.MOVING_RATIO_NANO)) {
                _context2.next = 10;
                break;
              }

              throw new Error("pool not found");

            case 10:
              pool = new Pool(this.algod, this, new PoolConfig(0, asset1Id, asset2Id, 0, poolType));
              _context2.next = 13;
              return pool.loadState();

            case 13:
              return _context2.abrupt("return", pool);

            case 14:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getPool(_x, _x2, _x3) {
      return _getPool.apply(this, arguments);
    }

    return getPool;
  }();

  _proto.hasPoolForLPAsset = function hasPoolForLPAsset(lpAssetId) {
    return lpAssetId in this.lpPoolMap;
  };

  _proto.getPoolByLPAsset = /*#__PURE__*/function () {
    var _getPoolByLPAsset = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(lpAssetId) {
      var pool;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              if (lpAssetId in this.lpPoolMap) {
                _context3.next = 2;
                break;
              }

              throw new Error("Pool not found");

            case 2:
              pool = this.lpPoolMap[lpAssetId];
              _context3.next = 5;
              return pool.loadState();

            case 5:
              return _context3.abrupt("return", pool);

            case 6:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getPoolByLPAsset(_x4) {
      return _getPoolByLPAsset.apply(this, arguments);
    }

    return getPoolByLPAsset;
  }();

  _proto.hasPoolsForAsset = function hasPoolsForAsset(assetId) {
    return assetId in this.assetPoolMap;
  };

  _proto.getPoolsByAsset = function getPoolsByAsset(assetId) {
    if (!(assetId in this.assetPoolMap)) {
      return [];
    }

    return this.assetPoolMap[assetId];
  };

  _proto.hasPoolForAppId = function hasPoolForAppId(appId) {
    return appId in this.pools;
  };

  _proto.getPoolByAppId = /*#__PURE__*/function () {
    var _getPoolByAppId = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(appId) {
      var pool;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              if (appId in this.pools) {
                _context4.next = 2;
                break;
              }

              throw new Error("Pool not found");

            case 2:
              pool = this.pools[appId];
              _context4.next = 5;
              return pool.loadState();

            case 5:
              return _context4.abrupt("return", pool);

            case 6:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getPoolByAppId(_x5) {
      return _getPoolByAppId.apply(this, arguments);
    }

    return getPoolByAppId;
  }();

  _proto.isAMMTransaction = function isAMMTransaction(txn) {
    var appId = txn['application-transaction']['application-id'];
    return appId in this.pools || appId == this.algofiClient.interfaces.lendingPools;
  };

  _proto.parseTransaction = function parseTransaction(txns, txnIdx, parsedTransactions) {
    var twoPreviousTxn = txns[txnIdx + 2];
    var previousTxn = txns[txnIdx + 1];
    var txn = txns[txnIdx];
    var subsequentTxn = txns[txnIdx - 1];
    var twoSubsequentTxn = txns[txnIdx - 2];
    var appId = txn['application-transaction']['application-id'];
    var assetsIn = {};
    var assetsOut = {};
    var command = Base64Encoder.decode(txn['application-transaction']['application-args'][0]);

    if (appId in this.pools) {
      switch (command) {
        case POOL_STRINGS.pool:
          {
            storeTransferDetails(twoPreviousTxn, assetsIn);
            storeTransferDetails(previousTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'].at(-1), assetsOut);

            if (subsequentTxn['inner-txns']) {
              storeTransferDetails(subsequentTxn['inner-txns'].at(-1), assetsOut);
            }

            if (twoSubsequentTxn['inner-txns']) {
              storeTransferDetails(twoSubsequentTxn['inner-txns'].at(-1), assetsOut);
            }

            parsedTransactions.push(new ParsedTransaction(txn, "AMM", appId, "POOL", [], assetsIn, assetsOut));
            break;
          }

        case POOL_STRINGS.swap_exact_for:
          {
            storeTransferDetails(previousTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'].at(-1), assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "AMM", appId, "SWAP", [], assetsIn, assetsOut));
            break;
          }

        case POOL_STRINGS.swap_for_exact:
          {
            storeTransferDetails(previousTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'].at(-1), assetsOut);

            if (subsequentTxn['inner-txns']) {
              storeTransferDetails(subsequentTxn['inner-txns'].at(-1), assetsOut);
            }

            parsedTransactions.push(new ParsedTransaction(txn, "AMM", appId, "SWAP", [], assetsIn, assetsOut));
            break;
          }

        case POOL_STRINGS.burn_asset1_out:
          {
            storeTransferDetails(previousTxn, assetsIn);
            storeTransferDetails(txn['inner-txns'].at(-1), assetsOut);
            storeTransferDetails(subsequentTxn['inner-txns'].at(-1), assetsOut);
            parsedTransactions.push(new ParsedTransaction(txn, "AMM", appId, "BURN", [], assetsIn, assetsOut));
            break;
          }

        default:
          return;
      }
    } else if (appId in this.algofiClient.interfaces.lendingPools) {
      return;
    }
  };

  return AMMClient;
}();

var BaseLendingClient$2 = /*#__PURE__*/function () {
  function BaseLendingClient(algofiClient) {
    this.v1 = new AMMClient(algofiClient);
  }

  var _proto = BaseLendingClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.v1.loadState();

            case 2:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  return BaseLendingClient;
}();

var _LendingPoolInterface;

var LendingPoolInterfaceConfig = function LendingPoolInterfaceConfig(appId, asset1Id, asset2Id, lpAssetId, market1AppId, market2AppId, poolAppId, opFarmAppId) {
  this.appId = appId;
  this.asset1Id = asset1Id;
  this.asset2Id = asset2Id;
  this.lpAssetId = lpAssetId;
  this.market1AppId = market1AppId;
  this.market2AppId = market2AppId;
  this.poolAppId = poolAppId;
  this.opFarmAppId = opFarmAppId;
};
var LendingPoolInterfaceConfigs = (_LendingPoolInterface = {}, _LendingPoolInterface[Network.MAINNET] = [/*#__PURE__*/new LendingPoolInterfaceConfig(1037244457, 31566704, 841126810, 841171328, 818182048, 841145020, 841170409, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037246265, 1, 841126810, 855717054, 818179346, 841145020, 855716333, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037246753, 386192725, 841126810, 870151164, 818183964, 841145020, 870150391, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037247557, 386195940, 841126810, 870150187, 818188286, 841145020, 870143131, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037247962, 841126810, 900652777, 900924035, 841145020, 900883415, 900923609, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037248443, 1, 31566704, 919950894, 818179346, 818182048, 919950071, 841189050), /*#__PURE__*/new LendingPoolInterfaceConfig(1037248737, 1, 900652777, 962367827, 818179346, 900883415, 962367416, 841189050)], _LendingPoolInterface[Network.TESTNET] = [/*#__PURE__*/new LendingPoolInterfaceConfig(1037248737, 1, 900652777, 962367827, 818179346, 900883415, 962367416, 841189050) // bad config
], _LendingPoolInterface); // STRING CONTSTANTS

var LENDING_POOL_INTERFACE_STRINGS = {
  market1_app_id: "market1_app_id",
  market2_app_id: "market2_app_id",
  lp_market_app_id: "lp_market_app_id",
  lending_manager_app_id: "lending_manager_app_id",
  pool_app_id: "pool_app_id",
  pool_manager_app_id: "pool_manager_app_id",
  op_farm_app_id: "op_farm_app_id",
  asset1_id: "asset1_id",
  asset2_id: "asset2_id",
  b_asset1_id: "b_asset1_id",
  b_asset2_id: "b_asset2_id",
  lp_asset_id: "lp_asset_id",
  pool_step_1: "pool_step_1",
  pool_step_2: "pool_step_2",
  pool_step_3: "pool_step_3",
  burn_step_1: "burn_step_1",
  burn_step_2: "burn_step_2",
  swap_step_1: "swap_step_1",
  swap_step_2: "swap_step_2",
  swap_step_3: "swap_step_3",
  swap_for_exact: "swap_for_exact",
  swap_exact_for: "swap_exact_for"
};

var IS_PROJECTED = true; // HELPER CLASSES
// INTERFACE

var LendingPoolInterface = /*#__PURE__*/function () {
  function LendingPoolInterface(algofiClient, config) {
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.appId = config.appId;
    this.asset1Id = config.asset1Id;
    this.asset2Id = config.asset2Id;
    this.lpAssetId = config.lpAssetId;
    this.market1AppId = config.market1AppId;
    this.market2AppId = config.market2AppId;
    this.poolAppId = config.poolAppId;
    this.opFarmAppId = config.opFarmAppId;
    this.address = getApplicationAddress(this.appId);
  }

  var _proto = LendingPoolInterface.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              this.market1 = this.algofiClient.lending.v2.markets[this.market1AppId];
              this.market2 = this.algofiClient.lending.v2.markets[this.market2AppId];
              _context.next = 4;
              return this.algofiClient.amm.v1.getPoolByLPAsset(this.lpAssetId);

            case 4:
              this.pool = _context.sent;

            case 5:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // GETTERS
  ;

  _proto.getTVL = function getTVL() {
    return this.pool.getTVL();
  };

  _proto.getAPR = /*#__PURE__*/function () {
    var _getAPR = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2() {
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              _context2.next = 2;
              return this.pool.getAPR();

            case 2:
              _context2.t0 = _context2.sent;
              _context2.next = 5;
              return this.market1.getSupplyAPR();

            case 5:
              _context2.t1 = _context2.sent;
              _context2.next = 8;
              return this.market2.getSupplyAPR();

            case 8:
              _context2.t2 = _context2.sent;
              _context2.t3 = _context2.t1 + _context2.t2;
              _context2.t4 = _context2.t3 / 2;
              return _context2.abrupt("return", _context2.t0 + _context2.t4);

            case 12:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getAPR() {
      return _getAPR.apply(this, arguments);
    }

    return getAPR;
  }() // QUOTES
  ;

  _proto.getEmptyPoolQuote = function getEmptyPoolQuote(asset1Amount, asset2Amount) {
    var bAsset1PooledAmount = this.market1.underlyingToBAsset(this.algofiClient.assetData.getAsset(asset1Amount, this.market1.underlyingAssetId)).amount;
    var bAsset2PooledAmount = this.market2.underlyingToBAsset(this.algofiClient.assetData.getAsset(asset2Amount, this.market2.underlyingAssetId)).amount;
    var poolQuote = this.pool.getEmptyPoolQuote(bAsset1PooledAmount, bAsset2PooledAmount);
    var lpsIssued = poolQuote.lpDelta;
    var numIter = poolQuote.iterations;
    return new PoolQuote(PoolQuoteType.POOL, -1 * asset1Amount, -1 * asset2Amount, lpsIssued, numIter);
  };

  _proto.getPoolQuote = function getPoolQuote(assetId, amount) {
    var asset1PooledAmount = 0;
    var bAsset1PooledAmount = 0;
    var asset2PooledAmount = 0;
    var bAsset2PooledAmount = 0;
    var lpsIssued = 0;
    var numIter = 0;
    var assetAmount = this.algofiClient.assetData.getAsset(amount, assetId);

    if (assetId == this.market1.underlyingAssetId) {
      asset1PooledAmount = assetAmount.amount;
      bAsset1PooledAmount = this.market1.underlyingToBAsset(assetAmount).amount;
      var poolQuote = this.pool.getPoolQuote(this.market1.bAssetId, bAsset1PooledAmount);
      bAsset2PooledAmount = -1 * poolQuote.asset2Delta;
      asset2PooledAmount = this.market2.bAssetToUnderlying(bAsset2PooledAmount).amount;
      lpsIssued = poolQuote.lpDelta;
      numIter = poolQuote.iterations;
    } else {
      asset2PooledAmount = assetAmount.amount;
      bAsset2PooledAmount = this.market2.underlyingToBAsset(assetAmount).amount;

      var _poolQuote = this.pool.getPoolQuote(this.market2.bAssetId, bAsset2PooledAmount);

      bAsset1PooledAmount = -1 * _poolQuote.asset1Delta;
      asset1PooledAmount = this.market1.bAssetToUnderlying(bAsset1PooledAmount).amount;
      lpsIssued = _poolQuote.lpDelta;
      numIter = _poolQuote.iterations;
    }

    return new PoolQuote(PoolQuoteType.POOL, -1 * asset1PooledAmount, -1 * asset2PooledAmount, lpsIssued, numIter);
  };

  _proto.getBurnQuote = function getBurnQuote(amount) {
    var lpsBurned = amount;
    var poolBurnQuote = this.pool.getBurnQuote(amount);
    var bAsset1BurnedAmount = poolBurnQuote.asset1Delta;
    var bAsset2BurnedAmount = poolBurnQuote.asset2Delta;
    var numIter = poolBurnQuote.iterations;
    var asset1BurnedAmount = this.market1.bAssetToUnderlying(bAsset1BurnedAmount).amount;
    var asset2BurnedAmount = this.market2.bAssetToUnderlying(bAsset2BurnedAmount).amount;
    return new PoolQuote(PoolQuoteType.BURN, asset1BurnedAmount, asset2BurnedAmount, -1 * lpsBurned, numIter);
  };

  _proto.getSwapExactForQuote = function getSwapExactForQuote(swapInAssetId, swapInAmount) {
    var asset1SwapAmount = 0;
    var bAsset1SwapAmount = 0;
    var asset2SwapAmount = 0;
    var bAsset2SwapAmount = 0;
    var numIter = 0;
    var swapInAssetAmount = this.algofiClient.assetData.getAsset(swapInAmount, swapInAssetId);

    if (swapInAssetId == this.market1.underlyingAssetId) {
      asset1SwapAmount = -1 * swapInAmount;
      bAsset1SwapAmount = this.market1.underlyingToBAsset(swapInAssetAmount).amount;
      var poolQuote = this.pool.getSwapExactForQuote(this.market1.bAssetId, bAsset1SwapAmount);
      bAsset2SwapAmount = poolQuote.asset2Delta;
      asset2SwapAmount = this.market2.bAssetToUnderlying(bAsset2SwapAmount).amount;
      numIter = poolQuote.iterations;
    } else {
      asset2SwapAmount = -1 * swapInAmount;
      bAsset2SwapAmount = this.market2.underlyingToBAsset(swapInAssetAmount).amount;

      var _poolQuote2 = this.pool.getSwapExactForQuote(this.market2.bAssetId, bAsset2SwapAmount);

      bAsset1SwapAmount = _poolQuote2.asset1Delta;
      asset1SwapAmount = this.market1.bAssetToUnderlying(bAsset1SwapAmount).amount;
      numIter = _poolQuote2.iterations;
    }

    return new PoolQuote(PoolQuoteType.SWAP_EXACT_FOR, asset1SwapAmount, asset2SwapAmount, 0, numIter);
  };

  _proto.getSwapForExactQuote = function getSwapForExactQuote(swapOutAssetId, swapOutAmount) {
    var asset1SwapAmount = 0;
    var bAsset1SwapAmount = 0;
    var asset2SwapAmount = 0;
    var bAsset2SwapAmount = 0;
    var numIter = 0;
    var swapOutAssetAmount = this.algofiClient.assetData.getAsset(swapOutAmount, swapOutAssetId);

    if (swapOutAssetId == this.market1.underlyingAssetId) {
      asset1SwapAmount = swapOutAmount;
      bAsset1SwapAmount = this.market1.underlyingToBAsset(swapOutAssetAmount).amount;
      var poolQuote = this.pool.getSwapForExactQuote(this.market1.bAssetId, bAsset1SwapAmount);
      bAsset2SwapAmount = poolQuote.asset2Delta;
      asset2SwapAmount = this.market2.bAssetToUnderlying(bAsset2SwapAmount).amount;
      numIter = poolQuote.iterations;
    } else {
      asset2SwapAmount = swapOutAmount;
      bAsset2SwapAmount = this.market2.underlyingToBAsset(swapOutAssetAmount).amount;

      var _poolQuote3 = this.pool.getSwapForExactQuote(this.market2.bAssetId, bAsset2SwapAmount);

      bAsset1SwapAmount = _poolQuote3.asset1Delta;
      asset1SwapAmount = this.market1.bAssetToUnderlying(bAsset1SwapAmount).amount;
      numIter = _poolQuote3.iterations;
    }

    return new PoolQuote(PoolQuoteType.SWAP_FOR_EXACT, asset1SwapAmount, asset2SwapAmount, 0, numIter);
  };

  _proto.getZapQuote = function getZapQuote(assetAID, assetAAmount, assetBAmount) {
    if (assetBAmount === void 0) {
      assetBAmount = 0;
    }

    var asset1Amount = assetAID == this.market1.underlyingAssetId ? assetAAmount : assetBAmount;
    var asset2Amount = assetAID == this.market1.underlyingAssetId ? assetBAmount : assetAAmount;
    var bAsset1Amount = this.market1.underlyingToBAsset(this.algofiClient.assetData.getAsset(asset1Amount, this.market1.underlyingAssetId), IS_PROJECTED).amount;
    var bAsset2Amount = this.market2.underlyingToBAsset(this.algofiClient.assetData.getAsset(asset2Amount, this.market2.underlyingAssetId), IS_PROJECTED).amount;
    var quote = this.pool.getZapQuote(this.market1.bAssetId, bAsset1Amount, bAsset2Amount);
    return new PoolQuote(PoolQuoteType.ZAP, this.market1.bAssetToUnderlying(quote.asset1Delta).amount, this.market2.bAssetToUnderlying(quote.asset2Delta).amount, quote.lpDelta, quote.iterations, this.market1.bAssetToUnderlying(quote.zapAsset1Swap).amount, this.market2.bAssetToUnderlying(quote.zapAsset2Swap).amount, quote.zapBonus);
  } // TRANSACTION GETTERS
  ;

  _proto.getPoolTxns =
  /*#__PURE__*/
  function () {
    var _getPoolTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3(user, quote, maximumSlippage, addToUserCollateral) {
      var params, transactions, additionalFees;
      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              if (addToUserCollateral === void 0) {
                addToUserCollateral = true;
              }

              _context3.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context3.sent;
              transactions = [];
              additionalFees = 27000 + quote.iterations * 1000 + (addToUserCollateral ? 3000 : 1000); // OPT IN TO LP (optional)

              if (!user.isOptedInToAsset(this.lpAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.lpAssetId, 0));
              } // SEND ASSET 1


              transactions.push(getPaymentTxn(params, user.address, this.address, this.market1.underlyingAssetId, -1 * quote.asset1Delta)); // SEND ASSET 2

              transactions.push(getPaymentTxn(params, user.address, this.address, this.market2.underlyingAssetId, -1 * quote.asset2Delta)); // POOL STEP 1 (mint)

              params.fee = additionalFees;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.pool_step_1), encodeUint64(quote.iterations)],
                accounts: [],
                foreignApps: [this.opFarmAppId, this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              })); // POOL STEP 2 (pool)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.pool_step_2), encodeUint64(maximumSlippage)],
                accounts: [],
                foreignApps: [this.poolAppId, this.pool.managerAppId],
                foreignAssets: [this.pool.asset1Id, this.pool.asset2Id, this.pool.lpAssetId],
                rekeyTo: undefined
              })); // POOL STEP 3 (burn)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.pool_step_3)],
                accounts: [],
                foreignApps: [this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              }));
              return _context3.abrupt("return", assignGroupID(transactions));

            case 16:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function getPoolTxns(_x, _x2, _x3, _x4) {
      return _getPoolTxns.apply(this, arguments);
    }

    return getPoolTxns;
  }();

  _proto.getBurnTxns = /*#__PURE__*/function () {
    var _getBurnTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(user, quote) {
      var params, transactions, additionalFees;
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return getParams(this.algod);

            case 2:
              params = _context4.sent;
              transactions = [];
              additionalFees = 18000 + quote.iterations * 1000; // OPT IN TO ASSET1 (optional)

              if (!user.isOptedInToAsset(this.market1.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market1.underlyingAssetId, 0));
              } // OPT IN TO ASSET2 (optional)


              if (!user.isOptedInToAsset(this.market2.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market2.underlyingAssetId, 0));
              } // SEND LP ASSET


              transactions.push(getPaymentTxn(params, user.address, this.address, this.lpAssetId, -1 * quote.lpDelta)); // BURN STEP 1 (burn lp token)

              params.fee = 1000 + additionalFees;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.burn_step_1), encodeUint64(quote.iterations)],
                accounts: [],
                foreignApps: [this.opFarmAppId, this.poolAppId, this.pool.managerAppId],
                foreignAssets: [this.pool.lpAssetId, this.pool.asset1Id, this.pool.asset2Id],
                rekeyTo: undefined
              })); // BURN STEP 2 (burn b tokens)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.burn_step_2)],
                accounts: [],
                foreignApps: [this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              }));
              return _context4.abrupt("return", assignGroupID(transactions));

            case 13:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getBurnTxns(_x5, _x6) {
      return _getBurnTxns.apply(this, arguments);
    }

    return getBurnTxns;
  }();

  _proto.getSwapTxns = /*#__PURE__*/function () {
    var _getSwapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(user, quote, maxSlippage) {
      var params, transactions, additionalFees, inputIsAsset1, inputAsset, inputbAsset, inputAmount, minBAssetOutputAmount;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              if (maxSlippage === void 0) {
                maxSlippage = 0.005;
              }

              _context5.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context5.sent;
              transactions = [];
              additionalFees = (quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR ? 17000 : 24000) + quote.iterations * 1000; // OPT IN TO ASSET1 (optional)

              if (!user.isOptedInToAsset(this.market1.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market1.underlyingAssetId, 0));
              } // OPT IN TO ASSET2 (optional)


              if (!user.isOptedInToAsset(this.market2.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market2.underlyingAssetId, 0));
              }

              inputIsAsset1 = quote.asset1Delta < 0;
              inputAsset = inputIsAsset1 ? this.market1.underlyingAssetId : this.market2.underlyingAssetId;
              inputbAsset = inputIsAsset1 ? this.market1.bAssetId : this.market2.bAssetId;
              inputAmount = inputIsAsset1 ? -1 * quote.asset1Delta : -1 * quote.asset2Delta;
              minBAssetOutputAmount = inputIsAsset1 ? this.market2.underlyingToBAsset(this.algofiClient.assetData.getAsset(quote.asset2Delta, this.market2.underlyingAssetId)).amount : this.market1.underlyingToBAsset(this.algofiClient.assetData.getAsset(quote.asset1Delta, this.market1.underlyingAssetId)).amount;

              if (quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR) {
                minBAssetOutputAmount = Math.floor(minBAssetOutputAmount * (1 - maxSlippage));
              } else {
                inputAmount = Math.ceil(inputAmount * (1 + maxSlippage));
              } // SEND ASSET


              transactions.push(getPaymentTxn(params, user.address, this.address, inputAsset, inputAmount)); // SWAP STEP 1 (mint)

              params.fee = 1000 + additionalFees;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.swap_step_1), encodeUint64(quote.iterations), encodeUint64(inputAsset)],
                accounts: [],
                foreignApps: [this.opFarmAppId, this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              })); // SWAP STEP 2 (swap)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.swap_step_2), encodeUint64(inputbAsset), quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR ? TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.swap_exact_for) : TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.swap_for_exact), encodeUint64(minBAssetOutputAmount)],
                accounts: [],
                foreignApps: [this.poolAppId, this.pool.managerAppId],
                foreignAssets: [this.pool.asset1Id, this.pool.asset2Id],
                rekeyTo: undefined
              })); // SWAP STEP 3 (burn)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_INTERFACE_STRINGS.swap_step_3)],
                accounts: [],
                foreignApps: [this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              }));
              return _context5.abrupt("return", assignGroupID(transactions));

            case 22:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getSwapTxns(_x7, _x8, _x9) {
      return _getSwapTxns.apply(this, arguments);
    }

    return getSwapTxns;
  }();

  _proto.getZapTxns = /*#__PURE__*/function () {
    var _getZapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(user, quote, maxSlippage, addToUserCollateral) {
      var swapQuote, swapTxns, poolQuote, poolMaxSlippage, poolTxns;
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              if (maxSlippage === void 0) {
                maxSlippage = 0.005;
              }

              if (addToUserCollateral === void 0) {
                addToUserCollateral = true;
              }

              swapQuote = new PoolQuote(PoolQuoteType.SWAP_FOR_EXACT, quote.zapAsset1Swap, quote.zapAsset2Swap, 0, Math.ceil(quote.iterations / 2));
              _context6.next = 5;
              return this.getSwapTxns(user, swapQuote, maxSlippage);

            case 5:
              swapTxns = _context6.sent;
              poolQuote = new PoolQuote(PoolQuoteType.POOL, quote.asset1Delta, quote.asset2Delta, quote.lpDelta, Math.floor(quote.iterations / 2));
              poolMaxSlippage = Math.floor(1000000 * maxSlippage);
              _context6.next = 10;
              return this.getPoolTxns(user, poolQuote, poolMaxSlippage, addToUserCollateral);

            case 10:
              poolTxns = _context6.sent;
              return _context6.abrupt("return", composeTransactions([swapTxns, poolTxns]));

            case 12:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getZapTxns(_x10, _x11, _x12, _x13) {
      return _getZapTxns.apply(this, arguments);
    }

    return getZapTxns;
  }();

  return LendingPoolInterface;
}();

var _LendingPoolRouterInt;

var LendingPoolRouterInterfaceConfig = function LendingPoolRouterInterfaceConfig(appId, asset1Id, intermediatebAssetId, asset2Id, market1AppId, market2AppId, pool1AppId, pool2AppId, opFarmAppId) {
  this.appId = appId;
  this.asset1Id = asset1Id;
  this.intermediatebAssetId = intermediatebAssetId;
  this.asset2Id = asset2Id;
  this.market1AppId = market1AppId;
  this.market2AppId = market2AppId;
  this.pool1AppId = pool1AppId;
  this.pool2AppId = pool2AppId;
  this.opFarmAppId = opFarmAppId;
};
var LendingPoolRouterInterfaceConfigs = (_LendingPoolRouterInt = {}, _LendingPoolRouterInt[Network.MAINNET] = [/*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037326737, 31566704, 841157954, 386192725, 818182048, 818183964, 841170409, 870150391, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037327812, 31566704, 841157954, 386195940, 818182048, 818188286, 841170409, 870143131, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037329564, 1, 841157954, 31566704, 818179346, 818182048, 855716333, 841170409, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037329803, 31566704, 841157954, 900652777, 818182048, 900883415, 841170409, 900923609, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037330104, 1, 841157954, 386192725, 818179346, 818183964, 855716333, 870150391, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037330316, 1, 841157954, 386195940, 818179346, 818188286, 855716333, 870143131, 841189050), /*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037330537, 386192725, 841157954, 386195940, 818183964, 818188286, 870150391, 870143131, 841189050)], _LendingPoolRouterInt[Network.TESTNET] = [/*#__PURE__*/new LendingPoolRouterInterfaceConfig(1037251860, 386192725, 841157954, 386195940, 818183964, 818188286, 870150391, 870143131, 841189050)], _LendingPoolRouterInt); // STRING CONTSTANTS

var LENDING_POOL_ROUTER_INTERFACE_STRINGS = {
  market1_app_id: "market1_app_id",
  market2_app_id: "market2_app_id",
  lp_market_app_id: "lp_market_app_id",
  lending_manager_app_id: "lending_manager_app_id",
  pool_app_id: "pool_app_id",
  pool_manager_app_id: "pool_manager_app_id",
  op_farm_app_id: "op_farm_app_id",
  asset1_id: "asset1_id",
  asset2_id: "asset2_id",
  b_asset1_id: "b_asset1_id",
  b_asset2_id: "b_asset2_id",
  lp_asset_id: "lp_asset_id",
  swap_step_1: "swap_step_1",
  swap_step_2: "swap_step_2",
  swap_step_3: "swap_step_3"
};

// INTERFACE

var LendingPoolInterface$1 = /*#__PURE__*/function () {
  function LendingPoolInterface(algofiClient, config) {
    this.algofiClient = algofiClient;
    this.algod = this.algofiClient.algod;
    this.appId = config.appId;
    this.asset1Id = config.asset1Id;
    this.intermediatebAssetId = config.intermediatebAssetId;
    this.asset2Id = config.asset2Id;
    this.market1AppId = config.market1AppId;
    this.market2AppId = config.market2AppId;
    this.pool1AppId = config.pool1AppId;
    this.pool2AppId = config.pool2AppId;
    this.opFarmAppId = config.opFarmAppId;
    this.address = getApplicationAddress(this.appId);
  }

  var _proto = LendingPoolInterface.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              this.market1 = this.algofiClient.lending.v2.markets[this.market1AppId];
              this.market2 = this.algofiClient.lending.v2.markets[this.market2AppId];
              _context.next = 4;
              return this.algofiClient.amm.v1.getPoolByAppId(this.pool1AppId);

            case 4:
              this.pool1 = _context.sent;
              _context.next = 7;
              return this.algofiClient.amm.v1.getPoolByAppId(this.pool2AppId);

            case 7:
              this.pool2 = _context.sent;

            case 8:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }() // GETTERS
  // QUOTES
  ;

  _proto.getSwapExactForQuote = function getSwapExactForQuote(swapInAssetId, swapInAmount) {
    var asset1SwapAmount = 0;
    var bAsset1SwapAmount = 0;
    var intermediatebAssetSwapAmount = 0;
    var asset2SwapAmount = 0;
    var bAsset2SwapAmount = 0;
    var numIter = 0;
    var swapInAssetAmount = this.algofiClient.assetData.getAsset(swapInAmount, swapInAssetId);

    if (swapInAssetId == this.market1.underlyingAssetId) {
      asset1SwapAmount = -1 * swapInAmount;
      bAsset1SwapAmount = this.market1.underlyingToBAsset(swapInAssetAmount).amount;
      var pool1Quote = this.pool1.getSwapExactForQuote(this.market1.bAssetId, bAsset1SwapAmount);
      intermediatebAssetSwapAmount = this.pool1.asset1Id == this.intermediatebAssetId ? pool1Quote.asset1Delta : pool1Quote.asset2Delta;
      var pool2Quote = this.pool2.getSwapExactForQuote(this.intermediatebAssetId, intermediatebAssetSwapAmount);
      bAsset2SwapAmount = this.pool2.asset1Id == this.market2.bAssetId ? pool2Quote.asset1Delta : pool2Quote.asset2Delta;
      asset2SwapAmount = this.market2.bAssetToUnderlying(bAsset2SwapAmount).amount;
      numIter = pool1Quote.iterations + pool2Quote.iterations;
    } else {
      asset2SwapAmount = -1 * swapInAmount;
      bAsset2SwapAmount = this.market2.underlyingToBAsset(swapInAssetAmount).amount;

      var _pool2Quote = this.pool2.getSwapExactForQuote(this.market2.bAssetId, bAsset2SwapAmount);

      intermediatebAssetSwapAmount = this.pool2.asset1Id == this.intermediatebAssetId ? _pool2Quote.asset1Delta : _pool2Quote.asset2Delta;

      var _pool1Quote = this.pool1.getSwapExactForQuote(this.intermediatebAssetId, intermediatebAssetSwapAmount);

      bAsset1SwapAmount = this.pool1.asset1Id == this.market1.bAssetId ? _pool1Quote.asset1Delta : _pool1Quote.asset2Delta;
      asset1SwapAmount = this.market1.bAssetToUnderlying(bAsset1SwapAmount).amount;
      numIter = _pool2Quote.iterations + _pool1Quote.iterations;
    }

    return new PoolQuote(PoolQuoteType.SWAP_EXACT_FOR, asset1SwapAmount, asset2SwapAmount, 0, numIter);
  } // TRANSACTION GETTERS
  ;

  _proto.getSwapTxns =
  /*#__PURE__*/
  function () {
    var _getSwapTxns = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(user, quote, maxSlippage) {
      var params, transactions, additionalFees, inputIsAsset1, inputAsset, inputAmount, minBAssetOutputAmount;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              if (maxSlippage === void 0) {
                maxSlippage = 0.005;
              }

              _context2.next = 3;
              return getParams(this.algod);

            case 3:
              params = _context2.sent;
              transactions = [];
              additionalFees = 30000 + quote.iterations * 1000; // OPT IN TO ASSET1 (optional)

              if (!user.isOptedInToAsset(this.market1.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market1.underlyingAssetId, 0));
              } // OPT IN TO ASSET2 (optional)


              if (!user.isOptedInToAsset(this.market2.underlyingAssetId)) {
                transactions.push(getPaymentTxn(params, user.address, user.address, this.market2.underlyingAssetId, 0));
              }

              inputIsAsset1 = quote.asset1Delta < 0;
              inputAsset = inputIsAsset1 ? this.market1.underlyingAssetId : this.market2.underlyingAssetId;
              inputAmount = inputIsAsset1 ? -1 * quote.asset1Delta : -1 * quote.asset2Delta;
              minBAssetOutputAmount = inputIsAsset1 ? this.market2.underlyingToBAsset(this.algofiClient.assetData.getAsset(quote.asset2Delta, this.market2.underlyingAssetId)).amount : this.market1.underlyingToBAsset(this.algofiClient.assetData.getAsset(quote.asset1Delta, this.market1.underlyingAssetId)).amount;

              if (quote.quoteType == PoolQuoteType.SWAP_EXACT_FOR) {
                minBAssetOutputAmount = Math.floor(minBAssetOutputAmount * (1 - maxSlippage));
              } else {
                inputAmount = Math.ceil(inputAmount * (1 + maxSlippage));
              } // SEND ASSET


              transactions.push(getPaymentTxn(params, user.address, this.address, inputAsset, inputAmount)); // SWAP STEP 1 (mint)

              params.fee = 1000 + additionalFees;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_ROUTER_INTERFACE_STRINGS.swap_step_1), encodeUint64(quote.iterations), encodeUint64(inputAsset)],
                accounts: [],
                foreignApps: [this.opFarmAppId, this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              })); // SWAP STEP 2 (swap)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_ROUTER_INTERFACE_STRINGS.swap_step_2), encodeUint64(inputAsset), encodeUint64(minBAssetOutputAmount)],
                accounts: [],
                foreignApps: [this.pool1AppId, this.pool2AppId, this.pool1.managerAppId],
                foreignAssets: [this.pool1.asset1Id, this.pool1.asset2Id, this.pool2.asset1Id, this.pool2.asset2Id],
                rekeyTo: undefined
              })); // SWAP STEP 3 (burn)

              params.fee = 0;
              transactions.push(algosdk.makeApplicationNoOpTxnFromObject({
                from: user.address,
                appIndex: this.appId,
                suggestedParams: params,
                appArgs: [TEXT_ENCODER.encode(LENDING_POOL_ROUTER_INTERFACE_STRINGS.swap_step_3)],
                accounts: [],
                foreignApps: [this.market1AppId, this.market2AppId, this.market1.managerAppId],
                foreignAssets: [this.market1.underlyingAssetId, this.market1.bAssetId, this.market2.underlyingAssetId, this.market2.bAssetId],
                rekeyTo: undefined
              }));
              return _context2.abrupt("return", assignGroupID(transactions));

            case 21:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getSwapTxns(_x, _x2, _x3) {
      return _getSwapTxns.apply(this, arguments);
    }

    return getSwapTxns;
  }();

  return LendingPoolInterface;
}();

var InterfaceClient = /*#__PURE__*/function () {
  function InterfaceClient(algofiClient) {
    this.lendingPools = {};
    this.assetLendingPoolMap = {};
    this.lpLendingPoolMap = {};
    this.lendingPoolRouters = {};
    this.assetLendingPoolRouterMap = {};
    this.algofiClient = algofiClient;
    this.network = this.algofiClient.network; // lending pool interface

    this.lendingPoolConfigs = LendingPoolInterfaceConfigs[algofiClient.network];
    this.lendingPoolRouterConfigs = LendingPoolRouterInterfaceConfigs[algofiClient.network];
  }

  var _proto = InterfaceClient.prototype;

  _proto.loadState = /*#__PURE__*/function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee3() {
      var _this = this;

      return _regeneratorRuntime().wrap(function _callee3$(_context3) {
        while (1) {
          switch (_context3.prev = _context3.next) {
            case 0:
              _context3.next = 2;
              return Promise.all(this.lendingPoolConfigs.map( /*#__PURE__*/function () {
                var _ref = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee(config) {
                  return _regeneratorRuntime().wrap(function _callee$(_context) {
                    while (1) {
                      switch (_context.prev = _context.next) {
                        case 0:
                          if (!(config.appId in _this.lendingPools)) {
                            _this.lendingPools[config.appId] = new LendingPoolInterface(_this.algofiClient, config);

                            if (!(config.asset1Id in _this.assetLendingPoolMap)) {
                              _this.assetLendingPoolMap[config.asset1Id] = {};
                            }

                            _this.assetLendingPoolMap[config.asset1Id][config.asset2Id] = _this.lendingPools[config.appId];
                            _this.lpLendingPoolMap[config.lpAssetId] = _this.lendingPools[config.appId];
                          }

                        case 1:
                        case "end":
                          return _context.stop();
                      }
                    }
                  }, _callee);
                }));

                return function (_x) {
                  return _ref.apply(this, arguments);
                };
              }()));

            case 2:
              _context3.next = 4;
              return Promise.all(this.lendingPoolRouterConfigs.map( /*#__PURE__*/function () {
                var _ref2 = _asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(config) {
                  return _regeneratorRuntime().wrap(function _callee2$(_context2) {
                    while (1) {
                      switch (_context2.prev = _context2.next) {
                        case 0:
                          if (!(config.appId in _this.lendingPoolRouters)) {
                            _this.lendingPoolRouters[config.appId] = new LendingPoolInterface$1(_this.algofiClient, config);

                            if (!(config.asset1Id in _this.assetLendingPoolRouterMap)) {
                              _this.assetLendingPoolRouterMap[config.asset1Id] = {};
                            }

                            _this.assetLendingPoolRouterMap[config.asset1Id][config.asset2Id] = _this.lendingPoolRouters[config.appId];
                          }

                        case 1:
                        case "end":
                          return _context2.stop();
                      }
                    }
                  }, _callee2);
                }));

                return function (_x2) {
                  return _ref2.apply(this, arguments);
                };
              }()));

            case 4:
            case "end":
              return _context3.stop();
          }
        }
      }, _callee3, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }();

  _proto.getLendingPool = /*#__PURE__*/function () {
    var _getLendingPool = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee4(appId) {
      return _regeneratorRuntime().wrap(function _callee4$(_context4) {
        while (1) {
          switch (_context4.prev = _context4.next) {
            case 0:
              _context4.next = 2;
              return this.lendingPools[appId].loadState();

            case 2:
              return _context4.abrupt("return", this.lendingPools[appId]);

            case 3:
            case "end":
              return _context4.stop();
          }
        }
      }, _callee4, this);
    }));

    function getLendingPool(_x3) {
      return _getLendingPool.apply(this, arguments);
    }

    return getLendingPool;
  }();

  _proto.hasLendingPoolForAssets = function hasLendingPoolForAssets(assetAId, assetBId) {
    var asset1Id = assetAId < assetBId ? assetAId : assetBId;
    var asset2Id = assetAId > assetBId ? assetAId : assetBId;
    return asset1Id in this.assetLendingPoolMap && asset2Id in this.assetLendingPoolMap[asset1Id];
  };

  _proto.getLendingPoolFromAssets = /*#__PURE__*/function () {
    var _getLendingPoolFromAssets = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee5(assetAId, assetBId) {
      var asset1Id, asset2Id;
      return _regeneratorRuntime().wrap(function _callee5$(_context5) {
        while (1) {
          switch (_context5.prev = _context5.next) {
            case 0:
              asset1Id = assetAId < assetBId ? assetAId : assetBId;
              asset2Id = assetAId > assetBId ? assetAId : assetBId;
              _context5.next = 4;
              return this.assetLendingPoolMap[asset1Id][asset2Id].loadState();

            case 4:
              return _context5.abrupt("return", this.assetLendingPoolMap[asset1Id][asset2Id]);

            case 5:
            case "end":
              return _context5.stop();
          }
        }
      }, _callee5, this);
    }));

    function getLendingPoolFromAssets(_x4, _x5) {
      return _getLendingPoolFromAssets.apply(this, arguments);
    }

    return getLendingPoolFromAssets;
  }();

  _proto.hasLendingPoolForLP = function hasLendingPoolForLP(lpAssetId) {
    return lpAssetId in this.lpLendingPoolMap;
  };

  _proto.getLendingPoolFromLP = /*#__PURE__*/function () {
    var _getLendingPoolFromLP = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee6(lpAssetId) {
      return _regeneratorRuntime().wrap(function _callee6$(_context6) {
        while (1) {
          switch (_context6.prev = _context6.next) {
            case 0:
              _context6.next = 2;
              return this.lpLendingPoolMap[lpAssetId].loadState();

            case 2:
              return _context6.abrupt("return", this.lpLendingPoolMap[lpAssetId]);

            case 3:
            case "end":
              return _context6.stop();
          }
        }
      }, _callee6, this);
    }));

    function getLendingPoolFromLP(_x6) {
      return _getLendingPoolFromLP.apply(this, arguments);
    }

    return getLendingPoolFromLP;
  }();

  _proto.getLendingPoolRouter = /*#__PURE__*/function () {
    var _getLendingPoolRouter = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee7(appId) {
      return _regeneratorRuntime().wrap(function _callee7$(_context7) {
        while (1) {
          switch (_context7.prev = _context7.next) {
            case 0:
              _context7.next = 2;
              return this.lendingPoolRouters[appId].loadState();

            case 2:
              return _context7.abrupt("return", this.lendingPoolRouters[appId]);

            case 3:
            case "end":
              return _context7.stop();
          }
        }
      }, _callee7, this);
    }));

    function getLendingPoolRouter(_x7) {
      return _getLendingPoolRouter.apply(this, arguments);
    }

    return getLendingPoolRouter;
  }();

  _proto.hasLendingPoolRouterForAssets = function hasLendingPoolRouterForAssets(assetAId, assetBId) {
    var asset1Id = assetAId < assetBId ? assetAId : assetBId;
    var asset2Id = assetAId > assetBId ? assetAId : assetBId;
    return asset1Id in this.assetLendingPoolRouterMap && asset2Id in this.assetLendingPoolRouterMap[asset1Id];
  };

  _proto.getLendingPoolRouterFromAssets = /*#__PURE__*/function () {
    var _getLendingPoolRouterFromAssets = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee8(assetAId, assetBId) {
      var asset1Id, asset2Id;
      return _regeneratorRuntime().wrap(function _callee8$(_context8) {
        while (1) {
          switch (_context8.prev = _context8.next) {
            case 0:
              asset1Id = assetAId < assetBId ? assetAId : assetBId;
              asset2Id = assetAId > assetBId ? assetAId : assetBId;
              _context8.next = 4;
              return this.assetLendingPoolRouterMap[asset1Id][asset2Id].loadState();

            case 4:
              return _context8.abrupt("return", this.assetLendingPoolRouterMap[asset1Id][asset2Id]);

            case 5:
            case "end":
              return _context8.stop();
          }
        }
      }, _callee8, this);
    }));

    function getLendingPoolRouterFromAssets(_x8, _x9) {
      return _getLendingPoolRouterFromAssets.apply(this, arguments);
    }

    return getLendingPoolRouterFromAssets;
  }();

  return InterfaceClient;
}();

var AlgofiClient = /*#__PURE__*/function () {
  /**
   * Constructor for the algofi client class
   *
   * @param algod - algod client
   * @param indexer - indexer client
   * @param network - chain network
   */
  function AlgofiClient(algod, indexer, network) {
    this.algod = algod;
    this.indexer = indexer;
    this.network = network; // lending

    this.lending = new BaseLendingClient(this); // staking

    this.staking = new BaseStakingClient(this); // governance

    this.governance = new BaseLendingClient$1(this); // amm

    this.amm = new BaseLendingClient$2(this); // assetData

    this.assetData = new AssetDataClient(this); // interfaces

    this.interfaces = new InterfaceClient(this);
  }
  /**
   * Function to load the state of all of the different types of clients.
   */


  var _proto = AlgofiClient.prototype;

  _proto.loadState =
  /*#__PURE__*/
  function () {
    var _loadState = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee() {
      var loadLendingPromise, loadGovernancePromise, loadAMMPromise;
      return _regeneratorRuntime().wrap(function _callee$(_context) {
        while (1) {
          switch (_context.prev = _context.next) {
            case 0:
              _context.next = 2;
              return this.assetData.loadState();

            case 2:
              // lending
              loadLendingPromise = this.lending.loadState(); // governance

              loadGovernancePromise = this.governance.loadState(); // amm

              loadAMMPromise = this.amm.loadState(); // wait for all to complete

              _context.next = 7;
              return Promise.all([loadLendingPromise, loadGovernancePromise, loadAMMPromise]);

            case 7:
              _context.next = 9;
              return this.assetData.loadLendingAssetState();

            case 9:
              _context.next = 11;
              return this.staking.loadState();

            case 11:
              _context.next = 13;
              return this.interfaces.loadState();

            case 13:
            case "end":
              return _context.stop();
          }
        }
      }, _callee, this);
    }));

    function loadState() {
      return _loadState.apply(this, arguments);
    }

    return loadState;
  }()
  /**
   * Function to get an algofi user given an address.
   *
   * @param address - address of the user
   * @returns an algofi user given the address passed in.
   */
  ;

  _proto.getUser =
  /*#__PURE__*/
  function () {
    var _getUser = /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime().mark(function _callee2(address) {
      var user;
      return _regeneratorRuntime().wrap(function _callee2$(_context2) {
        while (1) {
          switch (_context2.prev = _context2.next) {
            case 0:
              user = new AlgofiUser(this, address);
              _context2.next = 3;
              return user.loadState();

            case 3:
              return _context2.abrupt("return", user);

            case 4:
            case "end":
              return _context2.stop();
          }
        }
      }, _callee2, this);
    }));

    function getUser(_x) {
      return _getUser.apply(this, arguments);
    }

    return getUser;
  }();

  return AlgofiClient;
}();

export { AlgofiClient, AlgofiUser, AssetAmount, AssetConfig, Base64Encoder, MarketType, Network, PERMISSIONLESS_SENDER_LOGIC_SIG, Pool, PoolQuote, PoolQuoteType, PoolType, StakingConfig$1 as StakingConfig, TxnLoadMode, addressEquals, composeTransactions };
//# sourceMappingURL=js-sdk.esm.js.map