UNPKG

@atomiqlabs/chain-starknet

Version:
131 lines (117 loc) 4.98 kB
import {Call} from "starknet"; import {StarknetChainInterface} from "./StarknetChainInterface"; import {StarknetTx} from "./modules/StarknetTransactions"; import {StarknetFees, StarknetGas} from "./modules/StarknetFees"; /** * An action which contains multiple underlying contract calls (invokes), tracks their total gas limits * and allows creating a transaction, which will execute all the contract calls * * @category Chain Interface */ export class StarknetAction { /** * Total gas limit of all the contract calls */ gas: StarknetGas; /** * Address of the signer for this transaction */ readonly mainSigner: string; private readonly root: StarknetChainInterface; private readonly instructions: Call[]; private feeRate?: string; constructor( mainSigner: string, root: StarknetChainInterface, instructions: Call[] | Call = [], gasLimit?: StarknetGas, feeRate?: string ) { this.mainSigner = mainSigner; this.root = root; this.instructions = Array.isArray(instructions) ? instructions : [instructions]; this.gas = { l1Gas: gasLimit?.l1Gas ?? 0, l2Gas: gasLimit?.l2Gas ?? 0, l1DataGas: gasLimit?.l1DataGas ?? 0, }; this.feeRate = feeRate; } private estimateFeeRate(): Promise<string> { return this.root.Fees.getFeeRate(); } /** * Adds a single invoke call to the action along with the gas limits * * @param instruction Instruction to add to the action * @param gasLimit Gas limit required for the instruction */ public addIx(instruction: Call, gasLimit?: StarknetGas) { this.instructions.push(instruction); if(gasLimit!=null) this.gas = StarknetFees.starknetGasAdd(this.gas, gasLimit); } /** * Adds contract calls from another starknet action to this action, while also adding its gas limits * * @param action Calls from this action are added to current action */ public add(action: StarknetAction): this { return this.addAction(action); } /** * Adds contract calls from another starknet action to this action, while also adding its gas limits. Adds * the contract calls at a given index provided (by default at the end of existing calls) * * @param action Calls from this action are added to current action * @param index Index at which to add the calls (by defaults added at the end) */ public addAction(action: StarknetAction, index: number = this.instructions.length): this { if(action.mainSigner!==this.mainSigner) throw new Error("Actions need to have the same signer!"); if(this.gas.l1Gas==null && action.gas.l1Gas!=null) this.gas.l1Gas = action.gas.l1Gas; if(this.gas.l2Gas==null && action.gas.l2Gas!=null) this.gas.l2Gas = action.gas.l2Gas; if(this.gas.l1DataGas==null && action.gas.l1DataGas!=null) this.gas.l1DataGas = action.gas.l1DataGas; if(this.gas.l1Gas!=null && action.gas.l1Gas!=null) this.gas.l1Gas += action.gas.l1Gas; if(this.gas.l2Gas!=null && action.gas.l2Gas!=null) this.gas.l2Gas += action.gas.l2Gas; if(this.gas.l1DataGas!=null && action.gas.l1DataGas!=null) this.gas.l1DataGas += action.gas.l1DataGas; this.instructions.splice(index, 0, ...action.instructions); if(this.feeRate==null) this.feeRate = action.feeRate; return this; } /** * Creates an unsigned starknet transaction out of this action, which executes all the underlying contract calls * * @param feeRate Fee rate to use for the transaction */ public async tx(feeRate?: string): Promise<StarknetTx> { if(feeRate==null) feeRate = this.feeRate; if(feeRate==null) feeRate = await this.estimateFeeRate(); return { type: "INVOKE", tx: this.instructions, details: { ...this.root.Fees.getFeeDetails(this.gas, feeRate), walletAddress: this.mainSigner, cairoVersion: "1", chainId: this.root.starknetChainId, nonce: null!, accountDeploymentData: [], skipValidate: false } }; } /** * Adds the generated transaction to an already existing array of transaction * * @param txs Transaction executing this action will be added to this transactions array * @param feeRate Fee rate to use for this transaction */ public async addToTxs(txs: StarknetTx[], feeRate?: string): Promise<void> { txs.push(await this.tx(feeRate)); } /** * Number of individual contract calls in this action */ public ixsLength(): number { return this.instructions.length; } }