{"_id":"@ganache/flavor","_rev":"1-78c48f4b723113dda6a3496f4edcaa25","name":"@ganache/flavor","dist-tags":{"latest":"0.10.2"},"versions":{"0.10.1":{"name":"@ganache/flavor","publishConfig":{"access":"public"},"version":"0.10.1","description":"Ganache's flavors enumeration and TypeScript types","author":{"name":"David Murdoch","email":"david@trufflesuite.com","url":"https://davidmurdoch.com"},"homepage":"https://github.com/trufflesuite/ganache/tree/develop/packages/flavor#readme","license":"MIT","main":"lib/index.js","typings":"typings","source":"index.ts","directories":{"lib":"lib","test":"tests"},"repository":{"type":"git","url":"git+https://github.com/trufflesuite/ganache.git","directory":"packages/flavor"},"scripts":{"tsc":"tsc --build","test":"echo 'no tests'"},"bugs":{"url":"https://github.com/trufflesuite/ganache/issues"},"keywords":["ganache","ganache-flavor","ganache-flavors","ethereum","evm","blockchain","smart contracts","dapps","solidity","vyper","fe","web3","tooling"],"dependencies":{"@ganache/colors":"0.4.1","@ganache/options":"0.9.1","@ganache/utils":"0.9.1","@trufflesuite/uws-js-unofficial":"20.30.0-unofficial.0","chalk":"4.1.0"},"devDependencies":{"@types/mocha":"9.0.0","cross-env":"7.0.3","mocha":"9.1.3","ts-node":"10.9.1","typescript":"5.1.6"},"gitHead":"d4618893aaa38a41e2c4d51a603f7048b8635be1","_id":"@ganache/flavor@0.10.1","_nodeVersion":"20.5.1","_npmVersion":"lerna/4.0.0/node@v20.5.1+x64 (linux)","dist":{"integrity":"sha512-kh1Lc8qZI49xgLXsLI7MVWi7y3aplsvMTLUW+l1ppENtmyIiZk+nPfI1z5h9MLo9qjDZWe2ZeBo+zNeJcCIMgg==","shasum":"47b3ceefb104071401fb1b735a540d5d0f9bf40b","tarball":"https://registry.npmjs.org/@ganache/flavor/-/flavor-0.10.1.tgz","fileCount":52,"unpackedSize":66834,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIFarrg3/iTwzwxg4QUXve9iMt2oh4mUKNWS8i7DDkwXEAiEAhpkgIWtsakV1bFfOS3cv2SSS+dbxH/G2uENNTxAEkYw="}]},"_npmUser":{"name":"truffle-cicd","email":"david+truffle@trufflesuite.com"},"maintainers":[{"name":"jeff.smale","email":"jeff.smale@consensys.net"},{"name":"truffle-cicd","email":"david+truffle@trufflesuite.com"},{"name":"davidmurdoch","email":"david@davidmurdoch.com"},{"name":"micaiahreid","email":"micaiahreid@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/flavor_0.10.1_1692741552465_0.461229146566694"},"_hasShrinkwrap":false},"0.10.2":{"name":"@ganache/flavor","publishConfig":{"access":"public"},"version":"0.10.2","description":"Ganache's flavors enumeration and TypeScript types","author":{"name":"David Murdoch","email":"david@trufflesuite.com","url":"https://davidmurdoch.com"},"homepage":"https://github.com/trufflesuite/ganache/tree/develop/packages/flavor#readme","license":"MIT","main":"lib/index.js","typings":"typings","source":"index.ts","directories":{"lib":"lib","test":"tests"},"repository":{"type":"git","url":"git+https://github.com/trufflesuite/ganache.git","directory":"packages/flavor"},"scripts":{"tsc":"tsc --build","test":"echo 'no tests'"},"bugs":{"url":"https://github.com/trufflesuite/ganache/issues"},"keywords":["ganache","ganache-flavor","ganache-flavors","ethereum","evm","blockchain","smart contracts","dapps","solidity","vyper","fe","web3","tooling"],"dependencies":{"@ganache/colors":"0.4.2","@ganache/options":"0.9.2","@ganache/utils":"0.9.2","@trufflesuite/uws-js-unofficial":"20.30.0-unofficial.0","chalk":"4.1.0"},"devDependencies":{"@types/mocha":"9.0.0","cross-env":"7.0.3","mocha":"9.1.3","ts-node":"10.9.1","typescript":"5.1.6"},"gitHead":"547c900a50d19b094ef636a9aeccf4f7f2356430","_id":"@ganache/flavor@0.10.2","_nodeVersion":"20.10.0","_npmVersion":"lerna/4.0.0/node@v20.10.0+x64 (linux)","dist":{"integrity":"sha512-w5kzjVopDdUJ0ckok/jOl6io/v1OizCmPzhZLR37Dz6Mg7epSMiveR1GfbhVdC/mn38pkYEv7axIdmOx5b8NXg==","shasum":"7e2a8282a9631d514a54a3ad027f10f01df717ec","tarball":"https://registry.npmjs.org/@ganache/flavor/-/flavor-0.10.2.tgz","fileCount":52,"unpackedSize":66834,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEYCIQD5KpHJ6tKW/xAd/IFxunqF0jYTWagFo7h+QLI+p32ujgIhAIok9y1vBiJvUFIErK3998XqKYb4RZmyB3BpdRaq0vod"}]},"_npmUser":{"name":"truffle-cicd","email":"david+truffle@trufflesuite.com"},"maintainers":[{"name":"jeff.smale","email":"jeff.smale@consensys.net"},{"name":"truffle-cicd","email":"david+truffle@trufflesuite.com"},{"name":"davidmurdoch","email":"david@davidmurdoch.com"},{"name":"micaiahreid","email":"micaiahreid@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/flavor_0.10.2_1703118002039_0.2219844162763398"},"_hasShrinkwrap":false}},"time":{"created":"2023-08-22T21:59:12.351Z","0.10.1":"2023-08-22T21:59:12.626Z","modified":"2023-12-21T00:20:02.542Z","0.10.2":"2023-12-21T00:20:02.218Z"},"maintainers":[{"name":"jeff.smale","email":"jeff.smale@consensys.net"},{"name":"truffle-cicd","email":"david+truffle@trufflesuite.com"},{"name":"davidmurdoch","email":"david@davidmurdoch.com"},{"name":"micaiahreid","email":"micaiahreid@gmail.com"}],"description":"Ganache's flavors enumeration and TypeScript types","homepage":"https://github.com/trufflesuite/ganache/tree/develop/packages/flavor#readme","keywords":["ganache","ganache-flavor","ganache-flavors","ethereum","evm","blockchain","smart contracts","dapps","solidity","vyper","fe","web3","tooling"],"repository":{"type":"git","url":"git+https://github.com/trufflesuite/ganache.git","directory":"packages/flavor"},"author":{"name":"David Murdoch","email":"david@trufflesuite.com","url":"https://davidmurdoch.com"},"bugs":{"url":"https://github.com/trufflesuite/ganache/issues"},"license":"MIT","readme":"# `@ganache/flavor`\n\nGanache's flavor TypeScript types, helpers, and utility functions.\n\nGanache Flavors are plugins that can be used to launch test networks for chains\nother than Ganache's built-in Ethereum networks. They are loaded at runtime via\nGanache's `--flavor` flag.\n\n### Warnings and Gotchas\n\nGanache flavors are experimental, incomplete, and subject to change without\nnotice.\n\nGanache flavors are Ethereum JSON-RPC (2.0) inspired, and we are still working\nto understand the needs of other chains and how to extend the Ganache flavor\nmodel to support transports other than JSON-RPC 2.0 over HTTP/WS.\n\nAn example of shortcomings for non JSON-RPC chains:\n\n- ganache only accepts POST requests over a single configurable path (defaults\n  to `/`). If you have a need for something else, like JSON over REST, gRPC, SOAP,\n  etc, please open an issue describing your use case.\n- websocket subscription-based messaging is very limited and only supports\n  responsing like Ethereum JSON-RPC does.\n\n### How to create an experimental ganache flavor\n\nTo create a new flavor, you must create a new package that exports a `Flavor`. A\nflavor is a JavaScript object that implements the `Flavor` TypeScript interface.\n\nHere is an example of a \"Hello World\"-style flavor in TypeScript:\n\n```typescript\nimport { Flavor, Connector, CliSettings } from \"@ganache/flavor\";\n\nexport type Provider = { sayHi: (name: string) => string };\nexport type RequestPayload = { name: string };\nexport type ResponsePayload = { result: string };\n\nconst provider: Provider = {\n  sayHi(name: string) {\n    return `Hello, ${name}`;\n  }\n};\n\nconst helloConnector: Connector<Provider, RequestPayload, ResponsePayload> = {\n  // the `provider` is yours to implement however you'd like. In programmatic\n  // usage it will be returned to the user when they call\n  // `Ganache.provider()` or `Ganache.server().provider`\n  provider,\n\n  async connect(): Promise<void> {\n    // ganache will `await` the return of your `connect` method before\n    // forwarding any requests to your connector.\n    // if your connector doesn't need to do any async work to initialize you\n    // can leave this empty.\n  },\n\n  parse(message: Buffer) {\n    // the `message` doesn't have to be JSON, you can use any data interchange\n    // format you'd like.\n    // NOTE: If your connector's `parse` method throws, Ganache does\n    // _not_ call your `formatError` and instead returns a `400 Bad Request`\n    // response.\n    return JSON.parse(message);\n  },\n\n  async handle(\n    this: typeof helloConnector,\n    payload: RequestPayload\n  ): Promise<{ value: unknown }> {\n    if (!payload || typeof payload.name !== \"string\") {\n      // you can throw an Exception here and ganache will catch the error and\n      // pass it to your `formatError` function.\n      throw new Error(\"payload must have a `name` property of type `string`\");\n    }\n\n    // in this \"Hello World\" example we only have one method, but you can\n    // implement as many as you need in any way you want. Here we just call the\n    // our provider's `sayHi` with the user provided `payload`'s `name`\n    //  property.\n    const value = this.provider.sayHi(payload.name);\n\n    // Your `handle` function MUST always return any object with a `value`\n    // property. The value of `value` MAY itself be a `Promise`. The _resolved_\n    // `value` will be passed to your connector's `format` function.\n    //\n    // NOTE: if a client is connected via WebSockets, and the the `value` is a\n    // `PromiEvent` (a `Promise` that also has an `on` function) that emits a\n    // `\"message\"` event Ganache will subscribe to the `\"message\"` event. If\n    // the `PromiEvent` then emits a \"message\" its event data will be sent to\n    // the client.\n    // ATTENTION: A flavor cannot `format` this message though; it will always\n    // be sent as am Ethereum JSON-RPC 2.0 subscription style message. This\n    // behavior will change in the future *without notice*. It is not recommened\n    // that you use the PromiEvent feature at this time.\n    return { value };\n  },\n\n  format(result: ResponsePayload, payload: RequestPayload) {\n    console.log(\n      `formatting result (${result.result}) for payload (${payload.name})`\n    );\n    // You don't have to return a string here, you can also return a Buffer\n    // and the serialization doesn't have to be JSON. However...\n    // ATTENTION: ganache flavors don't yet support changing the `content-type`\n    // header so it always returns `content-type: application/json`. This will\n    // change in the future and flavors will be able to specify their own\n    // content-type and other HTTP headers.\n    //\n    // You can also return a Generator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator)\n    // which will cause ganache to send the response in chunks (one chunk for\n    // yield). This is useful if your response data is too large for Node.js to\n    // handle (string and Buffer sizes are limited to about 1-2GB, and memory is\n    // capped to 4GB on most systems).\n    return JSON.stringify({ result });\n  },\n\n  formatError(error: Error, payload: RequestPayload) {\n    // Ganache calls your `formatError` if any errors occured while processing\n    // a request.\n\n    console.log(`formatting error (${error.message}) for payload (${payload})`);\n    // you don't have to return a string here, you can also return a Buffer\n    // and the serialization doesn't have to be JSON\n    return JSON.stringify({ error: error.message });\n  },\n\n  async close() {\n    // ganache calls your connector's `close` function when shutting down.\n    // This is where you'd perform clean up, like closing database connections\n    // or cleaning temporary files.\n  }\n};\n\ntype HelloFlavor = Flavor<\"hello-chain\", typeof helloConnector>;\n\nconst HelloFlavor: HelloFlavor = {\n  flavor: \"hello-chain\",\n  options: {\n    // see the `example/` directory for how Options work\n  },\n  connect(providerOptions: never) {\n    return helloConnector;\n  },\n  // the `ready` function is required for your flavor to work with ganache on\n  // the CLI\n  ready: ({\n    provider,\n    options\n  }: {\n    provider: Provider;\n    options: { server: CliSettings };\n  }) => {\n    // this function is only called after ganache has fully initialized, and is\n    // only called when used via ganache cli (it is not used when your flavor is\n    // used programatically)\n    console.log(\n      `Hello Chain server is running at http://${options.server.host}:${options.server.port}`\n    );\n  }\n};\n\n/**\n * Your flavor needs to be exported as `default` so Ganache can find it.\n */\nexport default HelloFlavor;\n```\n\nCheck out the [example implementation](./example) for a more-in-depth example.\n","readmeFilename":"README.md"}