import { __awaiter, __extends, __generator, __spreadArray } from "tslib";
import { BorshAccountsCoder } from "@coral-xyz/anchor";
import { IdlCoder } from "@coral-xyz/anchor/dist/cjs/coder/borsh/idl";
import * as borsh from "@coral-xyz/borsh";
import { Message, MessageAccountKeys, PublicKey, } from "@solana/web3.js";
import bs58 from "bs58";
/**
 * Extended Anchor accounts coder to handle large account data.
 */
var LargeAccountsCoder = /** @class */ (function (_super) {
    __extends(LargeAccountsCoder, _super);
    function LargeAccountsCoder() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    // Getter to access the private accountLayouts property from base class.
    LargeAccountsCoder.prototype.getAccountLayouts = function () {
        // Base class has `Map<A, { discriminator: IdlDiscriminator; layout: Layout }`, but we only use layout here.
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        return this.accountLayouts;
    };
    // eslint-disable-next-line @typescript-eslint/no-explicit-any, require-await
    LargeAccountsCoder.prototype.encode = function (accountName, account) {
        return __awaiter(this, void 0, void 0, function () {
            var buffer, layout, len, accountData, discriminator;
            return __generator(this, function (_a) {
                buffer = Buffer.alloc(10240);
                layout = this.getAccountLayouts().get(accountName);
                if (!layout) {
                    throw new Error("Unknown account: ".concat(accountName));
                }
                len = layout.layout.encode(account, buffer);
                accountData = buffer.slice(0, len);
                discriminator = this.accountDiscriminator(accountName);
                return [2 /*return*/, Buffer.concat([discriminator, accountData])];
            });
        });
    };
    return LargeAccountsCoder;
}(BorshAccountsCoder));
export { LargeAccountsCoder };
/**
 * Extended version of legacy CompiledKeys to handle compilation of unsigned transactions. Base implementation is here:
 * https://github.com/solana-labs/solana-web3.js/blob/v1.95.3/src/message/compiled-keys.ts
 */
var UnsignedCompiledKeys = /** @class */ (function () {
    function UnsignedCompiledKeys(keyModeMap, payer) {
        this.keyModeMap = keyModeMap;
        this.payer = payer;
    }
    UnsignedCompiledKeys.compileUnsigned = function (instructions, payer) {
        var keyModeMap = new Map();
        var getOrInsertDefault = function (pubkey) {
            var address = pubkey.toBase58();
            var keyMode = keyModeMap.get(address);
            if (keyMode === undefined) {
                keyMode = {
                    isWritable: false,
                };
                keyModeMap.set(address, keyMode);
            }
            return keyMode;
        };
        if (payer !== undefined) {
            var payerKeyMode = getOrInsertDefault(payer);
            payerKeyMode.isWritable = true;
        }
        for (var _i = 0, instructions_1 = instructions; _i < instructions_1.length; _i++) {
            var ix = instructions_1[_i];
            getOrInsertDefault(ix.programId);
            for (var _a = 0, _b = ix.keys; _a < _b.length; _a++) {
                var accountMeta = _b[_a];
                var keyMode = getOrInsertDefault(accountMeta.pubkey);
                keyMode.isWritable || (keyMode.isWritable = accountMeta.isWritable);
            }
        }
        return new UnsignedCompiledKeys(keyModeMap, payer);
    };
    UnsignedCompiledKeys.prototype.getMessageComponents = function () {
        var mapEntries = Array.from(this.keyModeMap.entries());
        if (mapEntries.length > 256)
            throw new Error("Max static account keys length exceeded");
        var writableNonSigners = mapEntries.filter(function (_a) {
            var mode = _a[1];
            return mode.isWritable;
        });
        var readonlyNonSigners = mapEntries.filter(function (_a) {
            var mode = _a[1];
            return !mode.isWritable;
        });
        var header = {
            numRequiredSignatures: 0,
            numReadonlySignedAccounts: 0,
            numReadonlyUnsignedAccounts: readonlyNonSigners.length,
        };
        var staticAccountKeys = __spreadArray(__spreadArray([], writableNonSigners.map(function (_a) {
            var address = _a[0];
            return new PublicKey(address);
        }), true), readonlyNonSigners.map(function (_a) {
            var address = _a[0];
            return new PublicKey(address);
        }), true);
        return [header, staticAccountKeys];
    };
    return UnsignedCompiledKeys;
}());
/**
 * Extended version of legacy Message to handle compilation of unsigned transactions. Base implementation is here:
 * https://github.com/solana-labs/solana-web3.js/blob/v1.95.3/src/message/legacy.ts
 */
