@latticexyz/common 2.0.0-main-e0193e57 → 2.0.0-main-331dbfdc

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.
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- import{privateKeyToAccount as W}from"viem/accounts";function J(e){return{...W(e)}}import{getContract as M}from"viem";import O from"p-retry";import{BaseError as k,NonceTooHighError as R,NonceTooLowError as v}from"viem";import H from"debug";var p=H("mud:common");var x=p.extend("createNonceManager");function b({publicClient:e,address:t,blockTag:r}){let n={current:-1},a=typeof BroadcastChannel<"u"?new BroadcastChannel(`mud:createNonceManager:${e.chain?.id}:${t}`):null;a&&a.addEventListener("message",o=>{let T=JSON.parse(o.data);x("got nonce from broadcast channel",T),n.current=T});function c(){return n.current>=0}function d(){if(!c())throw new Error("call resetNonce before using nextNonce");let o=n.current++;return a?.postMessage(JSON.stringify(n.current)),o}async function u(){let o=await e.getTransactionCount({address:t,blockTag:r});n.current=o,a?.postMessage(JSON.stringify(n.current)),x("reset nonce to",n.current)}function C(o){return o instanceof k&&o.walk(T=>T instanceof v||T instanceof R)!=null}return{hasNonce:c,nextNonce:d,resetNonce:u,shouldResetNonce:C}}var m=p.extend("createContract");function E(e){let t=e.length&&Array.isArray(e[0]),r=t?e[0]:[],n=(t?e[1]:e[0])??{};return{args:r,options:n}}function me({abi:e,address:t,publicClient:r,walletClient:n,onWrite:a}){let c=M({abi:e,address:t,publicClient:r,walletClient:n});if(c.write){let d=0,u=b({publicClient:r,address:n.account.address});c.write=new Proxy({},{get(C,o){async function T(s){if(s.gas)return m("gas provided, skipping simulate",o,s),s;m("simulating write",o,s);let{request:l}=await r.simulateContract({...s,account:s.account??n.account});return l}async function w(s){let l=await T(s);return await O(async()=>{u.hasNonce()||await u.resetNonce();let i=u.nextNonce();return m("calling write function with nonce",i,l),await n.writeContract({nonce:i,...l})},{retries:3,onFailedAttempt:async i=>{if(u.shouldResetNonce(i)){m("got nonce error, retrying",i),await u.resetNonce();return}throw i}})}return(...s)=>{let l=`${n.chain.id}:${n.account.address}:${d++}`,{args:i,options:N}=E(s),f={address:t,abi:e,functionName:o,args:i,...N},g=w(f);return a?.({id:l,request:f,result:g}),g}}})}return c}import{generatePrivateKey as S,privateKeyToAccount as A}from"viem/accounts";import{isHex as $}from"viem";function B(e,t){if(!$(e))throw console.error("Private key found in cache is not valid hex",{privateKey:e,cacheKey:t}),new Error(`Private key found in cache (${t}) is not valid hex`);A(e)}function be(e="mud:burnerWallet"){let t=localStorage.getItem(e);if(t!=null)return B(t,e),t;let r=S();return console.log("New burner wallet created:",A(r)),localStorage.setItem(e,r),r}import{hexToString as h,sliceHex as P}from"viem";function ye(e){let t=h(P(e,0,16)).replace(/\0+$/,""),r=h(P(e,16,32)).replace(/\0+$/,"");return{namespace:t,name:r}}import{stringToHex as y,concatHex as G}from"viem";function He(e,t){return G([y(e.substring(0,16),{size:16}),y(t.substring(0,16),{size:16})])}import{keccak256 as q}from"viem";var I=p.extend("transportObserver");function Ee(e){return t=>{let r=e(t);return{...r,request:async a=>{if(a.method==="eth_sendRawTransaction"&&a.params instanceof Array){let c=a.params.map(d=>q(d));I("saw txs",c)}return r.request(a)}}}}export{J as createBurnerAccount,me as createContract,b as createNonceManager,be as getBurnerPrivateKey,ye as hexToTableId,He as tableIdToHex,Ee as transportObserver};
1
+ import{privateKeyToAccount as W}from"viem/accounts";function j(e){return{...W(e)}}import{getContract as O}from"viem";import E from"p-retry";import{BaseError as R,NonceTooHighError as v,NonceTooLowError as M}from"viem";import k from"debug";var p=k("mud:common");var b=p.extend("createNonceManager");function A({publicClient:e,address:t,blockTag:n}){let r={current:-1},a=typeof BroadcastChannel<"u"?new BroadcastChannel(`mud:createNonceManager:${e.chain?.id}:${t}`):null;a&&a.addEventListener("message",o=>{let l=JSON.parse(o.data);b("got nonce from broadcast channel",l),r.current=l});function s(){return r.current>=0}function m(){if(!s())throw new Error("call resetNonce before using nextNonce");let o=r.current++;return a?.postMessage(JSON.stringify(r.current)),o}async function u(){let o=await e.getTransactionCount({address:t,blockTag:n});r.current=o,a?.postMessage(JSON.stringify(r.current)),b("reset nonce to",r.current)}function f(o){return o instanceof R&&o.walk(l=>l instanceof M||l instanceof v)!=null}return{hasNonce:s,nextNonce:m,resetNonce:u,shouldResetNonce:f}}var d=p.extend("createContract");function $(e){let t=e.length&&Array.isArray(e[0]),n=t?e[0]:[],r=(t?e[1]:e[0])??{};return{args:n,options:r}}function fe({abi:e,address:t,publicClient:n,walletClient:r,onWrite:a}){let s=O({abi:e,address:t,publicClient:n,walletClient:r});if(s.write){let m=0,u=A({publicClient:n,address:r.account.address});s.write=new Proxy({},{get(f,o){async function l(c){if(c.gas)return d("gas provided, skipping simulate",o,c),c;d("simulating write",o,c);let{request:T}=await n.simulateContract({...c,account:c.account??r.account});return T}async function H(c){let T=await l(c);return await E(async()=>{u.hasNonce()||await u.resetNonce();let i=u.nextNonce();return d("calling write function with nonce",i,T),await r.writeContract({nonce:i,...T})},{retries:3,onFailedAttempt:async i=>{if(u.shouldResetNonce(i)){d("got nonce error, retrying",i),await u.resetNonce();return}throw i}})}return(...c)=>{let T=`${r.chain.id}:${r.account.address}:${m++}`,{args:i,options:N}=$(c),C={address:t,abi:e,functionName:o,args:i,...N},g=H(C);return a?.({id:T,request:C,result:g}),g}}})}return s}import{generatePrivateKey as S,privateKeyToAccount as h}from"viem/accounts";import{isHex as B}from"viem";function G(e,t){if(!B(e))throw console.error("Private key found in cache is not valid hex",{privateKey:e,cacheKey:t}),new Error(`Private key found in cache (${t}) is not valid hex`);h(e)}function he(e="mud:burnerWallet"){let t=localStorage.getItem(e);if(t!=null)return G(t,e),t;let n=S();return console.log("New burner wallet created:",h(n)),localStorage.setItem(e,n),n}import{hexToString as P,sliceHex as y}from"viem";function He(e){let t=P(y(e,0,16)).replace(/\0+$/,""),n=P(y(e,16,32)).replace(/\0+$/,"");return{namespace:t,name:n}}function x(e,t,n){return`0x${e.replace(/^0x/,"").slice(t*2,n!=null?n*2:void 0).padEnd(((n??t)-t)*2,"0")}`}import{concatHex as q}from"viem";function Me(e,t,n=0,r="0x"){return q([x(e,0,t),r,x(e,t+n)])}import{stringToHex as w,concatHex as I}from"viem";function Se(e,t){return I([w(e.substring(0,16),{size:16}),w(t.substring(0,16),{size:16})])}import{keccak256 as D}from"viem";var J=p.extend("transportObserver");function Je(e){return t=>{let n=e(t);return{...n,request:async a=>{if(a.method==="eth_sendRawTransaction"&&a.params instanceof Array){let s=a.params.map(m=>D(m));J("saw txs",s)}return n.request(a)}}}}export{j as createBurnerAccount,fe as createContract,A as createNonceManager,he as getBurnerPrivateKey,He as hexToTableId,x as readHex,Me as spliceHex,Se as tableIdToHex,Je as transportObserver};
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/createBurnerAccount.ts","../src/createContract.ts","../src/createNonceManager.ts","../src/debug.ts","../src/getBurnerPrivateKey.ts","../src/hexToTableId.ts","../src/tableIdToHex.ts","../src/transportObserver.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 {\n Abi,\n Account,\n Address,\n Chain,\n GetContractParameters,\n GetContractReturnType,\n Hex,\n PublicClient,\n SimulateContractParameters,\n Transport,\n WalletClient,\n WriteContractParameters,\n getContract,\n} from \"viem\";\nimport pRetry from \"p-retry\";\nimport { createNonceManager } from \"./createNonceManager\";\nimport { debug as parentDebug } from \"./debug\";\nimport { UnionOmit } from \"./type-utils/common\";\n\nconst debug = parentDebug.extend(\"createContract\");\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 CreateContractOptions<\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\nexport function createContract<\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}: CreateContractOptions<\n TTransport,\n TAddress,\n TAbi,\n TChain,\n TAccount,\n TPublicClient,\n TWalletClient\n>): GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress> {\n const contract = 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 let nextWriteId = 0;\n const nonceManager = createNonceManager({\n publicClient: publicClient as PublicClient,\n address: walletClient.account.address,\n });\n\n // Replace write calls with our own proxy. 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): GetContractReturnType<Abi, PublicClient, WalletClient>[\"write\"][string] {\n async function prepareWrite(\n options: WriteContractParameters\n ): Promise<WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>> {\n if (options.gas) {\n debug(\"gas provided, skipping simulate\", functionName, options);\n return options as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;\n }\n\n debug(\"simulating write\", functionName, options);\n const { request } = await publicClient.simulateContract({\n ...options,\n account: options.account ?? walletClient.account,\n } as unknown as SimulateContractParameters<TAbi, typeof functionName, TChain>);\n\n return request as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;\n }\n\n async function write(options: WriteContractParameters): Promise<Hex> {\n const preparedWrite = await prepareWrite(options);\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 walletClient.writeContract({\n nonce,\n ...preparedWrite,\n });\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 return (...parameters) => {\n const id = `${walletClient.chain.id}:${walletClient.account.address}:${nextWriteId++}`;\n const { args, options } = <\n {\n args: unknown[];\n options: UnionOmit<WriteContractParameters, \"address\" | \"abi\" | \"functionName\" | \"args\">;\n }\n >getFunctionParameters(parameters as any);\n\n const request = {\n address,\n abi,\n functionName,\n args,\n ...options,\n };\n\n const result = write(request);\n\n onWrite?.({ id, request, 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 BaseError,\n BlockTag,\n Hex,\n NonceTooHighError,\n NonceTooLowError,\n PublicClient,\n TransactionExecutionError,\n} from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"createNonceManager\");\n\ntype CreateNonceManagerOptions = {\n publicClient: PublicClient;\n address: Hex;\n blockTag?: BlockTag;\n};\n\ntype CreateNonceManagerResult = {\n hasNonce: () => boolean;\n nextNonce: () => number;\n resetNonce: () => Promise<void>;\n shouldResetNonce: (error: unknown) => boolean;\n};\n\nexport function createNonceManager({\n publicClient,\n address,\n blockTag,\n}: CreateNonceManagerOptions): CreateNonceManagerResult {\n const nonceRef = { current: -1 };\n const channel =\n typeof BroadcastChannel !== \"undefined\"\n ? // TODO: fetch chain ID or require it via types?\n new BroadcastChannel(`mud:createNonceManager:${publicClient.chain?.id}:${address}`)\n : null;\n\n if (channel) {\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 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 publicClient.getTransactionCount({ 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 { 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\";\n\nexport function hexToTableId(hex: Hex): { namespace: string; name: string } {\n const namespace = hexToString(sliceHex(hex, 0, 16)).replace(/\\0+$/, \"\");\n const name = hexToString(sliceHex(hex, 16, 32)).replace(/\\0+$/, \"\");\n return { namespace, name };\n}\n","import { Hex, stringToHex, concatHex } from \"viem\";\n\n// TODO: rename to `resourceIdToHex` or `resourceSelectorToHex` since it can be used with other resources than tables\nexport function tableIdToHex(namespace: string, name: string): Hex {\n return concatHex([\n stringToHex(namespace.substring(0, 16), { size: 16 }),\n stringToHex(name.substring(0, 16), { size: 16 }),\n ]);\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"],"mappings":"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","names":["privateKeyToAccount","createBurnerAccount","privateKey","getContract","pRetry","BaseError","NonceTooHighError","NonceTooLowError","createDebug","debug","debug","createNonceManager","publicClient","address","blockTag","nonceRef","channel","event","nonce","hasNonce","nextNonce","resetNonce","shouldResetNonce","error","BaseError","e","NonceTooLowError","NonceTooHighError","debug","getFunctionParameters","values","hasArgs","args","options","createContract","abi","address","publicClient","walletClient","onWrite","contract","getContract","nextWriteId","nonceManager","createNonceManager","_","functionName","prepareWrite","request","write","preparedWrite","pRetry","nonce","error","parameters","id","result","generatePrivateKey","privateKeyToAccount","isHex","assertPrivateKey","privateKey","cacheKey","getBurnerPrivateKey","cachedPrivateKey","hexToString","sliceHex","hexToTableId","hex","namespace","name","stringToHex","concatHex","tableIdToHex","namespace","name","keccak256","debug","transportObserver","transport","opts","result","req","txs","data","keccak256"]}
1
+ {"version":3,"sources":["../src/createBurnerAccount.ts","../src/createContract.ts","../src/createNonceManager.ts","../src/debug.ts","../src/getBurnerPrivateKey.ts","../src/hexToTableId.ts","../src/readHex.ts","../src/spliceHex.ts","../src/tableIdToHex.ts","../src/transportObserver.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 {\n Abi,\n Account,\n Address,\n Chain,\n GetContractParameters,\n GetContractReturnType,\n Hex,\n PublicClient,\n SimulateContractParameters,\n Transport,\n WalletClient,\n WriteContractParameters,\n getContract,\n} from \"viem\";\nimport pRetry from \"p-retry\";\nimport { createNonceManager } from \"./createNonceManager\";\nimport { debug as parentDebug } from \"./debug\";\nimport { UnionOmit } from \"./type-utils/common\";\n\nconst debug = parentDebug.extend(\"createContract\");\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 CreateContractOptions<\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\nexport function createContract<\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}: CreateContractOptions<\n TTransport,\n TAddress,\n TAbi,\n TChain,\n TAccount,\n TPublicClient,\n TWalletClient\n>): GetContractReturnType<TAbi, TPublicClient, TWalletClient, TAddress> {\n const contract = 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 let nextWriteId = 0;\n const nonceManager = createNonceManager({\n publicClient: publicClient as PublicClient,\n address: walletClient.account.address,\n });\n\n // Replace write calls with our own proxy. 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): GetContractReturnType<Abi, PublicClient, WalletClient>[\"write\"][string] {\n async function prepareWrite(\n options: WriteContractParameters\n ): Promise<WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>> {\n if (options.gas) {\n debug(\"gas provided, skipping simulate\", functionName, options);\n return options as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;\n }\n\n debug(\"simulating write\", functionName, options);\n const { request } = await publicClient.simulateContract({\n ...options,\n account: options.account ?? walletClient.account,\n } as unknown as SimulateContractParameters<TAbi, typeof functionName, TChain>);\n\n return request as unknown as WriteContractParameters<TAbi, typeof functionName, TChain, TAccount>;\n }\n\n async function write(options: WriteContractParameters): Promise<Hex> {\n const preparedWrite = await prepareWrite(options);\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 walletClient.writeContract({\n nonce,\n ...preparedWrite,\n });\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 return (...parameters) => {\n const id = `${walletClient.chain.id}:${walletClient.account.address}:${nextWriteId++}`;\n const { args, options } = <\n {\n args: unknown[];\n options: UnionOmit<WriteContractParameters, \"address\" | \"abi\" | \"functionName\" | \"args\">;\n }\n >getFunctionParameters(parameters as any);\n\n const request = {\n address,\n abi,\n functionName,\n args,\n ...options,\n };\n\n const result = write(request);\n\n onWrite?.({ id, request, 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 BaseError,\n BlockTag,\n Hex,\n NonceTooHighError,\n NonceTooLowError,\n PublicClient,\n TransactionExecutionError,\n} from \"viem\";\nimport { debug as parentDebug } from \"./debug\";\n\nconst debug = parentDebug.extend(\"createNonceManager\");\n\ntype CreateNonceManagerOptions = {\n publicClient: PublicClient;\n address: Hex;\n blockTag?: BlockTag;\n};\n\ntype CreateNonceManagerResult = {\n hasNonce: () => boolean;\n nextNonce: () => number;\n resetNonce: () => Promise<void>;\n shouldResetNonce: (error: unknown) => boolean;\n};\n\nexport function createNonceManager({\n publicClient,\n address,\n blockTag,\n}: CreateNonceManagerOptions): CreateNonceManagerResult {\n const nonceRef = { current: -1 };\n const channel =\n typeof BroadcastChannel !== \"undefined\"\n ? // TODO: fetch chain ID or require it via types?\n new BroadcastChannel(`mud:createNonceManager:${publicClient.chain?.id}:${address}`)\n : null;\n\n if (channel) {\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 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 publicClient.getTransactionCount({ 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 { 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\";\n\nexport function hexToTableId(hex: Hex): { namespace: string; name: string } {\n const namespace = hexToString(sliceHex(hex, 0, 16)).replace(/\\0+$/, \"\");\n const name = hexToString(sliceHex(hex, 16, 32)).replace(/\\0+$/, \"\");\n return { namespace, name };\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, stringToHex, concatHex } from \"viem\";\n\n// TODO: rename to `resourceIdToHex` or `resourceSelectorToHex` since it can be used with other resources than tables\nexport function tableIdToHex(namespace: string, name: string): Hex {\n return concatHex([\n stringToHex(namespace.substring(0, 16), { size: 16 }),\n stringToHex(name.substring(0, 16), { size: 16 }),\n ]);\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"],"mappings":"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","names":["privateKeyToAccount","createBurnerAccount","privateKey","getContract","pRetry","BaseError","NonceTooHighError","NonceTooLowError","createDebug","debug","debug","createNonceManager","publicClient","address","blockTag","nonceRef","channel","event","nonce","hasNonce","nextNonce","resetNonce","shouldResetNonce","error","BaseError","e","NonceTooLowError","NonceTooHighError","debug","getFunctionParameters","values","hasArgs","args","options","createContract","abi","address","publicClient","walletClient","onWrite","contract","getContract","nextWriteId","nonceManager","createNonceManager","_","functionName","prepareWrite","request","write","preparedWrite","pRetry","nonce","error","parameters","id","result","generatePrivateKey","privateKeyToAccount","isHex","assertPrivateKey","privateKey","cacheKey","getBurnerPrivateKey","cachedPrivateKey","hexToString","sliceHex","hexToTableId","hex","namespace","name","readHex","data","start","end","concatHex","spliceHex","data","start","deleteCount","newData","concatHex","readHex","stringToHex","concatHex","tableIdToHex","namespace","name","keccak256","debug","transportObserver","transport","opts","result","req","txs","data","keccak256"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@latticexyz/common",
3
- "version": "2.0.0-main-e0193e57",
3
+ "version": "2.0.0-main-331dbfdc",
4
4
  "description": "Common low level logic shared between packages",
5
5
  "repository": {
6
6
  "type": "git",
@@ -57,7 +57,7 @@
57
57
  "prettier": "^2.8.4",
58
58
  "prettier-plugin-solidity": "^1.1.2",
59
59
  "viem": "1.6.0",
60
- "@latticexyz/schema-type": "2.0.0-main-e0193e57"
60
+ "@latticexyz/schema-type": "2.0.0-main-331dbfdc"
61
61
  },
62
62
  "devDependencies": {
63
63
  "@types/debug": "^4.1.7",
package/src/index.ts CHANGED
@@ -3,5 +3,7 @@ export * from "./createContract";
3
3
  export * from "./createNonceManager";
4
4
  export * from "./getBurnerPrivateKey";
5
5
  export * from "./hexToTableId";
6
+ export * from "./readHex";
7
+ export * from "./spliceHex";
6
8
  export * from "./tableIdToHex";
7
9
  export * from "./transportObserver";
@@ -0,0 +1,15 @@
1
+ import { describe, expect, it } from "vitest";
2
+ import { readHex } from "./readHex";
3
+
4
+ describe("readHex", () => {
5
+ it("can slice empty hex", () => {
6
+ expect(readHex("0x", 6)).toBe("0x");
7
+ expect(readHex("0x", 6, 10)).toBe("0x00000000");
8
+ });
9
+ it("can slice hex out of bounds", () => {
10
+ expect(readHex("0x000100", 1)).toBe("0x0100");
11
+ expect(readHex("0x000100", 1, 4)).toBe("0x010000");
12
+ expect(readHex("0x000100", 3)).toBe("0x");
13
+ expect(readHex("0x000100", 3, 4)).toBe("0x00");
14
+ });
15
+ });
package/src/readHex.ts ADDED
@@ -0,0 +1,15 @@
1
+ import { Hex } from "viem";
2
+
3
+ /**
4
+ * Get the hex value at start/end positions. This will always return a valid hex string.
5
+ *
6
+ * If `start` is out of range, this returns `"0x"`.
7
+ *
8
+ * If `end` is specified and out of range, the result is right zero-padded to the desired length (`end - start`).
9
+ */
10
+ export function readHex(data: Hex, start: number, end?: number): Hex {
11
+ return `0x${data
12
+ .replace(/^0x/, "")
13
+ .slice(start * 2, end != null ? end * 2 : undefined)
14
+ .padEnd(((end ?? start) - start) * 2, "0")}`;
15
+ }
@@ -0,0 +1,6 @@
1
+ import { Hex, concatHex } from "viem";
2
+ import { readHex } from "./readHex";
3
+
4
+ export function spliceHex(data: Hex, start: number, deleteCount = 0, newData: Hex = "0x"): Hex {
5
+ return concatHex([readHex(data, 0, start), newData, readHex(data, start + deleteCount)]);
6
+ }
@@ -19,3 +19,5 @@ export type OrDefaults<T extends object, Defaults> = {
19
19
  };
20
20
 
21
21
  export type UnionOmit<T, K extends keyof any> = T extends any ? Omit<T, K> : never;
22
+ export type UnionKeys<T> = T extends any ? keyof T : never;
23
+ export type UnionPick<T, K extends UnionKeys<T>> = T extends any ? Pick<T, Extract<K, keyof T>> : never;