{"_id":"@deltaswapio/relayer-engine","name":"@deltaswapio/relayer-engine","dist-tags":{"latest":"0.3.2"},"versions":{"0.3.2":{"name":"@deltaswapio/relayer-engine","version":"0.3.2","description":"Relayer Engine","type":"module","main":"lib/cjs/index.js","types":"lib/cjs/index.d.ts","scripts":{"redis":"docker run --rm -p 6379:6379 --name redis-docker -d redis","test-redis":"docker run --rm -p 6301:6379 --name relayer-engine-test -d redis; npm run test; docker kill relayer-engine-test","test":"jest --silent=false","test-watch":"jest --silent=false --watch","build":"tsc -b ./tsconfig.cjs.json && tsc -b ./tsconfig.esm.json && bin/create-package.json.sh","watch":"tsc --watch","typecheck":"tsc --noEmit --skipLibCheck","prettier":"prettier --write $(git diff main --name-only --diff-filter u | grep '.ts$' | xargs)","mainnet-spy":"docker run --platform=linux/amd64 -p 7073:7073 --entrypoint /phylaxd ghcr.io/deltaswapio/phylaxd:latest spy --nodeKey /node.key --spyRPC \"[::]:7073\" --network /deltaswap/mainnet/2 --bootstrap /dns4/deltaswap-mainnet-v2-bootstrap.certus.one/udp/8999/quic/p2p/12D3KooWQp644DK27fd3d4Km3jr7gHiuJJ5ZGmy8hH4py7fP4FP7","testnet-spy":"docker run --platform=linux/amd64 -p 7073:7073 --entrypoint /phylaxd ghcr.io/deltaswapio/phylaxd:latest spy --nodeKey /node.key --spyRPC \"[::]:7073\" --network /deltaswap/testnet/2/1 --bootstrap /dns4/deltaswap-testnet-v2-bootstrap.certus.one/udp/8999/quic/p2p/12D3KooWAkB9ynDur1Jtoa97LBUp8RXdhzS5uHgAfdTquJbrbN7i","prepare":"npm run build"},"exports":{".":{"require":"./lib/cjs/index.js","import":"./lib/esm/index.js","default":"./lib/esm/index.js"},"./*":{"require":"./lib/cjs/*.js","import":"./lib/esm/*.js","default":"./lib/esm/*.js"}},"author":{"name":"Joe Howarth, xLabs Inc."},"license":"Apache-2.0","dependencies":{"@bull-board/api":"^5.8.1","@bull-board/koa":"^5.8.1","@deltaswapio/deltaswap-sdk":"^0.10.7","@deltaswapio/deltaswap-spydk":"^0.1.1","@datastructures-js/queue":"^4.2.3","@improbable-eng/grpc-web-node-http-transport":"^0.15.0","@mysten/sui.js":"^0.32.2","@sei-js/core":"^1.3.4","@xlabs-xyz/wallet-monitor":"0.2.16","bech32":"^2.0.0","bullmq":"^3.15.8","ethers":"^5.7.2","generic-pool":"^3.9.0","ioredis":"^5.3.2","koa":"^2.14.1","lru-cache":"^9.1.2","prom-client":"^14.2.0","winston":"^3.10.0"},"keywords":[],"devDependencies":{"@deltaswapio/deltaswap-sdk-proto-node":"^0.0.6","@cloudnc/grpc-web-testing-toolbox":"^2.2.0","@jest/globals":"^29.6.4","@types/bluebird":"^3.5.38","@types/bs58":"^4.0.1","@types/jest":"^29.5.4","@types/koa":"^2.13.8","@types/node":"^20.6.0","@types/winston":"^2.4.4","jest":"^29.6.4","prettier":"^2.8.8","ts-jest":"^29.1.1","typescript":"^5.2.2"},"gitHead":"e0da1e9aa68e8c40cf9d8bbfa4958a7c01f455c7","_id":"@deltaswapio/relayer-engine@0.3.2","_nodeVersion":"20.4.0","_npmVersion":"9.7.2","dist":{"integrity":"sha512-wrS65OoA+ueY95u9/rCZAMaLUubOFTXt//2uwmqaDsYuKdo9kCuYMObIv4Ehyhvf1VHMoK/CcDEYf/QP+Yk1lQ==","shasum":"0b680b7418c703a5f4528632505237e64739b4e0","tarball":"https://registry.npmjs.org/@deltaswapio/relayer-engine/-/relayer-engine-0.3.2.tgz","fileCount":319,"unpackedSize":1553507,"signatures":[{"keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA","sig":"MEUCIH/OAemPbGQkAeVbEsB5uAtbHIWXAt121y9EhdCkqW41AiEAtWIdoxjK9H2AKuf4UlsE6PKVkrCzlkQqYtGltM5viEE="}]},"_npmUser":{"name":"ad_delta","email":"deltaswap@proton.me"},"directories":{},"maintainers":[{"name":"ad_delta","email":"deltaswap@proton.me"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages","tmp":"tmp/relayer-engine_0.3.2_1700848897818_0.12790723070150545"},"_hasShrinkwrap":false}},"time":{"created":"2023-11-24T18:01:37.677Z","0.3.2":"2023-11-24T18:01:38.174Z","modified":"2023-11-24T18:01:38.440Z"},"maintainers":[{"name":"ad_delta","email":"deltaswap@proton.me"}],"description":"Relayer Engine","keywords":[],"author":{"name":"Joe Howarth, xLabs Inc."},"license":"Apache-2.0","readme":"# Relayer Engine\n\nThe Relayer Engine is a package meant to provide the structure and a starting point for a custom relayer.\n\nWith the Relayer Engine, a developer can write specific logic for filtering to receive only the messages they care about.\n\nOnce a deltaswap message is received, the developer may apply additional logic to parse custom payloads or submit the VAA to one or many destination chains.\n\nTo use the Relayer engine, a developer may specify how to relay deltaswap messages for their app using an idiomatic express/koa middleware inspired api then let the library handle all the details!\n\nCheckout the [quick start](#quick-start) example here, or for a more advanced relayer app, see the [advanced example](./advanced-example.md)\n\n# Quick Start\n\nThe source for this example is available [here](https://github.com/deltaswapio/relayer-engine/blob/main/examples/simple/src/app.ts)\n\n## Install Package\n\nFirst, install the `relayer-engine` package with your favorite package manager\n\n```sh\nnpm i @deltaswapio/relayer-engine\n```\n\n## Start Background Processes\n\n> note: These processes _must_ be running in order for the relayer app below to work\n\nNext, we must start a Spy to listen for available VAAs published on the phylax network as well as a persistence layer, in this case we're using Redis.\n\nMore details about the Spy are available in the [docs](https://docs.deltaswap.com/deltaswap/explore-deltaswap/spy)\n\n### Deltaswap Network Spy\n\nIn order for our Relayer app to receive messages, a local Spy must be running that watches the phylax network. Our relayer app will receive updates from this Spy.\n\n<details>\n<summary><b>Testnet Spy</b></summary>\n\n```bash\ndocker run --platform=linux/amd64 \\\n-p 7073:7073 \\\n--entrypoint /phylaxd ghcr.io/deltaswapio/phylaxd:latest \\\nspy \\\n--nodeKey /node.key \\\n--spyRPC \"[::]:7073\" \\\n--network /deltaswap/testnet/2/1 \\\n--bootstrap /dns4/deltaswap-testnet-v2-bootstrap.certus.one/udp/8999/quic/p2p/12D3KooWAkB9ynDur1Jtoa97LBUp8RXdhzS5uHgAfdTquJbrbN7i\n```\n\n</details>\n\n<details>\n<summary><b>Mainnet Spy</b></summary>\n\n```bash\ndocker run --platform=linux/amd64 \\\n-p 7073:7073 \\\n--entrypoint /phylaxd ghcr.io/deltaswapio/phylaxd:latest \\\nspy \\\n--nodeKey /node.key \\\n--spyRPC \"[::]:7073\" \\\n--network /deltaswap/mainnet/2 \\\n--bootstrap /dns4/deltaswap-mainnet-v2-bootstrap.certus.one/udp/8999/quic/p2p/12D3KooWQp644DK27fd3d4Km3jr7gHiuJJ5ZGmy8hH4py7fP4FP7\n```\n\n</details>\n\n### Redis Persistence\n\n> Note: While we're using Redis here, the persistence layer can be swapped out for some other db by implementing the appropriate [interface](https://github.com/deltaswapio/relayer-engine/blob/main/relayer/storage/redis-storage.ts).\n\nA Redis instance must also be available to persist job data for fetching VAAs from the Spy.\n\n```bash\ndocker run --rm -p 6379:6379 --name redis-docker -d redis\n```\n\n## Simple Relayer Code Example\n\nIn the following example, we'll:\n\n1. Set up a StandardRelayerApp, passing configuration options for our Relayer\n2. Add a filter to capture only those messages our app cares about with a callback to do _something_ with the VAA once we've gotten it\n3. Start the Relayer app\n\n```ts\nimport {\n  Environment,\n  StandardRelayerApp,\n  StandardRelayerContext,\n} from \"@deltaswapio/relayer-engine\";\nimport { CHAIN_ID_SOLANA } from \"@deltaswapio/deltaswap-sdk\";\n\n(async function main() {\n  // initialize relayer engine app, pass relevant config options\n  const app = new StandardRelayerApp<StandardRelayerContext>(\n    Environment.TESTNET,\n    // other app specific config options can be set here for things\n    // like retries, logger, or redis connection settings.\n    {\n      name: \"ExampleRelayer\",\n    },\n  );\n\n  // add a filter with a callback that will be\n  // invoked on finding a VAA that matches the filter\n  app.chain(CHAIN_ID_SOLANA).address(\n    // emitter address on Solana\n    \"DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe\",\n    // callback function to invoke on new message\n    async (ctx, next) => {\n      const vaa = ctx.vaa;\n      const hash = ctx.sourceTxHash;\n      console.log(\n        `Got a VAA with sequence: ${vaa.sequence} from with txhash: ${hash}`,\n      );\n    },\n  );\n\n  // add and configure any other middleware ..\n\n  // start app, blocks until unrecoverable error or process is stopped\n  await app.listen();\n})();\n```\n\n### Explanation\n\nThe first meaningful line instantiates the `StandardRelayerApp`, which is a subclass of the `RelayerApp` with common defaults.\n\n```ts\nexport class StandardRelayerApp<\n  ContextT extends StandardRelayerContext = StandardRelayerContext,\n> extends RelayerApp<ContextT> {\n  // ...\n  constructor(env: Environment, opts: StandardRelayerAppOpts) {\n```\n\nThe only field we pass in the `StandardRelayerAppOpts` is the name to help with identifying log messages and reserve a namespace in Redis.\n\n<details>\n<summary>\nOther `StandardRelayerAppOpts` options\n</summary>\n\n```ts\n  deltaswapRpcs?: string[];  // List of URLs from which to query missed VAAs\n  concurrency?: number;     // How many concurrent requests to make for workflows\n  spyEndpoint?: string;     // The hostname and port of our Spy\n  logger?: Logger;          // A custom Logger\n  privateKeys?: Partial<{ [k in ChainId]: any[]; }>; // A set of keys that can be used to sign and send transactions\n  tokensByChain?: TokensByChain;    // The token list we care about\n  workflows?: { retries: number; }; // How many times to retry a given workflow\n  providers?: ProvidersOpts;        // Configuration for the default providers\n  fetchSourceTxhash?: boolean;      // whether or not to get the original transaction id/hash\n  // Redis config\n  redisClusterEndpoints?: ClusterNode[];\n  redisCluster?: ClusterOptions;\n  redis?: RedisOptions;\n```\n\n</details>\n\nThe next meaningful line in the example adds a filter middleware component. This middleware will cause the Relayer app to request a subscription from the Spy for any VAAs that match the criteria and invoke the callback with the VAA.\n\nIf you'd like your program to subscribe to multiple chains and addresses, the same method can be called several times or the `multiple` helper can be used.\n\n```ts\napp.multiple(\n  {\n    [CHAIN_ID_SOLANA]: \"DZnkkTmCiFWfYTfT41X3Rd1kDgozqzxWaHqsw6W4x2oe\"\n    [CHAIN_ID_ETH]: [\"0xabc1230000000...\",\"0xdef456000.....\"]\n  },\n  myCallback\n);\n```\n\nThe last line in the simple example runs `await app.listen()`, which will start the relayer engine. Once started, the relayer engine will issue subscription requests to the spy and begin any other workflows (e.g. tracking missed VAAs).\n\nThis will run until the process is killed or it encounters an unrecoverable error. If you'd like to shut down the relayer gracefully, call `app.stop()`.\n\n## Advanced Example\n\nFor a more advanced example that details other middleware and more complex configuration and actions including a built in UI, see the [Advanced Tutorial](./advanced-example.md)\n","readmeFilename":"README.md"}