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/README.md +12 -2
- package/dist/{chunk-7ODYBEZH.js → chunk-F73OBTKE.js} +2 -2
- package/dist/{chunk-7ODYBEZH.js.map → chunk-F73OBTKE.js.map} +1 -1
- package/dist/{chunk-GMPQFX25.cjs → chunk-GUTZXV5S.cjs} +2 -2
- package/dist/{chunk-GMPQFX25.cjs.map → chunk-GUTZXV5S.cjs.map} +1 -1
- package/dist/documents/index.cjs +33 -33
- package/dist/documents/index.d.cts +6 -6
- package/dist/documents/index.d.ts +6 -6
- package/dist/documents/index.js +1 -1
- package/dist/index-B8xCRZt1.d.cts +452 -0
- package/dist/index-g1WcqTfP.d.ts +452 -0
- package/dist/index.cjs +493 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +182 -130
- package/dist/index.d.ts +182 -130
- package/dist/index.js +453 -59
- package/dist/index.js.map +1 -1
- package/dist/subgraph.d.cts +4 -415
- package/dist/subgraph.d.ts +4 -415
- package/package.json +1 -1
- package/dist/transport-0_X4HTI6.d.ts +0 -39
- package/dist/transport-uaC5Yl3p.d.cts +0 -39
package/dist/index.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { SEPOLIA_SANDBOX_MANIFEST, sandboxUserId } from './chunk-
|
|
2
|
-
export { SANDBOX_CHAIN_ID, SANDBOX_DEPLOYMENTS, SANDBOX_IMPLEMENTATION_VERSION, SANDBOX_TRAIT_IDS, SEPOLIA_CHAIN_ID, SEPOLIA_SANDBOX_MANIFEST, assertDocumentMatchesHash, buildAttestDocumentTransaction, buildDocumentAcceptanceTypedData, buildSandboxAddSelfTransaction, buildSandboxRegisterIssuerTransaction, buildSandboxSetSelfTraitTransaction, documentAttestorAbi, documentTraitId, getSandboxDeployment, hashDocument, hashDocumentAcceptance, probeSandboxRegistry, requireSandboxDeployment, sandboxAllowlistRegistryAbi, sandboxUserId, toEip1193Json, toEip1193TypedData, toEip712Json, toEip712JsonPayload, toEthersTypedData, toJsonRpcTransaction, toSandboxAddSelfWriteContractRequest, toSandboxRegisterIssuerWriteContractRequest, toSandboxSetSelfTraitWriteContractRequest, toViemTypedData, toWriteContractRequest, verifyAttestationSession } from './chunk-
|
|
1
|
+
import { SEPOLIA_SANDBOX_MANIFEST, sandboxUserId } from './chunk-F73OBTKE.js';
|
|
2
|
+
export { SANDBOX_CHAIN_ID, SANDBOX_DEPLOYMENTS, SANDBOX_IMPLEMENTATION_VERSION, SANDBOX_TRAIT_IDS, SEPOLIA_CHAIN_ID, SEPOLIA_SANDBOX_MANIFEST, assertDocumentMatchesHash, buildAttestDocumentTransaction, buildDocumentAcceptanceTypedData, buildSandboxAddSelfTransaction, buildSandboxRegisterIssuerTransaction, buildSandboxSetSelfTraitTransaction, documentAttestorAbi, documentTraitId, getSandboxDeployment, hashDocument, hashDocumentAcceptance, probeSandboxRegistry, requireSandboxDeployment, sandboxAllowlistRegistryAbi, sandboxUserId, toEip1193Json, toEip1193TypedData, toEip712Json, toEip712JsonPayload, toEthersTypedData, toJsonRpcTransaction, toSandboxAddSelfWriteContractRequest, toSandboxRegisterIssuerWriteContractRequest, toSandboxSetSelfTraitWriteContractRequest, toViemTypedData, toWriteContractRequest, verifyAttestationSession } from './chunk-F73OBTKE.js';
|
|
3
3
|
export { DOCUMENT_ACCEPTANCE_PRIMARY_TYPE, DOCUMENT_ACCEPTANCE_TYPEHASH, DOCUMENT_ACCEPTANCE_TYPES, DOCUMENT_ATTESTOR_DOMAIN_NAME, DOCUMENT_ATTESTOR_DOMAIN_VERSION, ECDSA_SIGNATURE_BYTES, EIP712_DOMAIN_TYPE, MAX_ATTESTATION_LIFETIME_SECONDS } from './chunk-2STMWRIV.js';
|
|
4
4
|
import { OpacityIssuerError } from './chunk-54Q3MU62.js';
|
|
5
5
|
export { OpacityAttestationError, OpacityConfigError, OpacityIssuerError } from './chunk-54Q3MU62.js';
|
|
6
|
-
import { parseAbi, keccak256, stringToHex, isAddress, zeroAddress, getAddress, maxUint256, zeroHash, encodeFunctionData, encodeDeployData, encodeAbiParameters,
|
|
6
|
+
import { parseAbi, keccak256, stringToHex, isAddress, zeroAddress, getAddress, maxUint256, zeroHash, encodeFunctionData, encodeDeployData, encodeAbiParameters, TransactionReceiptNotFoundError, decodeEventLog, BaseError, ContractFunctionZeroDataError, ContractFunctionRevertedError, toBytes, defineChain, createWalletClient, custom, hashTypedData, ExecutionRevertedError, decodeFunctionData, decodeFunctionResult } from 'viem';
|
|
7
7
|
import { generatePrivateKey, privateKeyToAccount } from 'viem/accounts';
|
|
8
8
|
|
|
9
9
|
var securityTokenVaultAbi = parseAbi([
|
|
@@ -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
|
|
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
|
|
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
|
|
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() !==
|
|
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:
|
|
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
|
|
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
|
|
6266
|
-
if (typeof
|
|
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() !==
|
|
6298
|
-
submittedHash:
|
|
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() !==
|
|
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() !==
|
|
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 = decodeEventLog({
|
|
@@ -7199,6 +7199,368 @@ function createPolicyReplacementBatch(currentCount, policies) {
|
|
|
7199
7199
|
return createPolicyBatch(changes);
|
|
7200
7200
|
}
|
|
7201
7201
|
|
|
7202
|
+
// src/issuers/discovery.ts
|
|
7203
|
+
var discoveryAbi = 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 zeroAddress;
|
|
7226
|
+
if (typeof value !== "string" || !isAddress(value, { strict: false }) || !optional && value.toLowerCase() === 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 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 = 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 BaseError ? cause.walk(
|
|
7473
|
+
(error) => error instanceof ContractFunctionZeroDataError || error instanceof ContractFunctionRevertedError
|
|
7474
|
+
) : void 0;
|
|
7475
|
+
if (!(cause instanceof OpacityIssuerOperationError && cause.code === "deployment-mismatch") && !(unsupported instanceof ContractFunctionZeroDataError) && !(unsupported instanceof 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
7565
|
var { chainId: chainId3, addresses } = SEPOLIA_SANDBOX_MANIFEST;
|
|
7204
7566
|
var SANDBOX_ISSUER_DEPLOYMENT = Object.freeze({
|
|
@@ -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,
|
|
7642
|
+
async function requireCode(client, address5, blockNumber) {
|
|
7250
7643
|
const code = await client.getBytecode({
|
|
7251
|
-
address:
|
|
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 ${
|
|
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
|
|
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
|
|
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:
|
|
7735
|
-
if (replacementReason || receipt.transactionHash.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() ===
|
|
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
|
|
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:
|
|
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,
|
|
@@ -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
|
|
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:
|
|
8199
|
-
if (replacementReason || receipt.transactionHash.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() ===
|
|
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
|
|
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 =
|
|
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
|
|
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 =
|
|
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
|
|
9462
|
+
const hash2 = await wallet.sendTransaction({
|
|
9069
9463
|
account: wallet.account ?? intent.existingWallet,
|
|
9070
9464
|
chain: wallet.chain ?? 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(
|
|
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
|
|
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:
|
|
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() !==
|
|
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 = 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() ===
|
|
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() !==
|
|
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 } = 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 = decodeFunctionData({ abi: sandboxWalletLinkAbi, data: tx.input });
|
|
9177
|
-
exactTransaction = tx.hash.toLowerCase() ===
|
|
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() ===
|
|
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
|
}
|
|
@@ -9413,6 +9807,6 @@ function restoreSandboxLinkedWallet(input, options) {
|
|
|
9413
9807
|
);
|
|
9414
9808
|
}
|
|
9415
9809
|
|
|
9416
|
-
export { DEFAULT_ISSUER_BEACON_VARIANT, EMPTY_ISSUER_ENGINE, ISSUER_CONTRACTS_COMMIT, ISSUER_CONTRACTS_PR, IssuerDenominatorMode, IssuerGuardMode, IssuerRuleType, OpacityIssuerOperationError, OpacityPurchaseError, OpacityTransferError, SANDBOX_ISSUER_DEPLOYMENT, SANDBOX_PURCHASE_DEPLOYMENT, SandboxLinkedWalletCreationError, SandboxTransferError, SandboxUserCreationError, SandboxWalletLinkError, buildAdapterOperation, buildConfigureVaultTransaction, buildForcedTransferTransaction, buildIssuerAdapterDeployment, buildIssuerDeployTokenTransaction, buildIssuerSandboxAddSelfTransaction, buildIssuerSandboxRegisterIssuerTransaction, buildIssuerSandboxSetSelfTraitTransaction, buildIssuerSandboxVaultDeployment, buildIssuerTokenTraitRegistryDeployment, buildIssuerVaultDeployment, buildMintTransaction, buildOverrideOperation, buildOverrideTransferTransaction, buildOverrideTransferTypedData, buildPaymentTokenOperation, buildPolicyEngineOperation, buildPolicyModuleOperation, buildPolicyRegistryOperation, buildPurchaseTransaction, buildPurchaseWriteRequest, buildRuleSetOperation, buildSandboxRegistryOperation, buildSandboxVaultOperation, buildSandboxWalletLinkTransaction, buildSandboxWalletLinkTypedData, buildSetIssuerAdminTransaction, buildSetUserTraitsTransactions, buildSetWalletsTransaction, buildTokenMetadataTransactions, buildTokenOperation, buildTransferTransaction, buildTransferWriteRequest, buildVaultOperation, createIssuersNamespace, createPolicyAttachment, createPolicyBatch, createPolicyReplacementBatch, createPurchasesNamespace, createSandboxLinkedWallet, createSandboxUser, createSandboxWalletLinksNamespace, createTransfersNamespace, encodeAllowedTransfereeConfig, encodeCeilingBalanceConfig, encodeDenylistConfig, encodeFloorBalanceConfig, encodeHolderCountCapConfig, encodeInsiderFreezeConfig, encodeSelfTransferOnlyConfig, encodeTradingDisabledConfig, issuerAdapterAbi, issuerAdapterBytecode, issuerBeaconRegistryAbi, issuerFactoryAbi, issuerLensAbi, issuerOverrideHelperAbi, issuerOverrideTypes, issuerPaymentTokenAbi, issuerPolicyEngineAbi, issuerPolicyModuleAbis, issuerPolicyRegistryAbi, issuerPolicyTypes, issuerRegistryAbi, issuerRuleSetOrchestratorAbi, issuerSandboxVaultAbi, issuerSandboxVaultBytecode, issuerTokenAbi, issuerTokenTraitRegistryAbi, issuerTokenTraitRegistryBytecode, issuerVaultAbi, issuerVaultBytecode, parsePurchaseAmount, parseTransferAmount, prepareSandboxUser, purchasePaymentTokenAbi, purchaseRegistryAbi, purchaseSecurityTokenAbi, resolveSandboxUserTraits, restoreSandboxLinkedWallet, restoreSandboxUserWallet, sandboxJurisdictionTraitId, sandboxTraitId, sandboxWalletLinkAbi, sandboxWalletLinkTypes, securityTokenVaultAbi, transferSandboxUser, validateSandboxLinkedWalletProgress, validateSandboxWalletLinkIntent, validateSandboxWalletLinkParams, waitForSandboxUserFunding, walletLinkData, walletLinkWaitOptions };
|
|
9810
|
+
export { DEFAULT_ISSUER_BEACON_VARIANT, EMPTY_ISSUER_ENGINE, ISSUER_CONTRACTS_COMMIT, ISSUER_CONTRACTS_PR, IssuerDenominatorMode, IssuerGuardMode, IssuerRuleType, OpacityIssuerOperationError, OpacityPurchaseError, OpacityTransferError, SANDBOX_ISSUER_DEPLOYMENT, SANDBOX_PURCHASE_DEPLOYMENT, SandboxLinkedWalletCreationError, SandboxTransferError, SandboxUserCreationError, SandboxWalletLinkError, buildAdapterOperation, buildConfigureVaultTransaction, buildForcedTransferTransaction, buildIssuerAdapterDeployment, buildIssuerDeployTokenTransaction, buildIssuerSandboxAddSelfTransaction, buildIssuerSandboxRegisterIssuerTransaction, buildIssuerSandboxSetSelfTraitTransaction, buildIssuerSandboxVaultDeployment, buildIssuerTokenTraitRegistryDeployment, buildIssuerVaultDeployment, buildMintTransaction, buildOverrideOperation, buildOverrideTransferTransaction, buildOverrideTransferTypedData, buildPaymentTokenOperation, buildPolicyEngineOperation, buildPolicyModuleOperation, buildPolicyRegistryOperation, buildPurchaseTransaction, buildPurchaseWriteRequest, buildRuleSetOperation, buildSandboxRegistryOperation, buildSandboxVaultOperation, buildSandboxWalletLinkTransaction, buildSandboxWalletLinkTypedData, buildSetIssuerAdminTransaction, buildSetUserTraitsTransactions, buildSetWalletsTransaction, buildTokenMetadataTransactions, buildTokenOperation, buildTransferTransaction, buildTransferWriteRequest, buildVaultOperation, createIssuersNamespace, createPolicyAttachment, createPolicyBatch, createPolicyReplacementBatch, createPurchasesNamespace, createSandboxLinkedWallet, createSandboxUser, createSandboxWalletLinksNamespace, createTransfersNamespace, encodeAllowedTransfereeConfig, encodeCeilingBalanceConfig, encodeDenylistConfig, encodeFloorBalanceConfig, encodeHolderCountCapConfig, encodeInsiderFreezeConfig, encodeSelfTransferOnlyConfig, encodeTradingDisabledConfig, issuerAdapterAbi, issuerAdapterBytecode, issuerBeaconRegistryAbi, issuerFactoryAbi, issuerLensAbi, issuerOverrideHelperAbi, issuerOverrideTypes, issuerPaymentTokenAbi, issuerPolicyEngineAbi, issuerPolicyModuleAbis, issuerPolicyRegistryAbi, issuerPolicyTypes, issuerRegistryAbi, issuerRuleSetOrchestratorAbi, issuerSandboxVaultAbi, issuerSandboxVaultBytecode, issuerTokenAbi, issuerTokenTraitRegistryAbi, issuerTokenTraitRegistryBytecode, issuerVaultAbi, issuerVaultBytecode, parsePurchaseAmount, parseTransferAmount, prepareSandboxUser, purchasePaymentTokenAbi, purchaseRegistryAbi, purchaseSecurityTokenAbi, resolveIssuerDeployment, resolveSandboxUserTraits, restoreSandboxLinkedWallet, restoreSandboxUserWallet, sandboxJurisdictionTraitId, sandboxTraitId, sandboxWalletLinkAbi, sandboxWalletLinkTypes, securityTokenVaultAbi, transferSandboxUser, validateSandboxLinkedWalletProgress, validateSandboxWalletLinkIntent, validateSandboxWalletLinkParams, waitForSandboxUserFunding, walletLinkData, walletLinkWaitOptions };
|
|
9417
9811
|
//# sourceMappingURL=index.js.map
|
|
9418
9812
|
//# sourceMappingURL=index.js.map
|