import { cM as B, cN as P, cO as x, m as R } from "./platform-Cil_UtAQ.mjs";
import { al as f, j as p, K as S, ao as I, ap as M, x as A, a as E } from "./unsignedTransaction-DCDxTFq8.mjs";
const _ = 0.5, y = 1, F = 1, b = 1e8, T = 5, L = 25e4;
async function $(r, t, e) {
  const [s, i] = await p.chainFromRpc(r), o = typeof t == "string" ? S.fromSecretKey(x.decode(t)) : t;
  if (e?.priorityFee && e.priorityFee.percentile && e.priorityFee.percentile > 1)
    throw new Error("priorityFeePercentile must be a number between 0 and 1");
  return new U(r, i, o, e?.debug ?? !1, e?.priorityFee ?? {}, e?.retries ?? T, e?.sendOpts);
}
class U {
  _rpc;
  _chain;
  _keypair;
  _debug;
  _priorityFee;
  _maxResubmits;
  _sendOpts;
  constructor(t, e, s, i = !1, o, l = T, a) {
    this._rpc = t, this._chain = e, this._keypair = s, this._debug = i, this._priorityFee = o, this._maxResubmits = l, this._sendOpts = a, this._sendOpts = this._sendOpts ?? {
      preflightCommitment: this._rpc.commitment
    };
  }
  chain() {
    return this._chain;
  }
  address() {
    return this._keypair.publicKey.toBase58();
  }
  // Handles retrying a Transaction if the error is deemed to be
  // recoverable. Currently handles:
  // - Transaction expired
  // - Blockhash not found
  // - Not enough bytes (storage account not seen yet)
  retryable(t) {
    if (t instanceof I)
      return !0;
    if (!(t instanceof M) || !t.message.includes("Transaction simulation failed"))
      return !1;
    if (t.message.includes("Blockhash not found"))
      return !0;
    const e = t.logs?.find((s) => s.startsWith("Program log: Error: "));
    return e ? !!(e.includes("Not enough bytes") || e.includes("Unexpected length of input")) : !1;
  }
  async signAndSend(t) {
    let { blockhash: e, lastValidBlockHeight: s } = await p.latestBlock(this._rpc);
    const i = [];
    for (const a of t) {
      const { description: u, transaction: { transaction: n, signers: d } } = a;
      this._debug && console.log(`Signing: ${u} for ${this.address()}`);
      let c;
      this._priorityFee?.percentile && this._priorityFee.percentile > 0 && (c = await C(this._rpc, n, this._priorityFee.percentile, this._priorityFee.percentileMultiple, this._priorityFee.min, this._priorityFee.max)), this._debug && O(n);
      for (let g = 0; g < this._maxResubmits; g++)
        try {
          if (f(n)) {
            if (c && g === 0) {
              const m = A.decompile(n.message);
              m.instructions.push(...c), n.message = m.compileToV0Message();
            }
            n.message.recentBlockhash = e, n.sign([this._keypair, ...d ?? []]);
          } else
            c && g === 0 && n.add(...c), n.recentBlockhash = e, n.lastValidBlockHeight = s, n.partialSign(this._keypair, ...d ?? []);
          this._debug && console.log("Submitting transactions ");
          const { signature: h } = await p.sendTxWithRetry(this._rpc, n.serialize(), this._sendOpts);
          i.push(h);
          break;
        } catch (h) {
          if (g === this._maxResubmits - 1 || !this.retryable(h))
            throw h;
          this._debug && console.log(`Failed to send transaction on attempt ${g}, retrying: `, h);
          const { blockhash: m, lastValidBlockHeight: k } = await p.latestBlock(this._rpc);
          s = k, e = m;
        }
    }
    this._debug && console.log("Waiting for confirmation for: ", i);
    const l = (await Promise.all(i.map(async (a) => {
      try {
        return await this._rpc.confirmTransaction({
          signature: a,
          blockhash: e,
          lastValidBlockHeight: s
        }, this._rpc.commitment);
      } catch (u) {
        throw console.error("Failed to confirm transaction: ", u), u;
      }
    }))).filter((a) => a.value.err).map((a) => a.value.err);
    if (l.length > 0)
      throw new Error(`Failed to confirm transaction: ${l}`);
    return i;
  }
}
function O(r) {
  if (f(r)) {
    console.log(r.signatures);
    const t = r.message, e = t.getAccountKeys();
    t.compiledInstructions.forEach((s) => {
      console.log("Program", e.get(s.programIdIndex).toBase58()), console.log("Data: ", R.encode(s.data)), console.log("Keys: ", s.accountKeyIndexes.map((i) => [i, e.get(i).toBase58()]));
    });
  } else
    console.log(r.signatures), console.log(r.feePayer), r.instructions.forEach((t) => {
      console.log("Program", t.programId.toBase58()), console.log("Data: ", t.data.toString("hex")), console.log("Keys: ", t.keys.map((e) => [e, e.pubkey.toBase58()]));
    });
}
async function C(r, t, e = _, s = y, i = F, o = b) {
  const [l, a] = await Promise.all([
    D(r, t),
    K(r, t, e, s, i, o)
  ]);
  return [
    E.setComputeUnitLimit({
      units: l
    }),
    E.setComputeUnitPrice({
      microLamports: a
    })
  ];
}
async function D(r, t) {
  let e = L;
  try {
    const s = await (f(t), r.simulateTransaction(t));
    s.value.err && console.error(`Error simulating Solana transaction: ${s.value.err}`), s?.value?.unitsConsumed && (e = Math.round(s.value.unitsConsumed * 1.2));
  } catch (s) {
    console.error(`Failed to calculate compute unit limit for Solana transaction: ${s}`);
  }
  return e;
}
async function w(r, t) {
  if (f(t)) {
    const e = (await Promise.all(t.message.addressTableLookups.map((o) => r.getAddressLookupTable(o.accountKey)))).map((o) => o.value).filter((o) => o !== null), s = t.message, i = s.getAccountKeys({
      addressLookupTableAccounts: e ?? void 0
    });
    return s.compiledInstructions.flatMap((o) => o.accountKeyIndexes).map((o) => s.isAccountWritable(o) ? i.get(o) : null).filter(Boolean);
  } else
    return t.instructions.flatMap((e) => e.keys).map((e) => e.isWritable ? e.pubkey : null).filter(Boolean);
}
async function K(r, t, e = _, s = y, i = F, o = b) {
  let l = i;
  const a = await w(r, t);
  try {
    const u = await r.getRecentPrioritizationFees({
      lockedWritableAccounts: a
    });
    if (u) {
      const n = u.map((c) => c.prioritizationFee).sort((c, g) => c - g), d = Math.ceil(n.length * e);
      if (n.length > d) {
        let c = n[d];
        s > 0 && (c *= s), l = Math.max(l, c);
      }
    }
  } catch (u) {
    console.error("Error fetching Solana recent fees", u);
  }
  return Math.min(Math.max(l, i), o);
}
async function v(r, t, e = _, s = y, i = F, o = b) {
  const l = e * 1e4;
  if (l < 1 || l > 1e4)
    throw new Error("percentile must be between 0.0001 and 1");
  const a = r._rpcRequest, n = [
    await w(r, t),
    {
      percentile: l
    }
  ], d = await a("getRecentPrioritizationFees", n);
  if (d.error)
    throw new Error(d.error);
  const c = d.result.map((h) => h.prioritizationFee);
  if (c.length === 0)
    return i;
  const g = Math.floor(B(c) * (s > 0 ? s : 1));
  return P(g, i, o);
}
export {
  K as a,
  v as d,
  $ as g
};
