@latticexyz/common 2.0.0-next.11 → 2.0.0-next.13

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.
Files changed (42) hide show
  1. package/dist/chunk-7WIPV3R3.js +2 -0
  2. package/dist/chunk-7WIPV3R3.js.map +1 -0
  3. package/dist/codegen.js +13 -13
  4. package/dist/codegen.js.map +1 -1
  5. package/dist/foundry.js +2 -2
  6. package/dist/foundry.js.map +1 -1
  7. package/dist/index.js +1 -1
  8. package/dist/index.js.map +1 -1
  9. package/dist/utils.js +1 -1
  10. package/dist/utils.js.map +1 -1
  11. package/package.json +3 -7
  12. package/src/codegen/debug.ts +3 -0
  13. package/src/codegen/utils/format.ts +1 -2
  14. package/src/codegen/utils/formatAndWrite.ts +8 -7
  15. package/src/codegen/utils/loadUserTypesFile.ts +2 -1
  16. package/src/common.ts +4 -2
  17. package/src/createNonceManager.ts +7 -2
  18. package/src/{createContract.ts → deprecated/createContract.ts} +1 -1
  19. package/src/deprecated/hexToResourceId.ts +4 -0
  20. package/src/deprecated/resourceIdToHex.ts +4 -0
  21. package/src/foundry/index.ts +7 -5
  22. package/src/getContract.ts +18 -4
  23. package/src/getNonceManager.ts +2 -2
  24. package/src/getNonceManagerId.ts +1 -0
  25. package/src/hexToResource.test.ts +11 -0
  26. package/src/{hexToResourceId.ts → hexToResource.ts} +5 -5
  27. package/src/index.ts +8 -3
  28. package/src/{resourceIdToHex.test.ts → resourceToHex.test.ts} +15 -11
  29. package/src/{resourceIdToHex.ts → resourceToHex.ts} +5 -5
  30. package/src/sendTransaction.ts +89 -0
  31. package/src/utils/index.ts +2 -0
  32. package/src/utils/mapObject.test.ts +23 -0
  33. package/src/utils/mapObject.ts +11 -0
  34. package/src/utils/uniqueBy.ts +7 -0
  35. package/src/writeContract.ts +34 -62
  36. package/dist/deprecated.js +0 -2
  37. package/dist/deprecated.js.map +0 -1
  38. package/src/deprecated/TableId.test.ts +0 -33
  39. package/src/deprecated/TableId.ts +0 -41
  40. package/src/deprecated/getTableIds.ts +0 -6
  41. package/src/deprecated/index.ts +0 -2
  42. package/src/hexToResourceId.test.ts +0 -11
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/createBurnerAccount.ts","../src/createNonceManager.ts","../src/debug.ts","../src/getNonceManagerId.ts","../src/getContract.ts","../src/writeContract.ts","../src/getNonceManager.ts","../src/getBurnerPrivateKey.ts","../src/hexToResourceId.ts","../src/resourceTypes.ts","../src/resourceIdToHex.ts","../src/readHex.ts","../src/spliceHex.ts","../src/transportObserver.ts","../src/createContract.ts"],"sourcesContent":["import { Account, Hex } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nexport function createBurnerAccount(privateKey: Hex): Account {\n const account = privateKeyToAccount(privateKey);\n // We may override account features here\n return {\n ...account,\n };\n}\n","import { BaseError, BlockTag, Client, Hex, NonceTooHighError, NonceTooLowError } from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\nimport { getNonceManagerId } from \"./getNonceManagerId\";\nimport { getTransactionCount } from \"viem/actions\";\n\nconst debug = parentDebug.extend(\"createNonceManager\");\n\nexport type CreateNonceManagerOptions = {\n client: Client;\n address: Hex;\n blockTag?: BlockTag;\n broadcastChannelName?: string;\n};\n\nexport type CreateNonceManagerResult = {\n hasNonce: () => boolean;\n nextNonce: () => number;\n resetNonce: () => Promise<void>;\n shouldResetNonce: (error: unknown) => boolean;\n};\n\nexport function createNonceManager({\n client,\n address,\n blockTag = \"latest\",\n broadcastChannelName,\n}: CreateNonceManagerOptions): CreateNonceManagerResult {\n const nonceRef = { current: -1 };\n let channel: BroadcastChannel | null = null;\n\n if (typeof BroadcastChannel !== \"undefined\") {\n const channelName = broadcastChannelName\n ? Promise.resolve(broadcastChannelName)\n : getNonceManagerId({ client, address, blockTag });\n channelName.then((name) => {\n channel = new BroadcastChannel(name);\n // TODO: emit some sort of \"connected\" event so other channels can broadcast current nonce\n channel.addEventListener(\"message\", (event) => {\n const nonce = JSON.parse(event.data);\n debug(\"got nonce from broadcast channel\", nonce);\n nonceRef.current = nonce;\n });\n });\n }\n\n function hasNonce(): boolean {\n return nonceRef.current >= 0;\n }\n\n function nextNonce(): number {\n if (!hasNonce()) throw new Error(\"call resetNonce before using nextNonce\");\n const nonce = nonceRef.current++;\n channel?.postMessage(JSON.stringify(nonceRef.current));\n return nonce;\n }\n\n async function resetNonce(): Promise<void> {\n const nonce = await getTransactionCount(client, { address, blockTag });\n nonceRef.current = nonce;\n channel?.postMessage(JSON.stringify(nonceRef.current));\n debug(\"reset nonce to\", nonceRef.current);\n }\n\n function shouldResetNonce(error: unknown): boolean {\n return (\n error instanceof BaseError &&\n error.walk((e) => e instanceof NonceTooLowError || e instanceof NonceTooHighError) != null\n );\n }\n\n return {\n hasNonce,\n nextNonce,\n resetNonce,\n shouldResetNonce,\n };\n}\n","import createDebug from \"debug\";\n\nexport const debug = createDebug(\"mud:common\");\n","import { BlockTag, Client, Hex, getAddress } from \"viem\";\nimport { getChainId } from \"viem/actions\";\n\nexport async function getNonceManagerId({\n client,\n address,\n blockTag,\n}: {\n client: Client;\n address: Hex;\n blockTag: BlockTag;\n}): Promise<string> {\n const chainId = client.chain?.id ?? (await getChainId(client));\n return `mud:createNonceManager:${chainId}:${getAddress(address)}:${blockTag}`;\n}\n","import {\n Abi,\n Account,\n Address,\n Chain,\n GetContractParameters,\n GetContractReturnType,\n PublicClient,\n Transport,\n WalletClient,\n WriteContractParameters,\n getContract as viem_getContract,\n} from \"viem\";\nimport { UnionOmit } from \"./type-utils/common\";\nimport { WriteContractOptions, writeContract } from \"./writeContract\";\n\n// copied from viem because this isn't exported\n// TODO: import from viem?\nfunction getFunctionParameters(values: [args?: readonly unknown[], options?: object]): {\n args: readonly unknown[];\n options: object;\n} {\n const hasArgs = values.length && Array.isArray(values[0]);\n const args = hasArgs ? values[0]! : [];\n const options = (hasArgs ? values[1] : values[0]) ?? {};\n return { args, options };\n}\n\nexport type GetContractOptions<\n TTransport extends Transport,\n TAddress extends Address,\n TAbi extends Abi,\n TChain extends Chain,\n TAccount extends Account,\n TPublicClient extends PublicClient<TTransport, TChain>,\n TWalletClient extends WalletClient<TTransport, TChain, TAccount>\n> = Required<GetContractParameters<TTransport, TChain, TAccount, TAbi, TPublicClient, TWalletClient, TAddress>> & {\n onWrite?: WriteContractOptions[\"onWrite\"];\n};\n\n// TODO: migrate away from this approach once we can hook into viem: https://github.com/wagmi-dev/viem/discussions/1230\n\nexport function getContract<\n TTransport extends Transport,\n TAddress extends Address,\n TAbi extends Abi,\n TChain extends Chain,\n TAccount extends Account,\n TPublicClient extends PublicClient<TTransport, TChain>,\n TWalletClient extends WalletClient<TTransport, TChain, TAccount>\n>({\n abi,\n address,\n publicClient,\n walletClient,\n onWrite,\n}: GetContractOptions<\n TTransport,\n TAddress,\n TAbi,\n TChain,\n TAccount,\n TPublicClient,\n TWalletClient\n>): GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress> {\n const contract = viem_getContract<TTransport, TAddress, TAbi, TChain, TAccount, TPublicClient, TWalletClient>({\n abi,\n address,\n publicClient,\n walletClient,\n }) as unknown as GetContractReturnType<Abi, PublicClient, WalletClient>;\n\n if (contract.write) {\n // Replace write calls with our own. Implemented ~the same as viem, but adds better handling of nonces (via queue + retries).\n contract.write = new Proxy(\n {},\n {\n get(_, functionName: string) {\n return (\n ...parameters: [\n args?: readonly unknown[],\n options?: UnionOmit<WriteContractParameters, \"abi\" | \"address\" | \"functionName\" | \"args\">\n ]\n ) => {\n const { args, options } = getFunctionParameters(parameters);\n return writeContract(walletClient, {\n abi,\n address,\n functionName,\n args,\n ...options,\n onWrite,\n } as unknown as WriteContractOptions<TAbi, typeof functionName, TChain, TAccount>);\n };\n },\n }\n );\n }\n\n return contract as unknown as GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress>;\n}\n","import {\n Abi,\n Account,\n Chain,\n Client,\n Hex,\n SimulateContractParameters,\n Transport,\n WriteContractParameters,\n WriteContractReturnType,\n} from \"viem\";\nimport { simulateContract, writeContract as viem_writeContract } from \"viem/actions\";\nimport pRetry from \"p-retry\";\nimport { debug as parentDebug } from \"./debug\";\nimport { getNonceManager } from \"./getNonceManager\";\nimport { parseAccount } from \"viem/accounts\";\n\nconst debug = parentDebug.extend(\"writeContract\");\nlet nextWriteId = 0;\n\nexport type ContractWrite<\n TAbi extends Abi | readonly unknown[] = Abi,\n TFunctionName extends string = string,\n TChain extends Chain | undefined = Chain,\n TAccount extends Account | undefined = Account | undefined,\n TChainOverride extends Chain | undefined = Chain | undefined\n> = {\n id: string;\n request: WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>;\n result: Promise<Hex>;\n};\n\nexport type WriteContractOptions<\n TAbi extends Abi | readonly unknown[] = Abi,\n TFunctionName extends string = string,\n TChain extends Chain | undefined = Chain,\n TAccount extends Account | undefined = Account | undefined,\n TChainOverride extends Chain | undefined = Chain | undefined\n> = WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride> & {\n onWrite?: (write: ContractWrite<TAbi, TFunctionName, TChain, TAccount, TChainOverride>) => void;\n};\n\n// TODO: migrate away from this approach once we can hook into viem's nonce management: https://github.com/wagmi-dev/viem/discussions/1230\n\nexport async function writeContract<\n TChain extends Chain | undefined,\n TAccount extends Account | undefined,\n TAbi extends Abi | readonly unknown[],\n TFunctionName extends string,\n TChainOverride extends Chain | undefined\n>(\n client: Client<Transport, TChain, TAccount>,\n { onWrite, ...request_ }: WriteContractOptions<TAbi, TFunctionName, TChain, TAccount, TChainOverride>\n): Promise<WriteContractReturnType> {\n const request = request_ as WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>;\n\n const account_ = request.account ?? client.account;\n if (!account_) {\n // TODO: replace with viem AccountNotFoundError once its exported\n throw new Error(\"No account provided\");\n }\n const account = parseAccount(account_);\n\n const nonceManager = await getNonceManager({\n client,\n address: account.address,\n });\n\n async function prepareWrite(): Promise<\n WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>\n > {\n if (request.gas) {\n debug(\"gas provided, skipping simulate\", request);\n return request;\n }\n\n debug(\"simulating write\", request);\n const result = await simulateContract<TChain, TAbi, TFunctionName, TChainOverride>(client, {\n ...request,\n account,\n } as unknown as SimulateContractParameters<TAbi, TFunctionName, TChain, TChainOverride>);\n\n return result.request as unknown as WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>;\n }\n\n async function write(): Promise<Hex> {\n const preparedWrite = await prepareWrite();\n\n return await pRetry(\n async () => {\n if (!nonceManager.hasNonce()) {\n await nonceManager.resetNonce();\n }\n\n const nonce = nonceManager.nextNonce();\n debug(\"calling write function with nonce\", nonce, preparedWrite);\n return await viem_writeContract(client, { nonce, ...preparedWrite } as typeof preparedWrite);\n },\n {\n retries: 3,\n onFailedAttempt: async (error) => {\n // On nonce errors, reset the nonce and retry\n if (nonceManager.shouldResetNonce(error)) {\n debug(\"got nonce error, retrying\", error);\n await nonceManager.resetNonce();\n return;\n }\n // TODO: prepareWrite again if there are gas errors?\n throw error;\n },\n }\n );\n }\n\n const result = write();\n\n onWrite?.({ id: `${nextWriteId++}`, request, result });\n\n return result;\n}\n","import { CreateNonceManagerOptions, CreateNonceManagerResult, createNonceManager } from \"./createNonceManager\";\nimport { getNonceManagerId } from \"./getNonceManagerId\";\n\nconst nonceManagers = new Map<string, CreateNonceManagerResult>();\n\nexport async function getNonceManager({\n client,\n address,\n blockTag = \"latest\",\n}: CreateNonceManagerOptions): Promise<CreateNonceManagerResult> {\n const id = await getNonceManagerId({ client, address, blockTag });\n\n const existingNonceManager = nonceManagers.get(id);\n if (existingNonceManager) {\n return existingNonceManager;\n }\n\n const nonceManager = createNonceManager({ client, address, blockTag });\n nonceManagers.set(id, nonceManager);\n return nonceManager;\n}\n","import { generatePrivateKey, privateKeyToAccount } from \"viem/accounts\";\nimport { isHex, Hex } from \"viem\";\n\nfunction assertPrivateKey(privateKey: string, cacheKey: string): asserts privateKey is Hex {\n if (!isHex(privateKey)) {\n console.error(\"Private key found in cache is not valid hex\", { privateKey, cacheKey });\n throw new Error(`Private key found in cache (${cacheKey}) is not valid hex`);\n }\n // ensure we can extract address from private key\n // this should throw on bad private keys\n privateKeyToAccount(privateKey);\n}\n\nexport function getBurnerPrivateKey(cacheKey = \"mud:burnerWallet\"): Hex {\n const cachedPrivateKey = localStorage.getItem(cacheKey);\n\n if (cachedPrivateKey != null) {\n assertPrivateKey(cachedPrivateKey, cacheKey);\n return cachedPrivateKey;\n }\n\n const privateKey = generatePrivateKey();\n console.log(\"New burner wallet created:\", privateKeyToAccount(privateKey));\n localStorage.setItem(cacheKey, privateKey);\n return privateKey;\n}\n","import { Hex, hexToString, sliceHex } from \"viem\";\nimport { ResourceId } from \"./common\";\nimport { ResourceType, resourceTypes } from \"./resourceTypes\";\nimport { resourceTypeIds } from \"./resourceIdToHex\";\nimport { ReverseMap } from \"./type-utils/common\";\n\nconst resourceTypeIdToType = Object.fromEntries(\n Object.entries(resourceTypeIds).map(([key, value]) => [value, key])\n) as ReverseMap<typeof resourceTypeIds>;\n\nfunction getResourceType(resourceTypeId: string): ResourceType | undefined {\n // TODO: replace Partial with `noUncheckedIndexedAccess`\n const type = (resourceTypeIdToType as Partial<Record<string, ResourceType>>)[resourceTypeId];\n if (resourceTypes.includes(type as ResourceType)) {\n return type;\n }\n}\n\nexport function hexToResourceId(hex: Hex): ResourceId {\n const resourceTypeId = hexToString(sliceHex(hex, 0, 2)).replace(/\\0+$/, \"\");\n const type = getResourceType(resourceTypeId);\n const namespace = hexToString(sliceHex(hex, 2, 16)).replace(/\\0+$/, \"\");\n const name = hexToString(sliceHex(hex, 16, 32)).replace(/\\0+$/, \"\");\n\n if (!type) {\n throw new Error(`Unknown resource type: ${resourceTypeId}`);\n }\n\n return { type, namespace, name };\n}\n","export const resourceTypes = [\"table\", \"offchainTable\", \"namespace\", \"module\", \"system\"] as const;\n\nexport type ResourceType = (typeof resourceTypes)[number];\n","import { Hex, stringToHex, concatHex } from \"viem\";\nimport { ResourceId } from \"./common\";\nimport { ResourceType } from \"./resourceTypes\";\n\n/** @internal */\nexport const resourceTypeIds = {\n // keep these in sync with storeResourceTypes.sol\n table: \"tb\",\n offchainTable: \"ot\",\n // keep these in sync with worldResourceTypes.sol\n namespace: \"ns\",\n module: \"md\",\n system: \"sy\",\n} as const satisfies Record<ResourceType, string>;\n\nexport function resourceIdToHex(resourceId: ResourceId): Hex {\n const typeId = resourceTypeIds[resourceId.type];\n return concatHex([\n stringToHex(typeId, { size: 2 }),\n stringToHex(resourceId.namespace.slice(0, 14), { size: 14 }),\n stringToHex(resourceId.name.slice(0, 16), { size: 16 }),\n ]);\n}\n","import { Hex } from \"viem\";\n\n/**\n * Get the hex value at start/end positions. This will always return a valid hex string.\n *\n * If `start` is out of range, this returns `\"0x\"`.\n *\n * If `end` is specified and out of range, the result is right zero-padded to the desired length (`end - start`).\n */\nexport function readHex(data: Hex, start: number, end?: number): Hex {\n return `0x${data\n .replace(/^0x/, \"\")\n .slice(start * 2, end != null ? end * 2 : undefined)\n .padEnd(((end ?? start) - start) * 2, \"0\")}`;\n}\n","import { Hex, concatHex } from \"viem\";\nimport { readHex } from \"./readHex\";\n\nexport function spliceHex(data: Hex, start: number, deleteCount = 0, newData: Hex = \"0x\"): Hex {\n return concatHex([readHex(data, 0, start), newData, readHex(data, start + deleteCount)]);\n}\n","import { Hex, Transport, keccak256 } from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"transportObserver\");\n\nexport function transportObserver<TTransport extends Transport>(transport: TTransport): TTransport {\n return ((opts) => {\n const result = transport(opts);\n const request: typeof result.request = async (req) => {\n if (req.method === \"eth_sendRawTransaction\" && req.params instanceof Array) {\n const txs = req.params.map((data: Hex) => keccak256(data));\n debug(\"saw txs\", txs);\n // TODO: pass these tx hashes into dev tools\n }\n // TODO: add support for `eth_sendTransaction`\n return result.request(req);\n };\n return {\n ...result,\n request,\n };\n }) as TTransport;\n}\n","import { getContract } from \"./getContract\";\n\n/** @deprecated use `getContract` instead */\nexport const createContract = getContract;\n"],"mappings":"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","names":["privateKeyToAccount","createBurnerAccount","privateKey","BaseError","NonceTooHighError","NonceTooLowError","createDebug","debug","getAddress","getChainId","getNonceManagerId","client","address","blockTag","getTransactionCount","debug","createNonceManager","client","address","blockTag","broadcastChannelName","nonceRef","channel","getNonceManagerId","name","event","nonce","hasNonce","nextNonce","resetNonce","shouldResetNonce","error","BaseError","e","NonceTooLowError","NonceTooHighError","viem_getContract","simulateContract","viem_writeContract","pRetry","nonceManagers","getNonceManager","client","address","blockTag","id","getNonceManagerId","existingNonceManager","nonceManager","createNonceManager","parseAccount","debug","nextWriteId","writeContract","client","onWrite","request_","request","account_","account","nonceManager","getNonceManager","prepareWrite","simulateContract","write","preparedWrite","pRetry","nonce","viem_writeContract","error","result","getFunctionParameters","values","hasArgs","args","options","getContract","abi","address","publicClient","walletClient","onWrite","contract","viem_getContract","_","functionName","parameters","writeContract","generatePrivateKey","privateKeyToAccount","isHex","assertPrivateKey","privateKey","cacheKey","getBurnerPrivateKey","cachedPrivateKey","hexToString","sliceHex","resourceTypes","stringToHex","concatHex","resourceTypeIds","resourceIdToHex","resourceId","typeId","resourceTypeIdToType","resourceTypeIds","key","value","getResourceType","resourceTypeId","type","resourceTypes","hexToResourceId","hex","hexToString","sliceHex","namespace","name","readHex","data","start","end","concatHex","spliceHex","data","start","deleteCount","newData","concatHex","readHex","keccak256","debug","transportObserver","transport","opts","result","req","txs","data","keccak256","createContract","getContract"]}
1
+ {"version":3,"sources":["../src/createBurnerAccount.ts","../src/createNonceManager.ts","../src/getNonceManagerId.ts","../src/getContract.ts","../src/writeContract.ts","../src/getNonceManager.ts","../src/getBurnerPrivateKey.ts","../src/hexToResource.ts","../src/resourceTypes.ts","../src/resourceToHex.ts","../src/readHex.ts","../src/sendTransaction.ts","../src/spliceHex.ts","../src/transportObserver.ts","../src/deprecated/createContract.ts","../src/deprecated/resourceIdToHex.ts","../src/deprecated/hexToResourceId.ts"],"sourcesContent":["import { Account, Hex } from \"viem\";\nimport { privateKeyToAccount } from \"viem/accounts\";\n\nexport function createBurnerAccount(privateKey: Hex): Account {\n const account = privateKeyToAccount(privateKey);\n // We may override account features here\n return {\n ...account,\n };\n}\n","import { BaseError, BlockTag, Client, Hex, NonceTooHighError, NonceTooLowError } from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\nimport { getNonceManagerId } from \"./getNonceManagerId\";\nimport { getTransactionCount } from \"viem/actions\";\nimport PQueue from \"p-queue\";\n\nconst debug = parentDebug.extend(\"createNonceManager\");\n\nexport type CreateNonceManagerOptions = {\n client: Client;\n address: Hex;\n blockTag?: BlockTag;\n broadcastChannelName?: string;\n};\n\nexport type CreateNonceManagerResult = {\n hasNonce: () => boolean;\n nextNonce: () => number;\n resetNonce: () => Promise<void>;\n shouldResetNonce: (error: unknown) => boolean;\n mempoolQueue: PQueue;\n};\n\nexport function createNonceManager({\n client,\n address, // TODO: rename to account?\n blockTag = \"pending\",\n broadcastChannelName,\n}: CreateNonceManagerOptions): CreateNonceManagerResult {\n const nonceRef = { current: -1 };\n let channel: BroadcastChannel | null = null;\n\n if (typeof BroadcastChannel !== \"undefined\") {\n const channelName = broadcastChannelName\n ? Promise.resolve(broadcastChannelName)\n : getNonceManagerId({ client, address, blockTag });\n channelName.then((name) => {\n channel = new BroadcastChannel(name);\n // TODO: emit some sort of \"connected\" event so other channels can broadcast current nonce\n channel.addEventListener(\"message\", (event) => {\n const nonce = JSON.parse(event.data);\n debug(\"got nonce from broadcast channel\", nonce);\n nonceRef.current = nonce;\n });\n });\n }\n\n function hasNonce(): boolean {\n return nonceRef.current >= 0;\n }\n\n function nextNonce(): number {\n if (!hasNonce()) throw new Error(\"call resetNonce before using nextNonce\");\n const nonce = nonceRef.current++;\n channel?.postMessage(JSON.stringify(nonceRef.current));\n return nonce;\n }\n\n async function resetNonce(): Promise<void> {\n const nonce = await getTransactionCount(client, { address, blockTag });\n nonceRef.current = nonce;\n channel?.postMessage(JSON.stringify(nonceRef.current));\n debug(\"reset nonce to\", nonceRef.current);\n }\n\n function shouldResetNonce(error: unknown): boolean {\n return (\n error instanceof BaseError &&\n error.walk((e) => e instanceof NonceTooLowError || e instanceof NonceTooHighError) != null\n );\n }\n\n const mempoolQueue = new PQueue({ concurrency: 1 });\n\n return {\n hasNonce,\n nextNonce,\n resetNonce,\n shouldResetNonce,\n mempoolQueue,\n };\n}\n","import { BlockTag, Client, Hex, getAddress } from \"viem\";\nimport { getChainId } from \"viem/actions\";\n\nexport async function getNonceManagerId({\n client,\n address,\n blockTag,\n}: {\n client: Client;\n address: Hex;\n blockTag: BlockTag;\n}): Promise<string> {\n // TODO: improve this so we don't have to call getChainId every time\n const chainId = client.chain?.id ?? (await getChainId(client));\n return `mud:createNonceManager:${chainId}:${getAddress(address)}:${blockTag}`;\n}\n","import {\n Abi,\n Account,\n Address,\n Chain,\n GetContractParameters,\n GetContractReturnType,\n Hex,\n PublicClient,\n Transport,\n WalletClient,\n WriteContractParameters,\n getContract as viem_getContract,\n} from \"viem\";\nimport { UnionOmit } from \"./type-utils/common\";\nimport { writeContract } from \"./writeContract\";\n\n// copied from viem because this isn't exported\n// TODO: import from viem?\nfunction getFunctionParameters(values: [args?: readonly unknown[], options?: object]): {\n args: readonly unknown[];\n options: object;\n} {\n const hasArgs = values.length && Array.isArray(values[0]);\n const args = hasArgs ? values[0]! : [];\n const options = (hasArgs ? values[1] : values[0]) ?? {};\n return { args, options };\n}\n\nexport type ContractWrite = {\n id: string;\n request: WriteContractParameters;\n result: Promise<Hex>;\n};\n\nexport type GetContractOptions<\n TTransport extends Transport,\n TAddress extends Address,\n TAbi extends Abi,\n TChain extends Chain,\n TAccount extends Account,\n TPublicClient extends PublicClient<TTransport, TChain>,\n TWalletClient extends WalletClient<TTransport, TChain, TAccount>\n> = Required<GetContractParameters<TTransport, TChain, TAccount, TAbi, TPublicClient, TWalletClient, TAddress>> & {\n onWrite?: (write: ContractWrite) => void;\n};\n\n// TODO: migrate away from this approach once we can hook into viem: https://github.com/wagmi-dev/viem/discussions/1230\n\nexport function getContract<\n TTransport extends Transport,\n TAddress extends Address,\n TAbi extends Abi,\n TChain extends Chain,\n TAccount extends Account,\n TPublicClient extends PublicClient<TTransport, TChain>,\n TWalletClient extends WalletClient<TTransport, TChain, TAccount>\n>({\n abi,\n address,\n publicClient,\n walletClient,\n onWrite,\n}: GetContractOptions<\n TTransport,\n TAddress,\n TAbi,\n TChain,\n TAccount,\n TPublicClient,\n TWalletClient\n>): GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress> {\n const contract = viem_getContract<TTransport, TAddress, TAbi, TChain, TAccount, TPublicClient, TWalletClient>({\n abi,\n address,\n publicClient,\n walletClient,\n }) as unknown as GetContractReturnType<Abi, PublicClient, WalletClient>;\n\n if (contract.write) {\n // Replace write calls with our own. Implemented ~the same as viem, but adds better handling of nonces (via queue + retries).\n let nextWriteId = 0;\n contract.write = new Proxy(\n {},\n {\n get(_, functionName: string) {\n return (\n ...parameters: [\n args?: readonly unknown[],\n options?: UnionOmit<WriteContractParameters, \"abi\" | \"address\" | \"functionName\" | \"args\">\n ]\n ) => {\n const { args, options } = getFunctionParameters(parameters);\n const request = {\n abi,\n address,\n functionName,\n args,\n ...options,\n onWrite,\n } as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;\n const result = writeContract(walletClient, request);\n\n const id = `${walletClient.chain.id}:${walletClient.account.address}:${nextWriteId++}`;\n onWrite?.({ id, request: request as WriteContractParameters, result });\n\n return result;\n };\n },\n }\n );\n }\n\n return contract as unknown as GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress>;\n}\n","import {\n Abi,\n Account,\n Chain,\n Client,\n SimulateContractParameters,\n Transport,\n WriteContractParameters,\n WriteContractReturnType,\n} from \"viem\";\nimport { simulateContract, writeContract as viem_writeContract } from \"viem/actions\";\nimport pRetry from \"p-retry\";\nimport { debug as parentDebug } from \"./debug\";\nimport { getNonceManager } from \"./getNonceManager\";\nimport { parseAccount } from \"viem/accounts\";\n\nconst debug = parentDebug.extend(\"writeContract\");\n\n// TODO: migrate away from this approach once we can hook into viem's nonce management: https://github.com/wagmi-dev/viem/discussions/1230\n\nexport async function writeContract<\n TChain extends Chain | undefined,\n TAccount extends Account | undefined,\n TAbi extends Abi | readonly unknown[],\n TFunctionName extends string,\n TChainOverride extends Chain | undefined\n>(\n client: Client<Transport, TChain, TAccount>,\n request: WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>\n): Promise<WriteContractReturnType> {\n const rawAccount = request.account ?? client.account;\n if (!rawAccount) {\n // TODO: replace with viem AccountNotFoundError once its exported\n throw new Error(\"No account provided\");\n }\n const account = parseAccount(rawAccount);\n\n const nonceManager = await getNonceManager({\n client,\n address: account.address,\n blockTag: \"pending\",\n });\n\n async function prepareWrite(): Promise<\n WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>\n > {\n if (request.gas) {\n debug(\"gas provided, skipping simulate\", request.functionName, request.address);\n return request;\n }\n\n debug(\"simulating\", request.functionName, \"at\", request.address);\n const result = await simulateContract<TChain, TAbi, TFunctionName, TChainOverride>(client, {\n ...request,\n blockTag: \"pending\",\n account,\n } as unknown as SimulateContractParameters<TAbi, TFunctionName, TChain, TChainOverride>);\n\n return result.request as unknown as WriteContractParameters<TAbi, TFunctionName, TChain, TAccount, TChainOverride>;\n }\n\n const preparedWrite = await prepareWrite();\n\n return nonceManager.mempoolQueue.add(\n () =>\n pRetry(\n async () => {\n if (!nonceManager.hasNonce()) {\n await nonceManager.resetNonce();\n }\n\n const nonce = nonceManager.nextNonce();\n debug(\"calling\", preparedWrite.functionName, \"with nonce\", nonce, \"at\", preparedWrite.address);\n return await viem_writeContract(client, { nonce, ...preparedWrite } as typeof preparedWrite);\n },\n {\n retries: 3,\n onFailedAttempt: async (error) => {\n // On nonce errors, reset the nonce and retry\n if (nonceManager.shouldResetNonce(error)) {\n debug(\"got nonce error, retrying\", error.message);\n await nonceManager.resetNonce();\n return;\n }\n // TODO: prepareWrite again if there are gas errors?\n throw error;\n },\n }\n ),\n { throwOnTimeout: true }\n );\n}\n","import { CreateNonceManagerOptions, CreateNonceManagerResult, createNonceManager } from \"./createNonceManager\";\nimport { getNonceManagerId } from \"./getNonceManagerId\";\n\nconst nonceManagers = new Map<string, CreateNonceManagerResult>();\n\nexport async function getNonceManager({\n client,\n address, // TODO: rename to account?\n blockTag = \"pending\",\n}: CreateNonceManagerOptions): Promise<CreateNonceManagerResult> {\n const id = await getNonceManagerId({ client, address, blockTag });\n\n const existingNonceManager = nonceManagers.get(id);\n if (existingNonceManager) {\n return existingNonceManager;\n }\n\n const nonceManager = createNonceManager({ client, address, blockTag });\n nonceManagers.set(id, nonceManager);\n return nonceManager;\n}\n","import { generatePrivateKey, privateKeyToAccount } from \"viem/accounts\";\nimport { isHex, Hex } from \"viem\";\n\nfunction assertPrivateKey(privateKey: string, cacheKey: string): asserts privateKey is Hex {\n if (!isHex(privateKey)) {\n console.error(\"Private key found in cache is not valid hex\", { privateKey, cacheKey });\n throw new Error(`Private key found in cache (${cacheKey}) is not valid hex`);\n }\n // ensure we can extract address from private key\n // this should throw on bad private keys\n privateKeyToAccount(privateKey);\n}\n\nexport function getBurnerPrivateKey(cacheKey = \"mud:burnerWallet\"): Hex {\n const cachedPrivateKey = localStorage.getItem(cacheKey);\n\n if (cachedPrivateKey != null) {\n assertPrivateKey(cachedPrivateKey, cacheKey);\n return cachedPrivateKey;\n }\n\n const privateKey = generatePrivateKey();\n console.log(\"New burner wallet created:\", privateKeyToAccount(privateKey));\n localStorage.setItem(cacheKey, privateKey);\n return privateKey;\n}\n","import { Hex, hexToString, sliceHex } from \"viem\";\nimport { Resource } from \"./common\";\nimport { ResourceType, resourceTypes } from \"./resourceTypes\";\nimport { resourceTypeIds } from \"./resourceToHex\";\nimport { ReverseMap } from \"./type-utils/common\";\n\nconst resourceTypeIdToType = Object.fromEntries(\n Object.entries(resourceTypeIds).map(([key, value]) => [value, key])\n) as ReverseMap<typeof resourceTypeIds>;\n\nfunction getResourceType(resourceTypeId: string): ResourceType | undefined {\n // TODO: replace Partial with `noUncheckedIndexedAccess`\n const type = (resourceTypeIdToType as Partial<Record<string, ResourceType>>)[resourceTypeId];\n if (resourceTypes.includes(type as ResourceType)) {\n return type;\n }\n}\n\nexport function hexToResource(hex: Hex): Resource {\n const resourceTypeId = hexToString(sliceHex(hex, 0, 2)).replace(/\\0+$/, \"\");\n const type = getResourceType(resourceTypeId);\n const namespace = hexToString(sliceHex(hex, 2, 16)).replace(/\\0+$/, \"\");\n const name = hexToString(sliceHex(hex, 16, 32)).replace(/\\0+$/, \"\");\n\n if (!type) {\n throw new Error(`Unknown type (${resourceTypeId}) for resource (${resourceTypeId}:${namespace}:${name})`);\n }\n\n return { resourceId: hex, type, namespace, name };\n}\n","export const resourceTypes = [\"table\", \"offchainTable\", \"namespace\", \"module\", \"system\"] as const;\n\nexport type ResourceType = (typeof resourceTypes)[number];\n","import { Hex, stringToHex, concatHex } from \"viem\";\nimport { Resource } from \"./common\";\nimport { ResourceType } from \"./resourceTypes\";\n\n/** @internal */\nexport const resourceTypeIds = {\n // keep these in sync with storeResourceTypes.sol\n table: \"tb\",\n offchainTable: \"ot\",\n // keep these in sync with worldResourceTypes.sol\n namespace: \"ns\",\n module: \"md\",\n system: \"sy\",\n} as const satisfies Record<ResourceType, string>;\n\nexport function resourceToHex(resource: Omit<Resource, \"resourceId\">): Hex {\n const typeId = resourceTypeIds[resource.type];\n return concatHex([\n stringToHex(typeId, { size: 2 }),\n stringToHex(resource.namespace.slice(0, 14), { size: 14 }),\n stringToHex(resource.name.slice(0, 16), { size: 16 }),\n ]);\n}\n","import { Hex } from \"viem\";\n\n/**\n * Get the hex value at start/end positions. This will always return a valid hex string.\n *\n * If `start` is out of range, this returns `\"0x\"`.\n *\n * If `end` is specified and out of range, the result is right zero-padded to the desired length (`end - start`).\n */\nexport function readHex(data: Hex, start: number, end?: number): Hex {\n return `0x${data\n .replace(/^0x/, \"\")\n .slice(start * 2, end != null ? end * 2 : undefined)\n .padEnd(((end ?? start) - start) * 2, \"0\")}`;\n}\n","import {\n Account,\n CallParameters,\n Chain,\n Client,\n SendTransactionParameters,\n Transport,\n WriteContractReturnType,\n} from \"viem\";\nimport { call, sendTransaction as viem_sendTransaction } from \"viem/actions\";\nimport pRetry from \"p-retry\";\nimport { debug as parentDebug } from \"./debug\";\nimport { getNonceManager } from \"./getNonceManager\";\nimport { parseAccount } from \"viem/accounts\";\n\nconst debug = parentDebug.extend(\"sendTransaction\");\n\n// TODO: migrate away from this approach once we can hook into viem's nonce management: https://github.com/wagmi-dev/viem/discussions/1230\n\nexport async function sendTransaction<\n TChain extends Chain | undefined,\n TAccount extends Account | undefined,\n TChainOverride extends Chain | undefined\n>(\n client: Client<Transport, TChain, TAccount>,\n request: SendTransactionParameters<TChain, TAccount, TChainOverride>\n): Promise<WriteContractReturnType> {\n const rawAccount = request.account ?? client.account;\n if (!rawAccount) {\n // TODO: replace with viem AccountNotFoundError once its exported\n throw new Error(\"No account provided\");\n }\n const account = parseAccount(rawAccount);\n\n const nonceManager = await getNonceManager({\n client,\n address: account.address,\n blockTag: \"pending\",\n });\n\n async function prepare(): Promise<SendTransactionParameters<TChain, TAccount, TChainOverride>> {\n if (request.gas) {\n debug(\"gas provided, skipping simulate\", request.to);\n return request;\n }\n\n debug(\"simulating tx to\", request.to);\n await call(client, {\n ...request,\n blockTag: \"pending\",\n account,\n } as CallParameters<TChain>);\n\n // TODO: estimate gas\n\n return request;\n }\n\n const preparedRequest = await prepare();\n\n return await nonceManager.mempoolQueue.add(\n () =>\n pRetry(\n async () => {\n if (!nonceManager.hasNonce()) {\n await nonceManager.resetNonce();\n }\n\n const nonce = nonceManager.nextNonce();\n debug(\"sending tx with nonce\", nonce, \"to\", preparedRequest.to);\n return await viem_sendTransaction(client, { nonce, ...preparedRequest });\n },\n {\n retries: 3,\n onFailedAttempt: async (error) => {\n // On nonce errors, reset the nonce and retry\n if (nonceManager.shouldResetNonce(error)) {\n debug(\"got nonce error, retrying\", error.message);\n await nonceManager.resetNonce();\n return;\n }\n // TODO: prepare again if there are gas errors?\n throw error;\n },\n }\n ),\n { throwOnTimeout: true }\n );\n}\n","import { Hex, concatHex } from \"viem\";\nimport { readHex } from \"./readHex\";\n\nexport function spliceHex(data: Hex, start: number, deleteCount = 0, newData: Hex = \"0x\"): Hex {\n return concatHex([readHex(data, 0, start), newData, readHex(data, start + deleteCount)]);\n}\n","import { Hex, Transport, keccak256 } from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"transportObserver\");\n\nexport function transportObserver<TTransport extends Transport>(transport: TTransport): TTransport {\n return ((opts) => {\n const result = transport(opts);\n const request: typeof result.request = async (req) => {\n if (req.method === \"eth_sendRawTransaction\" && req.params instanceof Array) {\n const txs = req.params.map((data: Hex) => keccak256(data));\n debug(\"saw txs\", txs);\n // TODO: pass these tx hashes into dev tools\n }\n // TODO: add support for `eth_sendTransaction`\n return result.request(req);\n };\n return {\n ...result,\n request,\n };\n }) as TTransport;\n}\n","import { getContract } from \"../getContract\";\n\n/** @deprecated use `getContract` instead */\nexport const createContract = getContract;\n","import { resourceToHex } from \"../resourceToHex\";\n\n/** @deprecated use `resourceToHex` instead */\nexport const resourceIdToHex = resourceToHex;\n","import { hexToResource } from \"../hexToResource\";\n\n/** @deprecated use `hexToResource` instead */\nexport const hexToResourceId = hexToResource;\n"],"mappings":"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","names":["privateKeyToAccount","createBurnerAccount","privateKey","BaseError","NonceTooHighError","NonceTooLowError","getAddress","getChainId","getNonceManagerId","client","address","blockTag","getTransactionCount","PQueue","debug","createNonceManager","client","address","blockTag","broadcastChannelName","nonceRef","channel","getNonceManagerId","name","event","nonce","hasNonce","nextNonce","resetNonce","shouldResetNonce","error","BaseError","e","NonceTooLowError","NonceTooHighError","mempoolQueue","viem_getContract","simulateContract","viem_writeContract","pRetry","nonceManagers","getNonceManager","client","address","blockTag","id","getNonceManagerId","existingNonceManager","nonceManager","createNonceManager","parseAccount","debug","writeContract","client","request","rawAccount","account","nonceManager","getNonceManager","prepareWrite","simulateContract","preparedWrite","pRetry","nonce","viem_writeContract","error","getFunctionParameters","values","hasArgs","args","options","getContract","abi","address","publicClient","walletClient","onWrite","contract","viem_getContract","nextWriteId","_","functionName","parameters","request","result","writeContract","id","generatePrivateKey","privateKeyToAccount","isHex","assertPrivateKey","privateKey","cacheKey","getBurnerPrivateKey","cachedPrivateKey","hexToString","sliceHex","resourceTypes","stringToHex","concatHex","resourceTypeIds","resourceToHex","resource","typeId","resourceTypeIdToType","resourceTypeIds","key","value","getResourceType","resourceTypeId","type","resourceTypes","hexToResource","hex","hexToString","sliceHex","namespace","name","readHex","data","start","end","call","viem_sendTransaction","pRetry","parseAccount","debug","sendTransaction","client","request","rawAccount","account","nonceManager","getNonceManager","prepare","call","preparedRequest","pRetry","nonce","viem_sendTransaction","error","concatHex","spliceHex","data","start","deleteCount","newData","concatHex","readHex","keccak256","debug","transportObserver","transport","opts","result","req","txs","data","keccak256","createContract","getContract","resourceIdToHex","resourceToHex","hexToResourceId","hexToResource"]}
package/dist/utils.js CHANGED
@@ -1,2 +1,2 @@
1
- function n(r,e){throw new Error(e??`Unexpected value: ${r}`)}function i(...r){return r.reduce((e,t)=>t>e?t:e)}function u(...r){return r.reduce((e,t)=>t<e?t:e)}function m(r,e){return r<e?-1:r>e?1:0}function*x(r,e){for(let t=0;t<r.length;t+=e)yield r.slice(t,t+e)}function c(r,...e){return(...t)=>r(...e,...t)}function l(r){return r}function T(r){return r!==void 0}function g(r){return r!==null}async function v(r){let e=[];for await(let t of r)e.push(t);return e}function F(r){return new Promise(e=>setTimeout(()=>e(),r))}function h(){return new Promise(r=>{requestIdleCallback(()=>r())})}export{n as assertExhaustive,i as bigIntMax,u as bigIntMin,m as bigIntSort,x as chunk,c as curry,l as identity,T as isDefined,g as isNotNull,v as iteratorToArray,F as wait,h as waitForIdle};
1
+ function o(e,r){throw new Error(r??`Unexpected value: ${e}`)}function i(...e){return e.reduce((r,t)=>t>r?t:r)}function s(...e){return e.reduce((r,t)=>t<r?t:r)}function m(e,r){return e<r?-1:e>r?1:0}function*c(e,r){for(let t=0;t<e.length;t+=r)yield e.slice(t,t+r)}function l(e,...r){return(...t)=>e(...r,...t)}function d(e){return e}function P(e){return e!==void 0}function v(e){return e!==null}async function k(e){let r=[];for await(let t of e)r.push(t);return r}function S(e,r){return Object.fromEntries(Object.entries(e).map(([t,n])=>[t,r(n,t)]))}function I(e,r){let t=new Map;for(let n of e)t.set(r(n),n);return Array.from(t.values())}function R(e){return new Promise(r=>setTimeout(()=>r(),e))}function j(){return new Promise(e=>{requestIdleCallback(()=>e())})}export{o as assertExhaustive,i as bigIntMax,s as bigIntMin,m as bigIntSort,c as chunk,l as curry,d as identity,P as isDefined,v as isNotNull,k as iteratorToArray,S as mapObject,I as uniqueBy,R as wait,j as waitForIdle};
2
2
  //# sourceMappingURL=utils.js.map
package/dist/utils.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/utils/assertExhaustive.ts","../src/utils/bigIntMax.ts","../src/utils/bigIntMin.ts","../src/utils/bigIntSort.ts","../src/utils/chunk.ts","../src/utils/curry.ts","../src/utils/identity.ts","../src/utils/isDefined.ts","../src/utils/isNotNull.ts","../src/utils/iteratorToArray.ts","../src/utils/wait.ts","../src/utils/waitForIdle.ts"],"sourcesContent":["export function assertExhaustive(value: never, message?: string): never {\n throw new Error(message ?? `Unexpected value: ${value}`);\n}\n","export function bigIntMax(...args: bigint[]): bigint {\n return args.reduce((m, e) => (e > m ? e : m));\n}\n","export function bigIntMin(...args: bigint[]): bigint {\n return args.reduce((m, e) => (e < m ? e : m));\n}\n","export function bigIntSort(a: bigint, b: bigint): -1 | 0 | 1 {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","export function* chunk<T>(arr: T[], n: number): Generator<T[], void> {\n for (let i = 0; i < arr.length; i += n) {\n yield arr.slice(i, i + n);\n }\n}\n","export function curry<F extends (...params: [...P, ...any[]]) => any, P extends any[]>(\n func: F,\n ...partialParams: P\n): CurryParams<F, P> {\n return ((...args: any[]) => func(...partialParams, ...args)) as CurryParams<F, P>;\n}\n\ntype CurryParams<F extends (...params: [...PartialParams, ...any[]]) => any, PartialParams extends any[]> = F extends (\n ...params: [...PartialParams, ...infer RemainingParams]\n) => infer Result\n ? (...params: RemainingParams) => Result\n : never;\n","export function identity<T>(value: T): T {\n return value;\n}\n","export function isDefined<T>(argument: T | undefined): argument is T {\n return argument !== undefined;\n}\n","export function isNotNull<T>(argument: T | null): argument is T {\n return argument !== null;\n}\n","export async function iteratorToArray<T>(iterator: AsyncIterable<T>): Promise<T[]> {\n const items: T[] = [];\n for await (const item of iterator) {\n items.push(item);\n }\n return items;\n}\n","export function wait(ms: number): Promise<void> {\n return new Promise<void>((resolve) => setTimeout(() => resolve(), ms));\n}\n","export function waitForIdle(): Promise<void> {\n return new Promise<void>((resolve) => {\n requestIdleCallback(() => resolve());\n });\n}\n"],"mappings":"AAAO,SAASA,EAAiBC,EAAcC,EAAyB,CACtE,MAAM,IAAI,MAAMA,GAAW,qBAAqBD,GAAO,CACzD,CCFO,SAASE,KAAaC,EAAwB,CACnD,OAAOA,EAAK,OAAO,CAACC,EAAGC,IAAOA,EAAID,EAAIC,EAAID,CAAE,CAC9C,CCFO,SAASE,KAAaC,EAAwB,CACnD,OAAOA,EAAK,OAAO,CAACC,EAAGC,IAAOA,EAAID,EAAIC,EAAID,CAAE,CAC9C,CCFO,SAASE,EAAWC,EAAWC,EAAuB,CAC3D,OAAOD,EAAIC,EAAI,GAAKD,EAAIC,EAAI,EAAI,CAClC,CCFO,SAAUC,EAASC,EAAUC,EAAiC,CACnE,QAASC,EAAI,EAAGA,EAAIF,EAAI,OAAQE,GAAKD,EACnC,MAAMD,EAAI,MAAME,EAAGA,EAAID,CAAC,CAE5B,CCJO,SAASE,EACdC,KACGC,EACgB,CACnB,MAAQ,IAAIC,IAAgBF,EAAK,GAAGC,EAAe,GAAGC,CAAI,CAC5D,CCLO,SAASC,EAAYC,EAAa,CACvC,OAAOA,CACT,CCFO,SAASC,EAAaC,EAAwC,CACnE,OAAOA,IAAa,MACtB,CCFO,SAASC,EAAaC,EAAmC,CAC9D,OAAOA,IAAa,IACtB,CCFA,eAAsBC,EAAmBC,EAA0C,CACjF,IAAMC,EAAa,CAAC,EACpB,cAAiBC,KAAQF,EACvBC,EAAM,KAAKC,CAAI,EAEjB,OAAOD,CACT,CCNO,SAASE,EAAKC,EAA2B,CAC9C,OAAO,IAAI,QAAeC,GAAY,WAAW,IAAMA,EAAQ,EAAGD,CAAE,CAAC,CACvE,CCFO,SAASE,GAA6B,CAC3C,OAAO,IAAI,QAAeC,GAAY,CACpC,oBAAoB,IAAMA,EAAQ,CAAC,CACrC,CAAC,CACH","names":["assertExhaustive","value","message","bigIntMax","args","m","e","bigIntMin","args","m","e","bigIntSort","a","b","chunk","arr","n","i","curry","func","partialParams","args","identity","value","isDefined","argument","isNotNull","argument","iteratorToArray","iterator","items","item","wait","ms","resolve","waitForIdle","resolve"]}
1
+ {"version":3,"sources":["../src/utils/assertExhaustive.ts","../src/utils/bigIntMax.ts","../src/utils/bigIntMin.ts","../src/utils/bigIntSort.ts","../src/utils/chunk.ts","../src/utils/curry.ts","../src/utils/identity.ts","../src/utils/isDefined.ts","../src/utils/isNotNull.ts","../src/utils/iteratorToArray.ts","../src/utils/mapObject.ts","../src/utils/uniqueBy.ts","../src/utils/wait.ts","../src/utils/waitForIdle.ts"],"sourcesContent":["export function assertExhaustive(value: never, message?: string): never {\n throw new Error(message ?? `Unexpected value: ${value}`);\n}\n","export function bigIntMax(...args: bigint[]): bigint {\n return args.reduce((m, e) => (e > m ? e : m));\n}\n","export function bigIntMin(...args: bigint[]): bigint {\n return args.reduce((m, e) => (e < m ? e : m));\n}\n","export function bigIntSort(a: bigint, b: bigint): -1 | 0 | 1 {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n","export function* chunk<T>(arr: T[], n: number): Generator<T[], void> {\n for (let i = 0; i < arr.length; i += n) {\n yield arr.slice(i, i + n);\n }\n}\n","export function curry<F extends (...params: [...P, ...any[]]) => any, P extends any[]>(\n func: F,\n ...partialParams: P\n): CurryParams<F, P> {\n return ((...args: any[]) => func(...partialParams, ...args)) as CurryParams<F, P>;\n}\n\ntype CurryParams<F extends (...params: [...PartialParams, ...any[]]) => any, PartialParams extends any[]> = F extends (\n ...params: [...PartialParams, ...infer RemainingParams]\n) => infer Result\n ? (...params: RemainingParams) => Result\n : never;\n","export function identity<T>(value: T): T {\n return value;\n}\n","export function isDefined<T>(argument: T | undefined): argument is T {\n return argument !== undefined;\n}\n","export function isNotNull<T>(argument: T | null): argument is T {\n return argument !== null;\n}\n","export async function iteratorToArray<T>(iterator: AsyncIterable<T>): Promise<T[]> {\n const items: T[] = [];\n for await (const item of iterator) {\n items.push(item);\n }\n return items;\n}\n","/**\n * Map each key of a source object via a given valueMap function\n */\nexport function mapObject<\n Source extends Record<string | number | symbol, unknown>,\n Target extends { [key in keyof Source]: unknown }\n>(source: Source, valueMap: (value: Source[typeof key], key: keyof Source) => Target[typeof key]): Target {\n return Object.fromEntries(\n Object.entries(source).map(([key, value]) => [key, valueMap(value as Source[keyof Source], key)])\n ) as Target;\n}\n","export function uniqueBy<value, key>(values: readonly value[], getKey: (value: value) => key): readonly value[] {\n const map = new Map<key, value>();\n for (const value of values) {\n map.set(getKey(value), value);\n }\n return Array.from(map.values());\n}\n","export function wait(ms: number): Promise<void> {\n return new Promise<void>((resolve) => setTimeout(() => resolve(), ms));\n}\n","export function waitForIdle(): Promise<void> {\n return new Promise<void>((resolve) => {\n requestIdleCallback(() => resolve());\n });\n}\n"],"mappings":"AAAO,SAASA,EAAiBC,EAAcC,EAAyB,CACtE,MAAM,IAAI,MAAMA,GAAW,qBAAqBD,GAAO,CACzD,CCFO,SAASE,KAAaC,EAAwB,CACnD,OAAOA,EAAK,OAAO,CAACC,EAAGC,IAAOA,EAAID,EAAIC,EAAID,CAAE,CAC9C,CCFO,SAASE,KAAaC,EAAwB,CACnD,OAAOA,EAAK,OAAO,CAACC,EAAGC,IAAOA,EAAID,EAAIC,EAAID,CAAE,CAC9C,CCFO,SAASE,EAAWC,EAAWC,EAAuB,CAC3D,OAAOD,EAAIC,EAAI,GAAKD,EAAIC,EAAI,EAAI,CAClC,CCFO,SAAUC,EAASC,EAAUC,EAAiC,CACnE,QAASC,EAAI,EAAGA,EAAIF,EAAI,OAAQE,GAAKD,EACnC,MAAMD,EAAI,MAAME,EAAGA,EAAID,CAAC,CAE5B,CCJO,SAASE,EACdC,KACGC,EACgB,CACnB,MAAQ,IAAIC,IAAgBF,EAAK,GAAGC,EAAe,GAAGC,CAAI,CAC5D,CCLO,SAASC,EAAYC,EAAa,CACvC,OAAOA,CACT,CCFO,SAASC,EAAaC,EAAwC,CACnE,OAAOA,IAAa,MACtB,CCFO,SAASC,EAAaC,EAAmC,CAC9D,OAAOA,IAAa,IACtB,CCFA,eAAsBC,EAAmBC,EAA0C,CACjF,IAAMC,EAAa,CAAC,EACpB,cAAiBC,KAAQF,EACvBC,EAAM,KAAKC,CAAI,EAEjB,OAAOD,CACT,CCHO,SAASE,EAGdC,EAAgBC,EAAwF,CACxG,OAAO,OAAO,YACZ,OAAO,QAAQD,CAAM,EAAE,IAAI,CAAC,CAACE,EAAKC,CAAK,IAAM,CAACD,EAAKD,EAASE,EAA+BD,CAAG,CAAC,CAAC,CAClG,CACF,CCVO,SAASE,EAAqBC,EAA0BC,EAAiD,CAC9G,IAAMC,EAAM,IAAI,IAChB,QAAWC,KAASH,EAClBE,EAAI,IAAID,EAAOE,CAAK,EAAGA,CAAK,EAE9B,OAAO,MAAM,KAAKD,EAAI,OAAO,CAAC,CAChC,CCNO,SAASE,EAAKC,EAA2B,CAC9C,OAAO,IAAI,QAAeC,GAAY,WAAW,IAAMA,EAAQ,EAAGD,CAAE,CAAC,CACvE,CCFO,SAASE,GAA6B,CAC3C,OAAO,IAAI,QAAeC,GAAY,CACpC,oBAAoB,IAAMA,EAAQ,CAAC,CACrC,CAAC,CACH","names":["assertExhaustive","value","message","bigIntMax","args","m","e","bigIntMin","args","m","e","bigIntSort","a","b","chunk","arr","n","i","curry","func","partialParams","args","identity","value","isDefined","argument","isNotNull","argument","iteratorToArray","iterator","items","item","mapObject","source","valueMap","key","value","uniqueBy","values","getKey","map","value","wait","ms","resolve","waitForIdle","resolve"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latticexyz/common",
3
- "version": "2.0.0-next.11",
3
+ "version": "2.0.0-next.13",
4
4
  "description": "Common low level logic shared between packages",
5
5
  "repository": {
6
6
  "type": "git",
@@ -13,7 +13,6 @@
13
13
  ".": "./dist/index.js",
14
14
  "./chains": "./dist/chains.js",
15
15
  "./codegen": "./dist/codegen.js",
16
- "./deprecated": "./dist/deprecated.js",
17
16
  "./errors": "./dist/errors.js",
18
17
  "./foundry": "./dist/foundry.js",
19
18
  "./type-utils": "./dist/type-utils.js",
@@ -30,9 +29,6 @@
30
29
  "codegen": [
31
30
  "./src/codegen/index.ts"
32
31
  ],
33
- "deprecated": [
34
- "./src/deprecated/index.ts"
35
- ],
36
32
  "errors": [
37
33
  "./src/errors/index.ts"
38
34
  ],
@@ -49,14 +45,14 @@
49
45
  },
50
46
  "dependencies": {
51
47
  "@solidity-parser/parser": "^0.16.0",
52
- "chalk": "^5.2.0",
53
48
  "debug": "^4.3.4",
54
49
  "execa": "^7.0.0",
50
+ "p-queue": "^7.4.1",
55
51
  "p-retry": "^5.1.2",
56
52
  "prettier": "^2.8.4",
57
53
  "prettier-plugin-solidity": "^1.1.2",
58
54
  "viem": "1.14.0",
59
- "@latticexyz/schema-type": "2.0.0-next.11"
55
+ "@latticexyz/schema-type": "2.0.0-next.13"
60
56
  },
61
57
  "devDependencies": {
62
58
  "@types/debug": "^4.1.7",
@@ -0,0 +1,3 @@
1
+ import { debug as parentDebug } from "../debug";
2
+
3
+ export const debug = parentDebug.extend("codegen");
@@ -1,4 +1,3 @@
1
- import chalk from "chalk";
2
1
  import prettier from "prettier";
3
2
  import prettierPluginSolidity from "prettier-plugin-solidity";
4
3
 
@@ -27,7 +26,7 @@ export async function formatSolidity(content: string, prettierConfigPath?: strin
27
26
  } else {
28
27
  message = error;
29
28
  }
30
- console.log(chalk.yellow(`Error during output formatting: ${message}`));
29
+ console.log(`Error during output formatting: ${message}`);
31
30
  return content;
32
31
  }
33
32
  }
@@ -1,14 +1,15 @@
1
- import { mkdirSync, writeFileSync } from "fs";
1
+ import { mkdir, writeFile } from "fs/promises";
2
2
  import { dirname } from "path";
3
3
  import { formatSolidity, formatTypescript } from "./format";
4
+ import { debug } from "../debug";
4
5
 
5
6
  export async function formatAndWriteSolidity(output: string, fullOutputPath: string, logPrefix: string): Promise<void> {
6
7
  const formattedOutput = await formatSolidity(output);
7
8
 
8
- mkdirSync(dirname(fullOutputPath), { recursive: true });
9
+ await mkdir(dirname(fullOutputPath), { recursive: true });
9
10
 
10
- writeFileSync(fullOutputPath, formattedOutput);
11
- console.log(`${logPrefix}: ${fullOutputPath}`);
11
+ await writeFile(fullOutputPath, formattedOutput);
12
+ debug(`${logPrefix}: ${fullOutputPath}`);
12
13
  }
13
14
 
14
15
  export async function formatAndWriteTypescript(
@@ -18,8 +19,8 @@ export async function formatAndWriteTypescript(
18
19
  ): Promise<void> {
19
20
  const formattedOutput = await formatTypescript(output);
20
21
 
21
- mkdirSync(dirname(fullOutputPath), { recursive: true });
22
+ await mkdir(dirname(fullOutputPath), { recursive: true });
22
23
 
23
- writeFileSync(fullOutputPath, formattedOutput);
24
- console.log(`${logPrefix}: ${fullOutputPath}`);
24
+ await writeFile(fullOutputPath, formattedOutput);
25
+ debug(`${logPrefix}: ${fullOutputPath}`);
25
26
  }
@@ -2,10 +2,11 @@ import { readFileSync } from "fs";
2
2
  import path from "path";
3
3
  import { SolidityUserDefinedType, extractUserTypes } from "./extractUserTypes";
4
4
  import { MUDError } from "../../errors";
5
+ import { SchemaAbiType } from "@latticexyz/schema-type";
5
6
 
6
7
  export type UserType = {
7
8
  filePath: string;
8
- internalType: string;
9
+ internalType: SchemaAbiType;
9
10
  };
10
11
 
11
12
  export function loadAndExtractUserTypes(
package/src/common.ts CHANGED
@@ -1,7 +1,9 @@
1
+ import { Hex } from "viem";
1
2
  import { ResourceType } from "./resourceTypes";
2
3
 
3
- export type ResourceId = {
4
+ export type Resource = {
5
+ resourceId: Hex;
6
+ type: ResourceType;
4
7
  namespace: string;
5
8
  name: string;
6
- type: ResourceType;
7
9
  };
@@ -2,6 +2,7 @@ import { BaseError, BlockTag, Client, Hex, NonceTooHighError, NonceTooLowError }
2
2
  import { debug as parentDebug } from "./debug";
3
3
  import { getNonceManagerId } from "./getNonceManagerId";
4
4
  import { getTransactionCount } from "viem/actions";
5
+ import PQueue from "p-queue";
5
6
 
6
7
  const debug = parentDebug.extend("createNonceManager");
7
8
 
@@ -17,12 +18,13 @@ export type CreateNonceManagerResult = {
17
18
  nextNonce: () => number;
18
19
  resetNonce: () => Promise<void>;
19
20
  shouldResetNonce: (error: unknown) => boolean;
21
+ mempoolQueue: PQueue;
20
22
  };
21
23
 
22
24
  export function createNonceManager({
23
25
  client,
24
- address,
25
- blockTag = "latest",
26
+ address, // TODO: rename to account?
27
+ blockTag = "pending",
26
28
  broadcastChannelName,
27
29
  }: CreateNonceManagerOptions): CreateNonceManagerResult {
28
30
  const nonceRef = { current: -1 };
@@ -68,10 +70,13 @@ export function createNonceManager({
68
70
  );
69
71
  }
70
72
 
73
+ const mempoolQueue = new PQueue({ concurrency: 1 });
74
+
71
75
  return {
72
76
  hasNonce,
73
77
  nextNonce,
74
78
  resetNonce,
75
79
  shouldResetNonce,
80
+ mempoolQueue,
76
81
  };
77
82
  }
@@ -1,4 +1,4 @@
1
- import { getContract } from "./getContract";
1
+ import { getContract } from "../getContract";
2
2
 
3
3
  /** @deprecated use `getContract` instead */
4
4
  export const createContract = getContract;
@@ -0,0 +1,4 @@
1
+ import { hexToResource } from "../hexToResource";
2
+
3
+ /** @deprecated use `hexToResource` instead */
4
+ export const hexToResourceId = hexToResource;
@@ -0,0 +1,4 @@
1
+ import { resourceToHex } from "../resourceToHex";
2
+
3
+ /** @deprecated use `resourceToHex` instead */
4
+ export const resourceIdToHex = resourceToHex;
@@ -1,5 +1,4 @@
1
1
  import { execa, Options } from "execa";
2
- import chalk from "chalk";
3
2
 
4
3
  export interface ForgeConfig {
5
4
  // project
@@ -84,9 +83,12 @@ export async function getRemappings(profile?: string): Promise<[string, string][
84
83
  * @param args The arguments to pass to forge
85
84
  * @param options { profile?: The foundry profile to use; silent?: If true, nothing will be logged to the console }
86
85
  */
87
- export async function forge(args: string[], options?: { profile?: string; silent?: boolean }): Promise<void> {
86
+ export async function forge(
87
+ args: string[],
88
+ options?: { profile?: string; silent?: boolean; env?: NodeJS.ProcessEnv }
89
+ ): Promise<void> {
88
90
  const execOptions: Options<string> = {
89
- env: { FOUNDRY_PROFILE: options?.profile },
91
+ env: { FOUNDRY_PROFILE: options?.profile, ...options?.env },
90
92
  stdout: "inherit",
91
93
  stderr: "pipe",
92
94
  };
@@ -124,13 +126,13 @@ export async function anvil(args: string[]): Promise<string> {
124
126
  async function execLog(command: string, args: string[], options?: Options<string>): Promise<string> {
125
127
  const commandString = `${command} ${args.join(" ")}`;
126
128
  try {
127
- console.log(chalk.gray(`running "${commandString}"`));
129
+ console.log(`running "${commandString}"`);
128
130
  const { stdout } = await execa(command, args, { stdout: "pipe", stderr: "pipe", ...options });
129
131
  return stdout;
130
132
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
133
  } catch (error: any) {
132
134
  let errorMessage = error?.stderr || error?.message || "";
133
- errorMessage += chalk.red(`\nError running "${commandString}"`);
135
+ errorMessage += `\nError running "${commandString}"`;
134
136
  throw new Error(errorMessage);
135
137
  }
136
138
  }
@@ -5,6 +5,7 @@ import {
5
5
  Chain,
6
6
  GetContractParameters,
7
7
  GetContractReturnType,
8
+ Hex,
8
9
  PublicClient,
9
10
  Transport,
10
11
  WalletClient,
@@ -12,7 +13,7 @@ import {
12
13
  getContract as viem_getContract,
13
14
  } from "viem";
14
15
  import { UnionOmit } from "./type-utils/common";
15
- import { WriteContractOptions, writeContract } from "./writeContract";
16
+ import { writeContract } from "./writeContract";
16
17
 
17
18
  // copied from viem because this isn't exported
18
19
  // TODO: import from viem?
@@ -26,6 +27,12 @@ function getFunctionParameters(values: [args?: readonly unknown[], options?: obj
26
27
  return { args, options };
27
28
  }
28
29
 
30
+ export type ContractWrite = {
31
+ id: string;
32
+ request: WriteContractParameters;
33
+ result: Promise<Hex>;
34
+ };
35
+
29
36
  export type GetContractOptions<
30
37
  TTransport extends Transport,
31
38
  TAddress extends Address,
@@ -35,7 +42,7 @@ export type GetContractOptions<
35
42
  TPublicClient extends PublicClient<TTransport, TChain>,
36
43
  TWalletClient extends WalletClient<TTransport, TChain, TAccount>
37
44
  > = Required<GetContractParameters<TTransport, TChain, TAccount, TAbi, TPublicClient, TWalletClient, TAddress>> & {
38
- onWrite?: WriteContractOptions["onWrite"];
45
+ onWrite?: (write: ContractWrite) => void;
39
46
  };
40
47
 
41
48
  // TODO: migrate away from this approach once we can hook into viem: https://github.com/wagmi-dev/viem/discussions/1230
@@ -72,6 +79,7 @@ export function getContract<
72
79
 
73
80
  if (contract.write) {
74
81
  // Replace write calls with our own. Implemented ~the same as viem, but adds better handling of nonces (via queue + retries).
82
+ let nextWriteId = 0;
75
83
  contract.write = new Proxy(
76
84
  {},
77
85
  {
@@ -83,14 +91,20 @@ export function getContract<
83
91
  ]
84
92
  ) => {
85
93
  const { args, options } = getFunctionParameters(parameters);
86
- return writeContract(walletClient, {
94
+ const request = {
87
95
  abi,
88
96
  address,
89
97
  functionName,
90
98
  args,
91
99
  ...options,
92
100
  onWrite,
93
- } as unknown as WriteContractOptions<TAbi, typeof functionName, TChain, TAccount>);
101
+ } as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;
102
+ const result = writeContract(walletClient, request);
103
+
104
+ const id = `${walletClient.chain.id}:${walletClient.account.address}:${nextWriteId++}`;
105
+ onWrite?.({ id, request: request as WriteContractParameters, result });
106
+
107
+ return result;
94
108
  };
95
109
  },
96
110
  }
@@ -5,8 +5,8 @@ const nonceManagers = new Map<string, CreateNonceManagerResult>();
5
5
 
6
6
  export async function getNonceManager({
7
7
  client,
8
- address,
9
- blockTag = "latest",
8
+ address, // TODO: rename to account?
9
+ blockTag = "pending",
10
10
  }: CreateNonceManagerOptions): Promise<CreateNonceManagerResult> {
11
11
  const id = await getNonceManagerId({ client, address, blockTag });
12
12
 
@@ -10,6 +10,7 @@ export async function getNonceManagerId({
10
10
  address: Hex;
11
11
  blockTag: BlockTag;
12
12
  }): Promise<string> {
13
+ // TODO: improve this so we don't have to call getChainId every time
13
14
  const chainId = client.chain?.id ?? (await getChainId(client));
14
15
  return `mud:createNonceManager:${chainId}:${getAddress(address)}:${blockTag}`;
15
16
  }
@@ -0,0 +1,11 @@
1
+ import { describe, it, expect } from "vitest";
2
+ import { hexToResource } from "./hexToResource";
3
+
4
+ describe("hexToResource", () => {
5
+ it("can convert from hex string", () => {
6
+ const resource = hexToResource("0x74626e616d65737061636500000000006e616d65000000000000000000000000");
7
+ expect(resource.type).toMatchInlineSnapshot('"table"');
8
+ expect(resource.namespace).toMatchInlineSnapshot('"namespace"');
9
+ expect(resource.name).toMatchInlineSnapshot('"name"');
10
+ });
11
+ });
@@ -1,7 +1,7 @@
1
1
  import { Hex, hexToString, sliceHex } from "viem";
2
- import { ResourceId } from "./common";
2
+ import { Resource } from "./common";
3
3
  import { ResourceType, resourceTypes } from "./resourceTypes";
4
- import { resourceTypeIds } from "./resourceIdToHex";
4
+ import { resourceTypeIds } from "./resourceToHex";
5
5
  import { ReverseMap } from "./type-utils/common";
6
6
 
7
7
  const resourceTypeIdToType = Object.fromEntries(
@@ -16,15 +16,15 @@ function getResourceType(resourceTypeId: string): ResourceType | undefined {
16
16
  }
17
17
  }
18
18
 
19
- export function hexToResourceId(hex: Hex): ResourceId {
19
+ export function hexToResource(hex: Hex): Resource {
20
20
  const resourceTypeId = hexToString(sliceHex(hex, 0, 2)).replace(/\0+$/, "");
21
21
  const type = getResourceType(resourceTypeId);
22
22
  const namespace = hexToString(sliceHex(hex, 2, 16)).replace(/\0+$/, "");
23
23
  const name = hexToString(sliceHex(hex, 16, 32)).replace(/\0+$/, "");
24
24
 
25
25
  if (!type) {
26
- throw new Error(`Unknown resource type: ${resourceTypeId}`);
26
+ throw new Error(`Unknown type (${resourceTypeId}) for resource (${resourceTypeId}:${namespace}:${name})`);
27
27
  }
28
28
 
29
- return { type, namespace, name };
29
+ return { resourceId: hex, type, namespace, name };
30
30
  }
package/src/index.ts CHANGED
@@ -5,13 +5,18 @@ export * from "./getContract";
5
5
  export * from "./getBurnerPrivateKey";
6
6
  export * from "./getNonceManager";
7
7
  export * from "./getNonceManagerId";
8
- export * from "./hexToResourceId";
8
+ export * from "./hexToResource";
9
9
  export * from "./readHex";
10
- export * from "./resourceIdToHex";
10
+ export * from "./resourceToHex";
11
11
  export * from "./resourceTypes";
12
+ export * from "./sendTransaction";
12
13
  export * from "./spliceHex";
13
14
  export * from "./transportObserver";
14
15
  export * from "./writeContract";
15
16
 
16
17
  /** @deprecated use `getContract` instead */
17
- export { createContract } from "./createContract";
18
+ export { createContract } from "./deprecated/createContract";
19
+ /** @deprecated use `resourceToHex` instead */
20
+ export { resourceIdToHex } from "./deprecated/resourceIdToHex";
21
+ /** @deprecated use `hexToResource` instead */
22
+ export { hexToResourceId } from "./deprecated/hexToResourceId";
@@ -1,67 +1,71 @@
1
1
  import { describe, it, expect } from "vitest";
2
- import { resourceIdToHex } from "./resourceIdToHex";
3
- import { hexToResourceId } from "./hexToResourceId";
2
+ import { resourceToHex } from "./resourceToHex";
3
+ import { hexToResource } from "./hexToResource";
4
4
 
5
- describe("resourceIdToHex", () => {
5
+ describe("resourceToHex", () => {
6
6
  it("can convert table resource to hex string", () => {
7
- const hex = resourceIdToHex({
7
+ const hex = resourceToHex({
8
8
  type: "table",
9
9
  namespace: "namespace",
10
10
  name: "name",
11
11
  });
12
12
  expect(hex).toMatchInlineSnapshot('"0x74626e616d65737061636500000000006e616d65000000000000000000000000"');
13
- expect(hexToResourceId(hex)).toMatchInlineSnapshot(`
13
+ expect(hexToResource(hex)).toMatchInlineSnapshot(`
14
14
  {
15
15
  "name": "name",
16
16
  "namespace": "namespace",
17
+ "resourceId": "0x74626e616d65737061636500000000006e616d65000000000000000000000000",
17
18
  "type": "table",
18
19
  }
19
20
  `);
20
21
  });
21
22
 
22
23
  it("can convert offchain table resource to hex string", () => {
23
- const hex = resourceIdToHex({
24
+ const hex = resourceToHex({
24
25
  type: "offchainTable",
25
26
  namespace: "namespace",
26
27
  name: "name",
27
28
  });
28
29
  expect(hex).toMatchInlineSnapshot('"0x6f746e616d65737061636500000000006e616d65000000000000000000000000"');
29
- expect(hexToResourceId(hex)).toMatchInlineSnapshot(`
30
+ expect(hexToResource(hex)).toMatchInlineSnapshot(`
30
31
  {
31
32
  "name": "name",
32
33
  "namespace": "namespace",
34
+ "resourceId": "0x6f746e616d65737061636500000000006e616d65000000000000000000000000",
33
35
  "type": "offchainTable",
34
36
  }
35
37
  `);
36
38
  });
37
39
 
38
40
  it("truncates namespaces >14 bytes", () => {
39
- const hex = resourceIdToHex({
41
+ const hex = resourceToHex({
40
42
  type: "table",
41
43
  namespace: "AVeryLongNamespace",
42
44
  name: "name",
43
45
  });
44
46
  expect(hex).toMatchInlineSnapshot('"0x746241566572794c6f6e674e616d65736e616d65000000000000000000000000"');
45
- expect(hexToResourceId(hex)).toMatchInlineSnapshot(`
47
+ expect(hexToResource(hex)).toMatchInlineSnapshot(`
46
48
  {
47
49
  "name": "name",
48
50
  "namespace": "AVeryLongNames",
51
+ "resourceId": "0x746241566572794c6f6e674e616d65736e616d65000000000000000000000000",
49
52
  "type": "table",
50
53
  }
51
54
  `);
52
55
  });
53
56
 
54
57
  it("truncates names >16 bytes", () => {
55
- const hex = resourceIdToHex({
58
+ const hex = resourceToHex({
56
59
  type: "table",
57
60
  namespace: "namespace",
58
61
  name: "AnUnnecessarilyLongName",
59
62
  });
60
63
  expect(hex).toMatchInlineSnapshot('"0x74626e616d6573706163650000000000416e556e6e65636573736172696c794c"');
61
- expect(hexToResourceId(hex)).toMatchInlineSnapshot(`
64
+ expect(hexToResource(hex)).toMatchInlineSnapshot(`
62
65
  {
63
66
  "name": "AnUnnecessarilyL",
64
67
  "namespace": "namespace",
68
+ "resourceId": "0x74626e616d6573706163650000000000416e556e6e65636573736172696c794c",
65
69
  "type": "table",
66
70
  }
67
71
  `);