UNPKG

ethstorage-sdk

Version:
1 lines 111 kB
{"version":3,"sources":["../src/utils/index.ts","../src/utils/util.ts","../src/param/abi.ts","../src/param/constant.ts","../src/param/bytecode.ts","../src/utils/blobs.ts","../src/utils/uploader.ts","../src/utils/web3.ts","../src/ethstorage.ts","../src/flatdirectory.ts"],"sourcesContent":["export * from './util';\nexport * from './blobs';\nexport * from './uploader';\nexport * from './web3';\n","import { ethers } from \"ethers\";\nimport { ContentLike, BufferLike, FileLike } from \"../param\";\n\nexport const stringToHex = (s: string): string => ethers.hexlify(ethers.toUtf8Bytes(s));\n\nexport async function getChainId(rpc: string): Promise<number> {\n const provider = new ethers.JsonRpcProvider(rpc);\n const network = await provider.getNetwork();\n return Number(network.chainId);\n}\n\nexport async function getContentChunk(content: ContentLike, start: number, end: number) {\n if (isBuffer(content)) {\n return content.slice(start, Math.min(end, content.length));\n } else {\n const slice = content.slice(start, Math.min(end, content.size));\n const data = await slice.arrayBuffer();\n return new Uint8Array(data);\n }\n}\n\nexport function isBuffer(content: ContentLike): content is BufferLike {\n return content instanceof Uint8Array;\n}\n\nexport function isFile(content: ContentLike): content is FileLike {\n if (isNodejs()) {\n return content && typeof content === 'object' &&\n typeof (content as any).isNodeJs === 'boolean' &&\n (content as any).isNodeJs;\n } else {\n return content instanceof File;\n }\n}\n\nexport function isNodejs(): boolean {\n return typeof process !== 'undefined' && !!process.versions && !!process.versions.node;\n}\n\nexport function computeVersionedCommitmentHash(commitment: Uint8Array): Uint8Array {\n const computedVersionedHash = new Uint8Array(32);\n computedVersionedHash.set([0x01], 0);\n const hash = ethers.getBytes(ethers.sha256(commitment));\n computedVersionedHash.set(hash.subarray(1), 1);\n return computedVersionedHash;\n}\n\nexport function convertToEthStorageHash(commitment: Uint8Array): string {\n const localHash = computeVersionedCommitmentHash(commitment);\n const hash = new Uint8Array(32);\n hash.set(localHash.subarray(0, 32 - 8));\n return ethers.hexlify(hash);\n}\n\nexport function convertToEthStorageHashes(commitments: Uint8Array[]): string[] {\n return commitments.map(commitment => convertToEthStorageHash(commitment));\n}\n\nexport async function retry<T>(fn: (...args: any[]) => Promise<T>, retries: number, ...args: any[]): Promise<T> {\n for (let i = 0; i < retries; i++) {\n try {\n return await fn(...args);\n } catch (error) {\n if (i === retries - 1) {\n throw error;\n }\n }\n }\n throw new Error('Function failed after maximum retries');\n}\n\nexport function copy(des: Uint8Array, desOff: number, src: Uint8Array, srcOff: number): number {\n const srcLength = src.length - srcOff;\n const desLength = des.length - desOff;\n const length = Math.min(srcLength, desLength);\n des.set(src.subarray(srcOff, srcOff + length), desOff);\n return length;\n}\n","\nexport const EthStorageAbi: readonly string[] = [\n 'function putBlobs(bytes32[] memory _keys, uint256[] memory _blobIdxs, uint256[] memory _lengths)',\n 'function putBlob(bytes32 _key, uint256 _blobIdx, uint256 _length) public payable',\n 'function get(bytes32 _key, uint8 _decodeType, uint256 _off, uint256 _len) public view returns (bytes memory)',\n 'function size(bytes32 _key) public view returns (uint256)',\n 'function upfrontPayment() public view returns (uint256)'\n];\n\nexport const FlatDirectoryAbi: readonly string[] = [\n \"constructor(uint8 slotLimit, uint32 maxChunkSize, address storageAddress) public\",\n \"function version() external view returns (string)\",\n \"function isSupportBlob() view external returns (bool)\",\n \"function setDefault(bytes memory _defaultFile) external\",\n \"function getChunkHash(bytes memory name, uint256 chunkId) public view returns (bytes32)\",\n \"function writeChunk(bytes memory name, uint256 chunkId, bytes calldata data) external payable\",\n \"function writeChunks(bytes memory name, uint256[] memory chunkIds, uint256[] memory sizes) external payable\",\n \"function remove(bytes memory name) external returns (uint256)\",\n \"function truncate(bytes memory name, uint256 chunkId) external returns (uint256)\",\n\n \"function readChunk(bytes memory name, uint256 chunkId) external view returns (bytes memory, bool)\",\n \"function countChunks(bytes memory name) external view returns (uint256)\",\n \"function getUploadInfo(bytes memory name) external view returns (uint8 mode, uint256 chunkCount, uint256 storageCost)\",\n \"function getChunkHashesBatch((bytes,uint256[])[] memory fileChunks) external view returns (bytes32[] memory)\",\n \"function getChunkCountsBatch(bytes[] memory names) external view returns (uint256[] memory)\"\n];\n","\nconst SEPOLIA_CHAIN_ID: number = 11155111;\nconst QUARKCHAIN_L2_DEVNET_CHAIN_ID: number = 42069;\nconst QUARKCHAIN_L2_TESTNET_CHAIN_ID: number = 3335;\n\nexport const ETHSTORAGE_MAPPING: Record<number, string> = {\n [SEPOLIA_CHAIN_ID]: '0x804C520d3c084C805E37A35E90057Ac32831F96f',\n [QUARKCHAIN_L2_DEVNET_CHAIN_ID]: '0x90a708C0dca081ca48a9851a8A326775155f87Fd',\n [QUARKCHAIN_L2_TESTNET_CHAIN_ID]: '0x64003adbdf3014f7E38FC6BE752EB047b95da89A',\n};\n\n\n\nconst BlobTxBytesPerFieldElement: number = 32; // Size in bytes of a field element\nconst BlobTxFieldElementsPerBlob: number = 4096;\nexport const BLOB_SIZE: number = BlobTxBytesPerFieldElement * BlobTxFieldElementsPerBlob;\n\nexport const OP_BLOB_DATA_SIZE: number = (4 * 31 + 3) * 1024 - 4;\n\n\n// DecodeType\nexport enum DecodeType {\n RawData,\n PaddingPer31Bytes,\n OptimismCompact,\n}\n\nexport const BLOB_COUNT_LIMIT: number = 6;\nexport const MAX_BLOB_COUNT: number = 3;\n\n\nexport enum UploadType {\n Undefined,\n Calldata,\n Blob,\n}\n\n\nexport const MAX_RETRIES: number = 3;\n\n/**\n * eth_call consumes gas, so we need to estimate the maximum number of chunks based on a 30 million gas limit.\n * Additionally, we need to reserve a portion of the gas for the cost of the request parameters (which can vary dynamically).\n */\nexport const MAX_CHUNKS: number = 120;\n\n\n// Randomly generated fixed hash for testing purposes\nexport const DUMMY_VERSIONED_COMMITMENT_HASH = '0x01f32ebe6ad26adca597cdb198f041f5d96fc197e3de72e299e86fbf1f5817c8';\n","\n// Contract bytecode\n// contracts/examples/FlatDirectory.sol\n\n// sol: 0.8.18, evm: london, code: https://github.com/ethstorage/evm-large-storage/commit/8d2feeb4c6697dee7ba2b8a0bd6504b85fc179dd old 1\n\n// sol: 0.8.27, evm: london, code: https://github.com/ethstorage/evm-large-storage/commit/ac89782cecbff79ef6cf3263b5eb27286fbfa877 old 2\n\n// sol: 0.8.29, evm: cancun, code: https://github.com/ethstorage/evm-large-storage/commit/e43bf61c9a779cca8ee6a4a005e22e2dddde18cb\n\n// sol: 0.8.20, evm: cancun, code: https://github.com/ethstorage/evm-large-storage/commit/1619d941d2db691e04392f2796216126033f949a\nexport const FlatDirectoryBytecode: string = \"0x60c06040525f60a0908152600a90620000199082620001cb565b5034801562000026575f80fd5b506040516200399a3803806200399a833981016040819052620000499162000293565b60ff8316608052828282818133806200007b57604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b6200008681620000da565b506004805463ffffffff909316600160a01b0263ffffffff60a01b1990931692909217909155600580546001600160a01b039092166001600160a01b031990921691909117905550620002f9945050505050565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200015457607f821691505b6020821081036200017357634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620001c6575f81815260208120601f850160051c81016020861015620001a15750805b601f850160051c820191505b81811015620001c257828155600101620001ad565b5050505b505050565b81516001600160401b03811115620001e757620001e76200012b565b620001ff81620001f884546200013f565b8462000179565b602080601f83116001811462000235575f84156200021d5750858301515b5f19600386901b1c1916600185901b178555620001c2565b5f85815260208120601f198616915b82811015620002655788860151825594840194600190910190840162000244565b50858210156200028357878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f805f60608486031215620002a6575f80fd5b835160ff81168114620002b7575f80fd5b602085015190935063ffffffff81168114620002d1575f80fd5b60408501519092506001600160a01b0381168114620002ee575f80fd5b809150509250925092565b608051613681620003195f395f81816105bf015261234801526136815ff3fe6080604052600436106200021d575f3560e01c80635ba1d9e51162000126578063caf1283611620000ae578063dd473fae1162000078578063dd473fae1462000847578063f14c7ad71462000864578063f2fde38b146200087b578063f53264ea146200089f578063f916c5b014620008c3576200021d565b8063caf12836146200078a578063cf86bf9314620007c4578063d84eb56c14620007ff578063dc38b0a21462000823576200021d565b806393b7628f11620000f057806393b7628f14620006c6578063956a3433146200070f578063a741f1cb1462000733578063c708dd141462000766576200021d565b80635ba1d9e51462000648578063715018a6146200066c5780638bf4515c14620006835780638da5cb5b14620006a7576200021d565b80631ccbc6da11620001aa5780634db654f911620001745780634db654f914620005995780634eed7cf114620005b057806354fd4d5014620005f557806358edef4c1462000624576200021d565b80631ccbc6da14620005145780631fbfa127146200053a57806342216bed1462000551578063492c7b2a1462000575576200021d565b8063152a4bb311620001ec578063152a4bb3146200044d5780631a7237e014620004825780631c5ee10c14620004b65780631c993ad514620004f0576200021d565b8063038cd79f146200039a5780630936286114620003c05780631089f40f14620003ef57806311ce02671462000413575b34801562000229575f80fd5b505f366060808284036200024d57505060408051602081019091525f81526200038f565b83835f81811062000262576200026262002a63565b9050013560f81c60f81b6001600160f81b031916602f60f81b14620002ae57505060408051808201909152600e81526d0d2dcc6dee4e4cac6e840e0c2e8d60931b60208201526200038f565b8383620002bd60018262002a8b565b818110620002cf57620002cf62002a63565b909101356001600160f81b031916602f60f81b039050620003315762000328620002fd846001818862002aa1565b600a604051602001620003139392919062002afe565b604051602081830303815290604052620008e7565b50905062000382565b6200037e62000344846001818862002aa1565b8080601f0160208091040260200160405190810160405280939291908181526020018383808284375f92019190915250620008e792505050565b5090505b6200038d81620009ab565b505b915050805190602001f35b348015620003a6575f80fd5b50620003be620003b836600462002cb8565b620009de565b005b348015620003cc575f80fd5b50620003d7620009fb565b604051620003e6919062002d73565b60405180910390f35b348015620003fb575f80fd5b50620003be6200040d36600462002d8e565b62000a8f565b3480156200041f575f80fd5b5060055462000434906001600160a01b031681565b6040516001600160a01b039091168152602001620003e6565b34801562000459575f80fd5b50620004716200046b36600462002db3565b62000abf565b604051620003e69392919062002e19565b3480156200048e575f80fd5b50620004a6620004a036600462002e3c565b62000b72565b604051620003e692919062002e81565b348015620004c2575f80fd5b50620004da620004d436600462002db3565b62000c1d565b60408051928352602083019190915201620003e6565b348015620004fc575f80fd5b50620003be6200050e36600462002db3565b62000cc1565b34801562000520575f80fd5b506200052b62000cdd565b604051908152602001620003e6565b620003be6200054b36600462002f35565b62000d50565b3480156200055d575f80fd5b506200052b6200056f36600462002e3c565b62000d67565b34801562000581575f80fd5b50620003be6200059336600462002fc0565b62000e00565b620003be620005aa36600462002f35565b62000e1e565b348015620005bc575f80fd5b507f000000000000000000000000000000000000000000000000000000000000000060ff1615155b6040519015158152602001620003e6565b34801562000601575f80fd5b506040805180820190915260058152640312e302e360dc1b6020820152620003d7565b34801562000630575f80fd5b506200052b6200064236600462002db3565b62000f82565b34801562000654575f80fd5b50620005e46200066636600462002e3c565b62001015565b34801562000678575f80fd5b50620003be62001098565b3480156200068f575f80fd5b50620004a6620006a136600462002db3565b620008e7565b348015620006b3575f80fd5b506004546001600160a01b031662000434565b348015620006d2575f80fd5b5062000700620006e436600462002db3565b80516020918201205f9081526009909152604090205460ff1690565b604051620003e6919062003031565b3480156200071b575f80fd5b506200052b6200072d36600462003046565b620010af565b3480156200073f575f80fd5b50620007576200075136600462003067565b6200114f565b604051620003e691906200311d565b34801562000772575f80fd5b50620007576200078436600462003162565b6200120a565b34801562000796575f80fd5b50620007ae620007a836600462002e3c565b620013ae565b60408051928352901515602083015201620003e6565b348015620007d0575f80fd5b50600454620007e990600160a01b900463ffffffff1681565b60405163ffffffff9091168152602001620003e6565b3480156200080b575f80fd5b506200052b6200081d36600462002e3c565b6200142b565b3480156200082f575f80fd5b50620003be620008413660046200326a565b620014a4565b34801562000853575f80fd5b50651b585b9d585b60d21b6200052b565b34801562000870575f80fd5b50620005e4620014d0565b34801562000887575f80fd5b50620003be620008993660046200326a565b620014fa565b348015620008ab575f80fd5b50620003be620008bd36600462002fc0565b6200153d565b348015620008cf575f80fd5b506200052b620008e136600462002db3565b6200162e565b60605f805f620009128580516020918201205f8181526009909252604090912054909160ff90911690565b909250905060028160028111156200092e576200092e62002de8565b036200094a576200093f82620016ac565b935093505050915091565b600181600281111562000961576200096162002de8565b0362000972576200093f8262001883565b5f5b6040519080825280601f01601f1916602001820160405280156200099f576020820181803683370190505b50955f95509350505050565b5f81516040620009bc919062003292565b9050601f19620009ce82601f62003292565b1690506020808303528060208303f35b620009e8620019c0565b620009f6835f848462000e00565b505050565b600a805462000a0a9062002aca565b80601f016020809104026020016040519081016040528092919081815260200182805462000a389062002aca565b801562000a875780601f1062000a5d5761010080835404028352916020019162000a87565b820191905f5260205f20905b81548152906001019060200180831162000a6957829003601f168201915b505050505081565b62000a99620019c0565b6004805463ffffffff909216600160a01b0263ffffffff60a01b19909216919091179055565b80516020808301919091205f8181526009909252604082205460ff16919081906002848181111562000af55762000af562002de8565b0362000b12575f818152600760205260409020545b925062000b47565b600184600281111562000b295762000b2962002de8565b0362000b43575f8181526002602052604090205462000b0a565b5f92505b6005546001600160a01b031662000b5f575f62000b69565b62000b6962000cdd565b93959294505050565b60605f805f62000b9d8680516020918201205f8181526009909252604090912054909160ff90911690565b9092509050600281600281111562000bb95762000bb962002de8565b0362000bd75762000bcb8286620019ef565b93509350505062000c16565b600181600281111562000bee5762000bee62002de8565b0362000c005762000bcb828662001ac6565b5050604080515f80825260208201909252925090505b9250929050565b80516020808301919091205f8181526009909252604082205482919060ff166002818181111562000c525762000c5262002de8565b0362000c78575f828152600860209081526040808320546007909252909120546200093f565b600181600281111562000c8f5762000c8f62002de8565b0362000cb5575f828152600360209081526040808320546002909252909120546200093f565b505f9485945092505050565b62000ccb620019c0565b600a62000cd98282620032f1565b5050565b60055460408051630e65e36d60e11b815290515f926001600160a01b031691631ccbc6da9160048083019260209291908290030181865afa15801562000d25573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062000d4b9190620033b9565b905090565b62000d5a620019c0565b620009f683838362000e1e565b81516020808401919091205f8181526009909252604082205460ff166002818181111562000d995762000d9962002de8565b0362000db55762000dab8285620010af565b9250505062000dfa565b600181600281111562000dcc5762000dcc62002de8565b0362000df4575f62000ddf838662001ac6565b508051602090910120935062000dfa92505050565b505f9150505b92915050565b62000e0a620019c0565b62000e18848484846200153d565b50505050565b62000e28620019c0565b62000e32620014d0565b62000e9d5760405162461bcd60e51b815260206004820152603060248201527f5468652063757272656e74206e6574776f726b20646f6573206e6f742073757060448201526f1c1bdc9d08189b1bd8881d5c1b1bd85960821b60648201526084015b60405180910390fd5b82516020808501919091205f81815260099092526040822054909160ff9091169081600281111562000ed35762000ed362002de8565b148062000ef45750600281600281111562000ef25762000ef262002de8565b145b62000f395760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642073746f72616765206d6f646560601b604482015260640162000e94565b5f81600281111562000f4f5762000f4f62002de8565b0362000f6e575f828152600960205260409020805460ff191660021790555b62000f7b82858562001b39565b5050505050565b5f62000f8d620019c0565b81516020808401919091205f81815260099092526040909120805460ff19811690915560ff166002818181111562000fc95762000fc962002de8565b0362000fe35762000fdb825f62001e56565b949350505050565b600181600281111562000ffa5762000ffa62002de8565b036200100c5762000fdb825f62001f83565b505f9392505050565b5f62001020620019c0565b82516020808501919091205f818152600990925260409091205460ff166002818181111562001053576200105362002de8565b03620010655762000dab828562002024565b60018160028111156200107c576200107c62002de8565b036200108e5762000dab828562002146565b505f949350505050565b620010a2620019c0565b620010ad5f620021d7565b565b6005545f83815260066020908152604080832085845290915280822054905163d8389dc560e01b815291926001600160a01b03169163d8389dc591620010fb9160040190815260200190565b602060405180830381865afa15801562001117573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200113d9190620033d1565b67ffffffffffffffff19169392505050565b60605f82516001600160401b038111156200116e576200116e62002b85565b60405190808252806020026020018201604052801562001198578160200160208202803683370190505b5090505f5b83518110156200120357620011ce848281518110620011c057620011c062002a63565b60200260200101516200162e565b828281518110620011e357620011e362002a63565b602090810291909101015280620011fa81620033fb565b9150506200119d565b5092915050565b60605f805b83518110156200125f578381815181106200122e576200122e62002a63565b602002602001015160200151518262001248919062003292565b9150806200125681620033fb565b9150506200120f565b505f816001600160401b038111156200127c576200127c62002b85565b604051908082528060200260200182016040528015620012a6578160200160208202803683370190505b5090505f805b8551811015620013a4575f5b868281518110620012cd57620012cd62002a63565b602002602001015160200151518110156200138e5762001349878381518110620012fb57620012fb62002a63565b60200260200101515f01518884815181106200131b576200131b62002a63565b60200260200101516020015183815181106200133b576200133b62002a63565b602002602001015162000d67565b8484815181106200135e576200135e62002a63565b6020908102919091010152826200137581620033fb565b93505080806200138590620033fb565b915050620012b8565b50806200139b81620033fb565b915050620012ac565b5090949350505050565b81516020808401919091205f8181526009909252604082205482919060ff1660028181811115620013e357620013e362002de8565b03620013f55762000bcb828662002228565b60018160028111156200140c576200140c62002de8565b036200141e5762000bcb8286620022e4565b505f958695509350505050565b5f62001436620019c0565b82516020808501919091205f818152600990925260409091205460ff166002818181111562001469576200146962002de8565b036200147b5762000dab828562001e56565b600181600281111562001492576200149262002de8565b036200108e5762000dab828562001f83565b620014ae620019c0565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b6005545f906001600160a01b03161580159062000d4b57505f620014f362000cdd565b1015905090565b62001504620019c0565b6001600160a01b0381166200152f57604051631e4fbdf760e01b81525f600482015260240162000e94565b6200153a81620021d7565b50565b62001547620019c0565b83516020808601919091205f81815260099092526040822054909160ff909116908160028111156200157d576200157d62002de8565b14806200159e575060018160028111156200159c576200159c62002de8565b145b620015e35760405162461bcd60e51b8152602060048201526014602482015273496e76616c69642073746f72616765206d6f646560601b604482015260640162000e94565b5f816002811115620015f957620015f962002de8565b0362001618575f828152600960205260409020805460ff191660011790555b620016268286868662002337565b505050505050565b80516020808301919091205f8181526009909252604082205460ff166002818181111562001660576200166062002de8565b036200167b57505f9081526007602052604090205492915050565b600181600281111562001692576200169262002de8565b036200100c575f8281526002602052604090205462000fdb565b60605f805f620016d4855f908152600860209081526040808320546007909252909120549091565b91509150805f03620016e7575f62000974565b5f826001600160401b0381111562001703576200170362002b85565b6040519080825280601f01601f1916602001820160405280156200172e576020820181803683370190505b5090505f805b8381101562001874575f88815260066020908152604080832084845290915280822054600554915163afd5644d60e01b8152600481018290529092916001600160a01b03169063afd5644d90602401602060405180830381865afa1580156200179f573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620017c59190620033b9565b60055460405163bea94b8b60e01b81529192506001600160a01b03169063bea94b8b90620017ff9085906002905f90879060040162003416565b5f60405180830381865afa1580156200181a573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405262001843919081019062003443565b508060406020868801013e6200185a818562003292565b9350505080806200186b90620033fb565b91505062001734565b50909660019650945050505050565b60605f805f620018ab855f908152600360209081526040808320546002909252909120549091565b91509150805f03620018be575f62000974565b5f826001600160401b03811115620018da57620018da62002b85565b6040519080825280601f01601f19166020018201604052801562001905576020820181803683370190505b509050602081015f5b8381101562001874575f88815260208181526040808320848452909152812054906200193a826200241b565b156200197b576200194b8260e01c90565b5f8b81526001602090815260408083208784529091529020909150620019739083866200242f565b50506200199a565b816200198781620024df565b50915062001996818662002504565b5050505b620019a6818562003292565b935050508080620019b790620033fb565b9150506200190e565b6004546001600160a01b03163314620010ad5760405163118cdaa760e01b815233600482015260240162000e94565b60605f80620019ff858562002228565b509050600181101562001a25575050604080515f80825260208201909252915062000c16565b6005545f86815260066020908152604080832088845290915280822054905163bea94b8b60e01b815291926001600160a01b03169163bea94b8b9162001a75916002908690889060040162003416565b5f60405180830381865afa15801562001a90573d5f803e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405262001ab9919081019062003443565b9660019650945050505050565b5f828152602081815260408083208484529091528120546060919062001aec816200241b565b1562001b23575f858152600160209081526040808320878452909152902062001b1690826200253c565b6001925092505062000c16565b62001b2e81620025df565b925092505062000c16565b815160055460408051630e65e36d60e11b815290515f926001600160a01b031691631ccbc6da9160048083019260209291908290030181865afa15801562001b83573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001ba99190620033b9565b905062001bb78282620034bd565b34101562001bff5760405162461bcd60e51b8152602060048201526014602482015273496e73756666696369656e742062616c616e636560601b604482015260640162000e94565b5f5b82811015620016265783818151811062001c1f5762001c1f62002a63565b60200260200101515f10801562001c6a5750600460149054906101000a900463ffffffff1663ffffffff1684828151811062001c5f5762001c5f62002a63565b602002602001015111155b62001caf5760405162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840c6d0eadcd640d8cadccee8d60631b604482015260640162000e94565b62001cf48686838151811062001cc95762001cc962002a63565b602002602001015186848151811062001ce65762001ce662002a63565b60200260200101516200265e565b5f338787848151811062001d0c5762001d0c62002a63565b602002602001015160405160200162001d43939291906001600160a01b039390931683526020830191909152604082015260600190565b60405160208183030381529060405280519060200120905060055f9054906101000a90046001600160a01b03166001600160a01b0316634581a92084838589878151811062001d965762001d9662002a63565b60200260200101516040518563ffffffff1660e01b815260040162001dce939291909283526020830191909152604082015260600190565b5f604051808303818588803b15801562001de6575f80fd5b505af115801562001df9573d5f803e3d5ffd5b50505050508060065f8981526020019081526020015f205f88858151811062001e265762001e2662002a63565b602002602001015181526020019081526020015f208190555050808062001e4d90620033fb565b91505062001c01565b5f5b5f8381526006602090815260408083208584529091529020541562001f7d576005545f84815260066020908152604080832086845290915280822054905163afd5644d60e01b815291926001600160a01b03169163afd5644d9162001ec39160040190815260200190565b602060405180830381865afa15801562001edf573d5f803e3d5ffd5b505050506040513d601f19601f8201168201806040525081019062001f059190620033b9565b90508060085f8681526020019081526020015f205f82825462001f29919062002a8b565b90915550505f84815260066020908152604080832086845282528083208390558683526007909152812080549162001f6183620034d7565b9190505550828062001f7390620033fb565b9350505062001e58565b50919050565b5f5b5f838152602081815260408083208584529091529020541562001f7d575f62001faf8484620022e4565b505f8581526020818152604080832087845282528083208390558783526002909152812080549293509062001fe483620034d7565b90915550505f84815260036020526040812080548392906200200890849062002a8b565b909155508390506200201a81620033fb565b9350505062001f85565b5f82815260076020526040812054620020409060019062002a8b565b82146200204f57505f62000dfa565b6005545f84815260066020908152604080832086845290915280822054905163afd5644d60e01b815291926001600160a01b03169163afd5644d916200209b9160040190815260200190565b602060405180830381865afa158015620020b7573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620020dd9190620033b9565b5f8581526006602090815260408083208784528252808320839055878352600790915281208054929350906200211383620034d7565b90915550505f84815260086020526040812080548392906200213790849062002a8b565b90915550600195945050505050565b5f82815260026020526040812054620021629060019062002a8b565b82146200217157505f62000dfa565b5f6200217e8484620022e4565b505f85815260208181526040808320878452825280832083905587835260029091528120805492935090620021b383620034d7565b90915550505f84815260036020526040812080548392906200213790849062002a8b565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f82815260076020526040812054819083106200224a57505f90508062000c16565b6005545f85815260066020908152604080832087845290915280822054905163afd5644d60e01b815291926001600160a01b03169163afd5644d91620022969160040190815260200190565b602060405180830381865afa158015620022b2573d5f803e3d5ffd5b505050506040513d601f19601f82011682018060405250810190620022d89190620033b9565b95600195509350505050565b5f8281526020818152604080832084845290915281205481908062002310575f80925092505062000c16565b6200231b816200241b565b156200232c5762001b168160e01c90565b62001b2e81620024df565b62002344848483620027d5565b60ff7f000000000000000000000000000000000000000000000000000000000000000016811115620023a9576200238c620023808383620028f7565b6001600160a01b031690565b5f8581526020818152604080832087845290915290205562000e18565b5f8481526001602090815260408083208684528252918290208251601f8501839004830281018301909352838352620023fe92909185908590819084018382808284375f920191909152506200293992505050565b5f8581526020818152604080832087845290915290205550505050565b5f80620024288360e01c90565b1192915050565b5f805f6200243d85620029d1565b808652909350905083601c841115620024d157601c81015f805b6020600162002468601c8a62002a8b565b6200247590602062003292565b62002481919062002a8b565b6200248d9190620034ef565b811015620024cd575f81815260208b81526040909120548085529250620024b690849062003292565b925080620024c481620033fb565b91505062002457565b5050505b600192505050935093915050565b5f806001600160a01b038316620024fa57505f928392509050565b50503b9081151590565b5f805f806200251386620024df565b91509150806200252b575f8093509350505062000c16565b815f86883c50946001945092505050565b60605f6200254a83620029eb565b92509050601c8111156200120357603c82015f805b6020600162002570601c8762002a8b565b6200257d90602062003292565b62002589919062002a8b565b620025959190620034ef565b811015620025d5575f81815260208881526040909120548085529250620025be90849062003292565b925080620025cc81620033fb565b9150506200255f565b5050505092915050565b60605f805f620025ef85620024df565b915091508062002600575f62000974565b5f826001600160401b038111156200261c576200261c62002b85565b6040519080825280601f01601f19166020018201604052801562002647576020820181803683370190505b509050825f60208301883c95600195509350505050565b5f83815260076020526040902054821115620026b65760405162461bcd60e51b8152602060048201526016602482015275135d5cdd081c995c1b1858d9481bdc88185c1c195b9960521b604482015260640162000e94565b5f838152600760205260409020548210156200278b576005545f84815260066020908152604080832086845290915280822054905163afd5644d60e01b815291926001600160a01b03169163afd5644d91620027189160040190815260200190565b602060405180830381865afa15801562002734573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906200275a9190620033b9565b90508060085f8681526020019081526020015f205f8282546200277e919062002a8b565b90915550620027ac915050565b5f838152600760205260408120805491620027a683620033fb565b91905055505b5f8381526008602052604081208054839290620027cb90849062003292565b9091555050505050565b5f838152602081815260408083208584529091529020548062002894578215806200282757505f848152602081905260408120816200281660018762002a8b565b81526020019081526020015f205414155b6200286e5760405162461bcd60e51b81526020600482015260166024820152751b5d5cdd081c995c1b1858d9481bdc88185c1c195b9960521b604482015260640162000e94565b5f8481526002602052604081208054916200288983620033fb565b9190505550620028cd565b5f620028a18585620022e4565b5090508060035f8781526020019081526020015f205f828254620028c6919062002a8b565b9091555050505b5f8481526003602052604081208054849290620028ec90849062003292565b909155505050505050565b5f808383604051620029099062002a55565b620029169291906200350f565b604051809103905ff08015801562002930573d5f803e3d5ffd5b50949350505050565b805160208083015160e083901b911c1790601c81111562001203575f603c8401815b602060016200296c601c8762002a8b565b6200297990602062003292565b62002985919062002a8b565b620029919190620034ef565b811015620025d55781519250620029aa82602062003292565b5f828152602089905260409020849055915080620029c881620033fb565b9150506200295b565b5f80620029de8360e01c90565b9360209390931b92915050565b5f6060620029f98360e01c90565b9150602083901b9250816001600160401b0381111562002a1d5762002a1d62002b85565b6040519080825280601f01601f19166020018201604052801562002a48576020820181803683370190505b5060208101939093525091565b61010e806200353e83390190565b634e487b7160e01b5f52603260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b8181038181111562000dfa5762000dfa62002a77565b5f808585111562002ab0575f80fd5b8386111562002abd575f80fd5b5050820193919092039150565b600181811c9082168062002adf57607f821691505b60208210810362001f7d57634e487b7160e01b5f52602260045260245ffd5b828482375f8382015f81525f845462002b178162002aca565b6001828116801562002b32576001811462002b485762002b76565b60ff198416865282151583028601945062002b76565b885f526020805f205f5b8581101562002b6d5781548982015290840190820162002b52565b50505082860194505b50929998505050505050505050565b634e487b7160e01b5f52604160045260245ffd5b604080519081016001600160401b038111828210171562002bbe5762002bbe62002b85565b60405290565b604051601f8201601f191681016001600160401b038111828210171562002bef5762002bef62002b85565b604052919050565b5f6001600160401b0382111562002c125762002c1262002b85565b50601f01601f191660200190565b5f82601f83011262002c30575f80fd5b813562002c4762002c418262002bf7565b62002bc4565b81815284602083860101111562002c5c575f80fd5b816020850160208301375f918101602001919091529392505050565b5f8083601f84011262002c89575f80fd5b5081356001600160401b0381111562002ca0575f80fd5b60208301915083602082850101111562000c16575f80fd5b5f805f6040848603121562002ccb575f80fd5b83356001600160401b038082111562002ce2575f80fd5b62002cf08783880162002c20565b9450602086013591508082111562002d06575f80fd5b5062002d158682870162002c78565b9497909650939450505050565b5f5b8381101562002d3e57818101518382015260200162002d24565b50505f910152565b5f815180845262002d5f81602086016020860162002d22565b601f01601f19169290920160200192915050565b602081525f62002d87602083018462002d46565b9392505050565b5f6020828403121562002d9f575f80fd5b813563ffffffff8116811462002d87575f80fd5b5f6020828403121562002dc4575f80fd5b81356001600160401b0381111562002dda575f80fd5b62000fdb8482850162002c20565b634e487b7160e01b5f52602160045260245ffd5b600381106200153a57634e487b7160e01b5f52602160045260245ffd5b6060810162002e288562002dfc565b938152602081019290925260409091015290565b5f806040838503121562002e4e575f80fd5b82356001600160401b0381111562002e64575f80fd5b62002e728582860162002c20565b95602094909401359450505050565b604081525f62002e95604083018562002d46565b905082151560208301529392505050565b5f6001600160401b0382111562002ec15762002ec162002b85565b5060051b60200190565b5f82601f83011262002edb575f80fd5b8135602062002eee62002c418362002ea6565b82815260059290921b8401810191818101908684111562002f0d575f80fd5b8286015b8481101562002f2a578035835291830191830162002f11565b509695505050505050565b5f805f6060848603121562002f48575f80fd5b83356001600160401b038082111562002f5f575f80fd5b62002f6d8783880162002c20565b9450602086013591508082111562002f83575f80fd5b62002f918783880162002ecb565b9350604086013591508082111562002fa7575f80fd5b5062002fb68682870162002ecb565b9150509250925092565b5f805f806060858703121562002fd4575f80fd5b84356001600160401b038082111562002feb575f80fd5b62002ff98883890162002c20565b955060208701359450604087013591508082111562003016575f80fd5b50620030258782880162002c78565b95989497509550505050565b60208101620030408362002dfc565b91905290565b5f806040838503121562003058575f80fd5b50508035926020909101359150565b5f602080838503121562003079575f80fd5b82356001600160401b038082111562003090575f80fd5b818501915085601f830112620030a4575f80fd5b8135620030b562002c418262002ea6565b81815260059190911b83018401908481019088831115620030d4575f80fd5b8585015b838110156200311057803585811115620030f1575f8081fd5b620031018b89838a010162002c20565b845250918601918601620030d8565b5098975050505050505050565b602080825282518282018190525f9190848201906040850190845b81811015620031565783518352928401929184019160010162003138565b50909695505050505050565b5f602080838503121562003174575f80fd5b82356001600160401b03808211156200318b575f80fd5b818501915085601f8301126200319f575f80fd5b8135620031b062002c418262002ea6565b81815260059190911b83018401908481019088831115620031cf575f80fd5b8585015b838110156200311057803585811115620031ec575f8081fd5b86016040818c03601f190181131562003204575f8081fd5b6200320e62002b99565b898301358881111562003220575f8081fd5b620032308e8c8387010162002c20565b82525090820135908782111562003246575f8081fd5b620032568d8b8486010162002ecb565b818b015285525050918601918601620031d3565b5f602082840312156200327b575f80fd5b81356001600160a01b038116811462002d87575f80fd5b8082018082111562000dfa5762000dfa62002a77565b601f821115620009f6575f81815260208120601f850160051c81016020861015620032d05750805b601f850160051c820191505b818110156200162657828155600101620032dc565b81516001600160401b038111156200330d576200330d62002b85565b62003325816200331e845462002aca565b84620032a8565b602080601f8311600181146200335b575f8415620033435750858301515b5f19600386901b1c1916600185901b17855562001626565b5f85815260208120601f198616915b828110156200338b578886015182559484019460019091019084016200336a565b5085821015620033a957878501515f19600388901b60f8161c191681555b5050505050600190811b01905550565b5f60208284031215620033ca575f80fd5b5051919050565b5f60208284031215620033e2575f80fd5b815167ffffffffffffffff198116811462002d87575f80fd5b5f600182016200340f576200340f62002a77565b5060010190565b84815260808101620034288562002dfc565b84602083015283604083015282606083015295945050505050565b5f6020828403121562003454575f80fd5b81516001600160401b038111156200346a575f80fd5b8201601f810184136200347b575f80fd5b80516200348c62002c418262002bf7565b818152856020838501011115620034a1575f80fd5b620034b482602083016020860162002d22565b95945050505050565b808202811582820484141762000dfa5762000dfa62002a77565b5f81620034e857620034e862002a77565b505f190190565b5f826200350a57634e487b7160e01b5f52601260045260245ffd5b500490565b60208152816020820152818360408301375f818301604090810191909152601f909201601f1916010191905056fe608060405234801561000f575f80fd5b5060405161010e38038061010e83398101604081905261002e9161004b565b80518060208301f35b634e487b7160e01b5f52604160045260245ffd5b5f602080838503121561005c575f80fd5b82516001600160401b0380821115610072575f80fd5b818501915085601f830112610085575f80fd5b81518181111561009757610097610037565b604051601f8201601f19908116603f011681019083821181831017156100bf576100bf610037565b8160405282815288868487010111156100d6575f80fd5b5f93505b828410156100f757848401860151818501870152928501926100da565b5f8684830101528096505050505050509291505056fea2646970667358221220013539101ab7ca3f2eb49334c743f86ec8a7b0cbff5788ba7432c9959515da3164736f6c63430008140033\";\nexport const FLAT_DIRECTORY_CONTRACT_VERSION_1_0_0: string = \"1.0.0\";\n","import { copy } from \"./util\";\nimport { BLOB_SIZE } from \"../param\";\n\n// OP BLOB\nconst MaxBlobDataSize = (4 * 31 + 3) * 1024 - 4;\nconst EncodingVersion = 0;\nconst Rounds = 1024; // number of encode/decode rounds\n\nexport function encodeOpBlobs(data: Uint8Array): Uint8Array[] {\n const len = data.length;\n if (len === 0) {\n throw new Error('invalid blob data');\n }\n const blobs: Uint8Array[] = [];\n for (let i = 0; i < len; i += MaxBlobDataSize) {\n let max = i + MaxBlobDataSize;\n if (max > len) {\n max = len;\n }\n const blob = encodeOpBlob(data.subarray(i, max));\n blobs.push(blob);\n }\n return blobs;\n}\n\nexport function encodeOpBlob(data: Uint8Array): Uint8Array {\n if (data.length > MaxBlobDataSize) {\n throw new Error(`too much data to encode in one blob, len=${data.length}`);\n }\n\n const b = new Uint8Array(BLOB_SIZE).fill(0);\n let readOffset = 0;\n\n // read 1 byte of input, 0 if there is no input left\n const read1 = (): number => {\n if (readOffset >= data.length) {\n return 0;\n }\n const out = data[readOffset];\n readOffset += 1;\n return out;\n }\n\n let writeOffset = 0;\n const buf31 = new Uint8Array(31);\n const zero31 = new Uint8Array(31);\n // Read up to 31 bytes of input (left-aligned), into buf31.\n const read31 = (): void => {\n if (readOffset >= data.length) {\n copy(buf31, 0, zero31, 0);\n return;\n }\n\n const n = copy(buf31, 0, data, readOffset); // copy as much data as we can\n copy(buf31, n, zero31, 0); // pad with zeroes (since there might not be enough data)\n readOffset += n;\n }\n // Write a byte, updates the write-offset.\n // Asserts that the write-offset matches encoding-algorithm expectations.\n // Asserts that the value is 6 bits.\n const write1 = (v: number): void => {\n if (writeOffset % 32 !== 0) {\n throw new Error(`blob encoding: invalid byte write offset: ${writeOffset}`);\n }\n\n const tag = v & 0b1100_0000;\n if (tag !== 0) {\n throw new Error(`blob encoding: invalid 6 bit value: 0b${v.toString(2)}`);\n }\n b[writeOffset] = v;\n writeOffset += 1;\n }\n // Write buf31 to the blob, updates the write-offset.\n // Asserts that the write-offset matches encoding-algorithm expectations.\n const write31 = (): void => {\n if (writeOffset % 32 !== 1) {\n throw new Error(`blob encoding: invalid bytes31 write offset: ${writeOffset}`);\n }\n\n copy(b, writeOffset, buf31, 0);\n writeOffset += 31;\n }\n\n for (let round = 0; round < Rounds && readOffset < data.length; round++) {\n // The first field element encodes the version and the length of the data in [1:5].\n // This is a manual substitute for read31(), preparing the buf31.\n if (round === 0) {\n buf31[0] = EncodingVersion;\n // Encode the length as big-endian uint24.\n // The length check at the start above ensures we can always fit the length value into only 3 bytes.\n const ilen = data.length;\n buf31[1] = (ilen >> 16) & 0xFF;\n buf31[2] = (ilen >> 8) & 0xFF;\n buf31[3] = ilen & 0xFF;\n\n readOffset += copy(buf31, 4, data, 0);\n } else {\n read31();\n }\n\n const x = read1();\n const A = x & 0b0011_1111;\n write1(A);\n write31();\n\n read31();\n const y = read1();\n const B = (y & 0b0000_1111) | ((x & 0b1100_0000) >> 2);\n write1(B);\n write31();\n\n read31();\n const z = read1();\n const C = z & 0b0011_1111;\n write1(C);\n write31();\n\n read31();\n const D = ((z & 0b1100_0000) >> 2) | ((y & 0b1111_0000) >> 4);\n write1(D);\n write31();\n }\n\n if (readOffset < data.length) {\n throw new Error(`expected to fit data but failed, read offset: ${readOffset}, data: ${data}`);\n }\n return b;\n}\n","import { ethers } from \"ethers\";\nimport { Mutex } from 'async-mutex';\nimport { computeVersionedCommitmentHash, convertToEthStorageHashes } from \"./util\";\nimport { KZG } from \"js-kzg\";\n\n// blob gas price\nconst MIN_BLOB_GASPRICE: bigint = 1n;\nconst BLOB_GASPRICE_UPDATE_FRACTION: bigint = 3338477n;\n\nfunction fakeExponential(factor: bigint, numerator: bigint, denominator: bigint): bigint {\n let i: bigint = 1n;\n let output: bigint = 0n;\n let numerator_accum: bigint = factor * denominator;\n while (numerator_accum > 0n) {\n output += numerator_accum;\n numerator_accum = (numerator_accum * numerator) / (denominator * i);\n i++;\n }\n return output / denominator;\n}\n\nexport class BlobUploader {\n private readonly provider: ethers.JsonRpcProvider;\n private readonly wallet: ethers.Wallet;\n private readonly mutex: Mutex;\n private readonly kzg: KZG;\n\n constructor(rpc: string, pk: string) {\n this.provider = new ethers.JsonRpcProvider(rpc);\n this.wallet = new ethers.Wallet(pk, this.provider);\n this.mutex = new Mutex();\n this.kzg = new KZG();\n }\n\n async getBlobGasPrice(): Promise<bigint> {\n // get current block\n const block = await this.provider.getBlock(\"latest\");\n if (block === null || block.excessBlobGas === null) {\n throw new Error(\"Block has no excessBlobGas\");\n }\n const excessBlobGas = BigInt(block.excessBlobGas);\n const gas = fakeExponential(MIN_BLOB_GASPRICE, excessBlobGas, BLOB_GASPRICE_UPDATE_FRACTION);\n return gas * 11n / 10n;\n }\n\n async getGasPrice(): Promise<ethers.FeeData> {\n return await this.provider.getFeeData();\n }\n\n async sendTx(\n tx: ethers.TransactionRequest,\n blobs: Uint8Array[] | null = null,\n commitments: Uint8Array[] | null = null,\n ): Promise<ethers.TransactionResponse> {\n return await this.send(tx, blobs, commitments, false);\n }\n\n async sendTxLock(\n tx: ethers.TransactionRequest,\n blobs: Uint8Array[] | null = null,\n commitments: Uint8Array[] | null = null,\n ): Promise<ethers.TransactionResponse> {\n return await this.send(tx, blobs, commitments, true);\n }\n\n private async send(\n tx: ethers.TransactionRequest,\n blobs: Uint8Array[] | null = null,\n commitments: Uint8Array[] | null = null,\n isLock: boolean = false\n ): Promise<ethers.TransactionResponse> {\n if (!blobs) {\n return isLock ? await this.lockSend(tx) : await this.wallet.sendTransaction(tx);\n }\n\n if (tx.maxFeePerBlobGas == null) {\n tx.maxFeePerBlobGas = await this.getBlobGasPrice();\n }\n\n // blobs\n const fullCommitments = commitments && commitments.length === blobs.length\n ? commitments\n : await this.kzg.computeCommitmentBatch(blobs);\n const proofs = await this.kzg.computeProofBatch(blobs, fullCommitments);\n\n const ethersBlobs: ethers.BlobLike[] = blobs.map((blob, i) => ({\n data: blob,\n proof: proofs[i],\n commitment: fullCommitments[i]\n }));\n\n const versionedHashes = fullCommitments.map(commitment =>\n ethers.hexlify(computeVersionedCommitmentHash(commitment))\n );\n\n // send\n tx.type = 3;\n tx.blobVersionedHashes = versionedHashes;\n tx.blobs = ethersBlobs;\n return isLock ? await this.lockSend(tx) : await this.wallet.sendTransaction(tx);\n }\n\n private async lockSend(tx: ethers.TransactionRequest): Promise<ethers.TransactionResponse> {\n const release = await this.mutex.acquire();\n try {\n return await this.wallet.sendTransaction(tx);\n } finally {\n release();\n }\n }\n\n async computeCommitmentsForBlobs(blobs: Uint8Array[]): Promise<Uint8Array[]> {\n return await this.kzg.computeCommitmentBatch(blobs);\n }\n\n async computeEthStorageHashesForBlobs(blobs: Uint8Array[]): Promise<string[]> {\n const commitments = await this.computeCommitmentsForBlobs(blobs);\n return convertToEthStorageHashes(commitments);\n }\n\n async close(): Promise<void> {\n await this.kzg.close();\n }\n}\n","import { retry, stringToHex } from \"./util\";\nimport { Contract } from \"ethers\";\nimport { UploadDetails, ChunkCountResult, FileBatch, ChunkHashResult } from \"../param\";\n\nexport async function getUploadInfo(contract: Contract, hexName: string, retries: number): Promise<UploadDetails> {\n const result = await retry(() => contract[\"getUploadInfo\"](hexName), retries);\n return {\n fileMode: Number(result[0]),\n oldChunkCount: Number(result[1]),\n cost: result[2] as bigint\n };\n}\n\nexport async function getChunkCounts(contract: Contract, batch: string[], retries: number): Promise<ChunkCountResult[]> {\n const names = batch.map(key => stringToHex(key));\n const counts = await retry(() => contract[\"getChunkCountsBatch\"](names), retries);\n const results: ChunkCountResult[] = [];\n let index = 0;\n for (const key of batch) {\n results.push({ key, chunkCount: Number(counts[index++]) });\n }\n return results;\n}\n\nexport async function getChunkHashes(contract: Contract, batch: FileBatch[], retries: number): Promise<ChunkHashResult[]> {\n const fileChunks = batch.map(file => [\n stringToHex(file.name),\n file.chunkIds\n ]);\n\n const hashes = await retry(() => contract[\"getChunkHashesBatch\"](fileChunks), retries);\n const results: ChunkHashResult[] = [];\n let index = 0;\n for (const file of batch) {\n for (let j = 0; j < file.chunkIds.length; j++) {\n results.push(<ChunkHashResult>{ name: file.name, chunkId: file.chunkIds[j], hash: hashes[index++] });\n }\n }\n return results;\n}\n","import { ethers } from \"ethers\";\nimport {\n BlobUploader,\n stringToHex,\n getChainId,\n encodeOpBlobs\n} from \"./utils\";\nimport {\n SDKConfig,\n DecodeType,\n CostEstimate,\n ETHSTORAGE_MAPPING,\n BLOB_SIZE,\n OP_BLOB_DATA_SIZE,\n EthStorageAbi,\n BLOB_COUNT_LIMIT,\n DUMMY_VERSIONED_COMMITMENT_HASH\n} from \"./param\";\n\nexport class EthStorage {\n private contractAddr!: string;\n\n private ethStorageRpc?: string;\n private wallet?: ethers.Wallet;\n private blobUploader?: BlobUploader;\n\n static async create(config: SDKConfig) {\n const ethStorage = new EthStorage();\n await ethStorage.init(config);\n return ethStorage;\n }\n\n private async init(config: SDKConfig) {\n const { rpc, privateKey, ethStorageRpc, address } = config;\n if (address) {\n this.contractAddr = address;\n } else if (rpc) {\n const chainId = await getChainId(rpc);\n this.contractAddr = ETHSTORAGE_MAPPING[chainId];\n }\n if (!this.contractAddr) {\n throw new Error(\"EthStorage: Network not supported yet.\");\n }\n\n this.ethStorageRpc = ethStorageRpc;\n\n if (privateKey && rpc) {\n const provider = new ethers.JsonRpcProvider(rpc);\n this.wallet = new ethers.Wallet(privateKey, provider);\n this.blobUploader = new BlobUploader(rpc, privateKey);\n }\n }\n\n async estimateCost(key: string, data: Uint8Array): Promise<CostEstimate> {\n this.checkData(data);\n const hexKey = ethers.keccak256(stringToHex(key));\n const contract = new ethers.Contract(this.contractAddr, EthStorageAbi, this._wallet);\n const [storageCost, maxFeePerBlobGas, gasFeeData] = await Promise.all([\n contract[\"upfrontPayment\"](),\n this._blobUploader.getBlobGasPrice(),\n this._blobUploader.getGasPrice(),\n ]);\n\n const gasLimit = await contract[\"putBlob\"].estimateGas(hexKey, 0, data.length, {\n value: storageCost,\n // Fixed dummy hashing to bypass the limitation that contracts need versioned hash when estimating gasLimit.\n blobVersionedHashes: [DUMMY_VERSIONED_COMMITMENT_HASH]\n });\n\n // get cost\n const totalGasCost = (gasFeeData.maxFeePerGas! + gasFeeData.maxPriorityFeePerGas!) * gasLimit;\n const totalBlobGasCost = maxFeePerBlobGas * BigInt(BLOB_SIZE);\n const gasCost = totalGasCost + totalBlobGasCost;\n return {\n storageCost,\n gasCost\n }\n }\n\n async write(key: string, data: Uint8Array): Promise<{ hash: string, success: boolean }> {\n this.checkData(data);\n\n const contract = new ethers.Contract(this.contractAddr, EthStorageAbi, this._wallet);\n cons