From af6fbdd927216e323f434e79f92e36bc7c71cffc Mon Sep 17 00:00:00 2001 From: OWK50GA Date: Tue, 14 Apr 2026 06:18:16 +0100 Subject: [PATCH 1/3] feat: superbridge integration --- .env.example | 5 +- packages/orchestrator/.env.example | 1 + packages/orchestrator/logs/combined.log | 375 ++++++++++++++++++ packages/orchestrator/logs/error.log | 24 ++ packages/orchestrator/src/app.ts | 18 + .../src/blockchain/IBridgeClient.ts | 119 ++++++ packages/orchestrator/src/blockchain/index.ts | 3 + .../superbridge/SuperbridgeClient.ts | 321 +++++++++++++++ packages/orchestrator/src/config/index.ts | 3 + .../src/settlement/BridgeSettler.ts | 268 +++++++++++++ .../orchestrator/src/settlement/ISettler.ts | 1 + .../src/settlement/SwapSettler.ts | 8 + .../blockchain/SuperbridgeClient.test.ts | 242 +++++++++++ .../tests/settlement/BridgeSettler.test.ts | 259 ++++++++++++ 14 files changed, 1646 insertions(+), 1 deletion(-) create mode 100644 packages/orchestrator/src/blockchain/IBridgeClient.ts create mode 100644 packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts create mode 100644 packages/orchestrator/src/settlement/BridgeSettler.ts create mode 100644 packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts create mode 100644 packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts diff --git a/.env.example b/.env.example index d8bea1b..04e92ff 100644 --- a/.env.example +++ b/.env.example @@ -5,4 +5,7 @@ THIRDWEB_SECRET_KEY= HASHKEY_RPC_URL=https://testnet.hsk.xyz GRIFFIN_VAULT_ADDRESS= GRIFFIN_OPERATOR_PRIVATE_KEY= -GRIFFIN_DEX_ADDRESS= \ No newline at end of file +GRIFFIN_DEX_ADDRESS= + +# Bridging +SUPERBRIDGE_API_KEY= \ No newline at end of file diff --git a/packages/orchestrator/.env.example b/packages/orchestrator/.env.example index f4d26e0..adefb87 100644 --- a/packages/orchestrator/.env.example +++ b/packages/orchestrator/.env.example @@ -33,6 +33,7 @@ GRIFFIN_DEX_ADDRESS= # Deployed GriffinDEX contract address ONEINCH_API_KEY=your-1inch-api-key THIRDWEB_CLIENT_ID=your-thirdweb-client-id THIRDWEB_SECRET_KEY=your-thirdweb-secret-key +SUPERBRIDGE_API_KEY= # Superbridge API key for cross-chain bridging # Security JWT_SECRET=your-jwt-secret-key diff --git a/packages/orchestrator/logs/combined.log b/packages/orchestrator/logs/combined.log index 7c34bcb..8f74e44 100644 --- a/packages/orchestrator/logs/combined.log +++ b/packages/orchestrator/logs/combined.log @@ -2671,3 +2671,378 @@ {"duration":"9739ms","level":"info","message":"Request completed","method":"PUT","requestId":"31831108-7c79-44e0-89cb-672baf098f69","service":"griffin-orchestrator","statusCode":200,"timestamp":"2026-04-13T10:18:15.768Z","url":"/0207efd7-c07e-4f37-b6d2-889550a5983b/execute"} {"ip":"::ffff:127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"70f7c7ed-cfdf-4d92-8d73-daa1b5dfed42","service":"griffin-orchestrator","timestamp":"2026-04-13T10:18:19.299Z","url":"/api/v1/intents/0207efd7-c07e-4f37-b6d2-889550a5983b","userAgent":"node"} {"duration":"4ms","level":"info","message":"Request completed","method":"GET","requestId":"70f7c7ed-cfdf-4d92-8d73-daa1b5dfed42","service":"griffin-orchestrator","statusCode":200,"timestamp":"2026-04-13T10:18:19.303Z","url":"/0207efd7-c07e-4f37-b6d2-889550a5983b"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.888Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.936Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.940Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.945Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.951Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge","superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.956Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.958Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.963Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.970Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.974Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.976Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.977Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.979Z","txHash":"0xbridgehash"} +{"durationMs":4,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.980Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.983Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.985Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.987Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.990Z","txHash":"0xbridgehash"} +{"durationMs":5,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.990Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.993Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.994Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.995Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:17.996Z","txHash":"0xbridgehash"} +{"durationMs":4,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.998Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:17.999Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.001Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.002Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.003Z","txHash":"0xbridgehash"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.004Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.006Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"high","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.008Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.009Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.010Z","txHash":"0xbridgehash"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.011Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.014Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.026Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Approve token","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.028Z","to":"0xApproveContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.029Z","txHash":"0xbridgehash"} +{"chainId":"eip155:1","description":"Bridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T00:41:18.030Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T00:41:18.031Z","txHash":"0xbridgehash"} +{"durationMs":6,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.032Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.034Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.036Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.062Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.063Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.065Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T00:41:18.066Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T00:41:18.068Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.161Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.311Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.320Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.329Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.333Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge","superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.339Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.343Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.349Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.357Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.362Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.364Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.366Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.368Z","txHash":"0xbridgehash"} +{"durationMs":8,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.372Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.377Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.380Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.381Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.384Z","txHash":"0xbridgehash"} +{"durationMs":8,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.387Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.392Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.394Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.395Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.396Z","txHash":"0xbridgehash"} +{"durationMs":4,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.398Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.400Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.403Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.404Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.405Z","txHash":"0xbridgehash"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.406Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.409Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"high","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.410Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.412Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.413Z","txHash":"0xbridgehash"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.413Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.415Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.417Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Approve token","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.419Z","to":"0xApproveContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.420Z","txHash":"0xbridgehash"} +{"chainId":"eip155:1","description":"Bridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T01:14:12.421Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T01:14:12.422Z","txHash":"0xbridgehash"} +{"durationMs":6,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.424Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.427Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.430Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.455Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.456Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.458Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T01:14:12.459Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T01:14:12.462Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.746Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.879Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.890Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.898Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.913Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge","superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.917Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.932Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.938Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.950Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.955Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.967Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:50.969Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:50.971Z","txHash":"0xbridgehash"} +{"durationMs":8,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.975Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.978Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.980Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:50.981Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:50.983Z","txHash":"0xbridgehash"} +{"durationMs":4,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.985Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.992Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:50.996Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:50.998Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.000Z","txHash":"0xbridgehash"} +{"durationMs":5,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.001Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.006Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.011Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.014Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.015Z","txHash":"0xbridgehash"} +{"durationMs":7,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.017Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.020Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"high","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.022Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.024Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.026Z","txHash":"0xbridgehash"} +{"durationMs":6,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.028Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.035Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.037Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Approve token","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.039Z","to":"0xApproveContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.040Z","txHash":"0xbridgehash"} +{"chainId":"eip155:1","description":"Bridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T05:15:51.042Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T05:15:51.043Z","txHash":"0xbridgehash"} +{"durationMs":8,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.045Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.054Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.056Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.093Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.095Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.097Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:15:51.097Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:51.100Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.414Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.473Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.479Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.482Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.485Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.487Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.489Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.491Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.495Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.498Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.503Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.508Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.514Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.517Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.519Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.556Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.564Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.567Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.570Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.573Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.577Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.578Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.580Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.581Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.584Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.587Z","toChain":"eip155:10"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.594Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:15:52.601Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"stellar:testnet","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.783Z"} +{"count":0,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"stellar:testnet","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.892Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"stellar:testnet","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.906Z"} +{"count":0,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"stellar:testnet","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.910Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.934Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.939Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.948Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.951Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.963Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.965Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.981Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.984Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.995Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:25.998Z"} +{"level":"info","message":"Finding routes","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.001Z"} +{"count":3,"level":"info","message":"Routes found","request":{"amount":"100","fromChain":"stellar:testnet","fromToken":"GABCDE","slippageTolerance":0.01,"toChain":"eip155:1","toToken":"GXYZ12"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.006Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:42:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":404},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.588Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Invalid input","stack":"ValidationError: Invalid input\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:59:31)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":400},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.740Z"} +{"error":{"code":"UNAUTHORIZED","message":"Unauthorized","stack":"UnauthorizedError: Unauthorized\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:70:31)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":401},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.745Z"} +{"error":{"code":"INTERNAL_SERVER_ERROR","message":"Something exploded","stack":"Error: Something exploded\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:86:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.786Z"} +{"error":{"code":"ERR","message":"Oops","stack":"AppError: Oops\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:100:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{"x-request-id":"req-abc-123"},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.803Z"} +{"error":{"code":"INTERNAL_SERVER_ERROR","message":"boom","stack":"Error: boom\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:114:18)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.821Z"} +{"fromChain":"eip155:133","intentId":"2dafff97-4524-4bd0-9916-3e8aafb290db","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:28.930Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"fromChain":"eip155:133","intentId":"da0ecc14-515f-4739-b4b4-f0f5e8150de8","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.022Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"fromChain":"eip155:133","intentId":"5efa2311-e8b8-4f7f-8009-62ddc125c738","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.028Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"fromChain":"eip155:133","intentId":"124a29df-93e4-49fd-ad10-57e408a3543b","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.036Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"error":{"code":"INVALID_AMOUNT","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"0","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.046Z"} +{"error":{"code":"INVALID_AMOUNT","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"-5","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.064Z"} +{"error":{"code":"UNSUPPORTED_CHAIN","details":{"chainId":"unknown:chain"},"name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"unknown:chain","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.071Z"} +{"error":{"code":"UNSUPPORTED_CHAIN","details":{"chainId":"unknown:chain"},"name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"unknown:chain","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.084Z"} +{"error":{"code":"MISSING_SIGNATURE","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.088Z"} +{"error":{"code":"INVALID_ADDRESS","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.092Z"} +{"fromChain":"eip155:133","intentId":"e60c43fb-61bf-4bf3-8fca-e0e0901d8da9","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.102Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"fromChain":"eip155:133","intentId":"b34e8900-fb38-490a-a125-578e180850ac","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.109Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"fromChain":"eip155:133","intentId":"cb661d81-22a1-4325-bd8f-3abc2b64c295","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.114Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"cb661d81-22a1-4325-bd8f-3abc2b64c295","level":"info","message":"Intent execution started","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.132Z"} +{"intentId":"cb661d81-22a1-4325-bd8f-3abc2b64c295","level":"info","message":"Intent completed","service":"griffin-orchestrator","settler":"swap","timestamp":"2026-04-14T05:17:29.137Z"} +{"fromChain":"eip155:133","intentId":"7911561c-85b5-418c-8ba0-adfc7d365393","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.142Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"7911561c-85b5-418c-8ba0-adfc7d365393","level":"info","message":"Intent execution started","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.144Z"} +{"intentId":"7911561c-85b5-418c-8ba0-adfc7d365393","level":"info","message":"Intent completed","service":"griffin-orchestrator","settler":"swap","timestamp":"2026-04-14T05:17:29.146Z"} +{"fromChain":"eip155:133","intentId":"aa2fdc68-0013-4d7d-a624-f377ffffd2bc","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.165Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"aa2fdc68-0013-4d7d-a624-f377ffffd2bc","level":"info","message":"Intent execution started","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.176Z"} +{"err":{},"intentId":"aa2fdc68-0013-4d7d-a624-f377ffffd2bc","level":"error","message":"Intent failed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.178Z"} +{"fromChain":"eip155:133","intentId":"4147b9ed-c4b3-41cd-8356-0b071147d2d7","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.268Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"4147b9ed-c4b3-41cd-8356-0b071147d2d7","level":"info","message":"Intent cancelled","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.271Z"} +{"fromChain":"eip155:133","intentId":"4f5d9d93-6608-4d30-91c6-77d54d9ee4b9","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.274Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"dexChains":[],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.627Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.779Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.794Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.804Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.822Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.827Z"} +{"dexChains":[],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.845Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.850Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.868Z"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.888Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.899Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"durationMs":2,"intentId":"intent-1","level":"info","message":"SwapSettler swap confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.901Z","txHash":"0xdeadbeef"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.928Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.930Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"durationMs":2,"intentId":"intent-1","level":"info","message":"SwapSettler swap confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.932Z","txHash":"0xdeadbeef"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.943Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.946Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"durationMs":9,"intentId":"intent-1","level":"info","message":"SwapSettler swap confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.954Z","txHash":"0xdeadbeef"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.025Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.029Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"SwapSettler swap confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.031Z","txHash":"0xdeadbeef"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.035Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.039Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"dexChains":["eip155:133"],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.135Z"} +{"amountIn":"10000000000000000000","expectedOut":"9700000000000000000","fromChain":"eip155:133","fromToken":"0xTokenIn","intentId":"intent-1","level":"info","message":"SwapSettler executing swap","minAmountOut":"9651500000000000000","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.138Z","toChain":"eip155:133","toToken":"0xTokenOut"} +{"dexChains":[],"level":"info","message":"SwapSettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.156Z"} +{"chains":[],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.118Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.264Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.287Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.300Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.305Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.314Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.325Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.329Z","toChain":"eip155:133","toToken":"0xToken"} +{"durationMs":7,"intentId":"intent-1","level":"info","message":"InventorySettler transfer confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.335Z","txHash":"0xdeadbeef"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.342Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.345Z","toChain":"eip155:133","toToken":"0xToken"} +{"durationMs":12,"intentId":"intent-1","level":"info","message":"InventorySettler transfer confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.356Z","txHash":"0xdeadbeef"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.360Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.366Z","toChain":"eip155:133","toToken":"0xToken"} +{"durationMs":2,"intentId":"intent-1","level":"info","message":"InventorySettler transfer confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.367Z","txHash":"0xdeadbeef"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.396Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.412Z","toChain":"eip155:133","toToken":"0xToken"} +{"durationMs":3,"intentId":"intent-1","level":"info","message":"InventorySettler transfer confirmed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.414Z","txHash":"0xdeadbeef"} +{"chains":[],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.427Z","vaultAddress":"0xVault"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.433Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.441Z","toChain":"eip155:133","toToken":"0xToken"} +{"chains":["eip155:133"],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.561Z","vaultAddress":"0xVault"} +{"amount":"10","decimals":18,"intentId":"intent-1","level":"info","message":"InventorySettler executing transfer","recipient":"0xRecipient","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.569Z","toChain":"eip155:133","toToken":"0xToken"} +{"chains":[],"level":"info","message":"InventorySettler initialised","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:30.580Z","vaultAddress":"0xVault"} +{"fromChain":"eip155:133","intentId":"bb421327-bf30-4b29-91f3-982fa9ec7afa","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.339Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"duration":1,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"healthy","timestamp":"2026-04-14T05:17:31.242Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:31:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"325","content-type":"application/json","host":"127.0.0.1:35953"},"method":"POST","url":"/api/v1/intents"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.601Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:31:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"amount":"100","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"315","content-type":"application/json","host":"127.0.0.1:39197"},"method":"POST","url":"/api/v1/intents"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.656Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:58:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:42587"},"method":"GET","url":"/api/v1/intents/not-a-uuid"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.724Z"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"1ed2d6a2-223e-43f0-bfcf-9f1439385d61","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.506Z","url":"/api/v1/test","userAgent":"test-agent"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:65:15\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:36667"},"method":"GET","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.801Z"} +{"fromChain":"eip155:133","intentId":"296747e2-3bb7-4d2f-847e-35e36fcd94da","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.841Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:88:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"0","host":"127.0.0.1:41001"},"method":"PUT","url":"/api/v1/intents/bad-id/execute"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.893Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.executeIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:62:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:93:42\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"0","host":"127.0.0.1:40929"},"method":"PUT","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000/execute"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.070Z"} +{"fromChain":"eip155:133","intentId":"dccf876b-d4f2-45f8-a18d-3d468e894131","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.157Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"dccf876b-d4f2-45f8-a18d-3d468e894131","level":"info","message":"Intent execution started","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.171Z"} +{"intentId":"dccf876b-d4f2-45f8-a18d-3d468e894131","level":"info","message":"Intent completed","service":"griffin-orchestrator","settler":"swap","timestamp":"2026-04-14T05:17:32.189Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:114:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:41125"},"method":"DELETE","url":"/api/v1/intents/bad-id"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.267Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.cancelIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:96:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:119:27\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:37021"},"method":"DELETE","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.363Z"} +{"fromChain":"eip155:133","intentId":"3eeef4d4-8c80-42b2-950d-ef6a14b7dd0e","level":"info","message":"Intent created","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.400Z","toChain":"eip155:133","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"} +{"intentId":"3eeef4d4-8c80-42b2-950d-ef6a14b7dd0e","level":"info","message":"Intent cancelled","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.551Z"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"ad086a19-fcf8-4b04-a4fa-58ab26f3ae38","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.527Z","url":"/api/v1/test","userAgent":"test-agent"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"70121697-af44-4a7d-ab56-d620742579ee","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.543Z","url":"/api/v1/test","userAgent":"test-agent"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"641e24b5-6384-4d40-855e-491d4879748b","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.562Z","url":"/api/v1/test","userAgent":"test-agent"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"3e153238-fa40-4f9e-9aa3-090f70ad0e0a","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.580Z","url":"/api/v1/test","userAgent":"test-agent"} +{"ip":"127.0.0.1","level":"info","message":"Incoming request","method":"GET","requestId":"5542b038-f332-4468-a8dd-b1719d00e799","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.591Z","url":"/api/v1/test","userAgent":"test-agent"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.166Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.239Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.243Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.273Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.277Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge","superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.294Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.298Z"} +{"chains":[],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.311Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.315Z"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.329Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.331Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.334Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.340Z","txHash":"0xbridgehash"} +{"durationMs":13,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.344Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.347Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.352Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.359Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.362Z","txHash":"0xbridgehash"} +{"durationMs":13,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.363Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.366Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.375Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.377Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.378Z","txHash":"0xbridgehash"} +{"durationMs":4,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.379Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.407Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.409Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.414Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.437Z","txHash":"0xbridgehash"} +{"durationMs":30,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.439Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.442Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"high","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.444Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.454Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.482Z","txHash":"0xbridgehash"} +{"durationMs":39,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.483Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.500Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.503Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Approve token","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.505Z","to":"0xApproveContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.509Z","txHash":"0xbridgehash"} +{"chainId":"eip155:1","description":"Bridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T05:17:32.511Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":1,"timestamp":"2026-04-14T05:17:32.514Z","txHash":"0xbridgehash"} +{"durationMs":14,"intentId":"intent-1","level":"info","message":"BridgeSettler bridge complete","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.517Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.521Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.524Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.588Z"} +{"amount":"1000000000000000000","estimatedTimeSeconds":300,"fromChain":"eip155:1","fromToken":"0xFromToken","intentId":"intent-1","level":"info","message":"BridgeSettler executing bridge","provider":"superbridge","recipient":"0xRecipient","routeId":"route-abc","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.590Z","toChain":"eip155:133","toToken":"0xToToken"} +{"chainId":"eip155:1","description":"Bridge via superbridge","intentId":"intent-1","level":"info","message":"BridgeSettler submitting step","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.591Z","to":"0xBridgeContract"} +{"intentId":"intent-1","level":"info","message":"BridgeSettler step submitted","service":"griffin-orchestrator","stepIndex":0,"timestamp":"2026-04-14T05:17:32.598Z","txHash":"0xbridgehash"} +{"chains":["eip155:1"],"level":"info","message":"BridgeSettler initialised","providers":["superbridge"],"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.608Z"} +{"duration":0,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"healthy","timestamp":"2026-04-14T05:17:31.268Z"} +{"duration":1,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"healthy","timestamp":"2026-04-14T05:17:31.275Z"} +{"duration":0,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"healthy","timestamp":"2026-04-14T05:17:31.290Z"} +{"duration":7,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"healthy","timestamp":"2026-04-14T05:17:31.304Z"} +{"duration":0,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"unhealthy","timestamp":"2026-04-14T05:17:31.325Z"} +{"duration":0,"level":"info","message":"Health check completed","service":"griffin-orchestrator","status":"unhealthy","timestamp":"2026-04-14T05:17:31.339Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.873Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.975Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.046Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.060Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.064Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.077Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.089Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.102Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.286Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.297Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.315Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.330Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.332Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.358Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.361Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.494Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.521Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.538Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.554Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.569Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.580Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.584Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.586Z"} +{"count":1,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.588Z","toChain":"eip155:133"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.597Z"} +{"count":0,"fromChain":"eip155:1","level":"info","message":"SuperbridgeClient routes fetched","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.600Z","toChain":"eip155:10"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.603Z"} +{"level":"info","message":"SuperbridgeClient initialised","sender":"0xSenderAddress","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.617Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/quotes.ts:29:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"fromChain":"stellar:testnet","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"92","content-type":"application/json","host":"127.0.0.1:46239"},"method":"POST","url":"/api/v1/quotes"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.598Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/quotes.ts:29:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"amount":"100","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"77","content-type":"application/json","host":"127.0.0.1:43277"},"method":"POST","url":"/api/v1/quotes"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.644Z"} +{"error":{"code":"NO_TOKENS_FOUND","message":"No tokens found for chain","stack":"AppError: No tokens found for chain\n at ChainService.getSupportedTokens (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/ChainService.ts:30:15)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/chains.ts:25:39\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at Route.dispatch (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:117:3)\n at handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:435:11)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:295:15\n at param (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:600:14)\n at param (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:610:14)\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:664:3)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at router.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:186:3)\n at router (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:60:12)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at trimPrefix (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:342:13)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:297:9\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:582:12)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at read (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/body-parser@2.2.2/node_modules/body-parser/lib/read.js:53:5)\n at jsonParser (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/body-parser@2.2.2/node_modules/body-parser/lib/types/json.js:88:5)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at trimPrefix (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:342:13)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:297:9\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:582:12)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at router.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:186:3)\n at app.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express@5.2.1/node_modules/express/lib/application.js:177:15)\n at Server.app (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express@5.2.1/node_modules/express/lib/express.js:38:9)\n at Server.emit (node:events:508:28)\n at parserOnIncoming (node:_http_server:1210:12)\n at HTTPParser.parserOnHeadersComplete (node:_http_common:125:17)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:42337"},"method":"GET","url":"/api/v1/chains/eip155:1/tokens"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.876Z"} diff --git a/packages/orchestrator/logs/error.log b/packages/orchestrator/logs/error.log index ea011ae..8c43c83 100644 --- a/packages/orchestrator/logs/error.log +++ b/packages/orchestrator/logs/error.log @@ -683,3 +683,27 @@ {"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.executeIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:62:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:93:42\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"0","host":"127.0.0.1:39531"},"method":"PUT","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000/execute"},"service":"griffin-orchestrator","timestamp":"2026-04-13T07:16:13.291Z"} {"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:114:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:39027"},"method":"DELETE","url":"/api/v1/intents/bad-id"},"service":"griffin-orchestrator","timestamp":"2026-04-13T07:16:13.344Z"} {"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.cancelIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:96:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:119:27\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:39041"},"method":"DELETE","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000"},"service":"griffin-orchestrator","timestamp":"2026-04-13T07:16:13.359Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:42:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":404},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.588Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Invalid input","stack":"ValidationError: Invalid input\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:59:31)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":400},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.740Z"} +{"error":{"code":"UNAUTHORIZED","message":"Unauthorized","stack":"UnauthorizedError: Unauthorized\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:70:31)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":401},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.745Z"} +{"error":{"code":"INTERNAL_SERVER_ERROR","message":"Something exploded","stack":"Error: Something exploded\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:86:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.786Z"} +{"error":{"code":"ERR","message":"Oops","stack":"AppError: Oops\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:100:17)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{"x-request-id":"req-abc-123"},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.803Z"} +{"error":{"code":"INTERNAL_SERVER_ERROR","message":"boom","stack":"Error: boom\n at Object. (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/tests/middleware/errorHandler.test.ts:114:18)\n at Promise.then.completed (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:298:28)\n at new Promise ()\n at callAsyncCircusFn (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/utils.js:231:10)\n at _callCircusTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:316:40)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)\n at _runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:252:3)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:126:9)\n at _runTestsForDescribeBlock (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:121:9)\n at run (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/run.js:71:3)\n at runAndTransformResultsToJestFormat (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapterInit.js:122:21)\n at jestAdapter (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-circus@29.7.0/node_modules/jest-circus/build/legacy-code-todo-rewrite/jestAdapter.js:79:19)\n at runTestInternal (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:367:16)\n at runTest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/runTest.js:444:34)\n at Object.worker (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/jest-runner@29.7.0/node_modules/jest-runner/build/testWorker.js:106:12)","statusCode":500},"level":"error","message":"Request error","request":{"body":{},"headers":{},"method":"GET","url":"/test"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:26.821Z"} +{"error":{"code":"INVALID_AMOUNT","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"0","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.046Z"} +{"error":{"code":"INVALID_AMOUNT","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"-5","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.064Z"} +{"error":{"code":"UNSUPPORTED_CHAIN","details":{"chainId":"unknown:chain"},"name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"unknown:chain","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.071Z"} +{"error":{"code":"UNSUPPORTED_CHAIN","details":{"chainId":"unknown:chain"},"name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"unknown:chain","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.084Z"} +{"error":{"code":"MISSING_SIGNATURE","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.088Z"} +{"error":{"code":"INVALID_ADDRESS","name":"AppError","statusCode":400},"level":"error","message":"Failed to create intent","request":{"amount":"100","fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.092Z"} +{"err":{},"intentId":"aa2fdc68-0013-4d7d-a624-f377ffffd2bc","level":"error","message":"Intent failed","service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:29.178Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:31:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"fromChain":"eip155:133","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"325","content-type":"application/json","host":"127.0.0.1:35953"},"method":"POST","url":"/api/v1/intents"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.601Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:31:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"amount":"100","fromToken":"0xb8F355f10569FD2A765296161d082Cc37c5843c2","recipient":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778","requestMessage":"msg","requestSignature":"sig","toChain":"eip155:133","toToken":"0xc4C2841367016C9e2652Fecc49bBA9229787bA82","userAddress":"0xB1655beD2370B9Ad33Dd4ab905a7923D29Ab6778"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"315","content-type":"application/json","host":"127.0.0.1:39197"},"method":"POST","url":"/api/v1/intents"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.656Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:58:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:42587"},"method":"GET","url":"/api/v1/intents/not-a-uuid"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.724Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:65:15\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:36667"},"method":"GET","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.801Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:88:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"0","host":"127.0.0.1:41001"},"method":"PUT","url":"/api/v1/intents/bad-id/execute"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:31.893Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.executeIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:62:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:93:42\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"0","host":"127.0.0.1:40929"},"method":"PUT","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000/execute"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.070Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:114:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:41125"},"method":"DELETE","url":"/api/v1/intents/bad-id"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.267Z"} +{"error":{"code":"INTENT_NOT_FOUND","message":"Intent not found","stack":"AppError: Intent not found\n at IntentService.cancelIntent (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/IntentService.ts:96:13)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/intents.ts:119:27\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:37021"},"method":"DELETE","url":"/api/v1/intents/550e8400-e29b-41d4-a716-446655440000"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:32.363Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/quotes.ts:29:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"fromChain":"stellar:testnet","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"92","content-type":"application/json","host":"127.0.0.1:46239"},"method":"POST","url":"/api/v1/quotes"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.598Z"} +{"error":{"code":"VALIDATION_ERROR","message":"Validation failed","stack":"AppError: Validation failed\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/quotes.ts:29:15\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at middleware (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express-validator@7.3.2/node_modules/express-validator/lib/middlewares/check.js:16:13)\n at processTicksAndRejections (node:internal/process/task_queues:104:5)","statusCode":400},"level":"error","message":"Request error","request":{"body":{"amount":"100","fromToken":"GABCDE","toChain":"eip155:1","toToken":"GXYZ12"},"headers":{"accept-encoding":"gzip, deflate","connection":"close","content-length":"77","content-type":"application/json","host":"127.0.0.1:43277"},"method":"POST","url":"/api/v1/quotes"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.644Z"} +{"error":{"code":"NO_TOKENS_FOUND","message":"No tokens found for chain","stack":"AppError: No tokens found for chain\n at ChainService.getSupportedTokens (/home/wilfrid_k/projects/Griffin/packages/orchestrator/src/services/ChainService.ts:30:15)\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/routes/chains.ts:25:39\n at /home/wilfrid_k/projects/Griffin/packages/orchestrator/src/middleware/errorHandler.ts:76:21\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:157:13)\n at Route.dispatch (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/route.js:117:3)\n at handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:435:11)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:295:15\n at param (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:600:14)\n at param (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:610:14)\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:664:3)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at router.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:186:3)\n at router (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:60:12)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at trimPrefix (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:342:13)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:297:9\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:582:12)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at read (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/body-parser@2.2.2/node_modules/body-parser/lib/read.js:53:5)\n at jsonParser (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/body-parser@2.2.2/node_modules/body-parser/lib/types/json.js:88:5)\n at Layer.handleRequest (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/lib/layer.js:152:17)\n at trimPrefix (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:342:13)\n at /home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:297:9\n at processParams (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:582:12)\n at next (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:291:5)\n at router.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/router@2.2.0/node_modules/router/index.js:186:3)\n at app.handle (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express@5.2.1/node_modules/express/lib/application.js:177:15)\n at Server.app (/home/wilfrid_k/projects/Griffin/node_modules/.pnpm/express@5.2.1/node_modules/express/lib/express.js:38:9)\n at Server.emit (node:events:508:28)\n at parserOnIncoming (node:_http_server:1210:12)\n at HTTPParser.parserOnHeadersComplete (node:_http_common:125:17)","statusCode":404},"level":"error","message":"Request error","request":{"headers":{"accept-encoding":"gzip, deflate","connection":"close","host":"127.0.0.1:42337"},"method":"GET","url":"/api/v1/chains/eip155:1/tokens"},"service":"griffin-orchestrator","timestamp":"2026-04-14T05:17:33.876Z"} diff --git a/packages/orchestrator/src/app.ts b/packages/orchestrator/src/app.ts index d70dd17..b41de67 100644 --- a/packages/orchestrator/src/app.ts +++ b/packages/orchestrator/src/app.ts @@ -12,10 +12,13 @@ import { HealthService } from "./services/HealthService"; import { SettlementEngine } from "./settlement/SettlementEngine"; import { InventorySettler } from "./settlement/InventorySettler"; import { SwapSettler } from "./settlement/SwapSettler"; +import { BridgeSettler } from "./settlement/BridgeSettler"; import { EvmClient } from "./blockchain/evm/EvmClient"; import { DexClient } from "./blockchain/evm/DexClient"; +import { SuperbridgeClient } from "./blockchain/superbridge/SuperbridgeClient"; import { type IChainClient } from "./blockchain/IChainClient"; import { type IDexClient } from "./blockchain/IDexClient"; +import { type IBridgeClient } from "./blockchain/IBridgeClient"; // Import routes import intentRoutes from "./routes/intents"; @@ -60,10 +63,25 @@ if (config.blockchain.hashkey.operatorPrivateKey && config.blockchain.hashkey.de logger.warn("GRIFFIN_DEX_ADDRESS not set — SwapSettler will decline all intents"); } +// Bridge clients — ordered by preference +const bridgeClients: IBridgeClient[] = []; + +if (config.external.superbridge.apiKey && config.blockchain.hashkey.operatorPrivateKey) { + bridgeClients.push( + new SuperbridgeClient({ + apiKey: config.external.superbridge.apiKey, + senderAddress: config.blockchain.hashkey.vaultAddress, + }), + ); +} else { + logger.warn("SUPERBRIDGE_API_KEY not set — BridgeSettler will decline all cross-chain intents"); +} + const routeService = new RouteService(); const settlementEngine = new SettlementEngine([ new InventorySettler(chainClients, config.blockchain.hashkey.vaultAddress), new SwapSettler(dexClients, chainClients), + new BridgeSettler(bridgeClients, chainClients, config.blockchain.hashkey.vaultAddress), ]); const intentService = new IntentService(settlementEngine); // ----------------------------------------------------------------------------- diff --git a/packages/orchestrator/src/blockchain/IBridgeClient.ts b/packages/orchestrator/src/blockchain/IBridgeClient.ts new file mode 100644 index 0000000..dcbc7c0 --- /dev/null +++ b/packages/orchestrator/src/blockchain/IBridgeClient.ts @@ -0,0 +1,119 @@ +/** + * A single step within a bridge route. + * Bridges often require multiple on-chain transactions (e.g. approve + bridge). + */ +export interface BridgeStep { + /** Step index within the route (0-based) */ + index: number; + /** Human-readable description, e.g. "Approve USDC" or "Bridge via Superbridge" */ + description: string; + /** Chain this step is executed on */ + chainId: string; + /** Whether this step requires an ERC-20 approval before execution */ + requiresApproval: boolean; +} + +/** + * A bridge route returned by getRoutes(). + * Represents one provider's offer to move tokens cross-chain. + */ +export interface BridgeRoute { + /** Opaque route identifier — pass back to getStepTransaction() */ + routeId: string; + /** Provider name, e.g. "superbridge", "across", "hop" */ + provider: string; + /** Source chain */ + fromChain: string; + /** Destination chain */ + toChain: string; + /** Token address on source chain */ + fromToken: string; + /** Token address on destination chain */ + toToken: string; + /** Input amount in raw token units */ + amountIn: string; + /** Expected output amount in raw token units */ + amountOut: string; + /** Estimated time for the bridge to complete, in seconds */ + estimatedTimeSeconds: number; + /** Total fees in USD (approximate) */ + feesUsd: string; + /** Ordered list of steps the user must execute */ + steps: BridgeStep[]; +} + +/** + * The calldata needed to execute one step of a bridge route. + */ +export interface BridgeStepTransaction { + /** Chain to submit this transaction on */ + chainId: string; + /** Contract to call */ + to: string; + /** Encoded calldata */ + data: string; + /** Native value to send with the transaction (in wei) */ + value: string; + /** Gas limit estimate */ + gasLimit?: string; +} + +// --------------------------------------------------------------------------- + +/** + * Interface every bridge provider client must implement. + * + * Implementations can be: + * - SDK wrappers (e.g. SuperbridgeClient using @superbridge-app/sdk) + * - HTTP API clients (e.g. AcrossClient, HopClient) + * + * BridgeSettler depends only on this interface — never on a concrete client. + * + * Unlike IDexClient, bridge clients are inherently cross-chain so chainId + * is part of the route rather than a per-call parameter. + */ +export interface IBridgeClient { + /** Human-readable name for logging, e.g. "superbridge", "across" */ + readonly name: string; + + /** + * Returns available bridge routes for moving `amount` of `fromToken` + * on `fromChain` to `toToken` on `toChain`. + * + * Returns an empty array if no routes are available. + * Must not submit any transaction or have side effects. + */ + getRoutes( + fromChain: string, + toChain: string, + fromToken: string, + toToken: string, + amount: string, + ): Promise; + + /** + * Returns the transaction calldata needed to execute a specific step + * of a previously fetched route. + * + * @param routeId - The routeId from a BridgeRoute + * @param stepIndex - Which step to build the transaction for + * @param sender - Address submitting the transaction (Griffin's operator wallet) + * @param recipient - Final destination address for the bridged tokens + */ + getStepTransaction( + routeId: string, + stepIndex: number, + sender: string, + recipient: string, + ): Promise; + + /** + * Waits for a bridge transaction to be fully confirmed on the destination chain. + * For multi-step bridges this should be called after the final step. + * + * @param txHash - Transaction hash of the submitted bridge transaction + * @param fromChain - Source chain ID + * @param toChain - Destination chain ID + */ + waitForCompletion(txHash: string, fromChain: string, toChain: string): Promise; +} diff --git a/packages/orchestrator/src/blockchain/index.ts b/packages/orchestrator/src/blockchain/index.ts index 73f77a8..2e5f0f9 100644 --- a/packages/orchestrator/src/blockchain/index.ts +++ b/packages/orchestrator/src/blockchain/index.ts @@ -1,7 +1,10 @@ export type { IChainClient } from "./IChainClient"; export type { IDexClient, DexQuote } from "./IDexClient"; +export type { IBridgeClient, BridgeRoute, BridgeStep, BridgeStepTransaction } from "./IBridgeClient"; export { EvmClient } from "./evm/EvmClient"; export { DexClient } from "./evm/DexClient"; export { StellarClient } from "./stellar/StellarClient"; +export { SuperbridgeClient } from "./superbridge/SuperbridgeClient"; export type { EvmClientConfig } from "./evm/EvmClient"; export type { DexClientConfig } from "./evm/DexClient"; +export type { SuperbridgeClientConfig } from "./superbridge/SuperbridgeClient"; diff --git a/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts b/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts new file mode 100644 index 0000000..42d88fa --- /dev/null +++ b/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts @@ -0,0 +1,321 @@ +import { type IBridgeClient, type BridgeRoute, type BridgeStep, type BridgeStepTransaction } from "../IBridgeClient"; +import { logger } from "../../utils/logger"; + +const BASE_URL = "https://api.superbridge.app"; + +// --------------------------------------------------------------------------- +// Superbridge API response shapes (subset we actually use) +// --------------------------------------------------------------------------- + +interface SbEvmTx { + to: string; + data: string; + value: string; + gas?: string; +} + +interface SbRouteQuote { + id: string; + provider: { name: string }; + fromChainId: number; + toChainId: number; + fromTokenAddress: string; + toTokenAddress: string; + amount: string; + estimatedReceived: string; + estimatedTimeSeconds: number; + fees: { totalUsd: string }; + initiatingTransaction: SbEvmTx; + tokenApproval?: { tx: SbEvmTx }; + revokeTokenApproval?: { tx: SbEvmTx }; +} + +interface SbRouteResult { + result: SbRouteQuote | { error: string }; +} + +interface SbRoutesResponse { + results: SbRouteResult[]; +} + +interface SbStepTxResponse { + to: string; + data: string; + value: string; + gas?: string; +} + +interface SbActivityStep { + action?: string; + confirmation?: { transactionHash: string }; + status?: string; +} + +interface SbActivity { + id: string; + provider: { name: string }; + nextCheckTimestamp?: number; + steps: SbActivityStep[]; +} + +// --------------------------------------------------------------------------- +// Type guards +// --------------------------------------------------------------------------- + +function isRouteQuote(r: SbRouteQuote | { error: string }): r is SbRouteQuote { + return !("error" in r); +} + +// --------------------------------------------------------------------------- +// Client +// --------------------------------------------------------------------------- + +export interface SuperbridgeClientConfig { + apiKey: string; + /** Griffin's operator wallet address — used as sender in route requests */ + senderAddress: string; +} + +/** + * IBridgeClient implementation backed by the Superbridge HTTP API. + * + * The Superbridge SDK (@superbridge/sdk) is not yet publicly available on npm, + * so we call the REST API directly using fetch. The implementation mirrors the + * official SDK examples exactly — when the SDK ships, this can be swapped in + * with minimal changes. + * + * Docs: https://docs.superbridge.app/api-reference + */ +export class SuperbridgeClient implements IBridgeClient { + readonly name = "superbridge"; + + private readonly apiKey: string; + private readonly senderAddress: string; + + // In-memory cache: routeId → SbRouteQuote, so getStepTransaction can look it up + private readonly routeCache = new Map(); + + constructor(config: SuperbridgeClientConfig) { + this.apiKey = config.apiKey; + this.senderAddress = config.senderAddress; + + logger.info("SuperbridgeClient initialised", { sender: config.senderAddress }); + } + + // ------------------------------------------------------------------------- + // getRoutes + // ------------------------------------------------------------------------- + + async getRoutes( + fromChain: string, + toChain: string, + fromToken: string, + toToken: string, + amount: string, + ): Promise { + const fromChainId = this.chainIdToNumeric(fromChain); + const toChainId = this.chainIdToNumeric(toChain); + + const body = { + fromChainId, + toChainId, + fromTokenAddress: fromToken, + toTokenAddress: toToken, + amount, + sender: this.senderAddress, + recipient: this.senderAddress, // overridden per-intent in getStepTransaction + }; + + const data = await this.post("/v1/routes", body); + + const routes: BridgeRoute[] = []; + + for (const result of data.results) { + if (!isRouteQuote(result.result)) continue; + + const q = result.result; + this.routeCache.set(q.id, q); + + const steps: BridgeStep[] = []; + let stepIndex = 0; + + if (q.revokeTokenApproval) { + steps.push({ index: stepIndex++, description: "Revoke existing token allowance", chainId: fromChain, requiresApproval: false }); + } + if (q.tokenApproval) { + steps.push({ index: stepIndex++, description: "Approve token for bridge", chainId: fromChain, requiresApproval: true }); + } + steps.push({ index: stepIndex, description: `Bridge via ${q.provider.name}`, chainId: fromChain, requiresApproval: false }); + + routes.push({ + routeId: q.id, + provider: q.provider.name, + fromChain, + toChain, + fromToken, + toToken, + amountIn: q.amount, + amountOut: q.estimatedReceived, + estimatedTimeSeconds: q.estimatedTimeSeconds, + feesUsd: q.fees.totalUsd, + steps, + }); + } + + logger.info("SuperbridgeClient routes fetched", { + fromChain, toChain, count: routes.length, + }); + + return routes; + } + + // ------------------------------------------------------------------------- + // getStepTransaction + // ------------------------------------------------------------------------- + + async getStepTransaction( + routeId: string, + stepIndex: number, + sender: string, + recipient: string, + ): Promise { + const quote = this.routeCache.get(routeId); + if (!quote) { + throw new Error(`Route ${routeId} not found in cache — call getRoutes first`); + } + + const steps = this.buildStepList(quote); + const step = steps[stepIndex]; + if (!step) { + throw new Error(`Step ${stepIndex} does not exist for route ${routeId}`); + } + + let tx: SbEvmTx; + + if (step.type === "revokeApproval") { + tx = quote.revokeTokenApproval!.tx; + } else if (step.type === "approval") { + tx = quote.tokenApproval!.tx; + } else { + // Initiating bridge transaction — fetch fresh calldata with correct recipient + const data = await this.post("/v1/get_step_transaction", { + id: quote.id, + action: "initiate", + provider: quote.provider.name, + submitter: sender, + recipient, + }); + tx = data; + } + + return { + chainId: this.numericToChainId(quote.fromChainId), + to: tx.to, + data: tx.data, + value: tx.value, + gasLimit: tx.gas, + }; + } + + // ------------------------------------------------------------------------- + // waitForCompletion + // ------------------------------------------------------------------------- + + async waitForCompletion(txHash: string, fromChain: string, toChain: string): Promise { + logger.info("SuperbridgeClient waiting for bridge completion", { txHash, fromChain, toChain }); + + const MAX_POLLS = 60; + const BASE_DELAY_MS = 10_000; + + for (let i = 0; i < MAX_POLLS; i++) { + const activities = await this.get( + `/v1/activity?evmAddress=${this.senderAddress}`, + ); + + const bridge = activities.find((a) => + a.steps.some((s) => s.confirmation?.transactionHash === txHash), + ); + + if (bridge) { + const allDone = bridge.steps.every( + (s) => s.status === "done" || s.status === "auto" || s.status === "info", + ); + + if (allDone) { + logger.info("SuperbridgeClient bridge complete", { txHash }); + return; + } + + const delay = bridge.nextCheckTimestamp + ? Math.max(bridge.nextCheckTimestamp - Date.now(), 2_000) + : BASE_DELAY_MS; + + await sleep(delay); + } else { + await sleep(BASE_DELAY_MS); + } + } + + throw new Error(`Bridge did not complete within polling window for tx ${txHash}`); + } + + // ------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------- + + private buildStepList(quote: SbRouteQuote): Array<{ type: "revokeApproval" | "approval" | "bridge" }> { + const steps: Array<{ type: "revokeApproval" | "approval" | "bridge" }> = []; + if (quote.revokeTokenApproval) steps.push({ type: "revokeApproval" }); + if (quote.tokenApproval) steps.push({ type: "approval" }); + steps.push({ type: "bridge" }); + return steps; + } + + /** Converts "eip155:133" → 133 */ + private chainIdToNumeric(chainId: string): number { + const parts = chainId.split(":"); + const numeric = parseInt(parts[parts.length - 1], 10); + if (isNaN(numeric)) throw new Error(`Cannot parse numeric chain ID from "${chainId}"`); + return numeric; + } + + /** Converts 133 → "eip155:133" */ + private numericToChainId(numeric: number): string { + return `eip155:${numeric}`; + } + + private async post(path: string, body: unknown): Promise { + const res = await fetch(`${BASE_URL}${path}`, { + method: "POST", + headers: { + "Content-Type": "application/json", + "x-api-key": this.apiKey, + }, + body: JSON.stringify(body), + }); + + if (!res.ok) { + const text = await res.text().catch(() => res.statusText); + throw new Error(`Superbridge API error ${res.status}: ${text}`); + } + + return res.json() as Promise; + } + + private async get(path: string): Promise { + const res = await fetch(`${BASE_URL}${path}`, { + headers: { "x-api-key": this.apiKey }, + }); + + if (!res.ok) { + const text = await res.text().catch(() => res.statusText); + throw new Error(`Superbridge API error ${res.status}: ${text}`); + } + + return res.json() as Promise; + } +} + +function sleep(ms: number): Promise { + return new Promise((r) => setTimeout(r, ms)); +} diff --git a/packages/orchestrator/src/config/index.ts b/packages/orchestrator/src/config/index.ts index c49d5dc..4140ba1 100644 --- a/packages/orchestrator/src/config/index.ts +++ b/packages/orchestrator/src/config/index.ts @@ -66,6 +66,9 @@ export const config = { clientId: process.env.THIRDWEB_CLIENT_ID || "", secretKey: process.env.THIRDWEB_SECRET_KEY || "", }, + superbridge: { + apiKey: process.env.SUPERBRIDGE_API_KEY || "", + }, }, security: { diff --git a/packages/orchestrator/src/settlement/BridgeSettler.ts b/packages/orchestrator/src/settlement/BridgeSettler.ts new file mode 100644 index 0000000..493b16d --- /dev/null +++ b/packages/orchestrator/src/settlement/BridgeSettler.ts @@ -0,0 +1,268 @@ +import { ethers } from "ethers"; +import { + type ISettler, + type SettleabilityCheck, + type SettlementResult, + SettlerType, +} from "./ISettler"; +import { type Intent } from "../types"; +import { type IBridgeClient, type BridgeRoute } from "../blockchain/IBridgeClient"; +import { type IChainClient } from "../blockchain/IChainClient"; +import { AppError } from "../middleware/errorHandler"; +import { logger } from "../utils/logger"; + +export class BridgeSettler implements ISettler { + readonly type = SettlerType.BRIDGE; + + /** + * Bridge clients — one or more providers (e.g. Superbridge, Across). + * BridgeSettler tries them in order and uses the first that returns routes. + */ + private readonly bridgeClients: IBridgeClient[]; + + /** + * Chain clients keyed by chainId — used to sign and submit transactions. + * The bridge client gives us calldata; the chain client submits it. + */ + private readonly chainClients: Map; + + /** Griffin's operator wallet address — used as sender in bridge requests */ + private readonly senderAddress: string; + + constructor( + bridgeClients: IBridgeClient[], + chainClients: Map, + senderAddress: string, + ) { + this.bridgeClients = bridgeClients; + this.chainClients = chainClients; + this.senderAddress = senderAddress; + + logger.info("BridgeSettler initialised", { + providers: bridgeClients.map((b) => b.name), + chains: Array.from(chainClients.keys()), + }); + } + + /** + * Capable if: + * 1. fromChain !== toChain (bridge is only for cross-chain) + * 2. We have a chain client for the source chain (to submit the tx) + * 3. At least one bridge provider returns a route + */ + async canSettle(intent: Intent): Promise { + if (intent.fromChain === intent.toChain) { + return { + capable: false, + reason: "Same-chain intent — use SwapSettler instead", + }; + } + + if (!this.chainClients.has(intent.fromChain)) { + return { + capable: false, + reason: `No chain client registered for source chain ${intent.fromChain}`, + }; + } + + for (const bridge of this.bridgeClients) { + try { + const routes = await bridge.getRoutes( + intent.fromChain, + intent.toChain, + intent.fromToken, + intent.toToken, + intent.amount, + ); + + if (routes.length > 0) { + return { capable: true }; + } + } catch (err) { + logger.debug("Bridge provider returned no routes", { + provider: bridge.name, + error: err instanceof Error ? err.message : String(err), + }); + } + } + + return { + capable: false, + reason: "No bridge routes available for this pair", + }; + } + + async settle(intent: Intent): Promise { + const startedAt = Date.now(); + + const chainClient = this.chainClients.get(intent.fromChain); + if (!chainClient) { + throw new AppError( + `No chain client for source chain ${intent.fromChain}`, + 500, + "NO_CHAIN_CLIENT", + ); + } + + // Find the best route across all providers + const { bridge, route } = await this.findBestRoute(intent); + + logger.info("BridgeSettler executing bridge", { + intentId: intent.id, + provider: bridge.name, + routeId: route.routeId, + fromChain: intent.fromChain, + toChain: intent.toChain, + fromToken: intent.fromToken, + toToken: intent.toToken, + amount: intent.amount, + recipient: intent.recipient, + estimatedTimeSeconds: route.estimatedTimeSeconds, + }); + + // Execute each step in order + let initiatingTxHash = ""; + + for (let i = 0; i < route.steps.length; i++) { + const step = route.steps[i]; + + const stepTx = await bridge.getStepTransaction( + route.routeId, + i, + this.senderAddress, + intent.recipient, + ); + + logger.info("BridgeSettler submitting step", { + intentId: intent.id, + stepIndex: i, + description: step.description, + chainId: stepTx.chainId, + to: stepTx.to, + }); + + // Submit the transaction via the chain client's provider + signer + const txHash = await this.submitTransaction(chainClient, stepTx); + + logger.info("BridgeSettler step submitted", { + intentId: intent.id, + stepIndex: i, + txHash, + }); + + // Wait for on-chain confirmation of this step before proceeding + await chainClient.waitForConfirmation(txHash); + + // The first non-approval step is the initiating bridge transaction + if (!step.requiresApproval && !initiatingTxHash) { + initiatingTxHash = txHash; + } + } + + // Wait for the bridge to complete on the destination chain + await bridge.waitForCompletion(initiatingTxHash, intent.fromChain, intent.toChain); + + const durationMs = Date.now() - startedAt; + + logger.info("BridgeSettler bridge complete", { + intentId: intent.id, + txHash: initiatingTxHash, + durationMs, + }); + + return { + transactionHash: initiatingTxHash, + actualInputAmount: intent.amount, + actualOutputAmount: route.amountOut, + settlerUsed: SettlerType.BRIDGE, + executedRoute: { + id: `bridge-${intent.id}`, + serviceId: bridge.name, + steps: route.steps.map((s) => ({ + type: "bridge" as const, + provider: bridge.name, + fromChain: intent.fromChain, + toChain: intent.toChain, + fromToken: intent.fromToken, + toToken: intent.toToken, + amount: intent.amount, + estimatedOutput: route.amountOut, + fees: { gasFee: "0", total: route.feesUsd }, + })), + totalCost: route.feesUsd, + estimatedTime: route.estimatedTimeSeconds, + slippageTolerance: 0, + gasEstimate: { gasPrice: "0", serviceCost: "0", totalCost: "0" }, + createdAt: new Date(startedAt), + expiresAt: new Date(startedAt + durationMs), + }, + durationMs, + }; + } + + // ------------------------------------------------------------------------- + // Helpers + // ------------------------------------------------------------------------- + + private async findBestRoute( + intent: Intent, + ): Promise<{ bridge: IBridgeClient; route: BridgeRoute }> { + for (const bridge of this.bridgeClients) { + const routes = await bridge.getRoutes( + intent.fromChain, + intent.toChain, + intent.fromToken, + intent.toToken, + intent.amount, + ); + + if (routes.length > 0) { + // Pick the route with the highest amountOut (best deal for recipient) + const best = routes.reduce((a, b) => + BigInt(b.amountOut) > BigInt(a.amountOut) ? b : a, + ); + return { bridge, route: best }; + } + } + + throw new AppError("No bridge routes available at settlement time", 500, "NO_BRIDGE_ROUTE"); + } + + /** + * Submits a raw transaction using the chain client's underlying provider. + * The chain client holds the signer — we just need to send the calldata. + */ + private async submitTransaction( + chainClient: IChainClient, + stepTx: { to: string; data: string; value: string; gasLimit?: string }, + ): Promise { + // IChainClient doesn't expose a raw sendTransaction — we reach into the + // EvmClient's provider via a duck-typed check. If the client exposes a + // sendRawTransaction method we use it; otherwise we fall back to transferToken + // for approval steps (value = 0, data = ERC-20 approve calldata). + // + // TODO: Add sendTransaction(to, data, value) to IChainClient when the + // interface is next revised — this avoids the duck-type cast. + const client = chainClient as unknown as { + signer?: ethers.Wallet; + provider?: ethers.JsonRpcProvider; + }; + + if (!client.signer) { + throw new AppError( + "Chain client does not expose a signer for raw transaction submission", + 500, + "NO_SIGNER", + ); + } + + const tx = await client.signer.sendTransaction({ + to: stepTx.to, + data: stepTx.data, + value: BigInt(stepTx.value), + ...(stepTx.gasLimit ? { gasLimit: BigInt(stepTx.gasLimit) } : {}), + }); + + return tx.hash; + } +} diff --git a/packages/orchestrator/src/settlement/ISettler.ts b/packages/orchestrator/src/settlement/ISettler.ts index 4901326..eaa4c8a 100644 --- a/packages/orchestrator/src/settlement/ISettler.ts +++ b/packages/orchestrator/src/settlement/ISettler.ts @@ -5,6 +5,7 @@ import { type Intent, type RouteInfo } from "../types"; export enum SettlerType { SWAP = "swap", INVENTORY = "inventory", + BRIDGE = "bridge", SOLVER = "solver", } diff --git a/packages/orchestrator/src/settlement/SwapSettler.ts b/packages/orchestrator/src/settlement/SwapSettler.ts index 4ce22e8..348b97f 100644 --- a/packages/orchestrator/src/settlement/SwapSettler.ts +++ b/packages/orchestrator/src/settlement/SwapSettler.ts @@ -48,6 +48,14 @@ export class SwapSettler implements ISettler { * 3. The quoted output is greater than zero */ async canSettle(intent: Intent): Promise { + // Swaps are same-chain only — cross-chain intents should use BridgeSettler + if (intent.fromChain !== intent.toChain) { + return { + capable: false, + reason: `Cross-chain intent detected (${intent.fromChain} → ${intent.toChain}), defaulting to bridge`, + }; + } + const dex = this.dexClients.get(intent.toChain); if (!dex) { diff --git a/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts b/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts new file mode 100644 index 0000000..6e86b8d --- /dev/null +++ b/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts @@ -0,0 +1,242 @@ +import { SuperbridgeClient } from "../../blockchain/superbridge/SuperbridgeClient"; + +// --------------------------------------------------------------------------- +// fetch mock helpers +// --------------------------------------------------------------------------- + +function mockFetch(status: number, body: unknown) { + return jest.fn().mockResolvedValue({ + ok: status >= 200 && status < 300, + status, + statusText: String(status), + json: () => Promise.resolve(body), + text: () => Promise.resolve(String(status)), + } as unknown as Response); +} + +function stubFetch(mock: jest.Mock) { + (global as any).fetch = mock; +} + +// --------------------------------------------------------------------------- +// Fixtures +// --------------------------------------------------------------------------- + +const FROM_CHAIN = "eip155:1"; +const TO_CHAIN = "eip155:133"; +const FROM_TOKEN = "0xFromToken"; +const TO_TOKEN = "0xToToken"; +const AMOUNT = "1000000000000000000"; +const SENDER = "0xSenderAddress"; +const RECIPIENT = "0xRecipientAddress"; + +const makeSbQuote = (overrides: Record = {}) => ({ + id: "route-123", + provider: { name: "superbridge" }, + fromChainId: 1, + toChainId: 133, + fromTokenAddress: FROM_TOKEN, + toTokenAddress: TO_TOKEN, + amount: AMOUNT, + estimatedReceived: "990000000000000000", + estimatedTimeSeconds: 300, + fees: { totalUsd: "1.50" }, + initiatingTransaction: { to: "0xBridge", data: "0xcalldata", value: "0" }, + ...overrides, +}); + +const makeRoutesResponse = (quotes: unknown[]) => ({ + results: quotes.map((q) => ({ result: q })), +}); + +let client: SuperbridgeClient; + +beforeEach(() => { + client = new SuperbridgeClient({ apiKey: "test-key", senderAddress: SENDER }); +}); + +// --------------------------------------------------------------------------- +// getRoutes +// --------------------------------------------------------------------------- + +describe("SuperbridgeClient.getRoutes", () => { + it("returns mapped BridgeRoute for a valid quote", async () => { + const spy = mockFetch(200, makeRoutesResponse([makeSbQuote()])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + expect(routes).toHaveLength(1); + expect(routes[0].routeId).toBe("route-123"); + expect(routes[0].provider).toBe("superbridge"); + expect(routes[0].amountOut).toBe("990000000000000000"); + expect(routes[0].estimatedTimeSeconds).toBe(300); + expect(routes[0].feesUsd).toBe("1.50"); + }); + + it("returns empty array when all results have errors", async () => { + const spy = mockFetch(200, makeRoutesResponse([{ error: "no route" }])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + expect(routes).toHaveLength(0); + }); + + it("returns empty array when results array is empty", async () => { + const spy = mockFetch(200, makeRoutesResponse([])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + expect(routes).toHaveLength(0); + }); + + it("includes a bridge step in every route", async () => { + const spy = mockFetch(200, makeRoutesResponse([makeSbQuote()])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + const bridgeStep = routes[0].steps.find((s) => !s.requiresApproval); + expect(bridgeStep).toBeDefined(); + expect(bridgeStep!.description).toMatch(/Bridge via/); + }); + + it("includes approval step when tokenApproval is present", async () => { + const quote = makeSbQuote({ + tokenApproval: { tx: { to: "0xToken", data: "0xapprove", value: "0" } }, + }); + const spy = mockFetch(200, makeRoutesResponse([quote])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + const approvalStep = routes[0].steps.find((s) => s.requiresApproval); + expect(approvalStep).toBeDefined(); + expect(routes[0].steps).toHaveLength(2); // approval + bridge + }); + + it("includes revoke + approval + bridge steps when revokeTokenApproval is present", async () => { + const quote = makeSbQuote({ + revokeTokenApproval: { tx: { to: "0xToken", data: "0xrevoke", value: "0" } }, + tokenApproval: { tx: { to: "0xToken", data: "0xapprove", value: "0" } }, + }); + const spy = mockFetch(200, makeRoutesResponse([quote])); + stubFetch(spy); + + const routes = await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + expect(routes[0].steps).toHaveLength(3); + }); + + it("sends correct chain IDs to the API", async () => { + const spy = mockFetch(200, makeRoutesResponse([makeSbQuote()])); + stubFetch(spy); + + await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + const body = JSON.parse(spy.mock.calls[0][1]?.body as string); + expect(body.fromChainId).toBe(1); // eip155:1 → 1 + expect(body.toChainId).toBe(133); // eip155:133 → 133 + }); + + it("throws on API error response", async () => { + stubFetch(mockFetch(500, {})); + await expect( + client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT), + ).rejects.toThrow("Superbridge API error 500"); + }); +}); + +// --------------------------------------------------------------------------- +// getStepTransaction +// --------------------------------------------------------------------------- + +describe("SuperbridgeClient.getStepTransaction", () => { + it("throws when route is not in cache", async () => { + await expect( + client.getStepTransaction("unknown-route", 0, SENDER, RECIPIENT), + ).rejects.toThrow("not found in cache"); + }); + + it("returns approval tx calldata for approval step without API call", async () => { + const quote = makeSbQuote({ + tokenApproval: { tx: { to: "0xToken", data: "0xapprove", value: "0" } }, + }); + stubFetch(mockFetch(200, makeRoutesResponse([quote]))); + await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + // Reset fetch mock — approval step should NOT call the API + const spy = jest.fn(); + stubFetch(spy); + + const stepTx = await client.getStepTransaction("route-123", 0, SENDER, RECIPIENT); + expect(stepTx.to).toBe("0xToken"); + expect(stepTx.data).toBe("0xapprove"); + expect(spy).not.toHaveBeenCalled(); // no API call for approval + }); + + it("calls /v1/get_step_transaction for bridge step", async () => { + stubFetch(mockFetch(200, makeRoutesResponse([makeSbQuote()]))); + await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + const stepTxResponse = { to: "0xBridge", data: "0xcalldata", value: "100" }; + const spy = mockFetch(200, stepTxResponse); + stubFetch(spy); + + const stepTx = await client.getStepTransaction("route-123", 0, SENDER, RECIPIENT); + expect(stepTx.to).toBe("0xBridge"); + expect(stepTx.value).toBe("100"); + + const body = JSON.parse(spy.mock.calls[0][1]?.body as string); + expect(body.recipient).toBe(RECIPIENT); + expect(body.submitter).toBe(SENDER); + }); + + it("returns correct chainId in step transaction", async () => { + stubFetch(mockFetch(200, makeRoutesResponse([makeSbQuote()]))); + await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + stubFetch(mockFetch(200, { to: "0xB", data: "0x", value: "0" })); + const stepTx = await client.getStepTransaction("route-123", 0, SENDER, RECIPIENT); + + expect(stepTx.chainId).toBe("eip155:1"); // fromChainId=1 → eip155:1 + }); + + it("throws when step index is out of range", async () => { + stubFetch(mockFetch(200, makeRoutesResponse([makeSbQuote()]))); + await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); + + await expect( + client.getStepTransaction("route-123", 99, SENDER, RECIPIENT), + ).rejects.toThrow("does not exist"); + }); +}); + +// --------------------------------------------------------------------------- +// chainId conversion +// --------------------------------------------------------------------------- + +describe("SuperbridgeClient chain ID conversion", () => { + it("correctly parses eip155:1 → 1 in API request", async () => { + const spy = mockFetch(200, makeRoutesResponse([])); + stubFetch(spy); + await client.getRoutes("eip155:1", "eip155:10", FROM_TOKEN, TO_TOKEN, AMOUNT); + const body = JSON.parse(spy.mock.calls[0][1]?.body as string); + expect(body.fromChainId).toBe(1); + expect(body.toChainId).toBe(10); + }); + + it("throws for unparseable chain ID", async () => { + stubFetch(mockFetch(200, makeRoutesResponse([]))); + await expect( + client.getRoutes("invalid", TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT), + ).rejects.toThrow("Cannot parse numeric chain ID"); + }); +}); + +// --------------------------------------------------------------------------- +// identity +// --------------------------------------------------------------------------- + +describe("SuperbridgeClient identity", () => { + it("has name superbridge", () => { + expect(client.name).toBe("superbridge"); + }); +}); diff --git a/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts b/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts new file mode 100644 index 0000000..f5100b6 --- /dev/null +++ b/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts @@ -0,0 +1,259 @@ +import { BridgeSettler } from "../../settlement/BridgeSettler"; +import { SettlerType } from "../../settlement/ISettler"; +import { type IBridgeClient, type BridgeRoute, type BridgeStepTransaction } from "../../blockchain/IBridgeClient"; +import { type IChainClient } from "../../blockchain/IChainClient"; +import { type Intent, IntentStatus } from "../../types"; +import { ethers } from "ethers"; + +// --------------------------------------------------------------------------- +// Helpers +// --------------------------------------------------------------------------- + +const FROM_CHAIN = "eip155:1"; +const TO_CHAIN = "eip155:133"; +const FROM_TOKEN = "0xFromToken"; +const TO_TOKEN = "0xToToken"; +const RECIPIENT = "0xRecipient"; +const SENDER = "0xSender"; +const TX_HASH = "0xbridgehash"; +const ROUTE_ID = "route-abc"; + +const makeIntent = (overrides: Partial = {}): Intent => ({ + id: "intent-1", + userAddress: SENDER, + fromChain: FROM_CHAIN, + toChain: TO_CHAIN, + fromToken: FROM_TOKEN, + toToken: TO_TOKEN, + amount: "1000000000000000000", + recipient: RECIPIENT, + status: IntentStatus.PENDING, + transactions: [], + createdAt: new Date(), + updatedAt: new Date(), + metadata: {}, + ...overrides, +}); + +const makeRoute = (overrides: Partial = {}): BridgeRoute => ({ + routeId: ROUTE_ID, + provider: "superbridge", + fromChain: FROM_CHAIN, + toChain: TO_CHAIN, + fromToken: FROM_TOKEN, + toToken: TO_TOKEN, + amountIn: "1000000000000000000", + amountOut: "990000000000000000", + estimatedTimeSeconds: 300, + feesUsd: "1.50", + steps: [ + { index: 0, description: "Bridge via superbridge", chainId: FROM_CHAIN, requiresApproval: false }, + ], + ...overrides, +}); + +const makeStepTx = (): BridgeStepTransaction => ({ + chainId: FROM_CHAIN, + to: "0xBridgeContract", + data: "0xcalldata", + value: "0", +}); + +const makeBridgeClient = (routes: BridgeRoute[] = [makeRoute()]): jest.Mocked => ({ + name: "superbridge", + getRoutes: jest.fn().mockResolvedValue(routes), + getStepTransaction: jest.fn().mockResolvedValue(makeStepTx()), + waitForCompletion: jest.fn().mockResolvedValue(undefined), +}); + +const makeChainClient = (): jest.Mocked & { signer: jest.Mocked } => { + const mockSigner = { + sendTransaction: jest.fn().mockResolvedValue({ hash: TX_HASH }), + } as unknown as jest.Mocked; + + return { + chainId: FROM_CHAIN, + getTokenBalance: jest.fn().mockResolvedValue(0n), + transferToken: jest.fn().mockResolvedValue(TX_HASH), + waitForConfirmation: jest.fn().mockResolvedValue(undefined), + signer: mockSigner, + }; +}; + +const makeSettler = ( + bridgeClients: IBridgeClient[] = [makeBridgeClient()], + chainClient?: ReturnType, +) => { + const chainMap = new Map(); + const client = chainClient ?? makeChainClient(); + chainMap.set(FROM_CHAIN, client as unknown as IChainClient); + return { + settler: new BridgeSettler(bridgeClients, chainMap, SENDER), + chainClient: client, + }; +}; + +// --------------------------------------------------------------------------- +// canSettle +// --------------------------------------------------------------------------- + +describe("BridgeSettler.canSettle", () => { + it("declines same-chain intents", async () => { + const { settler } = makeSettler(); + const result = await settler.canSettle(makeIntent({ fromChain: FROM_CHAIN, toChain: FROM_CHAIN })); + expect(result.capable).toBe(false); + expect(result.reason).toMatch(/Same-chain/); + }); + + it("declines when no chain client for source chain", async () => { + const settler = new BridgeSettler([makeBridgeClient()], new Map(), SENDER); + const result = await settler.canSettle(makeIntent()); + expect(result.capable).toBe(false); + expect(result.reason).toMatch(/No chain client/); + }); + + it("declines when all bridge clients return empty routes", async () => { + const bridge = makeBridgeClient([]); + const { settler } = makeSettler([bridge]); + const result = await settler.canSettle(makeIntent()); + expect(result.capable).toBe(false); + expect(result.reason).toMatch(/No bridge routes/); + }); + + it("declines when bridge client throws", async () => { + const bridge = makeBridgeClient(); + bridge.getRoutes.mockRejectedValueOnce(new Error("API down")); + const { settler } = makeSettler([bridge]); + const result = await settler.canSettle(makeIntent()); + expect(result.capable).toBe(false); + expect(result.reason).toMatch(/No bridge routes/); + }); + + it("returns capable=true when a route is available", async () => { + const { settler } = makeSettler(); + const result = await settler.canSettle(makeIntent()); + expect(result.capable).toBe(true); + }); + + it("tries multiple providers and succeeds if second has routes", async () => { + const noRoutes = makeBridgeClient([]); + const hasRoutes = makeBridgeClient([makeRoute()]); + const { settler } = makeSettler([noRoutes, hasRoutes]); + const result = await settler.canSettle(makeIntent()); + expect(result.capable).toBe(true); + }); + + it("calls getRoutes with correct intent fields", async () => { + const bridge = makeBridgeClient(); + const { settler } = makeSettler([bridge]); + const intent = makeIntent(); + await settler.canSettle(intent); + expect(bridge.getRoutes).toHaveBeenCalledWith( + FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, intent.amount, + ); + }); +}); + +// --------------------------------------------------------------------------- +// settle +// --------------------------------------------------------------------------- + +describe("BridgeSettler.settle", () => { + it("throws NO_CHAIN_CLIENT when source chain client is missing", async () => { + const settler = new BridgeSettler([makeBridgeClient()], new Map(), SENDER); + await expect(settler.settle(makeIntent())).rejects.toMatchObject({ code: "NO_CHAIN_CLIENT" }); + }); + + it("throws NO_BRIDGE_ROUTE when no provider has routes at settlement time", async () => { + const bridge = makeBridgeClient([]); + const { settler } = makeSettler([bridge]); + await expect(settler.settle(makeIntent())).rejects.toMatchObject({ code: "NO_BRIDGE_ROUTE" }); + }); + + it("calls getStepTransaction with correct args", async () => { + const bridge = makeBridgeClient(); + const { settler } = makeSettler([bridge]); + await settler.settle(makeIntent()); + expect(bridge.getStepTransaction).toHaveBeenCalledWith(ROUTE_ID, 0, SENDER, RECIPIENT); + }); + + it("calls waitForConfirmation after each step", async () => { + const bridge = makeBridgeClient(); + const { settler, chainClient } = makeSettler([bridge]); + await settler.settle(makeIntent()); + expect(chainClient.waitForConfirmation).toHaveBeenCalledWith(TX_HASH); + }); + + it("calls waitForCompletion with initiating tx hash", async () => { + const bridge = makeBridgeClient(); + const { settler } = makeSettler([bridge]); + const intent = makeIntent(); + await settler.settle(intent); + expect(bridge.waitForCompletion).toHaveBeenCalledWith(TX_HASH, FROM_CHAIN, TO_CHAIN); + }); + + it("returns SettlementResult with correct shape", async () => { + const { settler } = makeSettler(); + const result = await settler.settle(makeIntent()); + expect(result.transactionHash).toBe(TX_HASH); + expect(result.settlerUsed).toBe(SettlerType.BRIDGE); + expect(result.actualInputAmount).toBe("1000000000000000000"); + expect(result.actualOutputAmount).toBe("990000000000000000"); + expect(result.durationMs).toBeGreaterThanOrEqual(0); + }); + + it("picks the route with the highest amountOut across multiple routes", async () => { + const lowRoute = makeRoute({ routeId: "low", amountOut: "900000000000000000" }); + const highRoute = makeRoute({ routeId: "high", amountOut: "990000000000000000" }); + const bridge = makeBridgeClient([lowRoute, highRoute]); + const { settler } = makeSettler([bridge]); + const result = await settler.settle(makeIntent()); + // getStepTransaction should be called with the high-amountOut route + expect(bridge.getStepTransaction).toHaveBeenCalledWith("high", 0, SENDER, RECIPIENT); + expect(result.actualOutputAmount).toBe("990000000000000000"); + }); + + it("executes approval step before bridge step", async () => { + const routeWithApproval = makeRoute({ + steps: [ + { index: 0, description: "Approve token", chainId: FROM_CHAIN, requiresApproval: true }, + { index: 1, description: "Bridge", chainId: FROM_CHAIN, requiresApproval: false }, + ], + }); + const bridge = makeBridgeClient([routeWithApproval]); + bridge.getStepTransaction + .mockResolvedValueOnce({ ...makeStepTx(), to: "0xApproveContract" }) + .mockResolvedValueOnce({ ...makeStepTx(), to: "0xBridgeContract" }); + + const { settler, chainClient } = makeSettler([bridge]); + await settler.settle(makeIntent()); + + expect(bridge.getStepTransaction).toHaveBeenCalledTimes(2); + expect(chainClient.waitForConfirmation).toHaveBeenCalledTimes(2); + }); + + it("propagates error when getStepTransaction throws", async () => { + const bridge = makeBridgeClient(); + bridge.getStepTransaction.mockRejectedValueOnce(new Error("step tx failed")); + const { settler } = makeSettler([bridge]); + await expect(settler.settle(makeIntent())).rejects.toThrow("step tx failed"); + }); + + it("propagates error when waitForCompletion throws", async () => { + const bridge = makeBridgeClient(); + bridge.waitForCompletion.mockRejectedValueOnce(new Error("bridge timeout")); + const { settler } = makeSettler([bridge]); + await expect(settler.settle(makeIntent())).rejects.toThrow("bridge timeout"); + }); +}); + +// --------------------------------------------------------------------------- +// identity +// --------------------------------------------------------------------------- + +describe("BridgeSettler identity", () => { + it("has type BRIDGE", () => { + const { settler } = makeSettler(); + expect(settler.type).toBe(SettlerType.BRIDGE); + }); +}); From 41531e554afc02d7c823e6d1d28546f91dc7a7ab Mon Sep 17 00:00:00 2001 From: OWK50GA Date: Tue, 14 Apr 2026 06:43:01 +0100 Subject: [PATCH 2/3] prettier formatting --- packages/orchestrator/src/blockchain/index.ts | 7 +- .../superbridge/SuperbridgeClient.ts | 70 +++++++++++++------ .../src/settlement/BridgeSettler.ts | 4 +- .../blockchain/SuperbridgeClient.test.ts | 26 +++---- .../tests/settlement/BridgeSettler.test.ts | 37 +++++++--- 5 files changed, 93 insertions(+), 51 deletions(-) diff --git a/packages/orchestrator/src/blockchain/index.ts b/packages/orchestrator/src/blockchain/index.ts index 2e5f0f9..801fc49 100644 --- a/packages/orchestrator/src/blockchain/index.ts +++ b/packages/orchestrator/src/blockchain/index.ts @@ -1,6 +1,11 @@ export type { IChainClient } from "./IChainClient"; export type { IDexClient, DexQuote } from "./IDexClient"; -export type { IBridgeClient, BridgeRoute, BridgeStep, BridgeStepTransaction } from "./IBridgeClient"; +export type { + IBridgeClient, + BridgeRoute, + BridgeStep, + BridgeStepTransaction, +} from "./IBridgeClient"; export { EvmClient } from "./evm/EvmClient"; export { DexClient } from "./evm/DexClient"; export { StellarClient } from "./stellar/StellarClient"; diff --git a/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts b/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts index 42d88fa..03cb48f 100644 --- a/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts +++ b/packages/orchestrator/src/blockchain/superbridge/SuperbridgeClient.ts @@ -1,4 +1,9 @@ -import { type IBridgeClient, type BridgeRoute, type BridgeStep, type BridgeStepTransaction } from "../IBridgeClient"; +import { + type IBridgeClient, + type BridgeRoute, + type BridgeStep, + type BridgeStepTransaction, +} from "../IBridgeClient"; import { logger } from "../../utils/logger"; const BASE_URL = "https://api.superbridge.app"; @@ -114,15 +119,15 @@ export class SuperbridgeClient implements IBridgeClient { amount: string, ): Promise { const fromChainId = this.chainIdToNumeric(fromChain); - const toChainId = this.chainIdToNumeric(toChain); + const toChainId = this.chainIdToNumeric(toChain); const body = { fromChainId, toChainId, fromTokenAddress: fromToken, - toTokenAddress: toToken, + toTokenAddress: toToken, amount, - sender: this.senderAddress, + sender: this.senderAddress, recipient: this.senderAddress, // overridden per-intent in getStepTransaction }; @@ -140,30 +145,47 @@ export class SuperbridgeClient implements IBridgeClient { let stepIndex = 0; if (q.revokeTokenApproval) { - steps.push({ index: stepIndex++, description: "Revoke existing token allowance", chainId: fromChain, requiresApproval: false }); + steps.push({ + index: stepIndex++, + description: "Revoke existing token allowance", + chainId: fromChain, + requiresApproval: false, + }); } if (q.tokenApproval) { - steps.push({ index: stepIndex++, description: "Approve token for bridge", chainId: fromChain, requiresApproval: true }); + steps.push({ + index: stepIndex++, + description: "Approve token for bridge", + chainId: fromChain, + requiresApproval: true, + }); } - steps.push({ index: stepIndex, description: `Bridge via ${q.provider.name}`, chainId: fromChain, requiresApproval: false }); + steps.push({ + index: stepIndex, + description: `Bridge via ${q.provider.name}`, + chainId: fromChain, + requiresApproval: false, + }); routes.push({ - routeId: q.id, - provider: q.provider.name, + routeId: q.id, + provider: q.provider.name, fromChain, toChain, fromToken, toToken, - amountIn: q.amount, - amountOut: q.estimatedReceived, + amountIn: q.amount, + amountOut: q.estimatedReceived, estimatedTimeSeconds: q.estimatedTimeSeconds, - feesUsd: q.fees.totalUsd, + feesUsd: q.fees.totalUsd, steps, }); } logger.info("SuperbridgeClient routes fetched", { - fromChain, toChain, count: routes.length, + fromChain, + toChain, + count: routes.length, }); return routes; @@ -185,7 +207,7 @@ export class SuperbridgeClient implements IBridgeClient { } const steps = this.buildStepList(quote); - const step = steps[stepIndex]; + const step = steps[stepIndex]; if (!step) { throw new Error(`Step ${stepIndex} does not exist for route ${routeId}`); } @@ -199,9 +221,9 @@ export class SuperbridgeClient implements IBridgeClient { } else { // Initiating bridge transaction — fetch fresh calldata with correct recipient const data = await this.post("/v1/get_step_transaction", { - id: quote.id, - action: "initiate", - provider: quote.provider.name, + id: quote.id, + action: "initiate", + provider: quote.provider.name, submitter: sender, recipient, }); @@ -209,10 +231,10 @@ export class SuperbridgeClient implements IBridgeClient { } return { - chainId: this.numericToChainId(quote.fromChainId), - to: tx.to, - data: tx.data, - value: tx.value, + chainId: this.numericToChainId(quote.fromChainId), + to: tx.to, + data: tx.data, + value: tx.value, gasLimit: tx.gas, }; } @@ -263,10 +285,12 @@ export class SuperbridgeClient implements IBridgeClient { // Helpers // ------------------------------------------------------------------------- - private buildStepList(quote: SbRouteQuote): Array<{ type: "revokeApproval" | "approval" | "bridge" }> { + private buildStepList( + quote: SbRouteQuote, + ): Array<{ type: "revokeApproval" | "approval" | "bridge" }> { const steps: Array<{ type: "revokeApproval" | "approval" | "bridge" }> = []; if (quote.revokeTokenApproval) steps.push({ type: "revokeApproval" }); - if (quote.tokenApproval) steps.push({ type: "approval" }); + if (quote.tokenApproval) steps.push({ type: "approval" }); steps.push({ type: "bridge" }); return steps; } diff --git a/packages/orchestrator/src/settlement/BridgeSettler.ts b/packages/orchestrator/src/settlement/BridgeSettler.ts index 493b16d..bf6a85f 100644 --- a/packages/orchestrator/src/settlement/BridgeSettler.ts +++ b/packages/orchestrator/src/settlement/BridgeSettler.ts @@ -218,9 +218,7 @@ export class BridgeSettler implements ISettler { if (routes.length > 0) { // Pick the route with the highest amountOut (best deal for recipient) - const best = routes.reduce((a, b) => - BigInt(b.amountOut) > BigInt(a.amountOut) ? b : a, - ); + const best = routes.reduce((a, b) => (BigInt(b.amountOut) > BigInt(a.amountOut) ? b : a)); return { bridge, route: best }; } } diff --git a/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts b/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts index 6e86b8d..65a5c77 100644 --- a/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts +++ b/packages/orchestrator/src/tests/blockchain/SuperbridgeClient.test.ts @@ -23,12 +23,12 @@ function stubFetch(mock: jest.Mock) { // --------------------------------------------------------------------------- const FROM_CHAIN = "eip155:1"; -const TO_CHAIN = "eip155:133"; +const TO_CHAIN = "eip155:133"; const FROM_TOKEN = "0xFromToken"; -const TO_TOKEN = "0xToToken"; -const AMOUNT = "1000000000000000000"; -const SENDER = "0xSenderAddress"; -const RECIPIENT = "0xRecipientAddress"; +const TO_TOKEN = "0xToToken"; +const AMOUNT = "1000000000000000000"; +const SENDER = "0xSenderAddress"; +const RECIPIENT = "0xRecipientAddress"; const makeSbQuote = (overrides: Record = {}) => ({ id: "route-123", @@ -132,8 +132,8 @@ describe("SuperbridgeClient.getRoutes", () => { await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); const body = JSON.parse(spy.mock.calls[0][1]?.body as string); - expect(body.fromChainId).toBe(1); // eip155:1 → 1 - expect(body.toChainId).toBe(133); // eip155:133 → 133 + expect(body.fromChainId).toBe(1); // eip155:1 → 1 + expect(body.toChainId).toBe(133); // eip155:133 → 133 }); it("throws on API error response", async () => { @@ -150,9 +150,9 @@ describe("SuperbridgeClient.getRoutes", () => { describe("SuperbridgeClient.getStepTransaction", () => { it("throws when route is not in cache", async () => { - await expect( - client.getStepTransaction("unknown-route", 0, SENDER, RECIPIENT), - ).rejects.toThrow("not found in cache"); + await expect(client.getStepTransaction("unknown-route", 0, SENDER, RECIPIENT)).rejects.toThrow( + "not found in cache", + ); }); it("returns approval tx calldata for approval step without API call", async () => { @@ -203,9 +203,9 @@ describe("SuperbridgeClient.getStepTransaction", () => { stubFetch(mockFetch(200, makeRoutesResponse([makeSbQuote()]))); await client.getRoutes(FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, AMOUNT); - await expect( - client.getStepTransaction("route-123", 99, SENDER, RECIPIENT), - ).rejects.toThrow("does not exist"); + await expect(client.getStepTransaction("route-123", 99, SENDER, RECIPIENT)).rejects.toThrow( + "does not exist", + ); }); }); diff --git a/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts b/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts index f5100b6..96c9914 100644 --- a/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts +++ b/packages/orchestrator/src/tests/settlement/BridgeSettler.test.ts @@ -1,6 +1,10 @@ import { BridgeSettler } from "../../settlement/BridgeSettler"; import { SettlerType } from "../../settlement/ISettler"; -import { type IBridgeClient, type BridgeRoute, type BridgeStepTransaction } from "../../blockchain/IBridgeClient"; +import { + type IBridgeClient, + type BridgeRoute, + type BridgeStepTransaction, +} from "../../blockchain/IBridgeClient"; import { type IChainClient } from "../../blockchain/IChainClient"; import { type Intent, IntentStatus } from "../../types"; import { ethers } from "ethers"; @@ -10,13 +14,13 @@ import { ethers } from "ethers"; // --------------------------------------------------------------------------- const FROM_CHAIN = "eip155:1"; -const TO_CHAIN = "eip155:133"; +const TO_CHAIN = "eip155:133"; const FROM_TOKEN = "0xFromToken"; -const TO_TOKEN = "0xToToken"; -const RECIPIENT = "0xRecipient"; -const SENDER = "0xSender"; -const TX_HASH = "0xbridgehash"; -const ROUTE_ID = "route-abc"; +const TO_TOKEN = "0xToToken"; +const RECIPIENT = "0xRecipient"; +const SENDER = "0xSender"; +const TX_HASH = "0xbridgehash"; +const ROUTE_ID = "route-abc"; const makeIntent = (overrides: Partial = {}): Intent => ({ id: "intent-1", @@ -47,7 +51,12 @@ const makeRoute = (overrides: Partial = {}): BridgeRoute => ({ estimatedTimeSeconds: 300, feesUsd: "1.50", steps: [ - { index: 0, description: "Bridge via superbridge", chainId: FROM_CHAIN, requiresApproval: false }, + { + index: 0, + description: "Bridge via superbridge", + chainId: FROM_CHAIN, + requiresApproval: false, + }, ], ...overrides, }); @@ -100,7 +109,9 @@ const makeSettler = ( describe("BridgeSettler.canSettle", () => { it("declines same-chain intents", async () => { const { settler } = makeSettler(); - const result = await settler.canSettle(makeIntent({ fromChain: FROM_CHAIN, toChain: FROM_CHAIN })); + const result = await settler.canSettle( + makeIntent({ fromChain: FROM_CHAIN, toChain: FROM_CHAIN }), + ); expect(result.capable).toBe(false); expect(result.reason).toMatch(/Same-chain/); }); @@ -149,7 +160,11 @@ describe("BridgeSettler.canSettle", () => { const intent = makeIntent(); await settler.canSettle(intent); expect(bridge.getRoutes).toHaveBeenCalledWith( - FROM_CHAIN, TO_CHAIN, FROM_TOKEN, TO_TOKEN, intent.amount, + FROM_CHAIN, + TO_CHAIN, + FROM_TOKEN, + TO_TOKEN, + intent.amount, ); }); }); @@ -203,7 +218,7 @@ describe("BridgeSettler.settle", () => { }); it("picks the route with the highest amountOut across multiple routes", async () => { - const lowRoute = makeRoute({ routeId: "low", amountOut: "900000000000000000" }); + const lowRoute = makeRoute({ routeId: "low", amountOut: "900000000000000000" }); const highRoute = makeRoute({ routeId: "high", amountOut: "990000000000000000" }); const bridge = makeBridgeClient([lowRoute, highRoute]); const { settler } = makeSettler([bridge]); From a348f584fefb9fb3c2fe96957dcf593ecca4bbf5 Mon Sep 17 00:00:00 2001 From: OWK50GA Date: Tue, 14 Apr 2026 06:46:45 +0100 Subject: [PATCH 3/3] fixed linting errors --- packages/orchestrator/src/settlement/BridgeSettler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/orchestrator/src/settlement/BridgeSettler.ts b/packages/orchestrator/src/settlement/BridgeSettler.ts index bf6a85f..bf9c9fb 100644 --- a/packages/orchestrator/src/settlement/BridgeSettler.ts +++ b/packages/orchestrator/src/settlement/BridgeSettler.ts @@ -1,4 +1,4 @@ -import { ethers } from "ethers"; +import { type ethers } from "ethers"; import { type ISettler, type SettleabilityCheck, @@ -178,7 +178,7 @@ export class BridgeSettler implements ISettler { executedRoute: { id: `bridge-${intent.id}`, serviceId: bridge.name, - steps: route.steps.map((s) => ({ + steps: route.steps.map((_s) => ({ type: "bridge" as const, provider: bridge.name, fromChain: intent.fromChain,