@t2000/engine 0.46.10 → 0.46.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -219,6 +219,23 @@ interface GuardConfig {
219
219
  costWarning?: boolean;
220
220
  retryProtection?: boolean;
221
221
  inputValidation?: boolean;
222
+ /**
223
+ * Root-cause guard for "LLM types a recipient address from memory and
224
+ * loses funds to a wrong-but-valid address". When enabled (default),
225
+ * `send_transfer.to` is rejected unless the address can be sourced
226
+ * from a saved contact, the user's own wallet, or the user's recent
227
+ * messages. Set to `false` only if the host has its own equivalent
228
+ * upstream guard (e.g. an off-process verifier).
229
+ */
230
+ addressSource?: boolean;
231
+ /**
232
+ * Companion to `addressSource`: blocks send_transfer that defaults to
233
+ * USDC when the user's recent messages clearly named a non-USDC token
234
+ * (SUI, USDT, WAL, etc.). Without this, the LLM would call
235
+ * `send_transfer({ amount, to })` for a "send my SUI" request and the
236
+ * tool would silently ship USDC. Default on.
237
+ */
238
+ assetIntent?: boolean;
222
239
  }
223
240
  declare const DEFAULT_GUARD_CONFIG: GuardConfig;
224
241
  declare class BalanceTracker {
@@ -249,6 +266,7 @@ declare function createGuardRunnerState(): GuardRunnerState;
249
266
  declare function runGuards(tool: Tool, call: PendingToolCall, state: GuardRunnerState, config: GuardConfig, conversationContext: {
250
267
  fullText: string;
251
268
  lastAssistantText: string;
269
+ recentUserText: string;
252
270
  },
253
271
  /**
254
272
  * [v1.4 Item 4] Optional per-guard observation hook. Fired exactly
@@ -256,7 +274,21 @@ declare function runGuards(tool: Tool, call: PendingToolCall, state: GuardRunner
256
274
  * up in `events`/`injections`/`block`). Errors thrown by the host
257
275
  * are caught so a misbehaving collector can't break tool execution.
258
276
  */
259
- onGuardFired?: (guard: GuardMetric) => void): GuardCheckResult;
277
+ onGuardFired?: (guard: GuardMetric) => void,
278
+ /**
279
+ * Identity context for the address-source safety guard. The guard
280
+ * accepts `send_transfer.to` only when sourced from a saved contact,
281
+ * the user's own wallet, or the user's recent messages — preventing
282
+ * the LLM from typing addresses from memory and shipping funds to a
283
+ * wrong-but-syntactically-valid recipient.
284
+ */
285
+ identity?: {
286
+ contacts?: ReadonlyArray<{
287
+ name: string;
288
+ address: string;
289
+ }>;
290
+ walletAddress?: string;
291
+ }): GuardCheckResult;
260
292
  declare function updateGuardStateAfterToolResult(toolName: string, tool: Tool | undefined, input: unknown, result: unknown, isError: boolean, state: GuardRunnerState): void;
