blockintel-gate-sdk 0.3.9 → 0.4.0

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.js CHANGED
@@ -1042,13 +1042,21 @@ function computeTxDigest(binding) {
1042
1042
  return createHash("sha256").update(canonical, "utf8").digest("hex");
1043
1043
  }
1044
1044
 
1045
+ // src/metrics/GateMetricsSink.ts
1046
+ var noOpMetricsSink = {
1047
+ emit() {
1048
+ }
1049
+ };
1050
+
1045
1051
  // src/kms/wrapAwsSdkV3KmsClient.ts
1046
1052
  function wrapKmsClient(kmsClient, gateClient, options = {}) {
1047
1053
  const defaultOptions = {
1048
1054
  mode: options.mode || "enforce",
1055
+ requireReceiptForSign: options.requireReceiptForSign ?? false,
1049
1056
  onDecision: options.onDecision || (() => {
1050
1057
  }),
1051
- extractTxIntent: options.extractTxIntent || defaultExtractTxIntent
1058
+ extractTxIntent: options.extractTxIntent || defaultExtractTxIntent,
1059
+ metricsSink: options.metricsSink ?? noOpMetricsSink
1052
1060
  };
1053
1061
  const wrapped = new Proxy(kmsClient, {
1054
1062
  get(target, prop, receiver) {
@@ -1089,12 +1097,39 @@ function defaultExtractTxIntent(command) {
1089
1097
  // Backward compatibility
1090
1098
  };
1091
1099
  }
1100
+ function buildMetricLabels(gateClient, command, signerId, txIntent) {
1101
+ const config = gateClient.config;
1102
+ const keyId = command.input?.KeyId ?? command.KeyId;
1103
+ return {
1104
+ tenantId: config?.tenantId,
1105
+ signerId: signerId || void 0,
1106
+ adoptionStage: config?.adoptionStage ?? process.env.GATE_ADOPTION_STAGE,
1107
+ env: config?.env ?? process.env.GATE_ENV ?? process.env.NODE_ENV,
1108
+ chain: txIntent.chainId != null ? String(txIntent.chainId) : txIntent.networkFamily,
1109
+ kmsKeyId: keyId,
1110
+ region: process.env.AWS_REGION
1111
+ };
1112
+ }
1113
+ function emitMetric(sink, name, labels) {
1114
+ const event = { name, labels, timestampMs: Date.now() };
1115
+ try {
1116
+ const result = sink.emit(event);
1117
+ if (result && typeof result.catch === "function") {
1118
+ result.catch(() => {
1119
+ });
1120
+ }
1121
+ } catch {
1122
+ }
1123
+ }
1092
1124
  async function handleSignCommand(command, originalClient, gateClient, options) {
1093
1125
  const txIntent = options.extractTxIntent(command);
1094
1126
  const signerId = command.input?.KeyId ?? command.KeyId ?? "unknown";
1095
- gateClient.heartbeatManager.updateSignerId(signerId);
1096
- const heartbeatToken = gateClient.heartbeatManager.getToken();
1097
- if (!heartbeatToken) {
1127
+ const labels = buildMetricLabels(gateClient, command, signerId, txIntent);
1128
+ emitMetric(options.metricsSink, "sign_attempt_total", labels);
1129
+ let heartbeatToken;
1130
+ try {
1131
+ heartbeatToken = await gateClient.heartbeatManager.getTokenForSigner(signerId, 2e3);
1132
+ } catch {
1098
1133
  throw new BlockIntelBlockedError(
1099
1134
  "HEARTBEAT_MISSING",
1100
1135
  void 0,
@@ -1118,6 +1153,28 @@ async function handleSignCommand(command, originalClient, gateClient, options) {
1118
1153
  // Type assertion - txIntent may have extra fields
1119
1154
  signingContext
1120
1155
  });
1156
+ if (decision.decision === "ALLOW" && options.requireReceiptForSign) {
1157
+ const hasReceipt2 = decision.receipt != null || decision.decisionHash != null && decision.receiptSignature != null;
1158
+ if (!hasReceipt2) {
1159
+ emitMetric(options.metricsSink, "sign_blocked_missing_receipt_total", labels);
1160
+ options.onDecision("BLOCK", {
1161
+ error: new BlockIntelBlockedError(
1162
+ "RECEIPT_REQUIRED",
1163
+ decision.decisionId,
1164
+ decision.correlationId,
1165
+ void 0
1166
+ ),
1167
+ signerId,
1168
+ command
1169
+ });
1170
+ throw new BlockIntelBlockedError(
1171
+ "RECEIPT_REQUIRED",
1172
+ decision.decisionId,
1173
+ decision.correlationId,
1174
+ void 0
1175
+ );
1176
+ }
1177
+ }
1121
1178
  if (decision.decision === "ALLOW" && gateClient.getRequireDecisionToken() && decision.txDigest != null) {
1122
1179
  const binding = buildTxBindingObject(
1123
1180
  txIntent,
@@ -1146,6 +1203,11 @@ async function handleSignCommand(command, originalClient, gateClient, options) {
1146
1203
  );
1147
1204
  }
1148
1205
  }
1206
+ const hasReceipt = decision.receipt != null || decision.decisionHash != null && decision.receiptSignature != null;
1207
+ if (hasReceipt) {
1208
+ emitMetric(options.metricsSink, "sign_success_with_receipt_total", labels);
1209
+ }
1210
+ emitMetric(options.metricsSink, "sign_success_total", labels);
1149
1211
  options.onDecision("ALLOW", { decision, signerId, command });
1150
1212
  if (options.mode === "dry-run") {
1151
1213
  return await originalClient.send(new SignCommand(command));
@@ -1206,7 +1268,7 @@ var ProvenanceProvider = class {
1206
1268
  var HeartbeatManager = class {
1207
1269
  httpClient;
1208
1270
  tenantId;
1209
- signerId;
1271
+ defaultSignerId;
1210
1272
  environment;
1211
1273
  baseRefreshIntervalSeconds;
1212
1274
  clientInstanceId;
@@ -1215,22 +1277,27 @@ var HeartbeatManager = class {
1215
1277
  // SDK version for tracking
1216
1278
  apiKey;
1217
1279
  // x-gate-heartbeat-key for Control Plane auth
1218
- currentToken = null;
1219
- refreshTimer = null;
1280
+ signerEntries = /* @__PURE__ */ new Map();
1281
+ evictionTimer = null;
1220
1282
  started = false;
1221
- consecutiveFailures = 0;
1222
1283
  maxBackoffSeconds = 30;
1223
1284
  // Maximum backoff interval
1285
+ maxSigners;
1286
+ signerIdleTtlMs;
1287
+ localRateLimitMs;
1224
1288
  constructor(options) {
1225
1289
  this.httpClient = options.httpClient;
1226
1290
  this.tenantId = options.tenantId;
1227
- this.signerId = options.signerId;
1291
+ this.defaultSignerId = options.signerId;
1228
1292
  this.environment = options.environment ?? "prod";
1229
1293
  this.baseRefreshIntervalSeconds = options.refreshIntervalSeconds ?? 10;
1230
1294
  this.apiKey = options.apiKey;
1231
1295
  this.clientInstanceId = options.clientInstanceId || v4();
1232
1296
  this.sdkVersion = options.sdkVersion || "1.0.0";
1233
1297
  this.apiKey = options.apiKey;
1298
+ this.maxSigners = options.maxSigners ?? 20;
1299
+ this.signerIdleTtlMs = options.signerIdleTtlMs ?? 3e5;
1300
+ this.localRateLimitMs = options.localRateLimitMs ?? 2100;
1234
1301
  }
1235
1302
  /**
1236
1303
  * Start background heartbeat refresher.
@@ -1241,46 +1308,56 @@ var HeartbeatManager = class {
1241
1308
  return;
1242
1309
  }
1243
1310
  this.started = true;
1244
- this.acquireHeartbeat().catch((error) => {
1311
+ this.startEvictionTimer();
1312
+ this.getTokenForSigner(this.defaultSignerId, 0).catch((error) => {
1245
1313
  console.error("[HEARTBEAT] Failed to acquire initial heartbeat:", error instanceof Error ? error.message : error);
1246
1314
  });
1247
- this.scheduleNextRefresh();
1315
+ }
1316
+ startEvictionTimer() {
1317
+ if (this.evictionTimer) clearInterval(this.evictionTimer);
1318
+ this.evictionTimer = setInterval(() => {
1319
+ const now = Date.now();
1320
+ for (const [signerId, entry] of this.signerEntries) {
1321
+ if (now - entry.lastUsedMs > this.signerIdleTtlMs) {
1322
+ if (entry.refreshTimer) clearTimeout(entry.refreshTimer);
1323
+ this.signerEntries.delete(signerId);
1324
+ }
1325
+ }
1326
+ }, 6e4);
1248
1327
  }
1249
1328
  /**
1250
- * Schedule next refresh with jitter and backoff
1329
+ * Schedule next refresh with jitter and backoff for a specific signer
1251
1330
  */
1252
- scheduleNextRefresh() {
1253
- if (!this.started) {
1331
+ scheduleRefreshForSigner(signerId, entry) {
1332
+ if (!this.started || !this.signerEntries.has(signerId)) {
1254
1333
  return;
1255
1334
  }
1335
+ if (entry.refreshTimer) {
1336
+ clearTimeout(entry.refreshTimer);
1337
+ entry.refreshTimer = null;
1338
+ }
1256
1339
  const baseInterval = this.baseRefreshIntervalSeconds * 1e3;
1257
1340
  const jitter = Math.random() * 2e3;
1258
- const backoff = this.calculateBackoff();
1341
+ const backoff = Math.min(
1342
+ Math.pow(2, entry.consecutiveFailures) * 1e3,
1343
+ this.maxBackoffSeconds * 1e3
1344
+ );
1259
1345
  const interval = baseInterval + jitter + backoff;
1260
- this.refreshTimer = setTimeout(() => {
1261
- this.acquireHeartbeat().then(() => {
1262
- this.consecutiveFailures = 0;
1263
- this.scheduleNextRefresh();
1346
+ entry.refreshTimer = setTimeout(() => {
1347
+ if (!this.signerEntries.has(signerId)) return;
1348
+ entry.acquiring = true;
1349
+ entry.acquirePromise = this.acquireHeartbeatForSigner(signerId, entry).then(() => {
1350
+ this.scheduleRefreshForSigner(signerId, entry);
1264
1351
  }).catch((error) => {
1265
- this.consecutiveFailures++;
1266
- console.error("[HEARTBEAT] Refresh failed (will retry):", error);
1267
- this.scheduleNextRefresh();
1352
+ entry.consecutiveFailures++;
1353
+ console.error(`[HEARTBEAT] Refresh failed for signer ${signerId} (will retry):`, error.message || error);
1354
+ this.scheduleRefreshForSigner(signerId, entry);
1355
+ }).finally(() => {
1356
+ entry.acquiring = false;
1357
+ entry.acquirePromise = null;
1268
1358
  });
1269
1359
  }, interval);
1270
1360
  }
1271
- /**
1272
- * Calculate exponential backoff (capped at maxBackoffSeconds)
1273
- */
1274
- calculateBackoff() {
1275
- if (this.consecutiveFailures === 0) {
1276
- return 0;
1277
- }
1278
- const backoffSeconds = Math.min(
1279
- Math.pow(2, this.consecutiveFailures) * 1e3,
1280
- this.maxBackoffSeconds * 1e3
1281
- );
1282
- return backoffSeconds;
1283
- }
1284
1361
  /**
1285
1362
  * Stop background heartbeat refresher
1286
1363
  */
@@ -1289,45 +1366,153 @@ var HeartbeatManager = class {
1289
1366
  return;
1290
1367
  }
1291
1368
  this.started = false;
1292
- if (this.refreshTimer) {
1293
- clearTimeout(this.refreshTimer);
1294
- this.refreshTimer = null;
1369
+ if (this.evictionTimer) {
1370
+ clearInterval(this.evictionTimer);
1371
+ this.evictionTimer = null;
1372
+ }
1373
+ for (const [signerId, entry] of this.signerEntries) {
1374
+ if (entry.refreshTimer) {
1375
+ clearTimeout(entry.refreshTimer);
1376
+ entry.refreshTimer = null;
1377
+ }
1295
1378
  }
1379
+ this.signerEntries.clear();
1296
1380
  }
1297
1381
  /**
1298
- * Get current heartbeat token if valid
1382
+ * Get current heartbeat token if valid for the default signer
1383
+ * @deprecated Use getTokenForSigner() instead.
1299
1384
  */
1300
1385
  getToken() {
1301
- if (!this.currentToken) {
1302
- return null;
1386
+ const entry = this.signerEntries.get(this.defaultSignerId);
1387
+ if (entry && entry.token && entry.token.expiresAt > Math.floor(Date.now() / 1e3) + 2) {
1388
+ entry.lastUsedMs = Date.now();
1389
+ return entry.token.token;
1303
1390
  }
1304
- const now = Math.floor(Date.now() / 1e3);
1305
- if (this.currentToken.expiresAt <= now + 2) {
1306
- return null;
1307
- }
1308
- return this.currentToken.token;
1391
+ return null;
1309
1392
  }
1310
1393
  /**
1311
- * Check if current heartbeat token is valid
1394
+ * Check if current heartbeat token is valid for the default signer
1395
+ * @deprecated Use getTokenForSigner() instead.
1312
1396
  */
1313
1397
  isValid() {
1314
1398
  return this.getToken() !== null;
1315
1399
  }
1316
1400
  /**
1317
- * Update signer ID (called when signer is known)
1401
+ * Update signer ID (called when signer is known).
1402
+ * @deprecated Use getTokenForSigner() — signerId changes are handled automatically by the per-signer cache.
1318
1403
  */
1319
1404
  updateSignerId(signerId) {
1320
- if (this.signerId !== signerId) {
1321
- this.signerId = signerId;
1322
- this.currentToken = null;
1405
+ this.defaultSignerId = signerId;
1406
+ }
1407
+ /**
1408
+ * Get a valid heartbeat token for a specific signer.
1409
+ * Returns immediately if a cached valid token exists.
1410
+ * If no token, triggers acquisition and returns a Promise that resolves
1411
+ * when the token is available (or rejects after maxWaitMs).
1412
+ */
1413
+ async getTokenForSigner(signerId, maxWaitMs = 2e3) {
1414
+ if (!this.started) {
1415
+ throw new GateError("HEARTBEAT_MISSING" /* HEARTBEAT_MISSING */, "HeartbeatManager not started");
1323
1416
  }
1417
+ const startTime = Date.now();
1418
+ let entry = this.signerEntries.get(signerId);
1419
+ const now = Date.now();
1420
+ const getValidToken = (e) => {
1421
+ if (e.token && e.token.expiresAt > Math.floor(Date.now() / 1e3) + 2) {
1422
+ return e.token.token;
1423
+ }
1424
+ return null;
1425
+ };
1426
+ if (entry) {
1427
+ entry.lastUsedMs = now;
1428
+ const t2 = getValidToken(entry);
1429
+ if (t2) return t2;
1430
+ } else {
1431
+ if (this.signerEntries.size >= this.maxSigners) {
1432
+ let oldestSignerId = null;
1433
+ let oldestUsedMs = Infinity;
1434
+ for (const [sId, e] of this.signerEntries) {
1435
+ if (e.lastUsedMs < oldestUsedMs) {
1436
+ oldestUsedMs = e.lastUsedMs;
1437
+ oldestSignerId = sId;
1438
+ }
1439
+ }
1440
+ if (oldestSignerId) {
1441
+ const oldestEntry = this.signerEntries.get(oldestSignerId);
1442
+ if (oldestEntry?.refreshTimer) clearTimeout(oldestEntry.refreshTimer);
1443
+ this.signerEntries.delete(oldestSignerId);
1444
+ }
1445
+ }
1446
+ entry = {
1447
+ token: null,
1448
+ refreshTimer: null,
1449
+ consecutiveFailures: 0,
1450
+ lastAcquireAttemptMs: 0,
1451
+ lastUsedMs: now,
1452
+ acquiring: false,
1453
+ acquirePromise: null
1454
+ };
1455
+ this.signerEntries.set(signerId, entry);
1456
+ }
1457
+ if (entry.acquiring && entry.acquirePromise) {
1458
+ const remainingWait = Math.max(0, maxWaitMs - (Date.now() - startTime));
1459
+ try {
1460
+ await Promise.race([
1461
+ entry.acquirePromise,
1462
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), remainingWait))
1463
+ ]);
1464
+ } catch (e) {
1465
+ }
1466
+ const t2 = getValidToken(entry);
1467
+ if (t2) return t2;
1468
+ }
1469
+ const timeSinceLastAttempt = Date.now() - entry.lastAcquireAttemptMs;
1470
+ let timeToWaitBeforeFetch = 0;
1471
+ if (timeSinceLastAttempt < this.localRateLimitMs) {
1472
+ timeToWaitBeforeFetch = this.localRateLimitMs - timeSinceLastAttempt;
1473
+ }
1474
+ const remainingWait2 = Math.max(0, maxWaitMs - (Date.now() - startTime));
1475
+ if (timeToWaitBeforeFetch >= remainingWait2) {
1476
+ throw new GateError(
1477
+ "HEARTBEAT_MISSING" /* HEARTBEAT_MISSING */,
1478
+ "Signing blocked: Heartbeat token is missing or expired. Gate must be alive and enforcing policy."
1479
+ );
1480
+ }
1481
+ if (timeToWaitBeforeFetch > 0) {
1482
+ await new Promise((resolve) => setTimeout(resolve, timeToWaitBeforeFetch));
1483
+ }
1484
+ if (!entry.acquiring) {
1485
+ entry.acquiring = true;
1486
+ entry.acquirePromise = this.acquireHeartbeatForSigner(signerId, entry).finally(() => {
1487
+ if (entry) {
1488
+ entry.acquiring = false;
1489
+ entry.acquirePromise = null;
1490
+ }
1491
+ });
1492
+ }
1493
+ const remainingWait3 = Math.max(0, maxWaitMs - (Date.now() - startTime));
1494
+ try {
1495
+ if (entry.acquirePromise) {
1496
+ await Promise.race([
1497
+ entry.acquirePromise,
1498
+ new Promise((_, reject) => setTimeout(() => reject(new Error("timeout")), remainingWait3))
1499
+ ]);
1500
+ }
1501
+ } catch (e) {
1502
+ }
1503
+ const t = getValidToken(entry);
1504
+ if (t) return t;
1505
+ throw new GateError(
1506
+ "HEARTBEAT_MISSING" /* HEARTBEAT_MISSING */,
1507
+ "Signing blocked: Heartbeat token is missing or expired. Gate must be alive and enforcing policy."
1508
+ );
1324
1509
  }
1325
1510
  /**
1326
- * Acquire a new heartbeat token from Control Plane
1511
+ * Acquire a new heartbeat token from Control Plane for a specific signer
1327
1512
  * NEVER logs token value (security)
1328
1513
  * Requires x-gate-heartbeat-key header (apiKey) for authentication.
1329
1514
  */
1330
- async acquireHeartbeat() {
1515
+ async acquireHeartbeatForSigner(signerId, entry) {
1331
1516
  if (!this.apiKey || this.apiKey.length === 0) {
1332
1517
  throw new GateError(
1333
1518
  "UNAUTHORIZED" /* UNAUTHORIZED */,
@@ -1335,6 +1520,7 @@ var HeartbeatManager = class {
1335
1520
  {}
1336
1521
  );
1337
1522
  }
1523
+ entry.lastAcquireAttemptMs = Date.now();
1338
1524
  try {
1339
1525
  const response = await this.httpClient.request({
1340
1526
  method: "POST",
@@ -1344,12 +1530,15 @@ var HeartbeatManager = class {
1344
1530
  },
1345
1531
  body: {
1346
1532
  tenantId: this.tenantId,
1347
- signerId: this.signerId,
1533
+ signerId,
1348
1534
  environment: this.environment,
1349
1535
  clientInstanceId: this.clientInstanceId,
1350
1536
  sdkVersion: this.sdkVersion
1351
1537
  }
1352
1538
  });
1539
+ if (!this.signerEntries.has(signerId)) {
1540
+ return;
1541
+ }
1353
1542
  if (response.success && response.data) {
1354
1543
  const token = response.data.heartbeatToken;
1355
1544
  const expiresAt = response.data.expiresAt;
@@ -1359,18 +1548,23 @@ var HeartbeatManager = class {
1359
1548
  "Invalid heartbeat response: missing token or expiresAt"
1360
1549
  );
1361
1550
  }
1362
- this.currentToken = {
1551
+ entry.token = {
1363
1552
  token,
1364
1553
  expiresAt,
1365
1554
  jti: response.data.jti,
1366
1555
  policyHash: response.data.policyHash
1367
1556
  };
1557
+ entry.consecutiveFailures = 0;
1368
1558
  console.log("[HEARTBEAT] Acquired heartbeat token", {
1369
1559
  expiresAt,
1560
+ signerId,
1370
1561
  jti: response.data.jti,
1371
1562
  policyHash: response.data.policyHash?.substring(0, 8) + "..."
1372
1563
  // DO NOT log token value
1373
1564
  });
1565
+ if (!entry.refreshTimer) {
1566
+ this.scheduleRefreshForSigner(signerId, entry);
1567
+ }
1374
1568
  } else {
1375
1569
  const error = response.error || {};
1376
1570
  throw new GateError(
@@ -1379,7 +1573,7 @@ var HeartbeatManager = class {
1379
1573
  );
1380
1574
  }
1381
1575
  } catch (error) {
1382
- console.error("[HEARTBEAT] Failed to acquire heartbeat:", error.message || error);
1576
+ console.error(`[HEARTBEAT] Failed to acquire heartbeat for signer ${signerId}:`, error.message || error);
1383
1577
  throw error;
1384
1578
  }
1385
1579
  }
@@ -1636,6 +1830,7 @@ var IamPermissionRiskChecker = class {
1636
1830
  };
1637
1831
 
1638
1832
  // src/client/GateClient.ts
1833
+ var DEFAULT_SIGNER_ID = "gate-sdk-client";
1639
1834
  var GateClient = class {
1640
1835
  config;
1641
1836
  httpClient;
@@ -1710,7 +1905,7 @@ var GateClient = class {
1710
1905
  // 5s timeout for heartbeat
1711
1906
  userAgent: config.userAgent
1712
1907
  });
1713
- const initialSignerId = config.signerId ?? "trading-bot-signer";
1908
+ const initialSignerId = config.signerId ?? DEFAULT_SIGNER_ID;
1714
1909
  this.heartbeatManager = new HeartbeatManager({
1715
1910
  httpClient: heartbeatHttpClient,
1716
1911
  tenantId: config.tenantId,
@@ -1785,26 +1980,10 @@ var GateClient = class {
1785
1980
  const requestMode = req.mode || this.mode;
1786
1981
  const requireToken = this.getRequireDecisionToken();
1787
1982
  const executeRequest = async () => {
1788
- if (!this.config.local && this.heartbeatManager && req.signingContext?.signerId) {
1789
- this.heartbeatManager.updateSignerId(req.signingContext.signerId);
1790
- }
1791
1983
  let heartbeatToken = null;
1792
1984
  if (!this.config.local && this.heartbeatManager) {
1793
- heartbeatToken = this.heartbeatManager.getToken();
1794
- if (!heartbeatToken) {
1795
- const maxWaitMs = 2e3;
1796
- const startTime2 = Date.now();
1797
- while (!heartbeatToken && Date.now() - startTime2 < maxWaitMs) {
1798
- await new Promise((resolve) => setTimeout(resolve, 50));
1799
- heartbeatToken = this.heartbeatManager.getToken();
1800
- }
1801
- }
1802
- if (!heartbeatToken) {
1803
- throw new GateError(
1804
- "HEARTBEAT_MISSING" /* HEARTBEAT_MISSING */,
1805
- "Signing blocked: Heartbeat token is missing or expired. Gate must be alive and enforcing policy."
1806
- );
1807
- }
1985
+ const effectiveSignerId2 = req.signingContext?.signerId ?? req.signingContext?.actorPrincipal ?? DEFAULT_SIGNER_ID;
1986
+ heartbeatToken = await this.heartbeatManager.getTokenForSigner(effectiveSignerId2, 2e3);
1808
1987
  }
1809
1988
  const txIntent = { ...req.txIntent };
1810
1989
  if (txIntent.to && !txIntent.toAddress) {
@@ -1817,10 +1996,11 @@ var GateClient = class {
1817
1996
  if (txIntent.from && !txIntent.fromAddress) {
1818
1997
  delete txIntent.from;
1819
1998
  }
1999
+ const effectiveSignerId = req.signingContext?.signerId ?? req.signingContext?.actorPrincipal ?? DEFAULT_SIGNER_ID;
1820
2000
  const signingContext = {
1821
2001
  ...req.signingContext,
1822
- actorPrincipal: req.signingContext?.actorPrincipal ?? req.signingContext?.signerId ?? "gate-sdk-client",
1823
- signerId: req.signingContext?.signerId ?? req.signingContext?.actorPrincipal ?? "gate-sdk-client"
2002
+ actorPrincipal: req.signingContext?.actorPrincipal ?? req.signingContext?.signerId ?? DEFAULT_SIGNER_ID,
2003
+ signerId: effectiveSignerId
1824
2004
  };
1825
2005
  if (heartbeatToken) {
1826
2006
  signingContext.heartbeatToken = heartbeatToken;
@@ -1937,6 +2117,9 @@ var GateClient = class {
1937
2117
  enforced: responseData.enforced ?? requestMode === "ENFORCE",
1938
2118
  shadowWouldBlock: responseData.shadow_would_block ?? responseData.shadowWouldBlock ?? false,
1939
2119
  mode: responseData.mode ?? requestMode,
2120
+ receipt: responseData.receipt,
2121
+ decisionHash: responseData.decision_hash ?? responseData.decisionHash,
2122
+ receiptSignature: responseData.receipt_signature ?? responseData.receiptSignature,
1940
2123
  ...simulationData ? {
1941
2124
  simulation: {
1942
2125
  willRevert: simulationData.willRevert ?? simulationData.will_revert ?? false,
@@ -3010,6 +3193,6 @@ var GenericHsmSigner = class {
3010
3193
  }
3011
3194
  };
3012
3195
 
3013
- export { AwsKmsSigner, BlockIntelAuthError, BlockIntelBlockedError, BlockIntelStepUpRequiredError, BlockIntelUnavailableError, FireblocksSigner, Gate, GateClient, GateError, GateErrorCode, GcpKmsSigner, GenericHsmSigner, HeartbeatManager, ProvenanceProvider, StepUpNotConfiguredError, VaultSigner, buildTxBindingObject, computeTxDigest, createGateClient, GateClient as default, wrapKmsClient };
3196
+ export { AwsKmsSigner, BlockIntelAuthError, BlockIntelBlockedError, BlockIntelStepUpRequiredError, BlockIntelUnavailableError, FireblocksSigner, Gate, GateClient, GateError, GateErrorCode, GcpKmsSigner, GenericHsmSigner, HeartbeatManager, ProvenanceProvider, StepUpNotConfiguredError, VaultSigner, buildTxBindingObject, computeTxDigest, createGateClient, GateClient as default, noOpMetricsSink, wrapKmsClient };
3014
3197
  //# sourceMappingURL=index.js.map
3015
3198
  //# sourceMappingURL=index.js.map