@tokamak-private-dapps/private-state-cli 2.0.0 → 2.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,184 +0,0 @@
1
- import { ethers, getAddress } from "ethers";
2
- import {
3
- MAX_MT_LEAVES,
4
- TokamakL2StateManager,
5
- createTokamakL2Common,
6
- createTokamakL2StateManagerFromStateSnapshot,
7
- createTokamakL2Tx,
8
- getUserStorageKey,
9
- poseidon,
10
- } from "tokamak-l2js";
11
- import {
12
- addHexPrefix,
13
- bytesToBigInt,
14
- bytesToHex,
15
- createAddressFromString,
16
- hexToBigInt,
17
- hexToBytes,
18
- } from "@ethereumjs/util";
19
- import {
20
- resolveTokamakBlockInputConfig,
21
- } from "@tokamak-private-dapps/common-library/tokamak-runtime-paths";
22
-
23
- const { previousBlockHashCount: tokamakPrevBlockHashCount } = resolveTokamakBlockInputConfig();
24
-
25
- export function normalizeBytesHex(value, byteLength) {
26
- if (!Number.isInteger(byteLength) || byteLength <= 0) {
27
- throw new Error("normalizeBytesHex requires a positive byte length.");
28
- }
29
- const targetHexLength = byteLength * 2;
30
- let hex;
31
- if (typeof value === "string") {
32
- const trimmed = value.trim();
33
- if (!/^0x[0-9a-fA-F]*$/.test(trimmed)) {
34
- throw new Error(`Expected a hex string, received ${value}.`);
35
- }
36
- hex = trimmed.replace(/^0x/i, "");
37
- if (hex.length % 2 !== 0) {
38
- hex = `0${hex}`;
39
- }
40
- } else {
41
- hex = ethers.hexlify(value).replace(/^0x/i, "");
42
- }
43
- if (hex.length > targetHexLength) {
44
- throw new Error(`Expected at most ${byteLength} bytes, received ${Math.ceil(hex.length / 2)} bytes.`);
45
- }
46
- return `0x${hex.padStart(targetHexLength, "0").toLowerCase()}`;
47
- }
48
-
49
- export function normalizeBytes32Hex(hexValue) {
50
- return normalizeBytesHex(hexValue, 32);
51
- }
52
-
53
- export function bytes32FromHex(hexValue) {
54
- return normalizeBytes32Hex(hexValue);
55
- }
56
-
57
- export function bigintToHex32(value) {
58
- return normalizeBytes32Hex(ethers.toBeHex(value));
59
- }
60
-
61
- export function poseidonHexFromBytes(bytesLike) {
62
- return ethers.hexlify(poseidon(ethers.getBytes(bytesLike))).toLowerCase();
63
- }
64
-
65
- export function serializeBigInts(value) {
66
- return JSON.parse(JSON.stringify(value, (_key, current) => (
67
- typeof current === "bigint" ? current.toString() : current
68
- )));
69
- }
70
-
71
- export function buildTokamakTxSnapshot({ signerPrivateKey, senderPubKey, to, data, nonce }) {
72
- return serializeBigInts(
73
- createTokamakL2Tx(
74
- {
75
- nonce: ethers.toBigInt(nonce),
76
- to: createAddressFromString(to),
77
- data: hexToBytes(addHexPrefix(String(data ?? "").replace(/^0x/i, ""))),
78
- senderPubKey,
79
- },
80
- { common: createTokamakL2Common() },
81
- )
82
- .sign(signerPrivateKey)
83
- .captureTxSnapshot(),
84
- );
85
- }
86
-
87
- export async function fetchContractCodes(provider, addresses, { requireBytecode = false } = {}) {
88
- const codes = [];
89
- for (const address of addresses) {
90
- const normalizedAddress = getAddress(address);
91
- const code = await provider.getCode(normalizedAddress);
92
- if (requireBytecode && code === "0x") {
93
- throw new Error(`No deployed bytecode found at ${normalizedAddress}.`);
94
- }
95
- codes.push({ address: normalizedAddress, code });
96
- }
97
- return codes;
98
- }
99
-
100
- export async function buildStateManager(snapshot, contractCodes) {
101
- return createTokamakL2StateManagerFromStateSnapshot(snapshot, {
102
- contractCodes: contractCodes.map((entry) => ({
103
- address: createAddressFromString(entry.address),
104
- code: addHexPrefix(entry.code),
105
- })),
106
- });
107
- }
108
-
109
- export async function currentStorageBigInt(stateManager, address, keyHex) {
110
- const valueBytes = await stateManager.getStorage(
111
- createAddressFromString(address),
112
- hexToBytes(addHexPrefix(String(keyHex ?? "").replace(/^0x/i, ""))),
113
- );
114
- if (valueBytes.length === 0) {
115
- return 0n;
116
- }
117
- return bytesToBigInt(valueBytes);
118
- }
119
-
120
- export async function putStorageValue(stateManager, address, keyHex, nextValue) {
121
- await stateManager.putStorage(
122
- createAddressFromString(address),
123
- hexToBytes(addHexPrefix(String(keyHex ?? "").replace(/^0x/i, ""))),
124
- hexToBytes(addHexPrefix(String(bigintToHex32(nextValue) ?? "").replace(/^0x/i, ""))),
125
- );
126
- }
127
-
128
- export async function putStorageAndCapture(stateManager, address, keyHex, nextValue) {
129
- await currentStorageBigInt(stateManager, address, keyHex);
130
- await putStorageValue(stateManager, address, keyHex, nextValue);
131
- return stateManager.captureStateSnapshot();
132
- }
133
-
134
- export async function initializePrivateStateSnapshot({ controllerAddress, vaultAddress, channelId }) {
135
- const stateManager = new TokamakL2StateManager({ common: createTokamakL2Common() });
136
- const addresses = [controllerAddress, vaultAddress].map((address) => createAddressFromString(address));
137
- await stateManager._initializeForAddresses(addresses);
138
- stateManager._channelId = channelId;
139
- for (const address of addresses) {
140
- stateManager._commitResolvedStorageEntries(address, []);
141
- }
142
- return stateManager.captureStateSnapshot();
143
- }
144
-
145
- export async function getBlockInfoAt(provider, blockNumber, { send = (method, params) => provider.send(method, params) } = {}) {
146
- const blockTag = ethers.toQuantity(blockNumber);
147
- const block = await send("eth_getBlockByNumber", [blockTag, false]);
148
- const prevBlockHashes = [];
149
- for (let offset = 1; offset <= tokamakPrevBlockHashCount; offset += 1) {
150
- if (blockNumber <= offset) {
151
- prevBlockHashes.push("0x0");
152
- continue;
153
- }
154
- const previousBlock = await send("eth_getBlockByNumber", [ethers.toQuantity(blockNumber - offset), false]);
155
- prevBlockHashes.push(previousBlock.hash);
156
- }
157
- const chainId = await send("eth_chainId", []);
158
- return {
159
- coinBase: block.miner,
160
- timeStamp: block.timestamp,
161
- blockNumber: block.number,
162
- prevRanDao: block.prevRandao ?? block.mixHash ?? block.difficulty ?? "0x0",
163
- gasLimit: block.gasLimit,
164
- chainId,
165
- selfBalance: "0x0",
166
- baseFee: block.baseFeePerGas ?? "0x0",
167
- prevBlockHashes,
168
- };
169
- }
170
-
171
- export async function getFixedBlockInfo(provider, options = {}) {
172
- const send = options.send ?? ((method, params) => provider.send(method, params));
173
- const latestNumberHex = await send("eth_blockNumber", []);
174
- const latestNumber = Number(hexToBigInt(addHexPrefix(String(latestNumberHex ?? "").replace(/^0x/i, ""))));
175
- return getBlockInfoAt(provider, latestNumber, { send });
176
- }
177
-
178
- export function deriveLiquidBalanceStorageKey(l2Address, slot) {
179
- return normalizeBytes32Hex(bytesToHex(getUserStorageKey([l2Address, ethers.toBigInt(slot)], "TokamakL2")));
180
- }
181
-
182
- export function deriveChannelTokenVaultLeafIndex(storageKey) {
183
- return hexToBigInt(addHexPrefix(String(storageKey ?? "").replace(/^0x/i, ""))) % ethers.toBigInt(MAX_MT_LEAVES);
184
- }