var Q = Object.defineProperty;
var X = (O, e, t) => e in O ? Q(O, e, { enumerable: !0, configurable: !0, writable: !0, value: t }) : O[e] = t;
var d = (O, e, t) => X(O, typeof e != "symbol" ? e + "" : e, t);
import { A as b, S as g, a as Y } from "./index-Dw4gUoPq.mjs";
import { d9 as Z, a5 as C, a8 as $, da as _, an as I, db as v, dc as q, c8 as tt, cp as S, c9 as et, p as H, ce as K, dd as y, de as u, df as k, dg as U, bM as L, dh as z, di as st, dj as V, dk as ot, bR as nt, ak as rt } from "./index-CjwA7HmM.mjs";
import { A as at } from "./algorand-qEY4HHOc.mjs";
const G = Z.fromSignature("portal_transfer(byte[])byte[]"), c = class c {
  constructor(e, t, n, o) {
    d(this, "network");
    d(this, "chain");
    d(this, "connection");
    d(this, "contracts");
    d(this, "chainId");
    d(this, "coreBridge");
    d(this, "coreAppId");
    d(this, "coreAppAddress");
    d(this, "tokenBridgeAppId");
    d(this, "tokenBridgeAddress");
    if (this.network = e, this.chain = t, this.connection = n, this.contracts = o, this.chainId = $(t), !o.coreBridge)
      throw new Error(`Core contract address for chain ${t} not found`);
    const r = BigInt(o.coreBridge);
    if (this.coreAppId = r, this.coreAppAddress = _(r), this.coreBridge = new b(e, t, n, o), !o.tokenBridge)
      throw new Error(`TokenBridge contract address for chain ${t} not found`);
    const a = BigInt(o.tokenBridge);
    this.tokenBridgeAppId = a, this.tokenBridgeAddress = _(a);
  }
  static async fromRpc(e, t) {
    const [n, o] = await at.chainFromRpc(e), r = t[o];
    if (r.network !== n)
      throw new Error(`Network mismatch: ${r.network} != ${n}`);
    return new c(n, o, e, r.contracts);
  }
  // Checks a native address to see if it's a wrapped version
  async isWrappedAsset(e) {
    const t = new I(e).toInt();
    if (t === 0)
      return !1;
    const n = await this.connection.getAssetByID(t).do(), r = v.from_obj_for_encoding(n).params.creator, a = await this.connection.accountInformation(r).exclude("all").do(), s = q.from_obj_for_encoding(a);
    return (s == null ? void 0 : s.authAddr) === this.tokenBridgeAddress;
  }
  // Returns the original asset with its foreign chain
  async getOriginalAsset(e) {
    const t = new I(e).toInt(), n = await this.connection.getAssetByID(t).do(), o = v.from_obj_for_encoding(n), r = await g.decodeLocalState(this.connection, this.tokenBridgeAppId, o.params.creator);
    if (r.length < 94)
      throw new Error("Invalid local state data");
    const a = r.slice(92, 94), s = tt(S.decode(a)), p = new et(r.slice(60, 92));
    return { chain: s, address: p };
  }
  async getTokenUniversalAddress(e) {
    return new I(e).toUniversalAddress();
  }
  async getTokenNativeAddress(e, t) {
    return new I(t).toNative();
  }
  // Returns the address of the native version of this asset
  async getWrappedAsset(e) {
    if (H(e.address))
      throw new Error("native asset cannot be a wrapped asset");
    const t = g.forWrappedAsset(this.tokenBridgeAppId, e), n = await g.decodeLocalState(this.connection, this.tokenBridgeAppId, t.address());
    if (n.length < 8)
      throw new Error("Invalid wrapped asset data");
    return K(this.chain, S.decode(n.slice(0, 8)).toString());
  }
  // Checks if a wrapped version exists
  async hasWrappedAsset(e) {
    try {
      return await this.getWrappedAsset(e), !0;
    } catch {
    }
    return !1;
  }
  async getWrappedNative() {
    return K(this.chain, "0");
  }
  async isTransferCompleted(e) {
    const t = g.forMessageId(this.tokenBridgeAppId, {
      sequence: e.sequence,
      chain: e.emitterChain,
      emitter: e.emitterAddress
    });
    try {
      return await g.checkBitsSet(this.connection, this.tokenBridgeAppId, t.address(), e.sequence);
    } catch {
    }
    return !1;
  }
  // Creates a Token Attestation VAA containing metadata about
  // the token that may be submitted to a Token Bridge on another chain
  // to allow it to create a wrapped version of the token
  async *createAttestation(e, t) {
    if (!t)
      throw new Error("Payer required to create attestation");
    const n = new I(t).toString(), o = new I(e).toInt(), r = [], a = await this.connection.getTransactionParams().do(), s = g.forEmitter(this.coreAppId, new I(this.tokenBridgeAddress).toUint8Array()), { accounts: [p], txs: w } = await b.maybeCreateStorageTx(this.connection, n, this.coreAppId, s, a);
    r.push(...w);
    let f = "", i;
    if (o !== 0) {
      const l = await this.connection.getAssetByID(o).do(), j = v.from_obj_for_encoding(l), R = await this.connection.accountInformation(j.params.creator).do();
      if (i = q.from_obj_for_encoding(R), i.authAddr === this.tokenBridgeAddress.toString())
        throw new Error("Cannot re-attest wormhole assets");
    }
    const T = g.forNativeAsset(this.tokenBridgeAppId, BigInt(o)), B = await b.maybeCreateStorageTx(this.connection, n, this.tokenBridgeAppId, T);
    f = B.accounts[0], r.push(...B.txs);
    const m = y({
      from: n,
      appIndex: u(this.tokenBridgeAppId),
      onComplete: k.NoOpOC,
      appArgs: [c.noop],
      suggestedParams: a
    });
    r.push({ tx: m });
    const A = await this.coreBridge.getMessageFee();
    if (A > BigInt(0)) {
      const l = U({
        from: n,
        suggestedParams: a,
        to: this.tokenBridgeAddress,
        amount: A
      });
      r.push({ tx: l });
    }
    let W = [p, f, this.coreAppAddress];
    i && W.push(i.address);
    let h = y({
      appArgs: [c.attestToken, S.toBytes(o, 8)],
      accounts: W,
      appIndex: u(this.tokenBridgeAppId),
      foreignApps: [u(this.coreAppId)],
      foreignAssets: [o],
      from: n,
      onComplete: k.NoOpOC,
      suggestedParams: a
    });
    A > BigInt(0) ? h.fee *= 3 : h.fee *= 2, r.push({ tx: h });
    for (const l of r)
      yield this.createUnsignedTx(l, "TokenBridge.createAttestation", !0);
  }
  // Submits the Token Attestation VAA to the Token Bridge
  // to create the wrapped token represented by the data in the VAA
  async *submitAttestation(e, t, n) {
    if (!t)
      throw new Error("Sender required to submit attestation");
    n || (n = await this.connection.getTransactionParams().do());
    const o = t.toString(), a = g.forWrappedAsset(this.tokenBridgeAppId, e.payload.token).address(), s = [], p = [], w = await g.decodeLocalState(this.connection, this.tokenBridgeAppId, a);
    w.length > 8 && p.push(new I(w.slice(0, 8)).toInt()), s.push({
      tx: U({
        from: o,
        to: a,
        amount: 1e5,
        suggestedParams: n
      })
    });
    let f = new Uint8Array(1);
    f[0] = 1, s.push({
      tx: y({
        appArgs: [c.noop, f],
        appIndex: u(this.tokenBridgeAppId),
        from: o,
        onComplete: k.NoOpOC,
        suggestedParams: n
      })
    }), f = new Uint8Array(1), f[0] = 2, s.push({
      tx: y({
        appArgs: [c.noop, f],
        appIndex: u(this.tokenBridgeAppId),
        from: o,
        onComplete: k.NoOpOC,
        suggestedParams: n
      })
    }), s.push({
      tx: y({
        accounts: [],
        appArgs: [c.receiveAttest, L(e)],
        appIndex: u(this.tokenBridgeAppId),
        foreignAssets: p,
        from: o,
        onComplete: k.NoOpOC,
        suggestedParams: n
      })
    }), s[s.length - 1].tx.fee = s[s.length - 1].tx.fee * 2;
    for (const i of s)
      yield this.createUnsignedTx(i, "TokenBridge.submitAttestation", !0);
  }
  async *transfer(e, t, n, o, r) {
    const a = e.toString(), s = H(n) ? 0 : new I(n).toInt(), p = o, w = $(t.chain), f = t.address.toUniversalAddress().toUint8Array(), i = await this.connection.getTransactionParams().do(), T = BigInt(0), B = g.fromData({
      appId: this.coreAppId,
      appAddress: z(this.coreAppAddress).publicKey,
      idx: BigInt(0),
      address: z(this.tokenBridgeAddress).publicKey
    }), m = [], { accounts: [A], txs: W } = await b.maybeCreateStorageTx(this.connection, a, this.coreAppId, B, i);
    m.push(...W);
    let h = "", l, j = !1;
    if (s !== 0) {
      const x = await this.connection.getAssetByID(s).do();
      h = v.from_obj_for_encoding(x).params.creator;
      const E = await this.connection.accountInformation(h).do();
      l = q.from_obj_for_encoding(E), j = l.authAddr === this.tokenBridgeAddress.toString();
    }
    const R = await this.coreBridge.getMessageFee();
    if (R > 0 && m.push({
      tx: U({
        from: a,
        to: this.tokenBridgeAddress,
        amount: R,
        suggestedParams: i
      })
    }), !j) {
      const x = g.forNativeAsset(this.tokenBridgeAppId, BigInt(s)), { accounts: [N], txs: E } = await b.maybeCreateStorageTx(this.connection, a, this.tokenBridgeAppId, x, i);
      h = N, E.push(...E);
    }
    if (s !== 0 && !await c.isOptedInToAsset(this.connection, h, s)) {
      const x = U({
        from: a,
        to: h,
        amount: 1e5,
        suggestedParams: i
      });
      let N = y({
        from: a,
        appIndex: u(this.tokenBridgeAppId),
        onComplete: k.NoOpOC,
        appArgs: [c.optIn, st(s, 8)],
        foreignAssets: [s],
        accounts: [h],
        suggestedParams: i
      });
      N.fee *= 2, m.unshift({ tx: x }, { tx: N });
    }
    const J = y({
      from: a,
      appIndex: u(this.tokenBridgeAppId),
      onComplete: k.NoOpOC,
      appArgs: [c.noop],
      suggestedParams: i
    });
    m.push({ tx: J });
    let F = [];
    if (s === 0) {
      const x = U({
        from: a,
        to: h,
        amount: p,
        suggestedParams: i
      });
      m.push({ tx: x }), F = [A, h, h];
    } else {
      const x = V({
        from: a,
        to: h,
        amount: p,
        assetIndex: s,
        suggestedParams: i
      });
      m.push({ tx: x }), F = l != null && l.address ? [A, h, l.address] : [A, h];
    }
    const D = [
      c.sendTransfer,
      S.toBytes(s, 8),
      S.toBytes(p, 8),
      f,
      S.toBytes(w, 8),
      S.toBytes(T, 8)
    ];
    r && D.push(r);
    const P = y({
      from: a,
      appIndex: u(this.tokenBridgeAppId),
      onComplete: k.NoOpOC,
      appArgs: D,
      foreignApps: [u(this.coreAppId)],
      foreignAssets: [s],
      accounts: F,
      suggestedParams: i
    });
    P.fee *= 2, m.push({ tx: P });
    for (const x of m)
      yield this.createUnsignedTx(x, "TokenBridge.transfer", !0);
  }
  async *redeem(e, t, n = !0, o) {
    o || (o = await this.connection.getTransactionParams().do());
    const r = new I(e).toString(), { accounts: a, txs: s } = await b.submitVAAHeader(this.connection, this.coreAppId, this.tokenBridgeAppId, t, r);
    let p, w = "", f = [], i = 0;
    if (t.payload.token.chain !== this.chain) {
      p = g.forWrappedAsset(this.tokenBridgeAppId, t.payload.token), w = p.address();
      const A = await g.decodeLocalState(this.connection, this.tokenBridgeAppId, w);
      i = new I(A.slice(0, 8)).toInt();
    } else {
      const A = new I(t.payload.token.address).toBigInt();
      p = g.forNativeAsset(this.tokenBridgeAppId, A), w = p.address(), i = u(A);
    }
    a.push(w);
    let T = 0, B = "";
    if (t.payloadName === "TransferWithPayload" ? (T = new I(t.payload.to.address).toInt(), B = _(T)) : B = new I(t.payload.to.address.toUint8Array()).toString(), a.push(B), i !== 0 && (f.push(i), !await c.isOptedInToAsset(this.connection, B, i))) {
      if (r != B)
        throw new Error("Cannot ASA optin for somebody else (asset " + i.toString() + ")");
      s.unshift({
        tx: V({
          amount: 0,
          assetIndex: i,
          from: r,
          suggestedParams: o,
          to: r
        })
      });
    }
    const m = {
      accounts: a,
      appArgs: [c.completeTransfer, L(t)],
      appIndex: u(this.tokenBridgeAppId),
      foreignAssets: f,
      from: r,
      onComplete: k.NoOpOC,
      suggestedParams: o
    };
    s.push({
      tx: y(m)
    }), s[s.length - 1].tx.fee = s[s.length - 1].tx.fee * (t.payloadName === "Transfer" && t.payload.fee !== void 0 && t.payload.fee === 0n ? 2 : 3), t.payloadName === "TransferWithPayload" && (s[s.length - 1].tx.appForeignApps = [T], s.push({
      tx: y({
        appArgs: [
          G.getSelector(),
          G.args[0].type.encode(L(t))
        ],
        appIndex: T,
        foreignAssets: f,
        from: r,
        onComplete: k.NoOpOC,
        suggestedParams: o
      })
    }));
    for (const A of s)
      yield this.createUnsignedTx(A, "TokenBridge.redeem", !0);
  }
  /**
   * Checks if the asset has been opted in by the receiver
   * @param client Algodv2 client
   * @param asset Algorand asset index
   * @param receiver Account address
   * @returns Promise with True if the asset was opted in, False otherwise
   */
  static async isOptedInToAsset(e, t, n) {
    var o;
    try {
      const r = await e.accountAssetInformation(t, n).do();
      return (((o = ot.from_obj_for_encoding(r).assetHolding) == null ? void 0 : o.amount) ?? 0) > 0;
    } catch {
    }
    return !1;
  }
  createUnsignedTx(e, t, n = !0) {
    return new Y(e, this.network, this.chain, t, n);
  }
};
d(c, "sendTransfer", C.encode("sendTransfer")), d(c, "attestToken", C.encode("attestToken")), d(c, "noop", C.encode("nop")), d(c, "optIn", C.encode("optin")), d(c, "completeTransfer", C.encode("completeTransfer")), d(c, "receiveAttest", C.encode("receiveAttest"));
let M = c;
nt(rt, "TokenBridge", M);
export {
  M as AlgorandTokenBridge,
  G as TransferMethodSelector
};
