@ganache/flavor
Ganache的口味 TypeScript 类型,帮助器,和效用功能.
Ganache Flavors 是可用于启动链条测试网络的插件
除了Ganache的内置Ethereum网络。 在运行时通过
加纳切的 --flavor 旗帜.
警告和发现
Ganache的口味是实验性的,不完整的,可以不改变 备注.
Ganache的口味是Ethereum JSON-RPC(2.0)的灵感,我们仍在工作 了解其他链条的需求以及如何延长甘纳切口味 在HTTP/WS上支持JSON-RPC 2.0以外的传输的模型.
非JSON-RPC链的一个缺陷实例:
- ganache 只接受 POST 在一个可配置路径上的请求( 默认)
改为
/) (中文(简体) ). 如果你需要别的东西,如JSON over REST,GRPC,SOAP, 等,请打开一个问题描述您的使用案例 . - 基于 websocket 订阅的邮件非常有限,只支持 就像Ethereum JSON -RPC那样.
如何创建实验性甘露口味
要创造出新的口味, 您必须创建一个新包, 导出一个 FlavorA级
口味是一个 JavaScript 对象,用于执行 Flavor TypeScript 接口.
以下是TypeScript中"Hello World"风格口味的例子:
import { Flavor, Connector, CliSettings } from "@ganache/flavor";
export type Provider = { sayHi: (name: string) => string };
export type RequestPayload = { name: string };
export type ResponsePayload = { result: string };
const provider: Provider = {
sayHi(name: string) {
return `Hello, ${name}`;
}
};
const helloConnector: Connector<Provider, RequestPayload, ResponsePayload> = {
// the `provider` is yours to implement however you'd like. In programmatic
// usage it will be returned to the user when they call
// `Ganache.provider()` or `Ganache.server().provider`
provider,
async connect(): Promise<void> {
// ganache will `await` the return of your `connect` method before
// forwarding any requests to your connector.
// if your connector doesn't need to do any async work to initialize you
// can leave this empty.
},
parse(message: Buffer) {
// the `message` doesn't have to be JSON, you can use any data interchange
// format you'd like.
// NOTE: If your connector's `parse` method throws, Ganache does
// _not_ call your `formatError` and instead returns a `400 Bad Request`
// response.
return JSON.parse(message);
},
async handle(
this: typeof helloConnector,
payload: RequestPayload
): Promise<{ value: unknown }> {
if (!payload || typeof payload.name !== "string") {
// you can throw an Exception here and ganache will catch the error and
// pass it to your `formatError` function.
throw new Error("payload must have a `name` property of type `string`");
}
// in this "Hello World" example we only have one method, but you can
// implement as many as you need in any way you want. Here we just call the
// our provider's `sayHi` with the user provided `payload`'s `name`
// property.
const value = this.provider.sayHi(payload.name);
// Your `handle` function MUST always return any object with a `value`
// property. The value of `value` MAY itself be a `Promise`. The _resolved_
// `value` will be passed to your connector's `format` function.
//
// NOTE: if a client is connected via WebSockets, and the the `value` is a
// `PromiEvent` (a `Promise` that also has an `on` function) that emits a
// `"message"` event Ganache will subscribe to the `"message"` event. If
// the `PromiEvent` then emits a "message" its event data will be sent to
// the client.
// ATTENTION: A flavor cannot `format` this message though; it will always
// be sent as am Ethereum JSON-RPC 2.0 subscription style message. This
// behavior will change in the future *without notice*. It is not recommened
// that you use the PromiEvent feature at this time.
return { value };
},
format(result: ResponsePayload, payload: RequestPayload) {
console.log(
`formatting result (${result.result}) for payload (${payload.name})`
);
// You don't have to return a string here, you can also return a Buffer
// and the serialization doesn't have to be JSON. However...
// ATTENTION: ganache flavors don't yet support changing the `content-type`
// header so it always returns `content-type: application/json`. This will
// change in the future and flavors will be able to specify their own
// content-type and other HTTP headers.
//
// You can also return a Generator (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator)
// which will cause ganache to send the response in chunks (one chunk for
// yield). This is useful if your response data is too large for Node.js to
// handle (string and Buffer sizes are limited to about 1-2GB, and memory is
// capped to 4GB on most systems).
return JSON.stringify({ result });
},
formatError(error: Error, payload: RequestPayload) {
// Ganache calls your `formatError` if any errors occured while processing
// a request.
console.log(`formatting error (${error.message}) for payload (${payload})`);
// you don't have to return a string here, you can also return a Buffer
// and the serialization doesn't have to be JSON
return JSON.stringify({ error: error.message });
},
async close() {
// ganache calls your connector's `close` function when shutting down.
// This is where you'd perform clean up, like closing database connections
// or cleaning temporary files.
}
};
type HelloFlavor = Flavor<"hello-chain", typeof helloConnector>;
const HelloFlavor: HelloFlavor = {
flavor: "hello-chain",
options: {
// see the `example/` directory for how Options work
},
connect(providerOptions: never) {
return helloConnector;
},
// the `ready` function is required for your flavor to work with ganache on
// the CLI
ready: ({
provider,
options
}: {
provider: Provider;
options: { server: CliSettings };
}) => {
// this function is only called after ganache has fully initialized, and is
// only called when used via ganache cli (it is not used when your flavor is
// used programatically)
console.log(
`Hello Chain server is running at http://${options.server.host}:${options.server.port}`
);
}
};
/**
* Your flavor needs to be exported as `default` so Ganache can find it.
*/
export default HelloFlavor;
看看这个 实例执行 更深层次的例子.