261
293
  declare function extractConversationText(messages: Array<{
262
294
  role: string;
@@ -264,6 +296,7 @@ declare function extractConversationText(messages: Array<{
264
296
  }>): {
265
297
  fullText: string;
266
298
  lastAssistantText: string;
299
+ recentUserText: string;
267
300
  };
268
301
 
269
302
  /**
@@ -366,8 +399,20 @@ declare const PERMISSION_PRESETS: {
366
399
  * `config.autonomousDailyLimit`, an otherwise-`auto` tier is downgraded to
367
400
  * `confirm`. This is the runtime guard for the daily autonomous spend cap.
368
401
  * Tiers above `auto` are returned unchanged.
402
+ *
403
+ * Send-safety rule: when `operation === 'send'` and the destination
404
+ * address is a raw `0x...` (i.e. NOT one of the user's saved contacts),
405
+ * an otherwise-`auto` tier is downgraded to `confirm` regardless of
406
+ * amount. This bounds the "LLM/user typo silently ships funds" failure
407
+ * mode to a single confirmation per recipient — once saved as a contact,
408
+ * subsequent sends to the same address auto-approve under tier as normal.
369
409
  */
370
- declare function resolvePermissionTier(operation: string, amountUsd: number, config: UserPermissionConfig, sessionSpendUsd?: number): 'auto' | 'confirm' | 'explicit';
410
+ declare function resolvePermissionTier(operation: string, amountUsd: number, config: UserPermissionConfig, sessionSpendUsd?: number, sendContext?: {
411
+ to?: string;
412
+ contacts?: ReadonlyArray<{
413
+ address: string;
414
+ }>;
415
+ }): 'auto' | 'confirm' | 'explicit';
371
416
  declare function toolNameToOperation(toolName: string): PermissionOperation | undefined;
372
417
  /**
373
418
  * Resolve the USD value of a tool call from its inputs.
@@ -698,6 +743,18 @@ interface EngineConfig {
698
743
  priceCache?: Map<string, number>;
699
744
  /** Per-user permission config for USD-threshold write tool gating (B.4). */
700
745
  permissionConfig?: UserPermissionConfig;
746
+ /**
747
+ * Saved contacts for the current user. Used by `guardAddressSource`
748
+ * (a saved contact's address is considered a trusted source for
749
+ * `send_transfer.to`) and by `permission-rules.resolvePermissionTier`
750
+ * (sends to non-contact addresses always require confirmation,
751
+ * regardless of amount). Hosts SHOULD also surface these in the
752
+ * dynamic system prompt block so the LLM can resolve "send to <name>".
753
+ */
754
+ contacts?: ReadonlyArray<{
755
+ name: string;
756
+ address: string;
757
+ }>;
701
758
  /**
702
759
  * [v1.4] Cumulative USD already auto-executed in the current session.
703
760
  * Forwarded to `ToolContext` and consulted by `resolvePermissionTier` to
@@ -880,6 +937,7 @@ declare class QueryEngine {
880
937
  private readonly contextSummarizer;
881
938
  private readonly priceCache;
882
939
  private readonly permissionConfig;
940
+ private readonly contacts;
883
941
  private readonly sessionSpendUsd;
884
942
  private readonly onAutoExecuted;
885
943
  private readonly onGuardFired;
@@ -1810,13 +1868,15 @@ declare const withdrawTool: Tool<{
1810
1868
  }>;
1811
1869
 
1812
1870
  declare const sendTransferTool: Tool<{
1813
- amount: number;
1814
1871
  to: string;
1872
+ amount: number;
1873
+ asset?: string | undefined;
1815
1874
  memo?: string | undefined;
1816
1875
  }, {
1817
1876
  success: boolean;
1818
1877
  tx: string;
1819
1878
  amount: number;
1879
+ asset: "USDC" | "USDT" | "SUI" | "USDe" | "USDsui" | "WAL" | "ETH" | "NAVX" | "GOLD";
1820
1880
  to: string;
1821
1881
  contactName: string | undefined;
1822
1882
  gasCost: number;
@@ -1879,8 +1939,8 @@ declare const mppServicesTool: Tool<{
1879
1939
  }, Record<string, unknown>>;
1880
1940
 
1881
1941
  declare const swapExecuteTool: Tool<{
1882
- amount: number;
1883
1942
  to: string;
1943
+ amount: number;
1884
1944
  from: string;
1885
1945
  byAmountIn?: boolean | undefined;
1886
1946
  slippage?: number | undefined;
@@ -1896,8 +1956,8 @@ declare const swapExecuteTool: Tool<{
1896
1956
  }>;
1897
1957
 
1898
1958
  declare const swapQuoteTool: Tool<{
1899
- amount: number;
1900
1959
  to: string;
1960
+ amount: number;
1901
1961
  from: string;
1902
1962
  byAmountIn?: boolean | undefined;
1903
1963
  }, _t2000_sdk.SwapQuoteResult>;
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { resolveSymbol, getDecimalsForCoinType, assertAllowedAsset, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
2
+ import { ALL_NAVI_ASSETS, resolveSymbol, getDecimalsForCoinType, assertAllowedAsset, SUPPORTED_ASSETS, getSwapQuote, extractTransferDetails, classifyTransaction } from '@t2000/sdk';
3
3
  import { readdirSync, readFileSync } from 'fs';
4
4
  import { join } from 'path';
5
5
  import yaml from 'js-yaml';
@@ -1447,12 +1447,14 @@ var withdrawTool = buildTool({
1447
1447
  };
1448
1448
  }
1449
1449
  });
1450
+ var ASSET_LIST = ALL_NAVI_ASSETS.map((a) => String(a)).join(", ");
1450
1451
  var sendTransferTool = buildTool({
1451
1452
  name: "send_transfer",
1452
- description: "Send USDC to another Sui address or contact name. Validates the address, checks balance, and executes the on-chain transfer. Returns tx hash, gas cost, and updated balance.",
1453
+ description: `Send ANY supported token (${ASSET_LIST}) to another Sui address or contact name. Validates the address, checks balance, and executes the on-chain transfer. MUST set the \`asset\` field to the token symbol you want to send (case-insensitive). If \`asset\` is omitted, USDC is assumed \u2014 only do this when the user explicitly asks for USDC. When the user asks to send a token by name (SUI, USDT, etc.) or to send the proceeds of a just-completed swap, you MUST pass \`asset\` matching that token. Returns tx hash, gas cost, and updated balance.`,
1453
1454
  inputSchema: z.object({
1454
1455
  to: z.string().min(1),
1455
1456
  amount: z.number().positive(),
1457
+ asset: z.string().optional(),
1456
1458
  memo: z.string().optional()
1457
1459
  }),
1458
1460
  jsonSchema: {
@@ -1464,7 +1466,11 @@ var sendTransferTool = buildTool({
1464
1466
  },
1465
1467
  amount: {
1466
1468
  type: "number",
1467
- description: "Amount in USD to send"
1469
+ description: "Amount of the asset to send (denominated in the asset\u2019s own units, NOT USD). For USDC this is the USDC count; for SUI this is the SUI count."
1470
+ },
1471
+ asset: {
1472
+ type: "string",
1473
+ description: `Token symbol to send. One of: ${ASSET_LIST}. Defaults to USDC if omitted. REQUIRED whenever the user names a non-USDC token or you are forwarding the proceeds of a swap.`
1468
1474
  },
1469
1475
  memo: {
1470
1476
  type: "string",
@@ -1487,16 +1493,27 @@ var sendTransferTool = buildTool({
1487
1493
  if (input.amount <= 0) {
1488
1494
  return { valid: false, error: "Amount must be positive." };
1489
1495
  }
1496
+ if (input.asset !== void 0) {
1497
+ const normalized = String(input.asset).toUpperCase();
1498
+ if (!(normalized in SUPPORTED_ASSETS)) {
1499
+ return {
1500
+ valid: false,
1501
+ error: `Unsupported asset "${input.asset}". send_transfer accepts: ${ASSET_LIST}.`
1502
+ };
1503
+ }
1504
+ }
1490
1505
  return { valid: true };
1491
1506
  },
1492
1507
  async call(input, context) {
1493
1508
  const agent = requireAgent(context);
1494
- const result = await agent.send({ to: input.to, amount: input.amount });
1509
+ const asset = input.asset ? String(input.asset).toUpperCase() : "USDC";
1510
+ const result = await agent.send({ to: input.to, amount: input.amount, asset });
1495
1511
  return {
1496
1512
  data: {
1497
1513
  success: result.success,
1498
1514
  tx: result.tx,
1499
1515
  amount: result.amount,
1516
+ asset,
1500
1517
  to: result.to,
1501
1518
  contactName: result.contactName,
1502
1519
  gasCost: result.gasCost,
@@ -1504,7 +1521,7 @@ var sendTransferTool = buildTool({
1504
1521
  balance: result.balance,
1505
1522
  memo: input.memo ?? null
1506
1523
  },
1507
- displayText: `Sent $${result.amount.toFixed(2)} to ${result.contactName ?? result.to.slice(0, 10)}\u2026 (tx: ${result.tx.slice(0, 8)}\u2026)`
1524
+ displayText: `Sent ${result.amount} ${asset} to ${result.contactName ?? `${result.to.slice(0, 10)}\u2026`} (tx: ${result.tx.slice(0, 8)}\u2026)`
1508
1525
  };
1509
1526
  }
1510
1527
  });
@@ -3609,7 +3626,9 @@ var DEFAULT_GUARD_CONFIG = {
3609
3626
  artifactPreview: true,
3610
3627
  costWarning: true,
3611
3628
  retryProtection: true,
3612
- inputValidation: true
3629
+ inputValidation: true,
3630
+ addressSource: true,
3631
+ assetIntent: true
3613
3632
  };
3614
3633
  var BalanceTracker = class {
3615
3634
  lastBalanceAt = 0;
@@ -3666,7 +3685,7 @@ function guardIrreversibility(tool, _call, conversationText) {
3666
3685
  if (!tool.flags.irreversible) {
3667
3686
  return { verdict: "pass", gate: "irreversibility", tier: "safety" };
3668
3687
  }
3669
- const hasPreview = /preview|here.s what|confirm.*send|looks? good/i.test(conversationText);
3688
+ const hasPreview = /preview|here.{0,2}s what|confirm.{0,200}send|looks? good/i.test(conversationText);
3670
3689
  if (hasPreview) {
3671
3690
  return { verdict: "pass", gate: "irreversibility", tier: "safety" };
3672
3691
  }
@@ -3762,7 +3781,7 @@ function guardSlippage(tool, _call, lastAssistantText) {
3762
3781
  if (tool.name !== "swap_execute") {
3763
3782
  return { verdict: "pass", gate: "slippage_warning", tier: "financial" };
3764
3783
  }
3765
- const hasEstimate = /~?\$?[\d,]+\.?\d*\s*(SUI|USDC|USDT|WETH)/i.test(lastAssistantText) || /approximately|≈|about|expect|receive/i.test(lastAssistantText);
3784
+ const hasEstimate = /~?\$?\d[\d,]{0,30}(?:\.\d{1,10})?\s*(SUI|USDC|USDT|WETH)/i.test(lastAssistantText) || /approximately|≈|about|expect|receive/i.test(lastAssistantText);
3766
3785
  if (hasEstimate) {
3767
3786
  return { verdict: "pass", gate: "slippage_warning", tier: "financial" };
3768
3787
  }
@@ -3788,6 +3807,72 @@ function guardCostWarning(tool, _call, conversationText) {
3788
3807
  message: "This action has a monetary cost. Confirm the user is aware before proceeding."
3789
3808
  };
3790
3809
  }
3810
+ var SUI_ADDRESS_REGEX = /^0x[a-fA-F0-9]{64}$/;
3811
+ function normalizeAddress(addr) {
3812
+ return addr.trim().toLowerCase();
3813
+ }
3814
+ var NON_USDC_TOKEN_WORDS = [
3815
+ // Patterns are anchored with \b on both sides. Case-insensitive.
3816
+ { symbol: "SUI", pattern: /\bSUI\b/i },
3817
+ { symbol: "USDT", pattern: /\bUSDT\b/i },
3818
+ { symbol: "USDe", pattern: /\bUSDe\b/i },
3819
+ { symbol: "USDsui", pattern: /\bUSDsui\b/i },
3820
+ { symbol: "WAL", pattern: /\bWAL\b/i },
3821
+ { symbol: "ETH", pattern: /\bETH\b/i },
3822
+ { symbol: "NAVX", pattern: /\bNAVX\b/i },
3823
+ { symbol: "GOLD", pattern: /\bGOLD\b/i }
3824
+ ];
3825
+ function guardAssetIntent(tool, call, userText) {
3826
+ if (tool.name !== "send_transfer") {
3827
+ return { verdict: "pass", gate: "asset_intent", tier: "safety" };
3828
+ }
3829
+ const input = call.input;
3830
+ const assetWasSet = !(input.asset === void 0 || input.asset === null || input.asset === "");
3831
+ if (assetWasSet) {
3832
+ return { verdict: "pass", gate: "asset_intent", tier: "safety" };
3833
+ }
3834
+ const mentioned = NON_USDC_TOKEN_WORDS.find((t) => t.pattern.test(userText));
3835
+ if (!mentioned) {
3836
+ return { verdict: "pass", gate: "asset_intent", tier: "safety" };
3837
+ }
3838
+ return {
3839
+ verdict: "block",
3840
+ gate: "asset_intent",
3841
+ tier: "safety",
3842
+ message: `Asset mismatch: the user's recent messages mention "${mentioned.symbol}" but send_transfer was called without an \`asset\` field (defaults to USDC). If the user asked you to send ${mentioned.symbol}, re-issue send_transfer with \`asset: "${mentioned.symbol}"\`. If the user really meant USDC, set \`asset: "USDC"\` explicitly to confirm intent. Never default to USDC when the user named a different token.`
3843
+ };
3844
+ }
3845
+ function guardAddressSource(tool, call, userText, contacts, walletAddress) {
3846
+ if (tool.name !== "send_transfer") {
3847
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3848
+ }
3849
+ const input = call.input;
3850
+ const rawTo = String(input.to ?? "");
3851
+ if (!rawTo) {
3852
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3853
+ }
3854
+ if (!SUI_ADDRESS_REGEX.test(rawTo)) {
3855
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3856
+ }
3857
+ const normalizedTo = normalizeAddress(rawTo);
3858
+ if (walletAddress && normalizeAddress(walletAddress) === normalizedTo) {
3859
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3860
+ }
3861
+ for (const c of contacts) {
3862
+ if (normalizeAddress(c.address) === normalizedTo) {
3863
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3864
+ }
3865
+ }
3866
+ if (userText.toLowerCase().includes(normalizedTo)) {
3867
+ return { verdict: "pass", gate: "address_source", tier: "safety" };
3868
+ }
3869
+ return {
3870
+ verdict: "block",
3871
+ gate: "address_source",
3872
+ tier: "safety",
3873
+ message: `Safety check failed: the recipient address "${rawTo}" was not provided by the user (no saved contact matches, address is not the user's own wallet, and it does not appear verbatim in the user's recent messages). For safety, addresses must be supplied directly by the user \u2014 never reconstructed from memory or partial recall. Ask the user to paste the destination address again exactly.`
3874
+ };
3875
+ }
3791
3876
  function guardArtifactPreview(result) {
3792
3877
  if (!result || typeof result !== "object") return null;
3793
3878
  const r = result;
@@ -3815,7 +3900,7 @@ function createGuardRunnerState() {
3815
3900
  lastHealthFactor: null
3816
3901
  };
3817
3902
  }
3818
- function runGuards(tool, call, state, config, conversationContext, onGuardFired) {
3903
+ function runGuards(tool, call, state, config, conversationContext, onGuardFired, identity) {
3819
3904
  const results = [];
3820
3905
  const now = Date.now();
3821
3906
  const fire = (verdict, tier, gate, hadInjection) => {
@@ -3856,6 +3941,20 @@ function runGuards(tool, call, state, config, conversationContext, onGuardFired)
3856
3941
  if (config.retryProtection !== false) {
3857
3942
  results.push(guardRetryProtection(tool, call, state.retryTracker));
3858
3943
  }
3944
+ if (config.addressSource !== false) {
3945
+ results.push(
3946
+ guardAddressSource(
3947
+ tool,
3948
+ call,
3949
+ conversationContext.recentUserText,
3950
+ identity?.contacts ?? [],
3951
+ identity?.walletAddress
3952
+ )
3953
+ );
3954
+ }
3955
+ if (config.assetIntent !== false) {
3956
+ results.push(guardAssetIntent(tool, call, conversationContext.recentUserText));
3957
+ }
3859
3958
  if (config.irreversibility !== false) {
3860
3959
  results.push(guardIrreversibility(tool, call, conversationContext.fullText));
3861
3960
  }
@@ -3926,6 +4025,7 @@ function updateGuardStateAfterToolResult(toolName, tool, input, result, isError,
3926
4025
  }
3927
4026
  function extractConversationText(messages) {
3928
4027
  const textParts = [];
4028
+ const userParts = [];
3929
4029
  let lastAssistantText = "";
3930
4030
  for (const msg of messages) {
3931
4031
  if (!Array.isArray(msg.content)) continue;
@@ -3934,13 +4034,19 @@ function extractConversationText(messages) {
3934
4034
  textParts.push(block.text);
3935
4035
  if (msg.role === "assistant") {
3936
4036
  lastAssistantText = block.text;
4037
+ } else if (msg.role === "user") {
4038
+ userParts.push(block.text);
3937
4039
  }
3938
4040
  }
3939
4041
  }
3940
4042
  }
4043
+ const recentUserParts = userParts.slice(-10);
4044
+ const MAX_REGEX_INPUT = 16 * 1024;
4045
+ const cap = (s) => s.length <= MAX_REGEX_INPUT ? s : s.slice(-MAX_REGEX_INPUT);
3941
4046
  return {
3942
- fullText: textParts.join("\n"),
3943
- lastAssistantText
4047
+ fullText: cap(textParts.join("\n")),
4048
+ lastAssistantText: cap(lastAssistantText),
4049
+ recentUserText: cap(recentUserParts.join("\n"))
3944
4050
  };
3945
4051
  }
3946
4052
 
@@ -4240,7 +4346,12 @@ var PERMISSION_PRESETS = {
4240
4346
  ]
4241
4347
  }
4242
4348
  };
4243
- function resolvePermissionTier(operation, amountUsd, config, sessionSpendUsd) {
4349
+ function isKnownContactAddress(to, contacts) {
4350
+ if (!to) return false;
4351
+ const normalized = to.trim().toLowerCase();
4352
+ return contacts.some((c) => c.address.trim().toLowerCase() === normalized);
4353
+ }
4354
+ function resolvePermissionTier(operation, amountUsd, config, sessionSpendUsd, sendContext) {
4244
4355
  const rule = config.rules.find((r) => r.operation === operation);
4245
4356
  const autoBelow = rule?.autoBelow ?? config.globalAutoBelow;
4246
4357
  const confirmBetween = rule?.confirmBetween ?? 1e3;
@@ -4249,7 +4360,10 @@ function resolvePermissionTier(operation, amountUsd, config, sessionSpendUsd) {
4249
4360
  else if (amountUsd < confirmBetween) tier = "confirm";
4250
4361
  else tier = "explicit";
4251
4362
  if (tier === "auto" && typeof sessionSpendUsd === "number" && sessionSpendUsd + amountUsd > config.autonomousDailyLimit) {
4252
- return "confirm";
4363
+ tier = "confirm";
4364
+ }
4365
+ if (tier === "auto" && operation === "send" && sendContext?.to && !isKnownContactAddress(sendContext.to, sendContext.contacts ?? [])) {
4366
+ tier = "confirm";
4253
4367
  }
4254
4368
  return tier;
4255
4369
  }
@@ -4497,6 +4611,9 @@ var QueryEngine = class {
4497
4611
  contextSummarizer;
4498
4612
  priceCache;
4499
4613
  permissionConfig;
4614
+ // Saved contacts — consulted by `guardAddressSource` and the permission
4615
+ // tier resolver (sends to non-contact addresses always require confirm).
4616
+ contacts;
4500
4617
  // [v1.4] Session-scoped autonomous spend tracking.
4501
4618
  sessionSpendUsd;
4502
4619
  onAutoExecuted;
@@ -4545,6 +4662,7 @@ var QueryEngine = class {
4545
4662
  this.contextSummarizer = config.contextSummarizer;
4546
4663
  this.priceCache = config.priceCache;
4547
4664
  this.permissionConfig = config.permissionConfig;
4665
+ this.contacts = config.contacts ?? [];
4548
4666
  this.sessionSpendUsd = config.sessionSpendUsd;
4549
4667
  this.onAutoExecuted = config.onAutoExecuted;
4550
4668
  this.onGuardFired = config.onGuardFired;
@@ -5064,11 +5182,13 @@ ${recipeCtx}`;
5064
5182
  const operation = toolNameToOperation(call.name);
5065
5183
  if (operation) {
5066
5184
  const usdValue = resolveUsdValue(call.name, call.input, context.priceCache);
5185
+ const callInput = call.input;
5067
5186
  const tier = resolvePermissionTier(
5068
5187
  operation,
5069
5188
  usdValue,
5070
5189
  context.permissionConfig,
5071
- context.sessionSpendUsd
5190
+ context.sessionSpendUsd,
5191
+ operation === "send" ? { to: typeof callInput.to === "string" ? callInput.to : void 0, contacts: this.contacts } : void 0
5072
5192
  );
5073
5193
  return tier !== "auto";
5074
5194
  }
@@ -5098,7 +5218,8 @@ ${recipeCtx}`;
5098
5218
  this.guardState,
5099
5219
  this.guardConfig,
5100
5220
  convCtx,
5101
- this.onGuardFired
5221
+ this.onGuardFired,
5222
+ { contacts: this.contacts, walletAddress: this.walletAddress }
5102
5223
  );
5103
5224
  this.guardEvents.push(...check.events);
5104
5225
  if (check.blocked) {
@@ -5228,7 +5349,8 @@ ${recipeCtx}`;
5228
5349
  this.guardState,
5229
5350
  this.guardConfig,
5230
5351
  convCtx,
5231
- this.onGuardFired
5352
+ this.onGuardFired,
5353
+ { contacts: this.contacts, walletAddress: this.walletAddress }
5232
5354
  );
5233
5355
  this.guardEvents.push(...check.events);
5234
5356
  if (check.blocked) {