UNPKG

ethstorage-sdk-ts

Version:

eip-4844 blobs upload sdk from ethstorage-sdk

167 lines (166 loc) 7.58 kB
"use strict"; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var _BlobUploader_instances, _BlobUploader_kzg, _BlobUploader_jsonRpc, _BlobUploader_provider, _BlobUploader_wallet, _BlobUploader_getKzg; Object.defineProperty(exports, "__esModule", { value: true }); exports.BlobUploader = void 0; const ethers_1 = require("ethers"); const kzg_wasm_1 = require("kzg-wasm"); function sleep(ms) { return new Promise((resolve) => { setTimeout(resolve, ms); }); } function parseBigintValue(value) { if (typeof value == "bigint") { return "0x" + value.toString(16); } if (typeof value == "object") { const { _hex } = value; const c = BigInt(_hex); return "0x" + c.toString(16); } return value; } function computeVersionedHash(commitment, blobCommitmentVersion) { const computedVersionedHash = new Uint8Array(32); computedVersionedHash.set([blobCommitmentVersion], 0); const hash = ethers_1.ethers.getBytes(ethers_1.ethers.sha256(commitment)); computedVersionedHash.set(hash.subarray(1), 1); return computedVersionedHash; } function commitmentsToVersionedHashes(commitment) { return computeVersionedHash(commitment, 0x01); } // blob gas price const MIN_BLOB_GASPRICE = 1n; const BLOB_GASPRICE_UPDATE_FRACTION = 3338477n; function fakeExponential(factor, numerator, denominator) { let i = 1n; let output = 0n; let numerator_accum = factor * denominator; while (numerator_accum > 0) { output += BigInt(numerator_accum); numerator_accum = (numerator_accum * BigInt(numerator)) / (denominator * i); i++; } return output / denominator; } class BlobUploader { constructor(rpc, pk) { _BlobUploader_instances.add(this); _BlobUploader_kzg.set(this, void 0); _BlobUploader_jsonRpc.set(this, void 0); _BlobUploader_provider.set(this, void 0); _BlobUploader_wallet.set(this, void 0); __classPrivateFieldSet(this, _BlobUploader_jsonRpc, rpc, "f"); __classPrivateFieldSet(this, _BlobUploader_provider, new ethers_1.ethers.JsonRpcProvider(rpc), "f"); __classPrivateFieldSet(this, _BlobUploader_wallet, new ethers_1.ethers.Wallet(pk, __classPrivateFieldGet(this, _BlobUploader_provider, "f")), "f"); } async getNonce() { return await __classPrivateFieldGet(this, _BlobUploader_wallet, "f").getNonce(); } async getBlobGasPrice() { // get current block const block = (await __classPrivateFieldGet(this, _BlobUploader_provider, "f").getBlock("latest")); const excessBlobGas = BigInt(block.excessBlobGas); return fakeExponential(MIN_BLOB_GASPRICE, excessBlobGas, BLOB_GASPRICE_UPDATE_FRACTION); } async getGasPrice() { return await __classPrivateFieldGet(this, _BlobUploader_provider, "f").getFeeData(); } async estimateGas(params) { const limit = await __classPrivateFieldGet(this, _BlobUploader_provider, "f").send("eth_estimateGas", [params]); if (limit) { return (BigInt(limit) * 6n) / 5n; } return null; } async sendTx(tx, blobs) { if (!blobs) { return await __classPrivateFieldGet(this, _BlobUploader_wallet, "f").sendTransaction(tx); } // blobs const kzg = await __classPrivateFieldGet(this, _BlobUploader_instances, "m", _BlobUploader_getKzg).call(this); const ethersBlobs = []; const versionedHashes = []; for (let i = 0; i < blobs.length; i++) { const blob = blobs[i]; const commitment = kzg.blobToKzgCommitment(blob); const proof = kzg.computeBlobKzgProof(blob, commitment); ethersBlobs.push({ data: blob, proof: proof, commitment: commitment, }); const hash = commitmentsToVersionedHashes(commitment); versionedHashes.push(ethers_1.ethers.hexlify(hash)); } let { to, value, data, gasLimit, maxFeePerBlobGas } = tx; if (gasLimit == null) { const hexValue = parseBigintValue(value); gasLimit = await this.estimateGas({ from: __classPrivateFieldGet(this, _BlobUploader_wallet, "f").address, to, data, value: hexValue, blobVersionedHashes: versionedHashes, }); if (gasLimit == null) { throw Error("estimateGas: execution reverted"); } tx.gasLimit = gasLimit; } if (maxFeePerBlobGas == null) { maxFeePerBlobGas = await this.getBlobGasPrice(); maxFeePerBlobGas = (maxFeePerBlobGas * 6n) / 5n; tx.maxFeePerBlobGas = maxFeePerBlobGas; } // send tx.type = 3; tx.blobVersionedHashes = versionedHashes; tx.blobs = ethersBlobs; tx.kzg = kzg; return await __classPrivateFieldGet(this, _BlobUploader_wallet, "f").sendTransaction(tx); } async getBlobHash(blob) { const kzg = await __classPrivateFieldGet(this, _BlobUploader_instances, "m", _BlobUploader_getKzg).call(this); const commit = kzg.blobToKzgCommitment(blob); const localHash = commitmentsToVersionedHashes(commit); const hash = new Uint8Array(32); hash.set(localHash.subarray(0, 32 - 8)); return ethers_1.ethers.hexlify(hash); } async isTransactionMined(transactionHash) { const txReceipt = await __classPrivateFieldGet(this, _BlobUploader_provider, "f").getTransactionReceipt(transactionHash); if (txReceipt && txReceipt.blockNumber) { return txReceipt; } } async getTxReceipt(transactionHash) { let txReceipt; while (!txReceipt) { txReceipt = await this.isTransactionMined(transactionHash); if (txReceipt) break; await sleep(5000); } return txReceipt; } } exports.BlobUploader = BlobUploader; _BlobUploader_kzg = new WeakMap(), _BlobUploader_jsonRpc = new WeakMap(), _BlobUploader_provider = new WeakMap(), _BlobUploader_wallet = new WeakMap(), _BlobUploader_instances = new WeakSet(), _BlobUploader_getKzg = async function _BlobUploader_getKzg() { if (!__classPrivateFieldGet(this, _BlobUploader_kzg, "f")) { __classPrivateFieldSet(this, _BlobUploader_kzg, await (0, kzg_wasm_1.loadKZG)(), "f"); } return __classPrivateFieldGet(this, _BlobUploader_kzg, "f"); };