var UnsignedMessage = /** @class */ (function (_super) {
    __extends(UnsignedMessage, _super);
    function UnsignedMessage() {
        return _super !== null && _super.apply(this, arguments) || this;
    }
    UnsignedMessage.compileUnsigned = function (instructions, payer) {
        var compiledKeys = UnsignedCompiledKeys.compileUnsigned(instructions, payer);
        var _a = compiledKeys.getMessageComponents(), header = _a[0], staticAccountKeys = _a[1];
        var accountKeys = new MessageAccountKeys(staticAccountKeys);
        var compiledInstructions = accountKeys.compileInstructions(instructions).map(function (ix) { return ({
            programIdIndex: ix.programIdIndex,
            accounts: ix.accountKeyIndexes,
            data: bs58.encode(ix.data),
        }); });
        return new Message({
            header: header,
            accountKeys: staticAccountKeys,
            recentBlockhash: "", // Not used as we are not signing the transaction.
            instructions: compiledInstructions,
        });
    };
    return UnsignedMessage;
}(Message));
/**
 * Helper to encode MulticallHandler transactions.
 */
var MulticallHandlerCoder = /** @class */ (function () {
    function MulticallHandlerCoder(instructions, payerKey) {
        // Compile transaction message and keys.
        this.compiledMessage = UnsignedMessage.compileUnsigned(instructions, payerKey);
        // Setup the layout for the encoder.
        var fieldLayouts = [IdlCoder.fieldLayout(MulticallHandlerCoder.coderArg, MulticallHandlerCoder.coderTypes)];
        this.layout = borsh.struct(fieldLayouts);
    }
    Object.defineProperty(MulticallHandlerCoder.prototype, "readOnlyLen", {
        get: function () {
            return (this.compiledMessage.header.numReadonlySignedAccounts + this.compiledMessage.header.numReadonlyUnsignedAccounts);
        },
        enumerable: false,
        configurable: true
    });
    Object.defineProperty(MulticallHandlerCoder.prototype, "compiledKeyMetas", {
        get: function () {
            var _this = this;
            return this.compiledMessage.accountKeys.map(function (key, index) {
                return {
                    pubkey: key,
                    isSigner: _this.compiledMessage.isAccountSigner(index),
                    isWritable: _this.compiledMessage.isAccountWritable(index),
                };
            });
        },
        enumerable: false,
        configurable: true
    });
    MulticallHandlerCoder.prototype.encode = function () {
        var buffer = Buffer.alloc(1280);
        var len = this.layout.encode({ compiledIxs: this.compiledMessage.compiledInstructions }, buffer);
        return buffer.slice(0, len);
    };
    MulticallHandlerCoder.coderArg = {
        name: "compiledIxs",
        type: {
            vec: {
                defined: {
                    name: "compiledIx",
                },
            },
        },
    };
    MulticallHandlerCoder.coderTypes = [
        {
            name: "compiledIx",
            type: {
                kind: "struct",
                fields: [
                    {
                        name: "programIdIndex",
                        type: "u8",
                    },
                    {
                        name: "accountKeyIndexes",
                        type: {
                            vec: "u8",
                        },
                    },
                    {
                        name: "data",
                        type: "bytes",
                    },
                ],
            },
        },
    ];
    return MulticallHandlerCoder;
}());
export { MulticallHandlerCoder };
/**
 * Helper to encode Across+ messages.
 */
var AcrossPlusMessageCoder = /** @class */ (function () {
    function AcrossPlusMessageCoder(acrossPlusMessage) {
        this.acrossPlusMessage = acrossPlusMessage;
    }
    AcrossPlusMessageCoder.prototype.encode = function () {
        var fieldLayouts = [IdlCoder.fieldLayout(AcrossPlusMessageCoder.coderArg, AcrossPlusMessageCoder.coderTypes)];
        var layout = borsh.struct(fieldLayouts);
        var buffer = Buffer.alloc(12800);
        var len = layout.encode({ message: this.acrossPlusMessage }, buffer);
        return buffer.slice(0, len);
    };
    AcrossPlusMessageCoder.coderArg = {
        name: "message",
        type: {
            defined: {
                name: "acrossPlusMessage",
            },
        },
    };
    AcrossPlusMessageCoder.coderTypes = [
        {
            name: "acrossPlusMessage",
            type: {
                kind: "struct",
                fields: [
                    {
                        name: "handler",
                        type: "pubkey",
                    },
                    {
                        name: "readOnlyLen",
                        type: "u8",
                    },
                    {
                        name: "valueAmount",
                        type: "u64",
                    },
                    {
                        name: "accounts",
                        type: {
                            vec: "pubkey",
                        },
                    },
                    {
                        name: "handlerMessage",
                        type: "bytes",
                    },
                ],
            },
        },
    ];
    return AcrossPlusMessageCoder;
}());
export { AcrossPlusMessageCoder };
//# sourceMappingURL=coders.js.map