opacity-issuer-core 0.2.2 → 0.3.1

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.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var chunkGMPQFX25_cjs = require('./chunk-GMPQFX25.cjs');
3
+ var chunkGUTZXV5S_cjs = require('./chunk-GUTZXV5S.cjs');
4
4
  var chunk3L7NNVUV_cjs = require('./chunk-3L7NNVUV.cjs');
5
5
  var chunkHJQZWNZJ_cjs = require('./chunk-HJQZWNZJ.cjs');
6
6
  var viem = require('viem');
@@ -142,13 +142,13 @@ function parsePurchaseAmount(value, decimals) {
142
142
 
143
143
  // src/purchases/index.ts
144
144
  var SANDBOX_PURCHASE_DEPLOYMENT = deployment({
145
- chainId: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.chainId,
146
- vault: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.vault,
147
- token: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.mmfToken,
148
- tokenId: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.mmfTokenId,
149
- paymentToken: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.mockUSDC,
150
- allowlistRegistry: chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.registry,
151
- requiredGlobalTraits: [chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST.documentTraitId]
145
+ chainId: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.chainId,
146
+ vault: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.vault,
147
+ token: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.mmfToken,
148
+ tokenId: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.mmfTokenId,
149
+ paymentToken: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.mockUSDC,
150
+ allowlistRegistry: chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.addresses.registry,
151
+ requiredGlobalTraits: [chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST.documentTraitId]
152
152
  });
153
153
  function buildPurchaseWriteRequest(input) {
154
154
  const params = purchaseParams(input);
@@ -524,12 +524,12 @@ function createPurchasesNamespace(options = {}) {
524
524
  "Payment token returned false from approve."
525
525
  );
526
526
  const wallet = await walletFor(params);
527
- const hash = await wallet.writeContract({
527
+ const hash2 = await wallet.writeContract({
528
528
  ...step.request,
529
529
  account: wallet.account ?? params.buyer,
530
530
  chain: sendChain(wallet, params.deployment.chainId)
531
531
  });
532
- return { ...params, kind: "approval", step: step.kind, approvedAmount: step.amount, hash };
532
+ return { ...params, kind: "approval", step: step.kind, approvedAmount: step.amount, hash: hash2 };
533
533
  });
534
534
  }
535
535
  async function sendPurchase(input) {
@@ -538,17 +538,17 @@ function createPurchasesNamespace(options = {}) {
538
538
  await walletFor(params);
539
539
  const prepared = await simulatePurchase(params);
540
540
  const wallet = await walletFor(params);
541
- const hash = await wallet.writeContract({
541
+ const hash2 = await wallet.writeContract({
542
542
  ...prepared.request,
543
543
  account: wallet.account ?? params.buyer,
544
544
  chain: sendChain(wallet, params.deployment.chainId)
545
545
  });
546
- return { ...params, kind: "purchase", hash };
546
+ return { ...params, kind: "purchase", hash: hash2 };
547
547
  });
548
548
  }
549
549
  async function receiptFor(submitted, options2) {
550
550
  const params = purchaseParams(submitted);
551
- const hash = bytes32(submitted.hash, "hash", true);
551
+ const hash2 = bytes32(submitted.hash, "hash", true);
552
552
  for (const [name, value] of Object.entries(options2)) {
553
553
  if (value !== void 0 && (!Number.isSafeInteger(value) || value <= 0)) {
554
554
  throw new OpacityPurchaseError("invalid-input", `${name} must be a positive safe integer.`);
@@ -557,7 +557,7 @@ function createPurchasesNamespace(options = {}) {
557
557
  const client = await clientFor(params.deployment);
558
558
  let replacementReason;
559
559
  const receipt = await client.waitForTransactionReceipt({
560
- hash,
560
+ hash: hash2,
561
561
  ...options2.confirmations === void 0 ? {} : { confirmations: options2.confirmations },
562
562
  ...options2.timeout === void 0 ? {} : { timeout: options2.timeout },
563
563
  ...options2.pollingInterval === void 0 ? {} : { pollingInterval: options2.pollingInterval },
@@ -565,10 +565,10 @@ function createPurchasesNamespace(options = {}) {
565
565
  replacementReason = replacement.reason;
566
566
  }
567
567
  });
568
- const replaced = receipt.transactionHash.toLowerCase() !== hash.toLowerCase();
568
+ const replaced = receipt.transactionHash.toLowerCase() !== hash2.toLowerCase();
569
569
  return {
570
570
  status: replaced || replacementReason !== void 0 ? "replaced" : receipt.status === "reverted" ? "reverted" : "unverified",
571
- submittedHash: hash,
571
+ submittedHash: hash2,
572
572
  hash: receipt.transactionHash,
573
573
  receipt,
574
574
  ...replacementReason === void 0 ? {} : { replacementReason }
@@ -6246,14 +6246,14 @@ function createTransfersNamespace(options = {}) {
6246
6246
  rpcUrls: { default: { http: [] } }
6247
6247
  });
6248
6248
  const { gas, gasPrice, maxFeePerGas, maxPriorityFeePerGas } = prepared.gas;
6249
- const hash = await wallet.writeContract({
6249
+ const hash2 = await wallet.writeContract({
6250
6250
  ...prepared.request,
6251
6251
  account: wallet.account ?? params.sender,
6252
6252
  chain: chain2,
6253
6253
  gas,
6254
6254
  ...gasPrice === void 0 ? { maxFeePerGas, maxPriorityFeePerGas } : { gasPrice }
6255
6255
  });
6256
- return Object.freeze({ ...params, kind: "transfer", hash });
6256
+ return Object.freeze({ ...params, kind: "transfer", hash: hash2 });
6257
6257
  } finally {
6258
6258
  sendsInProgress.delete(key);
6259
6259
  }
@@ -6262,8 +6262,8 @@ function createTransfersNamespace(options = {}) {
6262
6262
  if (submitted?.kind !== "transfer")
6263
6263
  throw new OpacityTransferError("invalid-input", "Expected a submitted transfer record.");
6264
6264
  const params = transferParams(submitted);
6265
- const hash = submitted.hash;
6266
- if (typeof hash !== "string" || !/^0x[\da-fA-F]{64}$/.test(hash) || /^0x0+$/.test(hash)) {
6265
+ const hash2 = submitted.hash;
6266
+ if (typeof hash2 !== "string" || !/^0x[\da-fA-F]{64}$/.test(hash2) || /^0x0+$/.test(hash2)) {
6267
6267
  throw new OpacityTransferError("invalid-input", "hash must be nonzero bytes32.");
6268
6268
  }
6269
6269
  const waitOptions3 = {
@@ -6282,7 +6282,7 @@ function createTransfersNamespace(options = {}) {
6282
6282
  const client = await clientFor(params.deployment);
6283
6283
  let replacementReason;
6284
6284
  const received = await client.waitForTransactionReceipt({
6285
- hash,
6285
+ hash: hash2,
6286
6286
  ...waitOptions3,
6287
6287
  onReplaced: (replacement) => {
6288
6288
  replacementReason = replacement.reason;
@@ -6294,8 +6294,8 @@ function createTransfersNamespace(options = {}) {
6294
6294
  };
6295
6295
  await clientFor(params.deployment);
6296
6296
  const result = {
6297
- status: receipt.transactionHash.toLowerCase() !== hash.toLowerCase() || replacementReason !== void 0 ? "replaced" : receipt.status === "reverted" ? "reverted" : "unverified",
6298
- submittedHash: hash,
6297
+ status: receipt.transactionHash.toLowerCase() !== hash2.toLowerCase() || replacementReason !== void 0 ? "replaced" : receipt.status === "reverted" ? "reverted" : "unverified",
6298
+ submittedHash: hash2,
6299
6299
  hash: receipt.transactionHash,
6300
6300
  receipt,
6301
6301
  ...replacementReason === void 0 ? {} : { replacementReason }
@@ -6305,15 +6305,15 @@ function createTransfersNamespace(options = {}) {
6305
6305
  return result;
6306
6306
  let transaction;
6307
6307
  try {
6308
- transaction = { ...await client.getTransaction({ hash }) };
6308
+ transaction = { ...await client.getTransaction({ hash: hash2 }) };
6309
6309
  } catch {
6310
6310
  return result;
6311
6311
  }
6312
6312
  await clientFor(params.deployment);
6313
- if (transaction.chainId !== params.deployment.chainId || typeof transaction.hash !== "string" || transaction.hash.toLowerCase() !== hash.toLowerCase() || !sameAddress2(transaction.from, params.sender) || !sameAddress2(transaction.to, params.deployment.token) || transaction.value !== 0n || typeof transaction.input !== "string" || transaction.input.toLowerCase() !== buildTransferTransaction(params).data.toLowerCase())
6313
+ if (transaction.chainId !== params.deployment.chainId || typeof transaction.hash !== "string" || transaction.hash.toLowerCase() !== hash2.toLowerCase() || !sameAddress2(transaction.from, params.sender) || !sameAddress2(transaction.to, params.deployment.token) || transaction.value !== 0n || typeof transaction.input !== "string" || transaction.input.toLowerCase() !== buildTransferTransaction(params).data.toLowerCase())
6314
6314
  return result;
6315
6315
  for (const log of receipt.logs) {
6316
- if (!sameAddress2(log.address, params.deployment.token) || log.removed || log.transactionHash?.toLowerCase() !== hash.toLowerCase())
6316
+ if (!sameAddress2(log.address, params.deployment.token) || log.removed || log.transactionHash?.toLowerCase() !== hash2.toLowerCase())
6317
6317
  continue;
6318
6318
  try {
6319
6319
  const event = viem.decodeEventLog({
@@ -7199,8 +7199,370 @@ function createPolicyReplacementBatch(currentCount, policies) {
7199
7199
  return createPolicyBatch(changes);
7200
7200
  }
7201
7201
 
7202
+ // src/issuers/discovery.ts
7203
+ var discoveryAbi = viem.parseAbi([
7204
+ "function allowlistRegistry() view returns (address)",
7205
+ "function beaconRegistry() view returns (address)",
7206
+ "function platformOperator() view returns (address)",
7207
+ "function policyEngine() view returns (address)",
7208
+ "function policyRegistry() view returns (address)",
7209
+ "function getDefaultVariant() view returns (bytes32)",
7210
+ "function getBeacon(bytes32) view returns (address)",
7211
+ "function isVariantActive(bytes32) view returns (bool)",
7212
+ "function isAuthorizedFactory(address) view returns (bool)",
7213
+ "function getIssuerTokens(address) view returns (address[])",
7214
+ "function implementationsOf(bytes32) view returns (address[])",
7215
+ "function isApproved(address) view returns (bool)",
7216
+ "function policyTypeOf(address) view returns (bytes32)",
7217
+ "function policyType() view returns (bytes32)"
7218
+ ]);
7219
+ var policyKinds = Object.keys(issuerPolicyTypes);
7220
+ var receiptRetryDelaysMs = [500, 1e3, 2e3];
7221
+ function fail(message) {
7222
+ throw new OpacityIssuerOperationError("deployment-mismatch", message);
7223
+ }
7224
+ function address4(value, optional = false) {
7225
+ if (optional && value === null) return viem.zeroAddress;
7226
+ if (typeof value !== "string" || !viem.isAddress(value, { strict: false }) || !optional && value.toLowerCase() === viem.zeroAddress)
7227
+ fail("Issuer discovery returned an invalid contract address.");
7228
+ return value.toLowerCase();
7229
+ }
7230
+ function hash(value) {
7231
+ if (typeof value !== "string" || !/^0x[0-9a-fA-F]{64}$/.test(value))
7232
+ fail("Issuer discovery requires valid block and transaction hashes.");
7233
+ return value.toLowerCase();
7234
+ }
7235
+ function positiveBigint(value) {
7236
+ return typeof value === "bigint" && value > 0n;
7237
+ }
7238
+ function validateHead(meta) {
7239
+ if (!meta || meta.hasIndexingErrors !== false || typeof meta.deployment !== "string" || !meta.deployment || !positiveBigint(meta.block?.number) || !positiveBigint(meta.block.timestamp))
7240
+ fail("Issuer discovery requires a healthy subgraph with complete block evidence.");
7241
+ const age = BigInt(Math.floor(Date.now() / 1e3)) - meta.block.timestamp;
7242
+ if (age > 600n || age < -60n)
7243
+ fail("Issuer discovery requires a subgraph block from the last 10 minutes.");
7244
+ return {
7245
+ deployment: meta.deployment,
7246
+ number: meta.block.number,
7247
+ hash: hash(meta.block.hash),
7248
+ timestamp: meta.block.timestamp
7249
+ };
7250
+ }
7251
+ async function resolveIssuerDeployment(input, options) {
7252
+ if (!input || typeof input !== "object" || Array.isArray(input) || Object.keys(input).some((key) => !["chainId", "token", "maxTokens"].includes(key)) || !options || typeof options !== "object" || Array.isArray(options))
7253
+ throw new OpacityIssuerOperationError("invalid-input", "Invalid issuer discovery arguments.");
7254
+ const chainId4 = issuerChainId(input.chainId);
7255
+ const selectedToken = input.token === void 0 ? void 0 : issuerAddress(input.token, "token").toLowerCase();
7256
+ const maxTokens = input.maxTokens === void 0 ? 100 : input.maxTokens;
7257
+ if (!Number.isSafeInteger(maxTokens) || maxTokens < 1 || maxTokens > 1e3)
7258
+ throw new OpacityIssuerOperationError(
7259
+ "invalid-input",
7260
+ "maxTokens must be an integer between 1 and 1000."
7261
+ );
7262
+ const { indexer, publicClient: client } = options;
7263
+ if (!client || !indexer || ["getMetadata", "getRegistry", "listTokens", "getToken"].some(
7264
+ (method) => typeof indexer[method] !== "function"
7265
+ ) || typeof client.getChainId !== "function")
7266
+ throw new OpacityIssuerOperationError(
7267
+ "missing-client",
7268
+ "Issuer discovery requires publicClient and a configured indexer."
7269
+ );
7270
+ if (client.chain && client.chain.id !== chainId4 || await client.getChainId() !== chainId4)
7271
+ throw new OpacityIssuerOperationError(
7272
+ "chain-mismatch",
7273
+ "RPC and requested issuer discovery chains must agree."
7274
+ );
7275
+ const snapshot2 = validateHead(await indexer.getMetadata());
7276
+ function validateSnapshot(meta) {
7277
+ if (!meta || meta.hasIndexingErrors !== false || meta.deployment !== snapshot2.deployment || meta.block?.number !== snapshot2.number || meta.block.hash !== null && hash(meta.block.hash) !== snapshot2.hash || meta.block.timestamp !== null && meta.block.timestamp !== snapshot2.timestamp)
7278
+ fail("The subgraph snapshot changed during issuer discovery. Retry discovery.");
7279
+ }
7280
+ const atSnapshot = { blockHash: snapshot2.hash };
7281
+ const registryResult = await indexer.getRegistry(atSnapshot);
7282
+ validateSnapshot(registryResult.meta);
7283
+ if (!registryResult.item) fail("The configured subgraph has no indexed protocol registry.");
7284
+ const registry = address4(registryResult.item.contractAddress);
7285
+ const tokens = [];
7286
+ if (selectedToken !== void 0) {
7287
+ const result = await indexer.getToken(selectedToken, atSnapshot);
7288
+ validateSnapshot(result.meta);
7289
+ if (!result.item || address4(result.item.id) !== selectedToken)
7290
+ fail("The selected source token is not indexed in this environment.");
7291
+ tokens.push(result.item);
7292
+ } else {
7293
+ let cursor = null;
7294
+ const seenCursors = /* @__PURE__ */ new Set();
7295
+ do {
7296
+ const page = await indexer.listTokens({
7297
+ registry,
7298
+ ...atSnapshot,
7299
+ pageSize: Math.min(100, maxTokens - tokens.length),
7300
+ ...cursor ? { cursor } : {}
7301
+ });
7302
+ validateSnapshot(page.meta);
7303
+ if (!Array.isArray(page.items) || page.items.length > maxTokens - tokens.length)
7304
+ fail("Issuer discovery returned an invalid token page.");
7305
+ tokens.push(...page.items);
7306
+ cursor = page.nextCursor;
7307
+ if (cursor) {
7308
+ if (tokens.length >= maxTokens)
7309
+ fail("Issuer discovery exceeded maxTokens. Select a source token or raise maxTokens.");
7310
+ if (!page.items.length || seenCursors.has(cursor.after))
7311
+ fail("Issuer discovery pagination did not advance.");
7312
+ seenCursors.add(cursor.after);
7313
+ }
7314
+ } while (cursor);
7315
+ }
7316
+ if (!tokens.length)
7317
+ fail(
7318
+ "The configured subgraph has no indexed token deployments. Index the protocol deployment before discovering its factory; a new issuer does not need an existing token of their own."
7319
+ );
7320
+ const tokenAddresses = tokens.map((token) => address4(token.id));
7321
+ if (new Set(tokenAddresses).size !== tokens.length)
7322
+ fail("Issuer discovery returned duplicate source tokens.");
7323
+ const [indexedBlock, latest] = await Promise.all([
7324
+ client.getBlock({ blockNumber: snapshot2.number }),
7325
+ client.getBlock({ blockTag: "latest" })
7326
+ ]);
7327
+ if (indexedBlock.number !== snapshot2.number || hash(indexedBlock.hash) !== snapshot2.hash || indexedBlock.timestamp !== snapshot2.timestamp || !positiveBigint(latest.number) || latest.number < snapshot2.number || !positiveBigint(latest.timestamp) || latest.timestamp < snapshot2.timestamp)
7328
+ fail("Subgraph block evidence does not match the requested RPC chain.");
7329
+ const latestHash = hash(latest.hash);
7330
+ validateHead({
7331
+ deployment: snapshot2.deployment,
7332
+ hasIndexingErrors: false,
7333
+ block: { number: latest.number, hash: latestHash, timestamp: latest.timestamp }
7334
+ });
7335
+ const blocks = [.../* @__PURE__ */ new Set([snapshot2.number, latest.number])];
7336
+ const readCache = /* @__PURE__ */ new Map();
7337
+ function read(contract, functionName, args, blockNumber) {
7338
+ const key = `${contract}:${functionName}:${args.join(",")}:${blockNumber}`;
7339
+ let result = readCache.get(key);
7340
+ if (!result) {
7341
+ result = client.readContract({
7342
+ address: contract,
7343
+ abi: discoveryAbi,
7344
+ functionName,
7345
+ args,
7346
+ blockNumber
7347
+ });
7348
+ readCache.set(key, result);
7349
+ }
7350
+ return result;
7351
+ }
7352
+ const codeCache = /* @__PURE__ */ new Set();
7353
+ async function requireCode(contract, blockNumber) {
7354
+ const key = `${contract}:${blockNumber}`;
7355
+ if (codeCache.has(key)) return;
7356
+ const code = await client.getBytecode({ address: contract, blockNumber });
7357
+ if (!code || code === "0x") fail(`No contract code at discovered address ${contract}.`);
7358
+ codeCache.add(key);
7359
+ }
7360
+ async function sameAddressAtBoth(contract, functionName, expected, optional = false) {
7361
+ for (const block of blocks) {
7362
+ if (address4(await read(contract, functionName, [], block), optional) !== expected)
7363
+ fail(`Discovered ${functionName} differs from the indexed or current chain state.`);
7364
+ }
7365
+ }
7366
+ const factories = /* @__PURE__ */ new Set();
7367
+ const receiptCache = /* @__PURE__ */ new Map();
7368
+ for (const token of tokens) {
7369
+ const tokenAddress = address4(token.id);
7370
+ const tokenIssuer = address4(token.issuer?.id);
7371
+ if (address4(token.allowlistRegistry) !== registry)
7372
+ fail("An indexed source token belongs to a different registry.");
7373
+ if (!positiveBigint(token.deployedAtBlock) || token.deployedAtBlock > snapshot2.number)
7374
+ fail("The indexed token deployment block is invalid.");
7375
+ for (const block of blocks) await requireCode(tokenAddress, block);
7376
+ await sameAddressAtBoth(tokenAddress, "allowlistRegistry", registry);
7377
+ const engine = address4(token.policyEngine, true);
7378
+ await sameAddressAtBoth(tokenAddress, "policyEngine", engine, true);
7379
+ const txHash = hash(token.deployTxHash);
7380
+ let receipt = receiptCache.get(txHash);
7381
+ if (!receipt) {
7382
+ for (let attempt = 0; ; attempt++) {
7383
+ try {
7384
+ receipt = await client.getTransactionReceipt({ hash: txHash });
7385
+ break;
7386
+ } catch (cause) {
7387
+ const delay = receiptRetryDelaysMs[attempt];
7388
+ if (!(cause instanceof viem.TransactionReceiptNotFoundError) || delay === void 0)
7389
+ throw cause;
7390
+ await new Promise((resolve) => setTimeout(resolve, delay));
7391
+ }
7392
+ }
7393
+ receiptCache.set(txHash, receipt);
7394
+ }
7395
+ if (receipt.status !== "success" || hash(receipt.transactionHash) !== txHash || receipt.blockNumber !== token.deployedAtBlock)
7396
+ fail("The indexed token deployment receipt does not match the chain.");
7397
+ const deployedBlock = await client.getBlock({ blockNumber: receipt.blockNumber });
7398
+ if (deployedBlock.number !== token.deployedAtBlock || hash(deployedBlock.hash) !== hash(receipt.blockHash) || deployedBlock.timestamp !== token.deployedAtTimestamp)
7399
+ fail("The indexed token deployment receipt is not on the canonical chain.");
7400
+ const emitters = [];
7401
+ for (const log of receipt.logs) {
7402
+ if (log.removed) continue;
7403
+ try {
7404
+ const event = viem.decodeEventLog({
7405
+ abi: issuerFactoryAbi,
7406
+ eventName: "TokenDeployed",
7407
+ topics: log.topics,
7408
+ data: log.data,
7409
+ strict: true
7410
+ });
7411
+ if (address4(event.args.token) === tokenAddress && address4(event.args.issuer) === tokenIssuer && address4(event.args.allowlistRegistry) === registry)
7412
+ emitters.push(address4(log.address));
7413
+ } catch {
7414
+ }
7415
+ }
7416
+ if (emitters.length !== 1)
7417
+ fail("Expected exactly one matching TokenDeployed event in the indexed receipt.");
7418
+ const emitter = emitters[0];
7419
+ for (const block of blocks) {
7420
+ const issued = await read(emitter, "getIssuerTokens", [tokenIssuer], block);
7421
+ if (!Array.isArray(issued) || !issued.some((item) => address4(item) === tokenAddress))
7422
+ fail("The indexed token is not recorded by its deployment factory for that issuer.");
7423
+ }
7424
+ factories.add(emitter);
7425
+ }
7426
+ if (factories.size !== 1)
7427
+ fail(
7428
+ "Multiple protocol deployments are indexed. Select a source token explicitly; discovery never guesses a factory."
7429
+ );
7430
+ const factory = [...factories][0];
7431
+ for (const block of blocks) {
7432
+ await requireCode(factory, block);
7433
+ await requireCode(registry, block);
7434
+ }
7435
+ await sameAddressAtBoth(factory, "allowlistRegistry", registry);
7436
+ const beaconRegistry = address4(await read(factory, "beaconRegistry", [], snapshot2.number));
7437
+ await sameAddressAtBoth(factory, "beaconRegistry", beaconRegistry);
7438
+ const defaultBeaconVariant = hash(
7439
+ await read(beaconRegistry, "getDefaultVariant", [], snapshot2.number)
7440
+ );
7441
+ const beacon = address4(
7442
+ await read(beaconRegistry, "getBeacon", [defaultBeaconVariant], snapshot2.number)
7443
+ );
7444
+ for (const block of blocks) {
7445
+ await requireCode(beaconRegistry, block);
7446
+ await requireCode(beacon, block);
7447
+ const [variant, actualBeacon, active3, authorized] = await Promise.all([
7448
+ read(beaconRegistry, "getDefaultVariant", [], block),
7449
+ read(beaconRegistry, "getBeacon", [defaultBeaconVariant], block),
7450
+ read(beaconRegistry, "isVariantActive", [defaultBeaconVariant], block),
7451
+ read(beaconRegistry, "isAuthorizedFactory", [factory], block)
7452
+ ]);
7453
+ if (hash(variant) !== defaultBeaconVariant || address4(actualBeacon) !== beacon || active3 !== true || authorized !== true)
7454
+ fail("Discovered factory or default beacon is inactive, unauthorized, or changed.");
7455
+ }
7456
+ const deployment2 = {
7457
+ chainId: chainId4,
7458
+ factory,
7459
+ allowlistRegistry: registry,
7460
+ beaconRegistry
7461
+ };
7462
+ const policies = Object.fromEntries(policyKinds.map((kind) => [kind, []]));
7463
+ const policyEngine = await (async () => {
7464
+ try {
7465
+ const operator = address4(await read(registry, "platformOperator", [], snapshot2.number));
7466
+ await sameAddressAtBoth(registry, "platformOperator", operator);
7467
+ for (const block of blocks) await requireCode(operator, block);
7468
+ const governedEngine = address4(await read(operator, "policyEngine", [], snapshot2.number));
7469
+ await sameAddressAtBoth(operator, "policyEngine", governedEngine);
7470
+ return governedEngine;
7471
+ } catch (cause) {
7472
+ const unsupported = cause instanceof viem.BaseError ? cause.walk(
7473
+ (error) => error instanceof viem.ContractFunctionZeroDataError || error instanceof viem.ContractFunctionRevertedError
7474
+ ) : void 0;
7475
+ if (!(cause instanceof OpacityIssuerOperationError && cause.code === "deployment-mismatch") && !(unsupported instanceof viem.ContractFunctionZeroDataError) && !(unsupported instanceof viem.ContractFunctionRevertedError))
7476
+ throw cause;
7477
+ throw new OpacityIssuerOperationError(
7478
+ "deployment-mismatch",
7479
+ "Cannot verify registry-governed policy infrastructure. Automatic discovery requires a contract platformOperator exposing policyEngine at the indexed and current blocks; an EOA operator or incompatible deployment must be configured by protocol governance before discovery can proceed.",
7480
+ { cause }
7481
+ );
7482
+ }
7483
+ })();
7484
+ if (policyEngine) {
7485
+ const policyRegistry = address4(await read(policyEngine, "policyRegistry", [], snapshot2.number));
7486
+ for (const block of blocks) {
7487
+ await requireCode(policyEngine, block);
7488
+ await requireCode(policyRegistry, block);
7489
+ }
7490
+ await sameAddressAtBoth(policyEngine, "policyRegistry", policyRegistry);
7491
+ await sameAddressAtBoth(policyRegistry, "allowlistRegistry", registry);
7492
+ deployment2.policyEngine = policyEngine;
7493
+ deployment2.policyRegistry = policyRegistry;
7494
+ await Promise.all(
7495
+ policyKinds.map(async (kind) => {
7496
+ const policyType = issuerPolicyTypes[kind];
7497
+ const raw = await read(policyRegistry, "implementationsOf", [policyType], snapshot2.number);
7498
+ if (!Array.isArray(raw) || raw.length > 1e3)
7499
+ fail("The policy registry returned an invalid or excessive implementation catalog.");
7500
+ const implementations = raw.map((item) => address4(item));
7501
+ if (new Set(implementations).size !== implementations.length)
7502
+ fail("The policy registry returned duplicate implementations.");
7503
+ const current = await read(
7504
+ policyRegistry,
7505
+ "implementationsOf",
7506
+ [policyType],
7507
+ latest.number
7508
+ );
7509
+ if (!Array.isArray(current) || current.length !== implementations.length || current.some((item, i) => address4(item) !== implementations[i]))
7510
+ fail("The policy catalog changed since the indexed block. Wait for indexing and retry.");
7511
+ for (const implementation of implementations) {
7512
+ const approved = await read(
7513
+ policyRegistry,
7514
+ "isApproved",
7515
+ [implementation],
7516
+ snapshot2.number
7517
+ );
7518
+ if (typeof approved !== "boolean") fail("The policy registry returned invalid approval.");
7519
+ if (await read(policyRegistry, "isApproved", [implementation], latest.number) !== approved)
7520
+ fail("Policy approval changed since the indexed block. Wait for indexing and retry.");
7521
+ if (!approved) continue;
7522
+ for (const block of blocks) {
7523
+ await requireCode(implementation, block);
7524
+ const [registeredType, actualType] = await Promise.all([
7525
+ read(policyRegistry, "policyTypeOf", [implementation], block),
7526
+ read(implementation, "policyType", [], block)
7527
+ ]);
7528
+ if (hash(registeredType) !== policyType || hash(actualType) !== policyType)
7529
+ fail("An approved policy implementation does not match its registered policy type.");
7530
+ }
7531
+ policies[kind].push(implementation);
7532
+ }
7533
+ })
7534
+ );
7535
+ }
7536
+ const [finalIndexed, finalLatest] = await Promise.all([
7537
+ client.getBlock({ blockNumber: snapshot2.number }),
7538
+ client.getBlock({ blockNumber: latest.number })
7539
+ ]);
7540
+ if (hash(finalIndexed.hash) !== snapshot2.hash || hash(finalLatest.hash) !== latestHash)
7541
+ fail("The chain reorganized during issuer discovery. Retry discovery.");
7542
+ validateHead({
7543
+ deployment: snapshot2.deployment,
7544
+ hasIndexingErrors: false,
7545
+ block: { number: snapshot2.number, hash: snapshot2.hash, timestamp: snapshot2.timestamp }
7546
+ });
7547
+ return {
7548
+ deployment: deployment2,
7549
+ policies,
7550
+ defaultBeaconVariant,
7551
+ beacon,
7552
+ evidence: {
7553
+ subgraphDeployment: snapshot2.deployment,
7554
+ blockNumber: snapshot2.number,
7555
+ blockHash: snapshot2.hash,
7556
+ timestamp: snapshot2.timestamp,
7557
+ verifiedAtBlock: latest.number,
7558
+ verifiedAtBlockHash: latestHash,
7559
+ sourceTokens: tokenAddresses
7560
+ }
7561
+ };
7562
+ }
7563
+
7202
7564
  // src/issuers/sandbox-deployment.ts
7203
- var { chainId: chainId3, addresses } = chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST;
7565
+ var { chainId: chainId3, addresses } = chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST;
7204
7566
  var SANDBOX_ISSUER_DEPLOYMENT = Object.freeze({
7205
7567
  chainId: chainId3,
7206
7568
  factory: addresses.factory,
@@ -7217,6 +7579,37 @@ var SANDBOX_ISSUER_DEPLOYMENT = Object.freeze({
7217
7579
  function createIssuersNamespace(options = {}) {
7218
7580
  const configuredChain = options.chainId === void 0 ? void 0 : issuerChainId(options.chainId);
7219
7581
  const busy = /* @__PURE__ */ new Set();
7582
+ async function discoverDeployment(params = {}) {
7583
+ if (!params || typeof params !== "object" || Array.isArray(params) || ![Object.prototype, null].includes(Object.getPrototypeOf(params)))
7584
+ throw new OpacityIssuerOperationError(
7585
+ "invalid-input",
7586
+ "Discovery parameters must be a plain object."
7587
+ );
7588
+ const chainId4 = params.chainId === void 0 ? configuredChain : params.chainId;
7589
+ if (chainId4 === void 0)
7590
+ throw new OpacityIssuerOperationError(
7591
+ "invalid-input",
7592
+ "Configure chainId before discovering an issuer deployment."
7593
+ );
7594
+ issuerChainId(chainId4);
7595
+ if (configuredChain !== void 0 && chainId4 !== configuredChain)
7596
+ throw new OpacityIssuerOperationError(
7597
+ "chain-mismatch",
7598
+ "Discovery chain must match the configured issuer chain."
7599
+ );
7600
+ if (!options.indexer || !options.publicClient)
7601
+ throw new OpacityIssuerOperationError(
7602
+ "missing-client",
7603
+ "Deployment discovery requires an indexer and publicClient."
7604
+ );
7605
+ return resolveIssuerDeployment(
7606
+ { ...params, chainId: chainId4 },
7607
+ {
7608
+ indexer: options.indexer,
7609
+ publicClient: options.publicClient
7610
+ }
7611
+ );
7612
+ }
7220
7613
  async function clientFor(chainId4) {
7221
7614
  issuerChainId(chainId4);
7222
7615
  const client = options.publicClient;
@@ -7246,15 +7639,15 @@ function createIssuersNamespace(options = {}) {
7246
7639
  );
7247
7640
  return wallet;
7248
7641
  }
7249
- async function requireCode(client, address4, blockNumber) {
7642
+ async function requireCode(client, address5, blockNumber) {
7250
7643
  const code = await client.getBytecode({
7251
- address: address4,
7644
+ address: address5,
7252
7645
  ...blockNumber === void 0 ? {} : { blockNumber }
7253
7646
  });
7254
7647
  if (!code || code === "0x")
7255
7648
  throw new OpacityIssuerOperationError(
7256
7649
  "deployment-mismatch",
7257
- `No contract code at ${address4}.`
7650
+ `No contract code at ${address5}.`
7258
7651
  );
7259
7652
  }
7260
7653
  async function sandboxVersionAt(client, registry, blockNumber) {
@@ -7545,10 +7938,10 @@ function createIssuersNamespace(options = {}) {
7545
7938
  "deployment-blocked",
7546
7939
  `Issuer deployment blocked: ${prepared.blockers.join(", ")}.`
7547
7940
  );
7548
- const hash = await write(prepared.transaction);
7941
+ const hash2 = await write(prepared.transaction);
7549
7942
  return {
7550
7943
  kind: "deployment",
7551
- hash,
7944
+ hash: hash2,
7552
7945
  transaction: prepared.transaction,
7553
7946
  params,
7554
7947
  predictedToken: prepared.predictedToken,
@@ -7721,28 +8114,28 @@ function createIssuersNamespace(options = {}) {
7721
8114
  }
7722
8115
  async function waitForTransaction(record2, wait = {}) {
7723
8116
  const tx = issuerTransaction(record2.transaction);
7724
- const hash = issuerBytes(record2.hash, "hash", 32);
8117
+ const hash2 = issuerBytes(record2.hash, "hash", 32);
7725
8118
  const client = await clientFor(tx.chainId);
7726
8119
  let replacementReason;
7727
8120
  const receipt = await client.waitForTransactionReceipt({
7728
- hash,
8121
+ hash: hash2,
7729
8122
  ...wait,
7730
8123
  onReplaced: ({ reason }) => {
7731
8124
  replacementReason = reason;
7732
8125
  }
7733
8126
  });
7734
- const base = { submittedHash: hash, hash: receipt.transactionHash, receipt };
7735
- if (replacementReason || receipt.transactionHash.toLowerCase() !== hash.toLowerCase())
8127
+ const base = { submittedHash: hash2, hash: receipt.transactionHash, receipt };
8128
+ if (replacementReason || receipt.transactionHash.toLowerCase() !== hash2.toLowerCase())
7736
8129
  return {
7737
8130
  ...base,
7738
8131
  status: "replaced",
7739
8132
  ...replacementReason === void 0 ? {} : { replacementReason }
7740
8133
  };
7741
8134
  if (receipt.status === "reverted") return { ...base, status: "reverted" };
7742
- const actual = await client.getTransaction({ hash });
8135
+ const actual = await client.getTransaction({ hash: hash2 });
7743
8136
  const actualTo = actual.to ?? void 0;
7744
8137
  const sameTarget = tx.to === void 0 ? actualTo === void 0 : actualTo !== void 0 && sameIssuerAddress(tx.to, actualTo);
7745
- const verified = actual.hash.toLowerCase() === hash.toLowerCase() && sameIssuerAddress(actual.from, tx.from) && sameTarget && actual.input.toLowerCase() === tx.data.toLowerCase() && actual.value === tx.value && (actual.chainId === void 0 || actual.chainId === tx.chainId) && (tx.to !== void 0 || !!receipt.contractAddress);
8138
+ const verified = actual.hash.toLowerCase() === hash2.toLowerCase() && sameIssuerAddress(actual.from, tx.from) && sameTarget && actual.input.toLowerCase() === tx.data.toLowerCase() && actual.value === tx.value && (actual.chainId === void 0 || actual.chainId === tx.chainId) && (tx.to !== void 0 || !!receipt.contractAddress);
7746
8139
  return { ...base, status: verified ? "confirmed" : "unverified" };
7747
8140
  }
7748
8141
  async function waitForDeployment(record2, wait) {
@@ -7887,10 +8280,10 @@ function createIssuersNamespace(options = {}) {
7887
8280
  }
7888
8281
  async function getApprovedPolicies(input) {
7889
8282
  const client = await clientFor(input.chainId);
7890
- const address4 = issuerAddress(input.policyRegistry, "policyRegistry");
8283
+ const address5 = issuerAddress(input.policyRegistry, "policyRegistry");
7891
8284
  const policyType = issuerBytes(input.policyType, "policyType", 32);
7892
8285
  const { number: blockNumber } = await client.getBlock({ blockTag: "latest" });
7893
- const req = { address: address4, abi: issuerPolicyRegistryAbi, blockNumber };
8286
+ const req = { address: address5, abi: issuerPolicyRegistryAbi, blockNumber };
7894
8287
  const implementations = await client.readContract({
7895
8288
  ...req,
7896
8289
  functionName: "implementationsOf",
@@ -7990,6 +8383,7 @@ function createIssuersNamespace(options = {}) {
7990
8383
  };
7991
8384
  }
7992
8385
  return {
8386
+ discoverDeployment,
7993
8387
  prepareDeployment,
7994
8388
  simulateDeployment,
7995
8389
  sendDeployment,
@@ -8075,7 +8469,7 @@ async function prepareSandboxUser(publicClient, params) {
8075
8469
  publicClient,
8076
8470
  chainId: chainId4
8077
8471
  }).getSandboxCapabilities(context);
8078
- const userId = capabilities.userId === viem.zeroHash ? chunkGMPQFX25_cjs.sandboxUserId(wallet) : capabilities.userId;
8472
+ const userId = capabilities.userId === viem.zeroHash ? chunkGUTZXV5S_cjs.sandboxUserId(wallet) : capabilities.userId;
8079
8473
  const blockers = [];
8080
8474
  if (!capabilities.supportsSelfOnboarding || traits.length > 0 && !capabilities.supportsSelfTraits)
8081
8475
  blockers.push("unsupported-sandbox-version");
@@ -8182,21 +8576,21 @@ async function waitForSandboxUserFunding(publicClient, submission, wait) {
8182
8576
  };
8183
8577
  if (tx.value === 0n || tx.data !== "0x")
8184
8578
  invalid("Funding must be a positive native transfer with empty data.");
8185
- const hash = issuerBytes(submission.hash, "hash", 32);
8579
+ const hash2 = issuerBytes(submission.hash, "hash", 32);
8186
8580
  const options = waitOptions(wait);
8187
8581
  await checkChain(publicClient, tx.chainId);
8188
8582
  let replacementReason;
8189
8583
  const receipt = structuredClone(
8190
8584
  await publicClient.waitForTransactionReceipt({
8191
- hash,
8585
+ hash: hash2,
8192
8586
  ...options,
8193
8587
  onReplaced: ({ reason }) => {
8194
8588
  replacementReason = reason;
8195
8589
  }
8196
8590
  })
8197
8591
  );
8198
- const base = { submittedHash: hash, hash: receipt.transactionHash, receipt };
8199
- if (replacementReason || receipt.transactionHash.toLowerCase() !== hash.toLowerCase())
8592
+ const base = { submittedHash: hash2, hash: receipt.transactionHash, receipt };
8593
+ if (replacementReason || receipt.transactionHash.toLowerCase() !== hash2.toLowerCase())
8200
8594
  return {
8201
8595
  ...base,
8202
8596
  status: "replaced",
@@ -8205,11 +8599,11 @@ async function waitForSandboxUserFunding(publicClient, submission, wait) {
8205
8599
  if (receipt.status === "reverted") return { ...base, status: "reverted" };
8206
8600
  let actual;
8207
8601
  try {
8208
- actual = await publicClient.getTransaction({ hash });
8602
+ actual = await publicClient.getTransaction({ hash: hash2 });
8209
8603
  } catch {
8210
8604
  return { ...base, status: "unverified" };
8211
8605
  }
8212
- const verified = actual.hash.toLowerCase() === hash.toLowerCase() && sameIssuerAddress(actual.from, tx.from) && actual.to !== null && sameIssuerAddress(actual.to, tx.to) && actual.input === "0x" && actual.value === tx.value && (actual.chainId === void 0 || actual.chainId === tx.chainId);
8606
+ const verified = actual.hash.toLowerCase() === hash2.toLowerCase() && sameIssuerAddress(actual.from, tx.from) && actual.to !== null && sameIssuerAddress(actual.to, tx.to) && actual.input === "0x" && actual.value === tx.value && (actual.chainId === void 0 || actual.chainId === tx.chainId);
8213
8607
  return { ...base, status: verified ? "confirmed" : "unverified" };
8214
8608
  }
8215
8609
  function sameTransaction(a, b) {
@@ -8327,15 +8721,15 @@ async function createSandboxUser(publicClient, params) {
8327
8721
  await checkChain(publicClient, chainId4);
8328
8722
  if (!sameIssuerAddress(await walletAddress(sponsor, chainId4), from))
8329
8723
  invalid("Selected funding account changed before sending.");
8330
- const hash = await sponsor.sendTransaction({
8724
+ const hash2 = await sponsor.sendTransaction({
8331
8725
  account: sponsor.account ?? from,
8332
8726
  chain: sponsor.chain ?? chain2,
8333
8727
  to: account.address,
8334
8728
  value: transaction.value,
8335
8729
  data: "0x"
8336
8730
  });
8337
- state.funding = { kind: "funding", hash, transaction };
8338
- state.pending.hash = hash;
8731
+ state.funding = { kind: "funding", hash: hash2, transaction };
8732
+ state.pending.hash = hash2;
8339
8733
  state.stage = "waiting-funding";
8340
8734
  await save();
8341
8735
  const result = await waitForSandboxUserFunding(publicClient, state.funding, wait);
@@ -8590,15 +8984,15 @@ async function transferSandboxUser(publicClient, params) {
8590
8984
  await checkChain2(publicClient, chainId4);
8591
8985
  if (!sameIssuerAddress(await fundingAccount(sponsor, chainId4), from))
8592
8986
  invalid("Selected funding account changed before sending.");
8593
- const hash = await sponsor.sendTransaction({
8987
+ const hash2 = await sponsor.sendTransaction({
8594
8988
  account: sendAccount,
8595
8989
  chain: chain2,
8596
8990
  to: wallet,
8597
8991
  value: transaction.value,
8598
8992
  data: "0x"
8599
8993
  });
8600
- state.funding = { kind: "funding", hash, transaction: structuredClone(transaction) };
8601
- state.pending.hash = hash;
8994
+ state.funding = { kind: "funding", hash: hash2, transaction: structuredClone(transaction) };
8995
+ state.pending.hash = hash2;
8602
8996
  state.stage = "waiting-funding";
8603
8997
  await save();
8604
8998
  const result2 = structuredClone(
@@ -9065,7 +9459,7 @@ function createSandboxWalletLinksNamespace(options) {
9065
9459
  );
9066
9460
  const tx = buildSandboxWalletLinkTransaction(intent, signature);
9067
9461
  attempted = true;
9068
- const hash = await wallet.sendTransaction({
9462
+ const hash2 = await wallet.sendTransaction({
9069
9463
  account: wallet.account ?? intent.existingWallet,
9070
9464
  chain: wallet.chain ?? viem.defineChain({
9071
9465
  id: intent.chainId,
@@ -9078,7 +9472,7 @@ function createSandboxWalletLinksNamespace(options) {
9078
9472
  value: 0n,
9079
9473
  nonce: progress.senderNonce
9080
9474
  });
9081
- progress.hash = issuerBytes(hash, "transaction hash", 32);
9475
+ progress.hash = issuerBytes(hash2, "transaction hash", 32);
9082
9476
  progress.stage = "submitted";
9083
9477
  await save();
9084
9478
  return structuredClone(progress);
@@ -9118,7 +9512,7 @@ function createSandboxWalletLinksNamespace(options) {
9118
9512
  if (input.kind !== "wallet-link" || !["submitted", "complete"].includes(input.stage))
9119
9513
  invalid("Expected a submitted wallet link.");
9120
9514
  const intent = validateSandboxWalletLinkIntent(input.intent);
9121
- const hash = issuerBytes(input.hash, "hash", 32);
9515
+ const hash2 = issuerBytes(input.hash, "hash", 32);
9122
9516
  const senderNonce = input.senderNonce;
9123
9517
  if (!Number.isSafeInteger(senderNonce) || senderNonce < 0)
9124
9518
  invalid("senderNonce must be a nonnegative safe integer.");
@@ -9127,7 +9521,7 @@ function createSandboxWalletLinksNamespace(options) {
9127
9521
  let replacementReason;
9128
9522
  const receipt = structuredClone(
9129
9523
  await client.waitForTransactionReceipt({
9130
- hash,
9524
+ hash: hash2,
9131
9525
  ...waitOptions3,
9132
9526
  onReplaced: ({ reason }) => {
9133
9527
  replacementReason = reason;
@@ -9135,22 +9529,22 @@ function createSandboxWalletLinksNamespace(options) {
9135
9529
  })
9136
9530
  );
9137
9531
  await clientFor(intent.chainId);
9138
- const base = { submittedHash: hash, hash: receipt.transactionHash, receipt };
9532
+ const base = { submittedHash: hash2, hash: receipt.transactionHash, receipt };
9139
9533
  let exactTransaction = false;
9140
9534
  let result = { ...base, status: "unverified" };
9141
- if (replacementReason || receipt.transactionHash.toLowerCase() !== hash.toLowerCase())
9535
+ if (replacementReason || receipt.transactionHash.toLowerCase() !== hash2.toLowerCase())
9142
9536
  result = { ...base, status: "replaced", ...replacementReason ? { replacementReason } : {} };
9143
9537
  else if (receipt.status === "reverted") result = { ...base, status: "reverted" };
9144
9538
  else if (receipt.status === "success") {
9145
9539
  try {
9146
- const tx = await client.getTransaction({ hash });
9540
+ const tx = await client.getTransaction({ hash: hash2 });
9147
9541
  await clientFor(intent.chainId);
9148
9542
  const decoded = viem.decodeFunctionData({ abi: sandboxWalletLinkAbi, data: tx.input });
9149
- const matches = sameIssuerAddress(receipt.from, intent.existingWallet) && receipt.to !== null && sameIssuerAddress(receipt.to, intent.registryAddress) && tx.blockHash === receipt.blockHash && tx.blockNumber === receipt.blockNumber && tx.hash.toLowerCase() === hash.toLowerCase() && tx.chainId === intent.chainId && sameIssuerAddress(tx.from, intent.existingWallet) && tx.to !== null && sameIssuerAddress(tx.to, intent.registryAddress) && tx.value === 0n && (senderNonce === void 0 || tx.nonce === senderNonce) && decoded.functionName === "sandboxLinkWallet" && sameIssuerAddress(decoded.args[0], intent.newWallet) && decoded.args[1].toLowerCase() === intent.nonce.toLowerCase() && decoded.args[2] === intent.deadline;
9543
+ const matches = sameIssuerAddress(receipt.from, intent.existingWallet) && receipt.to !== null && sameIssuerAddress(receipt.to, intent.registryAddress) && tx.blockHash === receipt.blockHash && tx.blockNumber === receipt.blockNumber && tx.hash.toLowerCase() === hash2.toLowerCase() && tx.chainId === intent.chainId && sameIssuerAddress(tx.from, intent.existingWallet) && tx.to !== null && sameIssuerAddress(tx.to, intent.registryAddress) && tx.value === 0n && (senderNonce === void 0 || tx.nonce === senderNonce) && decoded.functionName === "sandboxLinkWallet" && sameIssuerAddress(decoded.args[0], intent.newWallet) && decoded.args[1].toLowerCase() === intent.nonce.toLowerCase() && decoded.args[2] === intent.deadline;
9150
9544
  exactTransaction = matches;
9151
9545
  if (matches)
9152
9546
  for (const log of receipt.logs) {
9153
- if (!sameIssuerAddress(log.address, intent.registryAddress) || log.removed || log.blockHash !== receipt.blockHash || log.blockNumber !== receipt.blockNumber || log.transactionHash?.toLowerCase() !== hash.toLowerCase())
9547
+ if (!sameIssuerAddress(log.address, intent.registryAddress) || log.removed || log.blockHash !== receipt.blockHash || log.blockNumber !== receipt.blockNumber || log.transactionHash?.toLowerCase() !== hash2.toLowerCase())
9154
9548
  continue;
9155
9549
  try {
9156
9550
  const { args } = viem.decodeEventLog({
@@ -9171,14 +9565,14 @@ function createSandboxWalletLinksNamespace(options) {
9171
9565
  const current = pending.get(keyFor(intent));
9172
9566
  if (current?.hash === void 0 && current?.stage === "sending" && result.status === "reverted") {
9173
9567
  try {
9174
- const tx = await client.getTransaction({ hash });
9568
+ const tx = await client.getTransaction({ hash: hash2 });
9175
9569
  await clientFor(intent.chainId);
9176
9570
  const decoded = viem.decodeFunctionData({ abi: sandboxWalletLinkAbi, data: tx.input });
9177
- exactTransaction = tx.hash.toLowerCase() === hash.toLowerCase() && tx.chainId === intent.chainId && sameIssuerAddress(tx.from, intent.existingWallet) && tx.to !== null && sameIssuerAddress(tx.to, intent.registryAddress) && tx.value === 0n && tx.nonce === senderNonce && tx.blockHash === receipt.blockHash && tx.blockNumber === receipt.blockNumber && decoded.functionName === "sandboxLinkWallet" && sameIssuerAddress(decoded.args[0], intent.newWallet) && decoded.args[1].toLowerCase() === intent.nonce.toLowerCase() && decoded.args[2] === intent.deadline;
9571
+ exactTransaction = tx.hash.toLowerCase() === hash2.toLowerCase() && tx.chainId === intent.chainId && sameIssuerAddress(tx.from, intent.existingWallet) && tx.to !== null && sameIssuerAddress(tx.to, intent.registryAddress) && tx.value === 0n && tx.nonce === senderNonce && tx.blockHash === receipt.blockHash && tx.blockNumber === receipt.blockNumber && decoded.functionName === "sandboxLinkWallet" && sameIssuerAddress(decoded.args[0], intent.newWallet) && decoded.args[1].toLowerCase() === intent.nonce.toLowerCase() && decoded.args[2] === intent.deadline;
9178
9572
  } catch {
9179
9573
  }
9180
9574
  }
9181
- if (current && pending.get(keyFor(intent)) === current && sameIntent(current.intent, intent) && (current.hash?.toLowerCase() === hash.toLowerCase() || current.hash === void 0 && current.stage === "sending" && current.senderNonce === senderNonce && exactTransaction) && (result.status === "confirmed" || result.status === "reverted" || result.status === "replaced"))
9575
+ if (current && pending.get(keyFor(intent)) === current && sameIntent(current.intent, intent) && (current.hash?.toLowerCase() === hash2.toLowerCase() || current.hash === void 0 && current.stage === "sending" && current.senderNonce === senderNonce && exactTransaction) && (result.status === "confirmed" || result.status === "reverted" || result.status === "replaced"))
9182
9576
  pending.delete(keyFor(intent));
9183
9577
  return result;
9184
9578
  }
@@ -9415,135 +9809,135 @@ function restoreSandboxLinkedWallet(input, options) {
9415
9809
 
9416
9810
  Object.defineProperty(exports, "SANDBOX_CHAIN_ID", {
9417
9811
  enumerable: true,
9418
- get: function () { return chunkGMPQFX25_cjs.SANDBOX_CHAIN_ID; }
9812
+ get: function () { return chunkGUTZXV5S_cjs.SANDBOX_CHAIN_ID; }
9419
9813
  });
9420
9814
  Object.defineProperty(exports, "SANDBOX_DEPLOYMENTS", {
9421
9815
  enumerable: true,
9422
- get: function () { return chunkGMPQFX25_cjs.SANDBOX_DEPLOYMENTS; }
9816
+ get: function () { return chunkGUTZXV5S_cjs.SANDBOX_DEPLOYMENTS; }
9423
9817
  });
9424
9818
  Object.defineProperty(exports, "SANDBOX_IMPLEMENTATION_VERSION", {
9425
9819
  enumerable: true,
9426
- get: function () { return chunkGMPQFX25_cjs.SANDBOX_IMPLEMENTATION_VERSION; }
9820
+ get: function () { return chunkGUTZXV5S_cjs.SANDBOX_IMPLEMENTATION_VERSION; }
9427
9821
  });
9428
9822
  Object.defineProperty(exports, "SANDBOX_TRAIT_IDS", {
9429
9823
  enumerable: true,
9430
- get: function () { return chunkGMPQFX25_cjs.SANDBOX_TRAIT_IDS; }
9824
+ get: function () { return chunkGUTZXV5S_cjs.SANDBOX_TRAIT_IDS; }
9431
9825
  });
9432
9826
  Object.defineProperty(exports, "SEPOLIA_CHAIN_ID", {
9433
9827
  enumerable: true,
9434
- get: function () { return chunkGMPQFX25_cjs.SEPOLIA_CHAIN_ID; }
9828
+ get: function () { return chunkGUTZXV5S_cjs.SEPOLIA_CHAIN_ID; }
9435
9829
  });
9436
9830
  Object.defineProperty(exports, "SEPOLIA_SANDBOX_MANIFEST", {
9437
9831
  enumerable: true,
9438
- get: function () { return chunkGMPQFX25_cjs.SEPOLIA_SANDBOX_MANIFEST; }
9832
+ get: function () { return chunkGUTZXV5S_cjs.SEPOLIA_SANDBOX_MANIFEST; }
9439
9833
  });
9440
9834
  Object.defineProperty(exports, "assertDocumentMatchesHash", {
9441
9835
  enumerable: true,
9442
- get: function () { return chunkGMPQFX25_cjs.assertDocumentMatchesHash; }
9836
+ get: function () { return chunkGUTZXV5S_cjs.assertDocumentMatchesHash; }
9443
9837
  });
9444
9838
  Object.defineProperty(exports, "buildAttestDocumentTransaction", {
9445
9839
  enumerable: true,
9446
- get: function () { return chunkGMPQFX25_cjs.buildAttestDocumentTransaction; }
9840
+ get: function () { return chunkGUTZXV5S_cjs.buildAttestDocumentTransaction; }
9447
9841
  });
9448
9842
  Object.defineProperty(exports, "buildDocumentAcceptanceTypedData", {
9449
9843
  enumerable: true,
9450
- get: function () { return chunkGMPQFX25_cjs.buildDocumentAcceptanceTypedData; }
9844
+ get: function () { return chunkGUTZXV5S_cjs.buildDocumentAcceptanceTypedData; }
9451
9845
  });
9452
9846
  Object.defineProperty(exports, "buildSandboxAddSelfTransaction", {
9453
9847
  enumerable: true,
9454
- get: function () { return chunkGMPQFX25_cjs.buildSandboxAddSelfTransaction; }
9848
+ get: function () { return chunkGUTZXV5S_cjs.buildSandboxAddSelfTransaction; }
9455
9849
  });
9456
9850
  Object.defineProperty(exports, "buildSandboxRegisterIssuerTransaction", {
9457
9851
  enumerable: true,
9458
- get: function () { return chunkGMPQFX25_cjs.buildSandboxRegisterIssuerTransaction; }
9852
+ get: function () { return chunkGUTZXV5S_cjs.buildSandboxRegisterIssuerTransaction; }
9459
9853
  });
9460
9854
  Object.defineProperty(exports, "buildSandboxSetSelfTraitTransaction", {
9461
9855
  enumerable: true,
9462
- get: function () { return chunkGMPQFX25_cjs.buildSandboxSetSelfTraitTransaction; }
9856
+ get: function () { return chunkGUTZXV5S_cjs.buildSandboxSetSelfTraitTransaction; }
9463
9857
  });
9464
9858
  Object.defineProperty(exports, "documentAttestorAbi", {
9465
9859
  enumerable: true,
9466
- get: function () { return chunkGMPQFX25_cjs.documentAttestorAbi; }
9860
+ get: function () { return chunkGUTZXV5S_cjs.documentAttestorAbi; }
9467
9861
  });
9468
9862
  Object.defineProperty(exports, "documentTraitId", {
9469
9863
  enumerable: true,
9470
- get: function () { return chunkGMPQFX25_cjs.documentTraitId; }
9864
+ get: function () { return chunkGUTZXV5S_cjs.documentTraitId; }
9471
9865
  });
9472
9866
  Object.defineProperty(exports, "getSandboxDeployment", {
9473
9867
  enumerable: true,
9474
- get: function () { return chunkGMPQFX25_cjs.getSandboxDeployment; }
9868
+ get: function () { return chunkGUTZXV5S_cjs.getSandboxDeployment; }
9475
9869
  });
9476
9870
  Object.defineProperty(exports, "hashDocument", {
9477
9871
  enumerable: true,
9478
- get: function () { return chunkGMPQFX25_cjs.hashDocument; }
9872
+ get: function () { return chunkGUTZXV5S_cjs.hashDocument; }
9479
9873
  });
9480
9874
  Object.defineProperty(exports, "hashDocumentAcceptance", {
9481
9875
  enumerable: true,
9482
- get: function () { return chunkGMPQFX25_cjs.hashDocumentAcceptance; }
9876
+ get: function () { return chunkGUTZXV5S_cjs.hashDocumentAcceptance; }
9483
9877
  });
9484
9878
  Object.defineProperty(exports, "probeSandboxRegistry", {
9485
9879
  enumerable: true,
9486
- get: function () { return chunkGMPQFX25_cjs.probeSandboxRegistry; }
9880
+ get: function () { return chunkGUTZXV5S_cjs.probeSandboxRegistry; }
9487
9881
  });
9488
9882
  Object.defineProperty(exports, "requireSandboxDeployment", {
9489
9883
  enumerable: true,
9490
- get: function () { return chunkGMPQFX25_cjs.requireSandboxDeployment; }
9884
+ get: function () { return chunkGUTZXV5S_cjs.requireSandboxDeployment; }
9491
9885
  });
9492
9886
  Object.defineProperty(exports, "sandboxAllowlistRegistryAbi", {
9493
9887
  enumerable: true,
9494
- get: function () { return chunkGMPQFX25_cjs.sandboxAllowlistRegistryAbi; }
9888
+ get: function () { return chunkGUTZXV5S_cjs.sandboxAllowlistRegistryAbi; }
9495
9889
  });
9496
9890
  Object.defineProperty(exports, "sandboxUserId", {
9497
9891
  enumerable: true,
9498
- get: function () { return chunkGMPQFX25_cjs.sandboxUserId; }
9892
+ get: function () { return chunkGUTZXV5S_cjs.sandboxUserId; }
9499
9893
  });
9500
9894
  Object.defineProperty(exports, "toEip1193Json", {
9501
9895
  enumerable: true,
9502
- get: function () { return chunkGMPQFX25_cjs.toEip1193Json; }
9896
+ get: function () { return chunkGUTZXV5S_cjs.toEip1193Json; }
9503
9897
  });
9504
9898
  Object.defineProperty(exports, "toEip1193TypedData", {
9505
9899
  enumerable: true,
9506
- get: function () { return chunkGMPQFX25_cjs.toEip1193TypedData; }
9900
+ get: function () { return chunkGUTZXV5S_cjs.toEip1193TypedData; }
9507
9901
  });
9508
9902
  Object.defineProperty(exports, "toEip712Json", {
9509
9903
  enumerable: true,
9510
- get: function () { return chunkGMPQFX25_cjs.toEip712Json; }
9904
+ get: function () { return chunkGUTZXV5S_cjs.toEip712Json; }
9511
9905
  });
9512
9906
  Object.defineProperty(exports, "toEip712JsonPayload", {
9513
9907
  enumerable: true,
9514
- get: function () { return chunkGMPQFX25_cjs.toEip712JsonPayload; }
9908
+ get: function () { return chunkGUTZXV5S_cjs.toEip712JsonPayload; }
9515
9909
  });
9516
9910
  Object.defineProperty(exports, "toEthersTypedData", {
9517
9911
  enumerable: true,
9518
- get: function () { return chunkGMPQFX25_cjs.toEthersTypedData; }
9912
+ get: function () { return chunkGUTZXV5S_cjs.toEthersTypedData; }
9519
9913
  });
9520
9914
  Object.defineProperty(exports, "toJsonRpcTransaction", {
9521
9915
  enumerable: true,
9522
- get: function () { return chunkGMPQFX25_cjs.toJsonRpcTransaction; }
9916
+ get: function () { return chunkGUTZXV5S_cjs.toJsonRpcTransaction; }
9523
9917
  });
9524
9918
  Object.defineProperty(exports, "toSandboxAddSelfWriteContractRequest", {
9525
9919
  enumerable: true,
9526
- get: function () { return chunkGMPQFX25_cjs.toSandboxAddSelfWriteContractRequest; }
9920
+ get: function () { return chunkGUTZXV5S_cjs.toSandboxAddSelfWriteContractRequest; }
9527
9921
  });
9528
9922
  Object.defineProperty(exports, "toSandboxRegisterIssuerWriteContractRequest", {
9529
9923
  enumerable: true,
9530
- get: function () { return chunkGMPQFX25_cjs.toSandboxRegisterIssuerWriteContractRequest; }
9924
+ get: function () { return chunkGUTZXV5S_cjs.toSandboxRegisterIssuerWriteContractRequest; }
9531
9925
  });
9532
9926
  Object.defineProperty(exports, "toSandboxSetSelfTraitWriteContractRequest", {
9533
9927
  enumerable: true,
9534
- get: function () { return chunkGMPQFX25_cjs.toSandboxSetSelfTraitWriteContractRequest; }
9928
+ get: function () { return chunkGUTZXV5S_cjs.toSandboxSetSelfTraitWriteContractRequest; }
9535
9929
  });
9536
9930
  Object.defineProperty(exports, "toViemTypedData", {
9537
9931
  enumerable: true,
9538
- get: function () { return chunkGMPQFX25_cjs.toViemTypedData; }
9932
+ get: function () { return chunkGUTZXV5S_cjs.toViemTypedData; }
9539
9933
  });
9540
9934
  Object.defineProperty(exports, "toWriteContractRequest", {
9541
9935
  enumerable: true,
9542
- get: function () { return chunkGMPQFX25_cjs.toWriteContractRequest; }
9936
+ get: function () { return chunkGUTZXV5S_cjs.toWriteContractRequest; }
9543
9937
  });
9544
9938
  Object.defineProperty(exports, "verifyAttestationSession", {
9545
9939
  enumerable: true,
9546
- get: function () { return chunkGMPQFX25_cjs.verifyAttestationSession; }
9940
+ get: function () { return chunkGUTZXV5S_cjs.verifyAttestationSession; }
9547
9941
  });
9548
9942
  Object.defineProperty(exports, "DOCUMENT_ACCEPTANCE_PRIMARY_TYPE", {
9549
9943
  enumerable: true,
@@ -9683,6 +10077,7 @@ exports.prepareSandboxUser = prepareSandboxUser;
9683
10077
  exports.purchasePaymentTokenAbi = purchasePaymentTokenAbi;
9684
10078
  exports.purchaseRegistryAbi = purchaseRegistryAbi;
9685
10079
  exports.purchaseSecurityTokenAbi = purchaseSecurityTokenAbi;
10080
+ exports.resolveIssuerDeployment = resolveIssuerDeployment;
9686
10081
  exports.resolveSandboxUserTraits = resolveSandboxUserTraits;
9687
10082
  exports.restoreSandboxLinkedWallet = restoreSandboxLinkedWallet;
9688
10083
  exports.restoreSandboxUserWallet = restoreSandboxUserWallet;