@rareprotocol/rare-cli 1.1.0 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -292,7 +292,7 @@ Error: ${message}`);
292
292
 
293
293
  // src/program.ts
294
294
  import { createInterface as createInterface7 } from "readline/promises";
295
- import { Command as Command22 } from "commander";
295
+ import { Command as Command23 } from "commander";
296
296
 
297
297
  // src/commands/configure.ts
298
298
  import { text } from "stream/consumers";
@@ -338,6 +338,7 @@ var contractAddresses = {
338
338
  sepolia: {
339
339
  factory: getAddress("0x3c7526a0975156299ceef369b8ff3c01cc670523"),
340
340
  auction: getAddress("0xC8Edc7049b233641ad3723D6C60019D1c8771612"),
341
+ rareBridge: getAddress("0xdC168291658f6C5F1D0b33E573c4d289DCA9dD08"),
341
342
  sovereignFactory: getAddress("0x46B2850ba7787734F648A6848b5eDE0815C1F8Bf"),
342
343
  lazySovereignFactory: getAddress("0xc5B8Ad9003673a23d005A6448C74d8955a1a38fA"),
343
344
  rareMinter: getAddress("0xd28Dc0B89104d7BBd902F338a0193fF063617ccE"),
@@ -355,6 +356,7 @@ var contractAddresses = {
355
356
  mainnet: {
356
357
  factory: getAddress("0xAe8E375a268Ed6442bEaC66C6254d6De5AeD4aB1"),
357
358
  auction: getAddress("0x6D7c44773C52D396F43c2D511B81aa168E9a7a42"),
359
+ rareBridge: getAddress("0x88135dd0e7a8a2e42272dda89849a997ce2e83f7"),
358
360
  sovereignFactory: getAddress("0xe980ec62378529d95ba446433f4deb6324129c59"),
359
361
  lazySovereignFactory: getAddress("0xba798BD606d86D207ca2751510173532899117a1"),
360
362
  rareMinter: getAddress("0x5fa112EFeD8297bec0010b312208d223E0cE891E"),
@@ -365,19 +367,27 @@ var contractAddresses = {
365
367
  marketplaceSettings: getAddress("0x61DBF87164d33FD3695256DC8Ba74D3B1d304170"),
366
368
  erc20ApprovalManager: getAddress("0xa837a7eAff154Ab837617Cf7250648D3Ec0A4436"),
367
369
  erc721ApprovalManager: getAddress("0x4bb0Deea6d1A30C601338aAB776d394C2AE5c0F8"),
368
- liquidFactory: getAddress("0xbb4341CFd588a098e9aCE1D224178836426c4a8E"),
370
+ liquidFactory: getAddress("0x25f993C222fE5e891128a782A5168f1C78629540"),
369
371
  swapRouter: getAddress("0xEBd58EdA8408d9EA409f2c2bE8898BD9738f3583"),
370
372
  v4Quoter: getAddress("0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203")
371
373
  },
372
374
  base: {
373
375
  factory: getAddress("0xf776204233bfb52ba0ddff24810cbdbf3dbf94dd"),
374
- auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2")
376
+ auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2"),
377
+ rareBridge: getAddress("0x3b41e21094611d152a08d3691a70837f1a077dae")
375
378
  },
376
379
  "base-sepolia": {
377
380
  factory: getAddress("0x2b181ae0f1aea6fed75591b04991b1a3f9868d51"),
378
- auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2")
381
+ auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2"),
382
+ rareBridge: getAddress("0xca491bb62A7730E97F500510132C47633DDD0229")
379
383
  }
380
384
  };
385
+ var ccipChainSelectors = {
386
+ mainnet: 5009297550715157269n,
387
+ sepolia: 16015286601757825753n,
388
+ base: 15971525489660198786n,
389
+ "base-sepolia": 10344971235874465080n
390
+ };
381
391
  var canonicalV4Pools = {
382
392
  sepolia: {
383
393
  rareEthPool: {
@@ -527,6 +537,16 @@ function getCanonicalV4Pools(chain) {
527
537
  }
528
538
  return pools;
529
539
  }
540
+ function getRareBridgeAddress(chain) {
541
+ const address = getContractAddresses(chain).rareBridge;
542
+ if (!address) {
543
+ throw new Error(`RareBridge is not configured on "${chain}". Supported RareBridge chains: mainnet, sepolia, base, base-sepolia.`);
544
+ }
545
+ return address;
546
+ }
547
+ function getCcipChainSelector(chain) {
548
+ return ccipChainSelectors[chain];
549
+ }
530
550
  function isSupportedChain(value) {
531
551
  return supportedChains.some((chain) => chain === value);
532
552
  }
@@ -1176,8 +1196,12 @@ import createClient from "openapi-fetch";
1176
1196
 
1177
1197
  // src/data-access/base-url.ts
1178
1198
  var DEFAULT_RARE_API_BASE_URL = "https://api.superrare.com";
1199
+ function normalizeRareApiBaseUrlCandidate(baseUrl) {
1200
+ const trimmedBaseUrl = baseUrl?.trim();
1201
+ return trimmedBaseUrl === "" ? void 0 : trimmedBaseUrl;
1202
+ }
1179
1203
  function resolveRareApiBaseUrl(baseUrl) {
1180
- return process.env.RARE_API_BASE_URL ?? baseUrl ?? DEFAULT_RARE_API_BASE_URL;
1204
+ return normalizeRareApiBaseUrlCandidate(process.env.RARE_API_BASE_URL) ?? normalizeRareApiBaseUrlCandidate(baseUrl) ?? DEFAULT_RARE_API_BASE_URL;
1181
1205
  }
1182
1206
 
1183
1207
  // src/data-access/client.ts
@@ -4418,6 +4442,50 @@ var auctionAbi = [
4418
4442
  ];
4419
4443
 
4420
4444
  // src/sdk/approvals-shell.ts
4445
+ var ApprovalSideEffectError = class extends Error {
4446
+ operation;
4447
+ approvals;
4448
+ constructor(params) {
4449
+ super(
4450
+ `${approvalSummary(params.approvals)} before ${params.operation}, but ${params.operation} did not complete. The approval remains valid; retry the operation or revoke approval if it should not remain active.`,
4451
+ { cause: params.cause }
4452
+ );
4453
+ this.name = "ApprovalSideEffectError";
4454
+ this.operation = params.operation;
4455
+ this.approvals = params.approvals;
4456
+ }
4457
+ };
4458
+ async function runWithApprovalSideEffectAlert(params) {
4459
+ try {
4460
+ return await params.run();
4461
+ } catch (error) {
4462
+ const approvals = params.approvals.filter(hasApprovalTxHash);
4463
+ if (approvals.length === 0) {
4464
+ throw error;
4465
+ }
4466
+ throw new ApprovalSideEffectError({
4467
+ operation: params.operation,
4468
+ approvals,
4469
+ cause: error
4470
+ });
4471
+ }
4472
+ }
4473
+ function hasApprovalTxHash(approval) {
4474
+ return approval.approvalTxHash !== void 0;
4475
+ }
4476
+ function approvalSummary(approvals) {
4477
+ const [approval] = approvals;
4478
+ return approvals.length === 1 && approval !== void 0 ? `Approval transaction ${approval.approvalTxHash} was mined (${approvalDetails(approval)})` : `Approval transactions were mined: ${approvals.map((sideEffect) => `${sideEffect.approvalTxHash} (${approvalDetails(sideEffect)})`).join(", ")}`;
4479
+ }
4480
+ function approvalDetails(approval) {
4481
+ if (approval.type === "erc20" || approval.type === "erc20-reset") {
4482
+ return `${approval.type}; token ${approval.target}; spender ${approval.spender ?? "unknown"}`;
4483
+ }
4484
+ if (approval.type === "minter") {
4485
+ return `minter; collection ${approval.target}; minter ${approval.minter ?? "unknown"}`;
4486
+ }
4487
+ return `nft; contract ${approval.target}; operator ${approval.operator ?? "unknown"}`;
4488
+ }
4421
4489
  var approvalAbi = [
4422
4490
  {
4423
4491
  inputs: [{ name: "owner", type: "address" }, { name: "operator", type: "address" }],
@@ -4570,7 +4638,7 @@ async function toTokenAmount(publicClient, token, value, field) {
4570
4638
  }
4571
4639
  async function ensureTokenAllowance(publicClient, walletClient, account, owner, token, spender, amount) {
4572
4640
  if (isAddressEqual5(token, ETH_ADDRESS) || amount === 0n) {
4573
- return;
4641
+ return void 0;
4574
4642
  }
4575
4643
  const allowance = await publicClient.readContract({
4576
4644
  address: token,
@@ -4579,7 +4647,7 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
4579
4647
  args: [owner, spender]
4580
4648
  });
4581
4649
  if (allowance >= amount) {
4582
- return;
4650
+ return void 0;
4583
4651
  }
4584
4652
  const approveTx = await walletClient.writeContract({
4585
4653
  address: token,
@@ -4589,7 +4657,14 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
4589
4657
  account,
4590
4658
  chain: void 0
4591
4659
  });
4592
- await publicClient.waitForTransactionReceipt({ hash: approveTx });
4660
+ await confirmErc20Approval(publicClient, {
4661
+ approvalTxHash: approveTx,
4662
+ currency: token,
4663
+ accountAddress: owner,
4664
+ spenderAddress: spender,
4665
+ requiredAmount: amount
4666
+ });
4667
+ return approveTx;
4593
4668
  }
4594
4669
  var PaymentApprovalRequiredError = class extends Error {
4595
4670
  requiredAmount;
@@ -4662,7 +4737,13 @@ async function preparePaymentAmountForSpender(opts) {
4662
4737
  account,
4663
4738
  chain: void 0
4664
4739
  });
4665
- await publicClient.waitForTransactionReceipt({ hash: approvalTxHash });
4740
+ await confirmErc20Approval(publicClient, {
4741
+ approvalTxHash,
4742
+ currency,
4743
+ accountAddress,
4744
+ spenderAddress,
4745
+ requiredAmount
4746
+ });
4666
4747
  return {
4667
4748
  value: 0n,
4668
4749
  requiredAmount,
@@ -4700,6 +4781,23 @@ async function readAllowance(publicClient, currency, accountAddress, spenderAddr
4700
4781
  args: [accountAddress, spenderAddress]
4701
4782
  });
4702
4783
  }
4784
+ async function confirmErc20Approval(publicClient, params) {
4785
+ const receipt = await publicClient.waitForTransactionReceipt({ hash: params.approvalTxHash });
4786
+ if (receipt.status !== "success") {
4787
+ throw new Error(`ERC20 approval transaction ${params.approvalTxHash} did not succeed.`);
4788
+ }
4789
+ const allowance = await readAllowance(
4790
+ publicClient,
4791
+ params.currency,
4792
+ params.accountAddress,
4793
+ params.spenderAddress
4794
+ );
4795
+ if (allowance < params.requiredAmount) {
4796
+ throw new Error(
4797
+ `ERC20 approval transaction ${params.approvalTxHash} was mined but allowance for spender ${params.spenderAddress} is ${allowance.toString()} raw units, below the required ${params.requiredAmount.toString()} raw units.`
4798
+ );
4799
+ }
4800
+ }
4703
4801
 
4704
4802
  // src/sdk/validation-core.ts
4705
4803
  import { isHex } from "viem";
@@ -5133,6 +5231,11 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
5133
5231
  accountAddress,
5134
5232
  currentUnixTimestamp()
5135
5233
  );
5234
+ const auctionType = await publicClient.readContract({
5235
+ address: addresses.auction,
5236
+ abi: auctionAbi,
5237
+ functionName: plan.auctionType === "scheduled" ? "SCHEDULED_AUCTION" : "COLDIE_AUCTION"
5238
+ });
5136
5239
  const approvalTxHash = await approveNftContractIfNeeded({
5137
5240
  publicClient,
5138
5241
  walletClient,
@@ -5142,30 +5245,37 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
5142
5245
  operator: addresses.auction,
5143
5246
  autoApprove: params.autoApprove
5144
5247
  });
5145
- const auctionType = await publicClient.readContract({
5146
- address: addresses.auction,
5147
- abi: auctionAbi,
5148
- functionName: plan.auctionType === "scheduled" ? "SCHEDULED_AUCTION" : "COLDIE_AUCTION"
5149
- });
5150
- const txHash = await walletClient.writeContract({
5151
- address: addresses.auction,
5152
- abi: auctionAbi,
5153
- functionName: "configureAuction",
5154
- args: [
5155
- auctionType,
5156
- plan.nftAddress,
5157
- plan.tokenId,
5158
- plan.startingPrice,
5159
- plan.currency,
5160
- plan.duration,
5161
- plan.startTime,
5162
- plan.splitAddresses,
5163
- plan.splitRatios
5164
- ],
5165
- account,
5166
- chain: void 0
5248
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5249
+ operation: "auction create",
5250
+ approvals: [{
5251
+ type: "nft",
5252
+ approvalTxHash,
5253
+ target: plan.nftAddress,
5254
+ operator: addresses.auction
5255
+ }],
5256
+ run: async () => {
5257
+ const targetTxHash = await walletClient.writeContract({
5258
+ address: addresses.auction,
5259
+ abi: auctionAbi,
5260
+ functionName: "configureAuction",
5261
+ args: [
5262
+ auctionType,
5263
+ plan.nftAddress,
5264
+ plan.tokenId,
5265
+ plan.startingPrice,
5266
+ plan.currency,
5267
+ plan.duration,
5268
+ plan.startTime,
5269
+ plan.splitAddresses,
5270
+ plan.splitRatios
5271
+ ],
5272
+ account,
5273
+ chain: void 0
5274
+ });
5275
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5276
+ return { txHash: targetTxHash, receipt: targetReceipt };
5277
+ }
5167
5278
  });
5168
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5169
5279
  return {
5170
5280
  txHash,
5171
5281
  receipt,
@@ -5191,22 +5301,34 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
5191
5301
  amount: plan.amount,
5192
5302
  autoApprove: params.autoApprove
5193
5303
  });
5194
- const txHash = await walletClient.writeContract({
5195
- address: addresses.auction,
5196
- abi: auctionAbi,
5197
- functionName: "bid",
5198
- args: [params.contract, plan.tokenId, plan.currency, plan.amount],
5199
- account,
5200
- chain: void 0,
5201
- value: payment.value
5304
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5305
+ operation: "auction bid",
5306
+ approvals: [{
5307
+ type: "erc20",
5308
+ approvalTxHash: payment.approvalTxHash,
5309
+ target: plan.currency,
5310
+ spender: addresses.auction
5311
+ }],
5312
+ run: async () => {
5313
+ const targetTxHash = await walletClient.writeContract({
5314
+ address: addresses.auction,
5315
+ abi: auctionAbi,
5316
+ functionName: "bid",
5317
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount],
5318
+ account,
5319
+ chain: void 0,
5320
+ value: payment.value
5321
+ });
5322
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5323
+ return { txHash: targetTxHash, receipt: targetReceipt };
5324
+ }
5202
5325
  });
5203
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5204
5326
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
5205
5327
  },
5206
5328
  async settle(params) {
5207
5329
  const { walletClient, account } = requireWallet(config);
5208
5330
  const plan = planAuctionTokenAction(params);
5209
- const txHash = await walletClient.writeContract({
5331
+ const targetTxHash = await walletClient.writeContract({
5210
5332
  address: addresses.auction,
5211
5333
  abi: auctionAbi,
5212
5334
  functionName: "settleAuction",
@@ -5214,13 +5336,13 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
5214
5336
  account,
5215
5337
  chain: void 0
5216
5338
  });
5217
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5218
- return { txHash, receipt };
5339
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5340
+ return { txHash: targetTxHash, receipt: targetReceipt };
5219
5341
  },
5220
5342
  async cancel(params) {
5221
5343
  const { walletClient, account } = requireWallet(config);
5222
5344
  const plan = planAuctionTokenAction(params);
5223
- const txHash = await walletClient.writeContract({
5345
+ const targetTxHash = await walletClient.writeContract({
5224
5346
  address: addresses.auction,
5225
5347
  abi: auctionAbi,
5226
5348
  functionName: "cancelAuction",
@@ -5228,8 +5350,8 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
5228
5350
  account,
5229
5351
  chain: void 0
5230
5352
  });
5231
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5232
- return { txHash, receipt };
5353
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5354
+ return { txHash: targetTxHash, receipt: targetReceipt };
5233
5355
  },
5234
5356
  async status(params) {
5235
5357
  const plan = planAuctionTokenAction(params);
@@ -5306,23 +5428,35 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
5306
5428
  amount: plan.amount,
5307
5429
  autoApprove: params.autoApprove
5308
5430
  });
5309
- const txHash = await walletClient.writeContract({
5310
- address: addresses.auction,
5311
- abi: auctionAbi,
5312
- functionName: "offer",
5313
- args: [params.contract, plan.tokenId, plan.currency, plan.amount, false],
5314
- account,
5315
- chain: void 0,
5316
- value: payment.value
5431
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5432
+ operation: "offer create",
5433
+ approvals: [{
5434
+ type: "erc20",
5435
+ approvalTxHash: payment.approvalTxHash,
5436
+ target: plan.currency,
5437
+ spender: addresses.auction
5438
+ }],
5439
+ run: async () => {
5440
+ const targetTxHash = await walletClient.writeContract({
5441
+ address: addresses.auction,
5442
+ abi: auctionAbi,
5443
+ functionName: "offer",
5444
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount, false],
5445
+ account,
5446
+ chain: void 0,
5447
+ value: payment.value
5448
+ });
5449
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5450
+ return { txHash: targetTxHash, receipt: targetReceipt };
5451
+ }
5317
5452
  });
5318
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5319
5453
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
5320
5454
  },
5321
5455
  async cancel(params) {
5322
5456
  const { walletClient, account } = requireWallet(config);
5323
5457
  const currency = params.currency === void 0 ? ETH_ADDRESS : resolveCurrencyForSdk(params.currency, chain).address;
5324
5458
  const plan = planOfferCancel({ ...params, currency });
5325
- const txHash = await walletClient.writeContract({
5459
+ const targetTxHash = await walletClient.writeContract({
5326
5460
  address: addresses.auction,
5327
5461
  abi: auctionAbi,
5328
5462
  functionName: "cancelOffer",
@@ -5330,8 +5464,8 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
5330
5464
  account,
5331
5465
  chain: void 0
5332
5466
  });
5333
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5334
- return { txHash, receipt };
5467
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5468
+ return { txHash: targetTxHash, receipt: targetReceipt };
5335
5469
  },
5336
5470
  async accept(params) {
5337
5471
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -5348,22 +5482,34 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
5348
5482
  operator: addresses.auction,
5349
5483
  autoApprove: params.autoApprove
5350
5484
  });
5351
- const txHash = await walletClient.writeContract({
5352
- address: addresses.auction,
5353
- abi: auctionAbi,
5354
- functionName: "acceptOffer",
5355
- args: [
5356
- params.contract,
5357
- plan.tokenId,
5358
- plan.currency,
5359
- plan.amount,
5360
- plan.splitAddresses,
5361
- plan.splitRatios
5362
- ],
5363
- account,
5364
- chain: void 0
5485
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5486
+ operation: "offer accept",
5487
+ approvals: [{
5488
+ type: "nft",
5489
+ approvalTxHash,
5490
+ target: params.contract,
5491
+ operator: addresses.auction
5492
+ }],
5493
+ run: async () => {
5494
+ const targetTxHash = await walletClient.writeContract({
5495
+ address: addresses.auction,
5496
+ abi: auctionAbi,
5497
+ functionName: "acceptOffer",
5498
+ args: [
5499
+ params.contract,
5500
+ plan.tokenId,
5501
+ plan.currency,
5502
+ plan.amount,
5503
+ plan.splitAddresses,
5504
+ plan.splitRatios
5505
+ ],
5506
+ account,
5507
+ chain: void 0
5508
+ });
5509
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5510
+ return { txHash: targetTxHash, receipt: targetReceipt };
5511
+ }
5365
5512
  });
5366
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5367
5513
  return { txHash, receipt, approvalTxHash };
5368
5514
  },
5369
5515
  async status(params) {
@@ -5428,29 +5574,41 @@ function createListingNamespace(publicClient, config, chain, addresses) {
5428
5574
  operator: addresses.auction,
5429
5575
  autoApprove: params.autoApprove
5430
5576
  });
5431
- const txHash = await walletClient.writeContract({
5432
- address: addresses.auction,
5433
- abi: auctionAbi,
5434
- functionName: "setSalePrice",
5435
- args: [
5436
- plan.nftAddress,
5437
- plan.tokenId,
5438
- plan.currency,
5439
- plan.price,
5440
- plan.target,
5441
- plan.splitAddresses,
5442
- plan.splitRatios
5443
- ],
5444
- account,
5445
- chain: void 0
5577
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5578
+ operation: "listing create",
5579
+ approvals: [{
5580
+ type: "nft",
5581
+ approvalTxHash,
5582
+ target: plan.nftAddress,
5583
+ operator: addresses.auction
5584
+ }],
5585
+ run: async () => {
5586
+ const targetTxHash = await walletClient.writeContract({
5587
+ address: addresses.auction,
5588
+ abi: auctionAbi,
5589
+ functionName: "setSalePrice",
5590
+ args: [
5591
+ plan.nftAddress,
5592
+ plan.tokenId,
5593
+ plan.currency,
5594
+ plan.price,
5595
+ plan.target,
5596
+ plan.splitAddresses,
5597
+ plan.splitRatios
5598
+ ],
5599
+ account,
5600
+ chain: void 0
5601
+ });
5602
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5603
+ return { txHash: targetTxHash, receipt: targetReceipt };
5604
+ }
5446
5605
  });
5447
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5448
5606
  return { txHash, receipt, approvalTxHash };
5449
5607
  },
5450
5608
  async cancel(params) {
5451
5609
  const { walletClient, account } = requireWallet(config);
5452
5610
  const plan = planListingCancel(params);
5453
- const txHash = await walletClient.writeContract({
5611
+ const targetTxHash = await walletClient.writeContract({
5454
5612
  address: addresses.auction,
5455
5613
  abi: auctionAbi,
5456
5614
  functionName: "removeSalePrice",
@@ -5458,8 +5616,8 @@ function createListingNamespace(publicClient, config, chain, addresses) {
5458
5616
  account,
5459
5617
  chain: void 0
5460
5618
  });
5461
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5462
- return { txHash, receipt };
5619
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5620
+ return { txHash: targetTxHash, receipt: targetReceipt };
5463
5621
  },
5464
5622
  async buy(params) {
5465
5623
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -5478,16 +5636,28 @@ function createListingNamespace(publicClient, config, chain, addresses) {
5478
5636
  amount: plan.amount,
5479
5637
  autoApprove: params.autoApprove
5480
5638
  });
5481
- const txHash = await walletClient.writeContract({
5482
- address: addresses.auction,
5483
- abi: auctionAbi,
5484
- functionName: "buy",
5485
- args: [params.contract, plan.tokenId, plan.currency, plan.amount],
5486
- account,
5487
- chain: void 0,
5488
- value: payment.value
5639
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
5640
+ operation: "listing buy",
5641
+ approvals: [{
5642
+ type: "erc20",
5643
+ approvalTxHash: payment.approvalTxHash,
5644
+ target: plan.currency,
5645
+ spender: addresses.auction
5646
+ }],
5647
+ run: async () => {
5648
+ const targetTxHash = await walletClient.writeContract({
5649
+ address: addresses.auction,
5650
+ abi: auctionAbi,
5651
+ functionName: "buy",
5652
+ args: [params.contract, plan.tokenId, plan.currency, plan.amount],
5653
+ account,
5654
+ chain: void 0,
5655
+ value: payment.value
5656
+ });
5657
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
5658
+ return { txHash: targetTxHash, receipt: targetReceipt };
5659
+ }
5489
5660
  });
5490
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
5491
5661
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
5492
5662
  },
5493
5663
  async status(params) {
@@ -6449,7 +6619,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6449
6619
  );
6450
6620
  }
6451
6621
  }
6452
- const approvalTxHashes = await approveNftContracts({
6622
+ const nftApprovals = await approveNftContracts({
6453
6623
  publicClient,
6454
6624
  walletClient,
6455
6625
  account,
@@ -6458,26 +6628,38 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6458
6628
  nftAddresses: uniqueContracts,
6459
6629
  autoApprove: params.autoApprove
6460
6630
  });
6461
- const txHash = await walletClient.writeContract({
6462
- address: addresses.batchListing,
6463
- abi: batchListingAbi,
6464
- functionName: "registerSalePriceMerkleRoot",
6465
- args: [
6466
- artifact.root,
6467
- artifact.currency,
6468
- BigInt(artifact.amount),
6469
- splitConfig.splitAddresses,
6470
- splitConfig.splitRatios
6471
- ],
6472
- account,
6473
- chain: void 0
6631
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
6632
+ operation: "batch listing create",
6633
+ approvals: nftApprovals.map((approval) => ({
6634
+ type: "nft",
6635
+ approvalTxHash: approval.txHash,
6636
+ target: approval.nftAddress,
6637
+ operator: addresses.erc721ApprovalManager
6638
+ })),
6639
+ run: async () => {
6640
+ const targetTxHash = await walletClient.writeContract({
6641
+ address: addresses.batchListing,
6642
+ abi: batchListingAbi,
6643
+ functionName: "registerSalePriceMerkleRoot",
6644
+ args: [
6645
+ artifact.root,
6646
+ artifact.currency,
6647
+ BigInt(artifact.amount),
6648
+ splitConfig.splitAddresses,
6649
+ splitConfig.splitRatios
6650
+ ],
6651
+ account,
6652
+ chain: void 0
6653
+ });
6654
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6655
+ return { txHash: targetTxHash, receipt: targetReceipt };
6656
+ }
6474
6657
  });
6475
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6476
6658
  return {
6477
6659
  txHash,
6478
6660
  receipt,
6479
6661
  root: artifact.root,
6480
- approvalTxHashes: approvalTxHashes.length > 0 ? approvalTxHashes : void 0
6662
+ approvalTxHashes: nftApprovals.length > 0 ? nftApprovals.map((approval) => approval.txHash) : void 0
6481
6663
  };
6482
6664
  },
6483
6665
  async cancel(params) {
@@ -6490,7 +6672,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6490
6672
  creator: accountAddress,
6491
6673
  params
6492
6674
  });
6493
- const txHash = await walletClient.writeContract({
6675
+ const targetTxHash = await walletClient.writeContract({
6494
6676
  address: addresses.batchListing,
6495
6677
  abi: batchListingAbi,
6496
6678
  functionName: "cancelSalePriceMerkleRoot",
@@ -6498,8 +6680,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6498
6680
  account,
6499
6681
  chain: void 0
6500
6682
  });
6501
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6502
- return { txHash, receipt, root };
6683
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6684
+ return { txHash: targetTxHash, receipt: targetReceipt, root };
6503
6685
  },
6504
6686
  async buy(params) {
6505
6687
  const { walletClient, account, accountAddress } = requireWallet(config);
@@ -6530,25 +6712,37 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6530
6712
  amount,
6531
6713
  autoApprove: params.autoApprove
6532
6714
  });
6533
- const txHash = await walletClient.writeContract({
6534
- address: addresses.batchListing,
6535
- abi: batchListingAbi,
6536
- functionName: "buyWithMerkleProof",
6537
- args: [
6538
- proofArtifact.contract,
6539
- tokenIdBig,
6540
- currency,
6541
- amount,
6542
- params.creator,
6543
- proofArtifact.root,
6544
- proofArtifact.proof,
6545
- allowListProof
6546
- ],
6547
- account,
6548
- chain: void 0,
6549
- value: payment.value
6715
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
6716
+ operation: "batch listing buy",
6717
+ approvals: [{
6718
+ type: "erc20",
6719
+ approvalTxHash: payment.approvalTxHash,
6720
+ target: currency,
6721
+ spender: addresses.erc20ApprovalManager
6722
+ }],
6723
+ run: async () => {
6724
+ const targetTxHash = await walletClient.writeContract({
6725
+ address: addresses.batchListing,
6726
+ abi: batchListingAbi,
6727
+ functionName: "buyWithMerkleProof",
6728
+ args: [
6729
+ proofArtifact.contract,
6730
+ tokenIdBig,
6731
+ currency,
6732
+ amount,
6733
+ params.creator,
6734
+ proofArtifact.root,
6735
+ proofArtifact.proof,
6736
+ allowListProof
6737
+ ],
6738
+ account,
6739
+ chain: void 0,
6740
+ value: payment.value
6741
+ });
6742
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6743
+ return { txHash: targetTxHash, receipt: targetReceipt };
6744
+ }
6550
6745
  });
6551
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6552
6746
  return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
6553
6747
  },
6554
6748
  async setAllowlist(params) {
@@ -6566,7 +6760,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6566
6760
  requireInput(params.endTime ?? params.artifact?.allowList?.endTimestamp, "endTime"),
6567
6761
  "endTime"
6568
6762
  );
6569
- const txHash = await walletClient.writeContract({
6763
+ const targetTxHash = await walletClient.writeContract({
6570
6764
  address: addresses.batchListing,
6571
6765
  abi: batchListingAbi,
6572
6766
  functionName: "setAllowListConfig",
@@ -6574,8 +6768,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
6574
6768
  account,
6575
6769
  chain: void 0
6576
6770
  });
6577
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
6578
- return { txHash, receipt, root, allowListRoot, endTime };
6771
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
6772
+ return { txHash: targetTxHash, receipt: targetReceipt, root, allowListRoot, endTime };
6579
6773
  },
6580
6774
  async status(params) {
6581
6775
  const resolvedParams = await resolveBatchListingStatusParams({
@@ -6804,7 +6998,7 @@ function isHash(value) {
6804
6998
  }
6805
6999
  async function approveNftContracts(opts) {
6806
7000
  return opts.nftAddresses.reduce(async (previous, nftAddress) => {
6807
- const hashes = await previous;
7001
+ const approvals = await previous;
6808
7002
  const txHash = await approveNftContractIfNeeded({
6809
7003
  publicClient: opts.publicClient,
6810
7004
  walletClient: opts.walletClient,
@@ -6814,7 +7008,7 @@ async function approveNftContracts(opts) {
6814
7008
  operator: opts.operator,
6815
7009
  autoApprove: opts.autoApprove
6816
7010
  });
6817
- return isHash(txHash) ? [...hashes, txHash] : hashes;
7011
+ return isHash(txHash) ? [...approvals, { nftAddress, txHash }] : approvals;
6818
7012
  }, Promise.resolve([]));
6819
7013
  }
6820
7014
  async function prepareBatchListingPayment(opts) {
@@ -7191,16 +7385,18 @@ function planBatchAuctionStatus(params) {
7191
7385
  }
7192
7386
  function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
7193
7387
  const hasAuction = details.startingTime > 0n && !isAddressEqual11(details.seller, zeroAddress3);
7194
- const hasRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n;
7195
- const duration = hasAuction ? details.duration : rootContext?.config.duration ?? 0n;
7388
+ const hasCurrentRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n && rootContext.rootNonce === rootContext.config.nonce;
7389
+ const currentRootConfig = hasCurrentRootConfig ? rootContext.config : void 0;
7390
+ const hasRootConfig = currentRootConfig !== void 0;
7391
+ const duration = hasAuction ? details.duration : currentRootConfig?.duration ?? 0n;
7196
7392
  const startingTime = hasAuction ? details.startingTime : 0n;
7197
7393
  const endTime = hasAuction ? startingTime + duration : null;
7198
7394
  const ended = endTime !== null && nowSeconds >= endTime;
7199
7395
  const currentBidder = currentBid.amount > 0n && !isAddressEqual11(currentBid.bidder, zeroAddress3) ? currentBid.bidder : null;
7200
7396
  const seller = hasAuction ? details.seller : rootContext?.creator ?? zeroAddress3;
7201
- const currency = hasAuction ? details.currency : rootContext?.config.currency ?? ETH_ADDRESS;
7202
- const reserveAmount = hasAuction ? details.reserveAmount : rootContext?.config.reserveAmount ?? 0n;
7203
- const tokenNonceConsumed = rootContext === void 0 ? null : rootContext.tokenNonce >= rootContext.config.nonce;
7397
+ const currency = hasAuction ? details.currency : currentRootConfig?.currency ?? ETH_ADDRESS;
7398
+ const reserveAmount = hasAuction ? details.reserveAmount : currentRootConfig?.reserveAmount ?? 0n;
7399
+ const tokenNonceConsumed = rootContext === void 0 ? null : !hasCurrentRootConfig || rootContext.tokenNonce >= rootContext.config.nonce;
7204
7400
  return {
7205
7401
  seller,
7206
7402
  root: rootContext?.root ?? null,
@@ -7210,8 +7406,8 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
7210
7406
  creationBlock: details.creationBlock,
7211
7407
  startingTime,
7212
7408
  endTime,
7213
- splitAddresses: resolveStatusSplitAddresses(hasAuction, details, rootContext),
7214
- splitRatios: resolveStatusSplitRatios(hasAuction, details, rootContext),
7409
+ splitAddresses: resolveStatusSplitAddresses(hasAuction, details, currentRootConfig),
7410
+ splitRatios: resolveStatusSplitRatios(hasAuction, details, currentRootConfig),
7215
7411
  hasRootConfig,
7216
7412
  rootNonce: rootContext?.rootNonce ?? null,
7217
7413
  tokenNonce: rootContext?.tokenNonce ?? null,
@@ -7347,23 +7543,23 @@ function uniqueAddresses2(addresses) {
7347
7543
  function addMinimumBidIncrease(amount) {
7348
7544
  return amount + amount * marketplaceFeePercentage / 100n;
7349
7545
  }
7350
- function resolveStatusSplitAddresses(hasAuction, details, rootContext) {
7546
+ function resolveStatusSplitAddresses(hasAuction, details, rootConfig) {
7351
7547
  if (hasAuction) {
7352
7548
  return [...details.splitAddresses];
7353
7549
  }
7354
- if (rootContext === void 0) {
7550
+ if (rootConfig === void 0) {
7355
7551
  return [];
7356
7552
  }
7357
- return [...rootContext.config.splitAddresses];
7553
+ return [...rootConfig.splitAddresses];
7358
7554
  }
7359
- function resolveStatusSplitRatios(hasAuction, details, rootContext) {
7555
+ function resolveStatusSplitRatios(hasAuction, details, rootConfig) {
7360
7556
  if (hasAuction) {
7361
7557
  return [...details.splitRatios];
7362
7558
  }
7363
- if (rootContext === void 0) {
7559
+ if (rootConfig === void 0) {
7364
7560
  return [];
7365
7561
  }
7366
- return [...rootContext.config.splitRatios];
7562
+ return [...rootConfig.splitRatios];
7367
7563
  }
7368
7564
  function resolveBatchAuctionState(params) {
7369
7565
  if (params.hasAuction) {
@@ -7397,7 +7593,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7397
7593
  currentUnixTimestamp2()
7398
7594
  );
7399
7595
  const erc721ApprovalManager = plan.approvalContracts.length === 0 ? void 0 : requireContractAddress(chain, "erc721ApprovalManager");
7400
- const approvalTxHashes = await approveNftContracts2({
7596
+ const nftApprovals = await approveNftContracts2({
7401
7597
  publicClient,
7402
7598
  account,
7403
7599
  accountAddress,
@@ -7406,31 +7602,43 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7406
7602
  nftAddresses: plan.approvalContracts,
7407
7603
  autoApprove: params.autoApprove
7408
7604
  });
7409
- const txHash = await walletClient.writeContract({
7410
- address: batchAuctionHouse,
7411
- abi: batchAuctionHouseAbi,
7412
- functionName: "registerAuctionMerkleRoot",
7413
- args: [
7414
- plan.root,
7415
- plan.currency,
7416
- plan.reserveAmount,
7417
- plan.duration,
7418
- plan.splitAddresses,
7419
- plan.splitRatios
7420
- ],
7421
- account,
7422
- chain: void 0
7423
- });
7424
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7425
- const logs = parseEventLogs3({
7426
- abi: batchAuctionHouseAbi,
7427
- logs: receipt.logs,
7428
- eventName: "AuctionMerkleRootRegistered"
7605
+ const { txHash, receipt, registered } = await runWithApprovalSideEffectAlert({
7606
+ operation: "batch auction create",
7607
+ approvals: nftApprovals.map((approval) => ({
7608
+ type: "nft",
7609
+ approvalTxHash: approval.txHash,
7610
+ target: approval.nftAddress,
7611
+ operator: erc721ApprovalManager
7612
+ })),
7613
+ run: async () => {
7614
+ const targetTxHash = await walletClient.writeContract({
7615
+ address: batchAuctionHouse,
7616
+ abi: batchAuctionHouseAbi,
7617
+ functionName: "registerAuctionMerkleRoot",
7618
+ args: [
7619
+ plan.root,
7620
+ plan.currency,
7621
+ plan.reserveAmount,
7622
+ plan.duration,
7623
+ plan.splitAddresses,
7624
+ plan.splitRatios
7625
+ ],
7626
+ account,
7627
+ chain: void 0
7628
+ });
7629
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7630
+ const logs = parseEventLogs3({
7631
+ abi: batchAuctionHouseAbi,
7632
+ logs: targetReceipt.logs,
7633
+ eventName: "AuctionMerkleRootRegistered"
7634
+ });
7635
+ const [registeredLog] = logs;
7636
+ if (!registeredLog) {
7637
+ throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
7638
+ }
7639
+ return { txHash: targetTxHash, receipt: targetReceipt, registered: registeredLog };
7640
+ }
7429
7641
  });
7430
- const [registered] = logs;
7431
- if (!registered) {
7432
- throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
7433
- }
7434
7642
  return {
7435
7643
  txHash,
7436
7644
  receipt,
@@ -7441,7 +7649,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7441
7649
  reserveAmount: registered.args.startingAmount,
7442
7650
  duration: registered.args.duration,
7443
7651
  nonce: registered.args.nonce,
7444
- approvalTxHashes
7652
+ approvalTxHashes: nftApprovals.map((approval) => approval.txHash)
7445
7653
  };
7446
7654
  },
7447
7655
  async cancel(params) {
@@ -7454,7 +7662,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7454
7662
  params
7455
7663
  );
7456
7664
  const plan = planBatchAuctionRoot(resolvedParams);
7457
- const txHash = await walletClient.writeContract({
7665
+ const targetTxHash = await walletClient.writeContract({
7458
7666
  address: batchAuctionHouse,
7459
7667
  abi: batchAuctionHouseAbi,
7460
7668
  functionName: "cancelAuctionMerkleRoot",
@@ -7462,10 +7670,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7462
7670
  account,
7463
7671
  chain: void 0
7464
7672
  });
7465
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7673
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7466
7674
  const logs = parseEventLogs3({
7467
7675
  abi: batchAuctionHouseAbi,
7468
- logs: receipt.logs,
7676
+ logs: targetReceipt.logs,
7469
7677
  eventName: "AuctionMerkleRootCancelled"
7470
7678
  });
7471
7679
  const [cancelled] = logs;
@@ -7473,8 +7681,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7473
7681
  throw new Error("Batch auction cancel transaction succeeded but AuctionMerkleRootCancelled was not found in logs.");
7474
7682
  }
7475
7683
  return {
7476
- txHash,
7477
- receipt,
7684
+ txHash: targetTxHash,
7685
+ receipt: targetReceipt,
7478
7686
  batchAuctionHouse,
7479
7687
  creator: cancelled.args.creator,
7480
7688
  root: cancelled.args.merkleRoot
@@ -7515,33 +7723,45 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7515
7723
  requiredAmount: plan.requiredPayment,
7516
7724
  autoApprove: params.autoApprove
7517
7725
  });
7518
- const txHash = await walletClient.writeContract({
7519
- address: batchAuctionHouse,
7520
- abi: batchAuctionHouseAbi,
7521
- functionName: "bidWithAuctionMerkleProof",
7522
- args: [
7523
- plan.currency,
7524
- plan.contract,
7525
- plan.tokenId,
7526
- plan.creator,
7527
- plan.root,
7528
- plan.amount,
7529
- plan.proof
7530
- ],
7531
- account,
7532
- chain: void 0,
7533
- value: payment.value
7534
- });
7535
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7536
- const logs = parseEventLogs3({
7537
- abi: batchAuctionHouseAbi,
7538
- logs: receipt.logs,
7539
- eventName: "AuctionMerkleBid"
7726
+ const { txHash, receipt, bid } = await runWithApprovalSideEffectAlert({
7727
+ operation: "batch auction bid",
7728
+ approvals: [{
7729
+ type: "erc20",
7730
+ approvalTxHash: payment.approvalTxHash,
7731
+ target: plan.currency,
7732
+ spender: erc20ApprovalManager
7733
+ }],
7734
+ run: async () => {
7735
+ const targetTxHash = await walletClient.writeContract({
7736
+ address: batchAuctionHouse,
7737
+ abi: batchAuctionHouseAbi,
7738
+ functionName: "bidWithAuctionMerkleProof",
7739
+ args: [
7740
+ plan.currency,
7741
+ plan.contract,
7742
+ plan.tokenId,
7743
+ plan.creator,
7744
+ plan.root,
7745
+ plan.amount,
7746
+ plan.proof
7747
+ ],
7748
+ account,
7749
+ chain: void 0,
7750
+ value: payment.value
7751
+ });
7752
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7753
+ const logs = parseEventLogs3({
7754
+ abi: batchAuctionHouseAbi,
7755
+ logs: targetReceipt.logs,
7756
+ eventName: "AuctionMerkleBid"
7757
+ });
7758
+ const [bidLog] = logs;
7759
+ if (!bidLog) {
7760
+ throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
7761
+ }
7762
+ return { txHash: targetTxHash, receipt: targetReceipt, bid: bidLog };
7763
+ }
7540
7764
  });
7541
- const [bid] = logs;
7542
- if (!bid) {
7543
- throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
7544
- }
7545
7765
  return {
7546
7766
  txHash,
7547
7767
  receipt,
@@ -7562,7 +7782,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7562
7782
  const batchAuctionHouse = requireContractAddress(chain, "batchAuctionHouse");
7563
7783
  const { walletClient, account } = requireWallet(config);
7564
7784
  const plan = planBatchAuctionStatus(params);
7565
- const txHash = await walletClient.writeContract({
7785
+ const targetTxHash = await walletClient.writeContract({
7566
7786
  address: batchAuctionHouse,
7567
7787
  abi: batchAuctionHouseAbi,
7568
7788
  functionName: "settleAuction",
@@ -7570,10 +7790,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7570
7790
  account,
7571
7791
  chain: void 0
7572
7792
  });
7573
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
7793
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
7574
7794
  const logs = parseEventLogs3({
7575
7795
  abi: batchAuctionHouseAbi,
7576
- logs: receipt.logs,
7796
+ logs: targetReceipt.logs,
7577
7797
  eventName: "AuctionSettled"
7578
7798
  });
7579
7799
  const [settled] = logs;
@@ -7581,8 +7801,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
7581
7801
  throw new Error("Batch auction settle transaction succeeded but AuctionSettled was not found in logs.");
7582
7802
  }
7583
7803
  return {
7584
- txHash,
7585
- receipt,
7804
+ txHash: targetTxHash,
7805
+ receipt: targetReceipt,
7586
7806
  batchAuctionHouse,
7587
7807
  seller: settled.args.seller,
7588
7808
  bidder: settled.args.bidder,
@@ -7769,7 +7989,7 @@ async function approveNftContracts2(opts) {
7769
7989
  }
7770
7990
  const { walletClient, operator } = opts;
7771
7991
  return opts.nftAddresses.reduce(async (previous, nftAddress) => {
7772
- const hashes = await previous;
7992
+ const approvals = await previous;
7773
7993
  const txHash = await approveNftContract({
7774
7994
  publicClient: opts.publicClient,
7775
7995
  walletClient,
@@ -7779,7 +7999,7 @@ async function approveNftContracts2(opts) {
7779
7999
  nftAddress,
7780
8000
  autoApprove: opts.autoApprove
7781
8001
  });
7782
- return txHash === void 0 ? hashes : [...hashes, txHash];
8002
+ return txHash === void 0 ? approvals : [...approvals, { nftAddress, txHash }];
7783
8003
  }, Promise.resolve([]));
7784
8004
  }
7785
8005
  async function approveNftContract(opts) {
@@ -8119,25 +8339,37 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8119
8339
  amount: plan.amount,
8120
8340
  autoApprove: params.autoApprove
8121
8341
  });
8122
- const txHash = await walletClient.writeContract({
8123
- address: batchOfferCreator,
8124
- abi: batchOfferAbi,
8125
- functionName: "createBatchOffer",
8126
- args: [plan.root, plan.amount, plan.currency, plan.expiry],
8127
- account,
8128
- chain: void 0,
8129
- value: payment.value
8130
- });
8131
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
8132
- const logs = parseEventLogs4({
8133
- abi: batchOfferAbi,
8134
- logs: receipt.logs,
8135
- eventName: "BatchOfferCreated"
8342
+ const { txHash, receipt, created } = await runWithApprovalSideEffectAlert({
8343
+ operation: "batch offer create",
8344
+ approvals: [{
8345
+ type: "erc20",
8346
+ approvalTxHash: payment.approvalTxHash,
8347
+ target: plan.currency,
8348
+ spender: batchOfferCreator
8349
+ }],
8350
+ run: async () => {
8351
+ const targetTxHash = await walletClient.writeContract({
8352
+ address: batchOfferCreator,
8353
+ abi: batchOfferAbi,
8354
+ functionName: "createBatchOffer",
8355
+ args: [plan.root, plan.amount, plan.currency, plan.expiry],
8356
+ account,
8357
+ chain: void 0,
8358
+ value: payment.value
8359
+ });
8360
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
8361
+ const logs = parseEventLogs4({
8362
+ abi: batchOfferAbi,
8363
+ logs: targetReceipt.logs,
8364
+ eventName: "BatchOfferCreated"
8365
+ });
8366
+ const [createdLog] = logs;
8367
+ if (!createdLog) {
8368
+ throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
8369
+ }
8370
+ return { txHash: targetTxHash, receipt: targetReceipt, created: createdLog };
8371
+ }
8136
8372
  });
8137
- const [created] = logs;
8138
- if (!created) {
8139
- throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
8140
- }
8141
8373
  return {
8142
8374
  txHash,
8143
8375
  receipt,
@@ -8163,7 +8395,7 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8163
8395
  params
8164
8396
  });
8165
8397
  const plan = planBatchOfferRoot(resolvedParams);
8166
- const txHash = await walletClient.writeContract({
8398
+ const targetTxHash = await walletClient.writeContract({
8167
8399
  address: batchOfferCreator,
8168
8400
  abi: batchOfferAbi,
8169
8401
  functionName: "revokeBatchOffer",
@@ -8171,10 +8403,10 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8171
8403
  account,
8172
8404
  chain: void 0
8173
8405
  });
8174
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
8406
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
8175
8407
  const logs = parseEventLogs4({
8176
8408
  abi: batchOfferAbi,
8177
- logs: receipt.logs,
8409
+ logs: targetReceipt.logs,
8178
8410
  eventName: "BatchOfferRevoked"
8179
8411
  });
8180
8412
  const [revoked] = logs;
@@ -8182,8 +8414,8 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8182
8414
  throw new Error("Batch offer revoke transaction succeeded but BatchOfferRevoked was not found in logs.");
8183
8415
  }
8184
8416
  return {
8185
- txHash,
8186
- receipt,
8417
+ txHash: targetTxHash,
8418
+ receipt: targetReceipt,
8187
8419
  batchOfferCreator,
8188
8420
  creator: revoked.args.creator,
8189
8421
  root: revoked.args.rootHash,
@@ -8220,32 +8452,44 @@ function createBatchOfferNamespace(publicClient, config, chain) {
8220
8452
  operator: batchOfferCreator,
8221
8453
  autoApprove: plan.autoApprove
8222
8454
  });
8223
- const txHash = await walletClient.writeContract({
8224
- address: batchOfferCreator,
8225
- abi: batchOfferAbi,
8226
- functionName: "acceptBatchOffer",
8227
- args: [
8228
- plan.creator,
8229
- plan.proof,
8230
- plan.root,
8231
- plan.contract,
8232
- plan.tokenId,
8233
- plan.splitAddresses,
8234
- plan.splitRatios
8235
- ],
8236
- account,
8237
- chain: void 0
8238
- });
8239
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
8240
- const logs = parseEventLogs4({
8241
- abi: batchOfferAbi,
8242
- logs: receipt.logs,
8243
- eventName: "BatchOfferAccepted"
8455
+ const { txHash, receipt, accepted } = await runWithApprovalSideEffectAlert({
8456
+ operation: "batch offer accept",
8457
+ approvals: [{
8458
+ type: "nft",
8459
+ approvalTxHash,
8460
+ target: plan.contract,
8461
+ operator: batchOfferCreator
8462
+ }],
8463
+ run: async () => {
8464
+ const targetTxHash = await walletClient.writeContract({
8465
+ address: batchOfferCreator,
8466
+ abi: batchOfferAbi,
8467
+ functionName: "acceptBatchOffer",
8468
+ args: [
8469
+ plan.creator,
8470
+ plan.proof,
8471
+ plan.root,
8472
+ plan.contract,
8473
+ plan.tokenId,
8474
+ plan.splitAddresses,
8475
+ plan.splitRatios
8476
+ ],
8477
+ account,
8478
+ chain: void 0
8479
+ });
8480
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
8481
+ const logs = parseEventLogs4({
8482
+ abi: batchOfferAbi,
8483
+ logs: targetReceipt.logs,
8484
+ eventName: "BatchOfferAccepted"
8485
+ });
8486
+ const [acceptedLog] = logs;
8487
+ if (!acceptedLog) {
8488
+ throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
8489
+ }
8490
+ return { txHash: targetTxHash, receipt: targetReceipt, accepted: acceptedLog };
8491
+ }
8244
8492
  });
8245
- const [accepted] = logs;
8246
- if (!accepted) {
8247
- throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
8248
- }
8249
8493
  return {
8250
8494
  txHash,
8251
8495
  receipt,
@@ -8866,6 +9110,7 @@ var liquidFactoryAbi = [
8866
9110
  var TICK_BASE = 1.0001;
8867
9111
  var TICK_LOG_BASE = Math.log(TICK_BASE);
8868
9112
  var TOKEN_BASE_UNITS = 1e18;
9113
+ var SHARE_SCALE_UNITS = 10n ** 18n;
8869
9114
  var RESERVE_TAIL_SHARES_PERCENT = 2;
8870
9115
  var RESERVE_TAIL_END_PRICE_MULTIPLE = 100;
8871
9116
  var SHARES_SUM_TOLERANCE = 1e-6;
@@ -8924,12 +9169,66 @@ function toValidNumber(value) {
8924
9169
  if (typeof value !== "number" || !Number.isFinite(value)) return null;
8925
9170
  return value;
8926
9171
  }
8927
- function toValidShareNumber(value) {
8928
- const numeric = typeof value === "string" ? Number(value) : toValidNumber(value);
8929
- if (numeric === null || numeric <= 0 || numeric > 1) {
9172
+ function toNormalizedShare(value) {
9173
+ if (typeof value === "number") {
9174
+ if (!Number.isFinite(value) || value <= 0 || value > 1) {
9175
+ return null;
9176
+ }
9177
+ return parseShareDecimalString(expandFiniteNumber(value));
9178
+ }
9179
+ if (typeof value !== "string") {
8930
9180
  return null;
8931
9181
  }
8932
- return numeric;
9182
+ return parseShareDecimalString(value);
9183
+ }
9184
+ function expandFiniteNumber(value) {
9185
+ const rawValue = value.toString();
9186
+ const [coefficient = "", exponentValue] = rawValue.toLowerCase().split("e");
9187
+ if (exponentValue === void 0) {
9188
+ return rawValue;
9189
+ }
9190
+ const exponent = Number(exponentValue);
9191
+ const [integerPart = "", fractionalPart = ""] = coefficient.split(".");
9192
+ const digits = `${integerPart}${fractionalPart}`;
9193
+ const decimalIndex = integerPart.length + exponent;
9194
+ if (decimalIndex <= 0) {
9195
+ return `0.${"0".repeat(Math.abs(decimalIndex))}${digits}`;
9196
+ }
9197
+ if (decimalIndex >= digits.length) {
9198
+ return `${digits}${"0".repeat(decimalIndex - digits.length)}`;
9199
+ }
9200
+ return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
9201
+ }
9202
+ function parseShareDecimalString(value) {
9203
+ const normalized = value.trim();
9204
+ if (!/^(?:\d+\.?\d*|\.\d+)$/.test(normalized)) {
9205
+ return null;
9206
+ }
9207
+ const shareParts = normalized.startsWith(".") ? ["0", normalized.slice(1)] : normalized.split(".");
9208
+ const integerPart = shareParts[0] ?? "";
9209
+ const fractionalDigits = shareParts[1] ?? "";
9210
+ const excessFractionalDigits = fractionalDigits.slice(18);
9211
+ if (/[1-9]/.test(excessFractionalDigits)) {
9212
+ return null;
9213
+ }
9214
+ const integerUnits = BigInt(integerPart === "" ? "0" : integerPart);
9215
+ const fractionalUnits = BigInt(fractionalDigits.slice(0, 18).padEnd(18, "0"));
9216
+ const scaledUnits = integerUnits * SHARE_SCALE_UNITS + fractionalUnits;
9217
+ if (scaledUnits <= 0n || scaledUnits > SHARE_SCALE_UNITS) {
9218
+ return null;
9219
+ }
9220
+ return {
9221
+ decimal: formatScaledShareDecimal(scaledUnits),
9222
+ scaledUnits
9223
+ };
9224
+ }
9225
+ function formatScaledShareDecimal(scaledUnits) {
9226
+ const integerUnits = scaledUnits / SHARE_SCALE_UNITS;
9227
+ const fractionalUnits = scaledUnits % SHARE_SCALE_UNITS;
9228
+ if (fractionalUnits === 0n) {
9229
+ return integerUnits.toString();
9230
+ }
9231
+ return `${integerUnits}.${fractionalUnits.toString().padStart(18, "0").replace(/0+$/, "")}`;
8933
9232
  }
8934
9233
  function toApproxTokenAmount(value, label) {
8935
9234
  const numeric = typeof value === "number" ? value : Number(value);
@@ -9078,8 +9377,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
9078
9377
  if (invalidResult !== void 0) {
9079
9378
  return invalidResult.result;
9080
9379
  }
9081
- const parsedSegments = normalizedResults.filter((result) => result.isValid).map((result) => result.segment);
9082
- const totalPositions = parsedSegments.reduce((sum, segment) => sum + segment.numPositions, 0);
9380
+ const parsedEntries = normalizedResults.filter((result) => result.isValid).map((result) => result.entry);
9381
+ const totalPositions = parsedEntries.reduce((sum, entry) => sum + entry.segment.numPositions, 0);
9083
9382
  if (totalPositions > MAX_TOTAL_POSITIONS) {
9084
9383
  return {
9085
9384
  isValid: false,
@@ -9087,8 +9386,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
9087
9386
  errorMessage: `Total positions across all curves must not exceed ${MAX_TOTAL_POSITIONS}`
9088
9387
  };
9089
9388
  }
9090
- const sortedSegments = [...parsedSegments].sort((a, b) => a.tickLower - b.tickLower);
9091
- const hasGapOrOverlap = sortedSegments.slice(1).some((current, index) => current.tickLower !== sortedSegments[index]?.tickUpper);
9389
+ const sortedEntries = [...parsedEntries].sort((a, b) => a.segment.tickLower - b.segment.tickLower);
9390
+ const hasGapOrOverlap = sortedEntries.slice(1).some((current, index) => current.segment.tickLower !== sortedEntries[index]?.segment.tickUpper);
9092
9391
  if (hasGapOrOverlap) {
9093
9392
  return {
9094
9393
  isValid: false,
@@ -9096,10 +9395,11 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
9096
9395
  errorMessage: "Curve segments must be contiguous (no overlap or gaps)"
9097
9396
  };
9098
9397
  }
9099
- const shareSum = sortedSegments.reduce((sum, segment) => sum + Number(segment.shares), 0);
9100
- if (Math.abs(shareSum - 1) > SHARES_SUM_TOLERANCE) {
9398
+ const shareSum = sortedEntries.reduce((sum, entry) => sum + entry.shareScaledUnits, 0n);
9399
+ if (shareSum !== SHARE_SCALE_UNITS) {
9101
9400
  return { isValid: false, error: "share-sum-invalid", errorMessage: "Curve share values must add up to 1" };
9102
9401
  }
9402
+ const sortedSegments = sortedEntries.map((entry) => entry.segment);
9103
9403
  const narrowSegment = sortedSegments.find((segment) => {
9104
9404
  const minSpan = segment.numPositions * tickSpacing;
9105
9405
  return segment.tickUpper - segment.tickLower < minSpan || computeGrossLiquidityAtFarTick(segment.tickLower, segment.tickUpper - segment.tickLower, segment.numPositions, Number(segment.shares), totalCurveSupplyTokens) > MAX_LIQUIDITY_PER_TICK;
@@ -9128,8 +9428,8 @@ function normalizeSegment(segment, tickSpacing) {
9128
9428
  const tickLower = toValidNumber(segment.tickLower);
9129
9429
  const tickUpper = toValidNumber(segment.tickUpper);
9130
9430
  const numPositions = toValidNumber(segment.numPositions);
9131
- const shares = toValidShareNumber(segment.shares);
9132
- if (tickLower === null || tickUpper === null || numPositions === null || shares === null) {
9431
+ const share = toNormalizedShare(segment.shares);
9432
+ if (tickLower === null || tickUpper === null || numPositions === null || share === null) {
9133
9433
  return invalidSegmentResult();
9134
9434
  }
9135
9435
  if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper) || !Number.isInteger(numPositions) || numPositions <= 0) {
@@ -9146,11 +9446,14 @@ function normalizeSegment(segment, tickSpacing) {
9146
9446
  }
9147
9447
  return {
9148
9448
  isValid: true,
9149
- segment: {
9150
- tickLower,
9151
- tickUpper,
9152
- numPositions,
9153
- shares: `${shares}`
9449
+ entry: {
9450
+ segment: {
9451
+ tickLower,
9452
+ tickUpper,
9453
+ numPositions,
9454
+ shares: share.decimal
9455
+ },
9456
+ shareScaledUnits: share.scaledUnits
9154
9457
  }
9155
9458
  };
9156
9459
  }
@@ -9521,9 +9824,23 @@ function missingLiquidEditionAddressError(txHash, receipt, cause) {
9521
9824
  const message = `Liquid Edition deploy transaction succeeded, but the deployed contract address could not be read from the LiquidTokenCreated event logs after ${LIQUID_EDITION_ADDRESS_LOG_RETRY_ATTEMPTS + 1} attempts. Transaction hash: ${txHash}. Block: ${receipt.blockNumber}. The connected RPC may be delayed or returning incomplete receipt logs; retry with a synced RPC or inspect the transaction hash.`;
9522
9825
  return cause instanceof Error ? new Error(message, { cause }) : new Error(message);
9523
9826
  }
9524
- function liquidEditionDeployRevertedError(txHash, receipt) {
9827
+ function liquidEditionRevertedReceiptError(message, txHash, receipt) {
9525
9828
  return new Error(
9526
- `Liquid Edition deploy transaction reverted before emitting LiquidTokenCreated. Transaction hash: ${txHash}. Block: ${receipt.blockNumber}.`
9829
+ `${message} Transaction hash: ${txHash}. Block: ${receipt.blockNumber}.`
9830
+ );
9831
+ }
9832
+ function liquidEditionDeployRevertedError(txHash, receipt) {
9833
+ return liquidEditionRevertedReceiptError(
9834
+ "Liquid Edition deploy transaction reverted before emitting LiquidTokenCreated.",
9835
+ txHash,
9836
+ receipt
9837
+ );
9838
+ }
9839
+ function liquidEditionSetRenderContractRevertedError(txHash, receipt) {
9840
+ return liquidEditionRevertedReceiptError(
9841
+ 'Liquid Edition setRenderContract transaction was confirmed with status "reverted".',
9842
+ txHash,
9843
+ receipt
9527
9844
  );
9528
9845
  }
9529
9846
  async function waitForLiquidEditionAddress(publicClient, txHash) {
@@ -9609,7 +9926,13 @@ function createLiquidNamespace(config, chain, addresses) {
9609
9926
  throw new Error(validation.errorMessage ?? "Invalid curve configuration");
9610
9927
  }
9611
9928
  const initialRareLiquidity = params.initialRareLiquidity !== void 0 ? await toTokenAmount(publicClient, factoryConfig.baseToken, params.initialRareLiquidity, "initialRareLiquidity") : 0n;
9612
- await ensureTokenAllowance(
9929
+ const curves = validation.curves.map((curve) => ({
9930
+ tickLower: curve.tickLower,
9931
+ tickUpper: curve.tickUpper,
9932
+ numPositions: curve.numPositions,
9933
+ shares: parseUnits6(curve.shares, 18)
9934
+ }));
9935
+ const approvalTxHash = await ensureTokenAllowance(
9613
9936
  publicClient,
9614
9937
  walletClient,
9615
9938
  account,
@@ -9618,43 +9941,49 @@ function createLiquidNamespace(config, chain, addresses) {
9618
9941
  liquidFactory,
9619
9942
  initialRareLiquidity
9620
9943
  );
9621
- const curves = validation.curves.map((curve) => ({
9622
- tickLower: curve.tickLower,
9623
- tickUpper: curve.tickUpper,
9624
- numPositions: curve.numPositions,
9625
- shares: parseUnits6(curve.shares, 18)
9626
- }));
9627
- const txHash = customMaxTotalSupply === void 0 ? await walletClient.writeContract({
9628
- address: liquidFactory,
9629
- abi: liquidFactoryAbi,
9630
- functionName: "createLiquidTokenMultiCurve",
9631
- args: [
9632
- accountAddress,
9633
- params.tokenUri,
9634
- params.name,
9635
- params.symbol,
9636
- initialRareLiquidity,
9637
- curves
9638
- ],
9639
- account,
9640
- chain: void 0
9641
- }) : await walletClient.writeContract({
9642
- address: liquidFactory,
9643
- abi: liquidFactoryAbi,
9644
- functionName: "createLiquidTokenMultiCurveWithSupply",
9645
- args: [
9646
- accountAddress,
9647
- params.tokenUri,
9648
- params.name,
9649
- params.symbol,
9650
- initialRareLiquidity,
9651
- curves,
9652
- customMaxTotalSupply
9653
- ],
9654
- account,
9655
- chain: void 0
9944
+ const { txHash, receipt, contract } = await runWithApprovalSideEffectAlert({
9945
+ operation: "liquid edition deploy",
9946
+ approvals: [{
9947
+ type: "erc20",
9948
+ approvalTxHash,
9949
+ target: factoryConfig.baseToken,
9950
+ spender: liquidFactory
9951
+ }],
9952
+ run: async () => {
9953
+ const targetTxHash = customMaxTotalSupply === void 0 ? await walletClient.writeContract({
9954
+ address: liquidFactory,
9955
+ abi: liquidFactoryAbi,
9956
+ functionName: "createLiquidTokenMultiCurve",
9957
+ args: [
9958
+ accountAddress,
9959
+ params.tokenUri,
9960
+ params.name,
9961
+ params.symbol,
9962
+ initialRareLiquidity,
9963
+ curves
9964
+ ],
9965
+ account,
9966
+ chain: void 0
9967
+ }) : await walletClient.writeContract({
9968
+ address: liquidFactory,
9969
+ abi: liquidFactoryAbi,
9970
+ functionName: "createLiquidTokenMultiCurveWithSupply",
9971
+ args: [
9972
+ accountAddress,
9973
+ params.tokenUri,
9974
+ params.name,
9975
+ params.symbol,
9976
+ initialRareLiquidity,
9977
+ curves,
9978
+ customMaxTotalSupply
9979
+ ],
9980
+ account,
9981
+ chain: void 0
9982
+ });
9983
+ const deployed = await waitForLiquidEditionAddress(publicClient, targetTxHash);
9984
+ return { txHash: targetTxHash, receipt: deployed.receipt, contract: deployed.contract };
9985
+ }
9656
9986
  });
9657
- const { receipt, contract } = await waitForLiquidEditionAddress(publicClient, txHash);
9658
9987
  return {
9659
9988
  txHash,
9660
9989
  receipt,
@@ -9689,6 +10018,9 @@ function createLiquidNamespace(config, chain, addresses) {
9689
10018
  chain: void 0
9690
10019
  });
9691
10020
  const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
10021
+ if (receipt.status === "reverted") {
10022
+ throw liquidEditionSetRenderContractRevertedError(txHash, receipt);
10023
+ }
9692
10024
  return {
9693
10025
  txHash,
9694
10026
  receipt,
@@ -9795,6 +10127,312 @@ function createLiquidNamespace(config, chain, addresses) {
9795
10127
  };
9796
10128
  }
9797
10129
 
10130
+ // src/sdk/bridge.ts
10131
+ import { encodeFunctionData } from "viem";
10132
+
10133
+ // src/contracts/abis/rare-bridge.ts
10134
+ var rareBridgeAbi = [
10135
+ {
10136
+ type: "function",
10137
+ name: "getFee",
10138
+ inputs: [
10139
+ {
10140
+ name: "_destinationChainSelector",
10141
+ type: "uint64",
10142
+ internalType: "uint64"
10143
+ },
10144
+ {
10145
+ name: "_destinationChainRecipient",
10146
+ type: "address",
10147
+ internalType: "address"
10148
+ },
10149
+ {
10150
+ name: "_distributionData",
10151
+ type: "bytes",
10152
+ internalType: "bytes"
10153
+ },
10154
+ {
10155
+ name: "_extraArgs",
10156
+ type: "bytes",
10157
+ internalType: "bytes"
10158
+ },
10159
+ {
10160
+ name: "_payFeesInLink",
10161
+ type: "bool",
10162
+ internalType: "bool"
10163
+ }
10164
+ ],
10165
+ outputs: [
10166
+ {
10167
+ name: "fee",
10168
+ type: "uint256",
10169
+ internalType: "uint256"
10170
+ }
10171
+ ],
10172
+ stateMutability: "view"
10173
+ },
10174
+ {
10175
+ type: "function",
10176
+ name: "send",
10177
+ inputs: [
10178
+ {
10179
+ name: "_destinationChainSelector",
10180
+ type: "uint64",
10181
+ internalType: "uint64"
10182
+ },
10183
+ {
10184
+ name: "_destinationChainRecipient",
10185
+ type: "address",
10186
+ internalType: "address"
10187
+ },
10188
+ {
10189
+ name: "_distributionData",
10190
+ type: "bytes",
10191
+ internalType: "bytes"
10192
+ },
10193
+ {
10194
+ name: "_extraArgs",
10195
+ type: "bytes",
10196
+ internalType: "bytes"
10197
+ },
10198
+ {
10199
+ name: "_payFeesInLink",
10200
+ type: "bool",
10201
+ internalType: "bool"
10202
+ }
10203
+ ],
10204
+ outputs: [],
10205
+ stateMutability: "payable"
10206
+ },
10207
+ {
10208
+ type: "event",
10209
+ name: "MessageSent",
10210
+ inputs: [
10211
+ {
10212
+ name: "messageId",
10213
+ type: "bytes32",
10214
+ indexed: true,
10215
+ internalType: "bytes32"
10216
+ },
10217
+ {
10218
+ name: "destinationChainSelector",
10219
+ type: "uint64",
10220
+ indexed: true,
10221
+ internalType: "uint64"
10222
+ },
10223
+ {
10224
+ name: "destinationChainRecipient",
10225
+ type: "address",
10226
+ indexed: true,
10227
+ internalType: "address"
10228
+ },
10229
+ {
10230
+ name: "fee",
10231
+ type: "uint256",
10232
+ indexed: false,
10233
+ internalType: "uint256"
10234
+ },
10235
+ {
10236
+ name: "payFeesInLink",
10237
+ type: "bool",
10238
+ indexed: false,
10239
+ internalType: "bool"
10240
+ }
10241
+ ],
10242
+ anonymous: false
10243
+ }
10244
+ ];
10245
+
10246
+ // src/sdk/bridge-core.ts
10247
+ import { encodeAbiParameters } from "viem";
10248
+ var allowedBridgePairs = [
10249
+ { sourceChain: "mainnet", destinationChain: "base" },
10250
+ { sourceChain: "base", destinationChain: "mainnet" },
10251
+ { sourceChain: "sepolia", destinationChain: "base-sepolia" },
10252
+ { sourceChain: "base-sepolia", destinationChain: "sepolia" }
10253
+ ];
10254
+ function validateBridgeRoute(route) {
10255
+ const supported = allowedBridgePairs.some(
10256
+ (pair) => pair.sourceChain === route.sourceChain && pair.destinationChain === route.destinationChain
10257
+ );
10258
+ if (supported) {
10259
+ return { isValid: true };
10260
+ }
10261
+ return {
10262
+ isValid: false,
10263
+ error: "unsupported_bridge_route",
10264
+ errorMessage: `Unsupported RARE bridge route "${route.sourceChain}" -> "${route.destinationChain}". Supported routes: mainnet <-> base, sepolia <-> base-sepolia.`
10265
+ };
10266
+ }
10267
+ function getBridgeInfo(chain) {
10268
+ return {
10269
+ chain,
10270
+ chainId: chainIds[chain],
10271
+ rareBridgeAddress: getRareBridgeAddress(chain),
10272
+ rareTokenAddress: resolveCurrency("rare", chain),
10273
+ ccipChainSelector: getCcipChainSelector(chain)
10274
+ };
10275
+ }
10276
+ function encodeBridgeDistribution(params) {
10277
+ return encodeAbiParameters(
10278
+ [
10279
+ { name: "recipients", type: "address[]" },
10280
+ { name: "amounts", type: "uint256[]" }
10281
+ ],
10282
+ [[params.recipient], [params.amount]]
10283
+ );
10284
+ }
10285
+ function buildBridgeSendArgs(params) {
10286
+ return [
10287
+ params.destinationBridgeInfo.ccipChainSelector,
10288
+ params.destinationBridgeInfo.rareBridgeAddress,
10289
+ params.distributionData,
10290
+ "0x",
10291
+ false
10292
+ ];
10293
+ }
10294
+ function buildCcipExplorerUrl(txHash) {
10295
+ return `https://ccip.chain.link/tx/${txHash}`;
10296
+ }
10297
+
10298
+ // src/sdk/bridge.ts
10299
+ function createBridgeNamespace(publicClient, config, sourceChain) {
10300
+ return {
10301
+ async quote(params) {
10302
+ return buildBridgeQuote(publicClient, config, sourceChain, params);
10303
+ },
10304
+ async send(params) {
10305
+ return executeBridge(publicClient, config, sourceChain, params);
10306
+ }
10307
+ };
10308
+ }
10309
+ async function executeBridge(publicClient, config, sourceChain, params) {
10310
+ const { walletClient, account, accountAddress } = requireWallet(config);
10311
+ const quote = await buildBridgeQuote(publicClient, config, sourceChain, {
10312
+ ...params,
10313
+ recipient: params.recipient ?? accountAddress
10314
+ }, {
10315
+ estimateGas: false
10316
+ });
10317
+ const approval = await preparePaymentAmountForSpender({
10318
+ publicClient,
10319
+ walletClient,
10320
+ account,
10321
+ accountAddress,
10322
+ spenderAddress: quote.sourceBridgeAddress,
10323
+ currency: quote.rareTokenAddress,
10324
+ requiredAmount: quote.amount,
10325
+ autoApprove: params.autoApprove
10326
+ });
10327
+ const sendArgs = buildBridgeSendArgs({
10328
+ destinationBridgeInfo: getBridgeInfo(quote.destinationChain),
10329
+ distributionData: quote.distributionData
10330
+ });
10331
+ const { txHash, receipt, estimatedGas } = await runWithApprovalSideEffectAlert({
10332
+ operation: "bridge send",
10333
+ approvals: [{
10334
+ type: "erc20",
10335
+ approvalTxHash: approval.approvalTxHash,
10336
+ target: quote.rareTokenAddress,
10337
+ spender: quote.sourceBridgeAddress
10338
+ }],
10339
+ run: async () => {
10340
+ const gas = await estimateBridgeGas(publicClient, {
10341
+ account: accountAddress,
10342
+ sourceBridgeAddress: quote.sourceBridgeAddress,
10343
+ args: sendArgs,
10344
+ nativeFee: quote.nativeFee
10345
+ });
10346
+ const targetTxHash = await walletClient.writeContract({
10347
+ address: quote.sourceBridgeAddress,
10348
+ abi: rareBridgeAbi,
10349
+ functionName: "send",
10350
+ args: sendArgs,
10351
+ value: quote.nativeFee,
10352
+ account,
10353
+ chain: void 0
10354
+ });
10355
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
10356
+ return { txHash: targetTxHash, receipt: targetReceipt, estimatedGas: gas };
10357
+ }
10358
+ });
10359
+ return {
10360
+ ...quote,
10361
+ estimatedGas,
10362
+ txHash,
10363
+ receipt,
10364
+ approvalTxHash: approval.approvalTxHash,
10365
+ ccipExplorerUrl: buildCcipExplorerUrl(txHash)
10366
+ };
10367
+ }
10368
+ async function buildBridgeQuote(publicClient, config, sourceChain, params, options = {}) {
10369
+ const routeValidation = validateBridgeRoute({
10370
+ sourceChain,
10371
+ destinationChain: params.destinationChain
10372
+ });
10373
+ if (!routeValidation.isValid) {
10374
+ throw new Error(routeValidation.errorMessage);
10375
+ }
10376
+ const sourceBridgeInfo = getBridgeInfo(sourceChain);
10377
+ const destinationBridgeInfo = getBridgeInfo(params.destinationChain);
10378
+ const recipient = resolveRecipient(params.recipient, config);
10379
+ const amount = toPositiveWei(params.amount, "amount");
10380
+ const distributionData = encodeBridgeDistribution({ recipient, amount });
10381
+ const args = buildBridgeSendArgs({
10382
+ destinationBridgeInfo,
10383
+ distributionData
10384
+ });
10385
+ const nativeFee = await publicClient.readContract({
10386
+ address: sourceBridgeInfo.rareBridgeAddress,
10387
+ abi: rareBridgeAbi,
10388
+ functionName: "getFee",
10389
+ args
10390
+ });
10391
+ const estimatedGas = options.estimateGas === false ? void 0 : await estimateBridgeGas(publicClient, {
10392
+ account: getConfiguredAccountAddress2(config),
10393
+ sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
10394
+ args,
10395
+ nativeFee
10396
+ });
10397
+ return {
10398
+ sourceChain,
10399
+ sourceChainId: sourceBridgeInfo.chainId,
10400
+ destinationChain: params.destinationChain,
10401
+ destinationChainId: destinationBridgeInfo.chainId,
10402
+ sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
10403
+ destinationBridgeAddress: destinationBridgeInfo.rareBridgeAddress,
10404
+ rareTokenAddress: sourceBridgeInfo.rareTokenAddress,
10405
+ destinationCcipChainSelector: destinationBridgeInfo.ccipChainSelector,
10406
+ amount,
10407
+ recipient,
10408
+ distributionData,
10409
+ nativeFee,
10410
+ estimatedGas
10411
+ };
10412
+ }
10413
+ function resolveRecipient(recipient, config) {
10414
+ const resolved = recipient ?? getConfiguredAccountAddress2(config);
10415
+ if (resolved === void 0) {
10416
+ throw new Error("No recipient available for bridge quote. Pass params.recipient or provide config.account/walletClient with an account.");
10417
+ }
10418
+ return resolved;
10419
+ }
10420
+ async function estimateBridgeGas(publicClient, params) {
10421
+ if (params.account === void 0) {
10422
+ return void 0;
10423
+ }
10424
+ return publicClient.estimateGas({
10425
+ account: params.account,
10426
+ to: params.sourceBridgeAddress,
10427
+ data: encodeFunctionData({
10428
+ abi: rareBridgeAbi,
10429
+ functionName: "send",
10430
+ args: params.args
10431
+ }),
10432
+ value: params.nativeFee
10433
+ });
10434
+ }
10435
+
9798
10436
  // src/contracts/abis/liquid-router.ts
9799
10437
  var liquidRouterAbi = [
9800
10438
  {
@@ -10181,7 +10819,7 @@ async function quoteRouteSteps(publicClient, quoterAddress, routeSteps, currentA
10181
10819
 
10182
10820
  // src/swap/route-encoding.ts
10183
10821
  import {
10184
- encodeAbiParameters,
10822
+ encodeAbiParameters as encodeAbiParameters2,
10185
10823
  encodePacked as encodePacked2,
10186
10824
  getAddress as getAddress8,
10187
10825
  parseAbiParameters
@@ -10293,13 +10931,13 @@ function getV4ExecutionMode(v4BlockStartIndex, nextIndex, routeLength) {
10293
10931
  };
10294
10932
  }
10295
10933
  function encodeWrapEth(recipient, amount) {
10296
- return encodeAbiParameters(
10934
+ return encodeAbiParameters2(
10297
10935
  parseAbiParameters("address recipient, uint256 amount"),
10298
10936
  [recipient, amount]
10299
10937
  );
10300
10938
  }
10301
10939
  function encodeUnwrapWeth(recipient, amountMinimum) {
10302
- return encodeAbiParameters(
10940
+ return encodeAbiParameters2(
10303
10941
  parseAbiParameters("address recipient, uint256 amountMinimum"),
10304
10942
  [recipient, amountMinimum]
10305
10943
  );
@@ -10319,23 +10957,23 @@ function encodeV4ExactIn({
10319
10957
  step.poolKey.hooks,
10320
10958
  "0x"
10321
10959
  ]);
10322
- const swapParams = encodeAbiParameters(
10960
+ const swapParams = encodeAbiParameters2(
10323
10961
  parseAbiParameters("(address,(address,uint24,int24,address,bytes)[],uint128,uint128)"),
10324
10962
  [[currencyIn, pathKeysArray, amountIn, minAmountOut]]
10325
10963
  );
10326
10964
  const settleAction = executionMode.inputSource === "user" ? V4_ACTIONS.SETTLE_ALL : V4_ACTIONS.SETTLE;
10327
- const settleParams = executionMode.inputSource === "user" ? encodeAbiParameters(
10965
+ const settleParams = executionMode.inputSource === "user" ? encodeAbiParameters2(
10328
10966
  parseAbiParameters("address currency, uint128 maxAmount"),
10329
10967
  [currencyIn, amountIn]
10330
- ) : encodeAbiParameters(
10968
+ ) : encodeAbiParameters2(
10331
10969
  parseAbiParameters("address currency, uint256 amount, bool payerIsUser"),
10332
10970
  [currencyIn, ROUTER_AMOUNT_CONSTANTS.contractBalance, false]
10333
10971
  );
10334
10972
  const takeAction = executionMode.outputTarget === "user" ? V4_ACTIONS.TAKE_ALL : V4_ACTIONS.TAKE;
10335
- const takeParams = executionMode.outputTarget === "user" ? encodeAbiParameters(
10973
+ const takeParams = executionMode.outputTarget === "user" ? encodeAbiParameters2(
10336
10974
  parseAbiParameters("address currency, uint128 minAmount"),
10337
10975
  [currencyOut, minAmountOut]
10338
- ) : encodeAbiParameters(
10976
+ ) : encodeAbiParameters2(
10339
10977
  parseAbiParameters("address currency, address recipient, uint256 amount"),
10340
10978
  [currencyOut, ROUTER_RECIPIENTS.addressThis, ROUTER_AMOUNT_CONSTANTS.openDelta]
10341
10979
  );
@@ -10348,7 +10986,7 @@ function encodeV4ExactIn({
10348
10986
  ["uint8", "uint8", "uint8"],
10349
10987
  [settleAction, V4_ACTIONS.SWAP_EXACT_IN_SINGLE, takeAction]
10350
10988
  );
10351
- return encodeAbiParameters(
10989
+ return encodeAbiParameters2(
10352
10990
  parseAbiParameters("bytes actions, bytes[] params"),
10353
10991
  [
10354
10992
  actions2,
@@ -10364,7 +11002,7 @@ function encodeV4ExactIn({
10364
11002
  ["uint8", "uint8", "uint8"],
10365
11003
  [V4_ACTIONS.SWAP_EXACT_IN, settleAction, takeAction]
10366
11004
  );
10367
- return encodeAbiParameters(
11005
+ return encodeAbiParameters2(
10368
11006
  parseAbiParameters("bytes actions, bytes[] params"),
10369
11007
  [actions, [swapParams, settleParams, takeParams]]
10370
11008
  );
@@ -10383,7 +11021,7 @@ function encodeV4ExactInSingle(step, amountIn, minAmountOut) {
10383
11021
  minAmountOut,
10384
11022
  "0x"
10385
11023
  ];
10386
- return encodeAbiParameters(
11024
+ return encodeAbiParameters2(
10387
11025
  parseAbiParameters("((address,address,uint24,int24,address),bool,uint128,uint128,bytes)"),
10388
11026
  [swapExactInSingleTuple]
10389
11027
  );
@@ -10990,7 +11628,7 @@ async function executeRawRouterBuy(params) {
10990
11628
  const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
10991
11629
  const ethAmount = toWei(amountIn);
10992
11630
  const minTokensOut = await toTokenAmount(params.publicClient, params.token, minAmountOutInput, "minAmountOut");
10993
- const txHash = await walletClient.writeContract({
11631
+ const targetTxHash = await walletClient.writeContract({
10994
11632
  address: router,
10995
11633
  abi: liquidRouterAbi,
10996
11634
  functionName: "buy",
@@ -10999,8 +11637,8 @@ async function executeRawRouterBuy(params) {
10999
11637
  chain: void 0,
11000
11638
  value: ethAmount
11001
11639
  });
11002
- const receipt = await params.publicClient.waitForTransactionReceipt({ hash: txHash });
11003
- return { txHash, receipt, minAmountOut: minTokensOut };
11640
+ const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11641
+ return { txHash: targetTxHash, receipt: targetReceipt, minAmountOut: minTokensOut };
11004
11642
  }
11005
11643
  async function executeRawRouterSell(params) {
11006
11644
  const { walletClient, account, accountAddress } = requireWallet(params.config);
@@ -11010,25 +11648,37 @@ async function executeRawRouterSell(params) {
11010
11648
  const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
11011
11649
  const tokenAmount = await toTokenAmount(params.publicClient, params.token, amountIn, "amountIn");
11012
11650
  const minEthOut = toWei(minAmountOutInput);
11013
- await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
11014
- const txHash = await walletClient.writeContract({
11015
- address: router,
11016
- abi: liquidRouterAbi,
11017
- functionName: "sell",
11018
- args: [
11019
- params.token,
11020
- tokenAmount,
11021
- params.recipient ?? accountAddress,
11022
- minEthOut,
11023
- params.commands,
11024
- [...params.inputs],
11025
- resolveDeadline(params.deadline)
11026
- ],
11027
- account,
11028
- chain: void 0
11651
+ const approvalTxHash = await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
11652
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
11653
+ operation: "swap sell",
11654
+ approvals: [{
11655
+ type: "erc20",
11656
+ approvalTxHash,
11657
+ target: params.token,
11658
+ spender: router
11659
+ }],
11660
+ run: async () => {
11661
+ const targetTxHash = await walletClient.writeContract({
11662
+ address: router,
11663
+ abi: liquidRouterAbi,
11664
+ functionName: "sell",
11665
+ args: [
11666
+ params.token,
11667
+ tokenAmount,
11668
+ params.recipient ?? accountAddress,
11669
+ minEthOut,
11670
+ params.commands,
11671
+ [...params.inputs],
11672
+ resolveDeadline(params.deadline)
11673
+ ],
11674
+ account,
11675
+ chain: void 0
11676
+ });
11677
+ const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11678
+ return { txHash: targetTxHash, receipt: targetReceipt };
11679
+ }
11029
11680
  });
11030
- const receipt = await params.publicClient.waitForTransactionReceipt({ hash: txHash });
11031
- return { txHash, receipt, minAmountOut: minEthOut, tokenAmount };
11681
+ return { txHash, receipt, minAmountOut: minEthOut, tokenAmount, approvalTxHash };
11032
11682
  }
11033
11683
  function isRawTokenTradeParams(params) {
11034
11684
  return params.route === "raw";
@@ -11072,28 +11722,38 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11072
11722
  validateRouterPayload(params.commands, params.inputs);
11073
11723
  const amountIn = await toTokenAmount(publicClient, params.tokenIn, params.amountIn, "amountIn");
11074
11724
  const minAmountOut = await toTokenAmount(publicClient, params.tokenOut, params.minAmountOut, "minAmountOut");
11075
- if (params.tokenIn !== ETH_ADDRESS) {
11076
- await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.tokenIn, router, amountIn);
11077
- }
11078
- const txHash = await walletClient.writeContract({
11079
- address: router,
11080
- abi: liquidRouterAbi,
11081
- functionName: "swap",
11082
- args: [
11083
- params.tokenIn,
11084
- amountIn,
11085
- params.tokenOut,
11086
- params.recipient ?? accountAddress,
11087
- minAmountOut,
11088
- params.commands,
11089
- [...params.inputs],
11090
- resolveDeadline(params.deadline)
11091
- ],
11092
- account,
11093
- chain: void 0,
11094
- value: params.tokenIn === ETH_ADDRESS ? amountIn : void 0
11725
+ const approvalTxHash = params.tokenIn === ETH_ADDRESS ? void 0 : await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.tokenIn, router, amountIn);
11726
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
11727
+ operation: "swap tokens",
11728
+ approvals: [{
11729
+ type: "erc20",
11730
+ approvalTxHash,
11731
+ target: params.tokenIn,
11732
+ spender: router
11733
+ }],
11734
+ run: async () => {
11735
+ const targetTxHash = await walletClient.writeContract({
11736
+ address: router,
11737
+ abi: liquidRouterAbi,
11738
+ functionName: "swap",
11739
+ args: [
11740
+ params.tokenIn,
11741
+ amountIn,
11742
+ params.tokenOut,
11743
+ params.recipient ?? accountAddress,
11744
+ minAmountOut,
11745
+ params.commands,
11746
+ [...params.inputs],
11747
+ resolveDeadline(params.deadline)
11748
+ ],
11749
+ account,
11750
+ chain: void 0,
11751
+ value: params.tokenIn === ETH_ADDRESS ? amountIn : void 0
11752
+ });
11753
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11754
+ return { txHash: targetTxHash, receipt: targetReceipt };
11755
+ }
11095
11756
  });
11096
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
11097
11757
  return { txHash, receipt };
11098
11758
  },
11099
11759
  async quoteBuyToken(params) {
@@ -11160,7 +11820,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11160
11820
  });
11161
11821
  if (quoteDetails.kind === "local") {
11162
11822
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
11163
- const txHash = await walletClient.writeContract({
11823
+ const targetTxHash = await walletClient.writeContract({
11164
11824
  address: router,
11165
11825
  abi: liquidRouterAbi,
11166
11826
  functionName: "buy",
@@ -11176,10 +11836,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11176
11836
  chain: void 0,
11177
11837
  value: quoteDetails.quote.amountIn
11178
11838
  });
11179
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
11839
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11180
11840
  return {
11181
- txHash,
11182
- receipt,
11841
+ txHash: targetTxHash,
11842
+ receipt: targetReceipt,
11183
11843
  estimatedAmountOut: quoteDetails.quote.estimatedAmountOut,
11184
11844
  minAmountOut: quoteDetails.quote.minAmountOut,
11185
11845
  routeSource: quoteDetails.quote.routeSource,
@@ -11271,24 +11931,36 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11271
11931
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
11272
11932
  const amountIn = requireInput(params.amountIn, "amountIn");
11273
11933
  const tokenAmount = await toTokenAmount(publicClient, params.token, amountIn, "amountIn");
11274
- await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
11275
- const txHash = await walletClient.writeContract({
11276
- address: router,
11277
- abi: liquidRouterAbi,
11278
- functionName: "sell",
11279
- args: [
11280
- params.token,
11281
- tokenAmount,
11282
- params.recipient ?? accountAddress,
11283
- quoteDetails.quote.minAmountOut,
11284
- quoteDetails.quote.commands,
11285
- [...quoteDetails.quote.inputs],
11286
- resolveDeadline(params.deadline)
11287
- ],
11288
- account,
11289
- chain: void 0
11934
+ const approvalTxHash2 = await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
11935
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
11936
+ operation: "sell token",
11937
+ approvals: [{
11938
+ type: "erc20",
11939
+ approvalTxHash: approvalTxHash2,
11940
+ target: params.token,
11941
+ spender: router
11942
+ }],
11943
+ run: async () => {
11944
+ const targetTxHash = await walletClient.writeContract({
11945
+ address: router,
11946
+ abi: liquidRouterAbi,
11947
+ functionName: "sell",
11948
+ args: [
11949
+ params.token,
11950
+ tokenAmount,
11951
+ params.recipient ?? accountAddress,
11952
+ quoteDetails.quote.minAmountOut,
11953
+ quoteDetails.quote.commands,
11954
+ [...quoteDetails.quote.inputs],
11955
+ resolveDeadline(params.deadline)
11956
+ ],
11957
+ account,
11958
+ chain: void 0
11959
+ });
11960
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11961
+ return { txHash: targetTxHash, receipt: targetReceipt };
11962
+ }
11290
11963
  });
11291
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
11292
11964
  return {
11293
11965
  txHash,
11294
11966
  receipt,
@@ -11297,7 +11969,8 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11297
11969
  routeSource: quoteDetails.quote.routeSource,
11298
11970
  execution: quoteDetails.quote.execution,
11299
11971
  commands: quoteDetails.quote.commands,
11300
- inputs: quoteDetails.quote.inputs
11972
+ inputs: quoteDetails.quote.inputs,
11973
+ approvalTxHash: approvalTxHash2
11301
11974
  };
11302
11975
  }
11303
11976
  const approval = await requestUniswapApproval({
@@ -11316,14 +11989,33 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11316
11989
  accountAddress,
11317
11990
  chainId
11318
11991
  })).txHash : void 0;
11319
- const swapResponse = await requestUniswapSwap({
11320
- apiKey: quoteDetails.apiKey,
11321
- quote: quoteDetails.rawQuote,
11322
- deadline: uniswapDeadline
11323
- });
11324
- const sent = await sendPreparedTransaction(publicClient, walletClient, account, swapResponse.swap, {
11325
- accountAddress,
11326
- chainId
11992
+ const sent = await runWithApprovalSideEffectAlert({
11993
+ operation: "sell token",
11994
+ approvals: [
11995
+ {
11996
+ type: "erc20-reset",
11997
+ approvalTxHash: approvalResetTxHash,
11998
+ target: params.token,
11999
+ spender: approval.cancel?.to
12000
+ },
12001
+ {
12002
+ type: "erc20",
12003
+ approvalTxHash,
12004
+ target: params.token,
12005
+ spender: approval.approval?.to
12006
+ }
12007
+ ],
12008
+ run: async () => {
12009
+ const swapResponse = await requestUniswapSwap({
12010
+ apiKey: quoteDetails.apiKey,
12011
+ quote: quoteDetails.rawQuote,
12012
+ deadline: uniswapDeadline
12013
+ });
12014
+ return sendPreparedTransaction(publicClient, walletClient, account, swapResponse.swap, {
12015
+ accountAddress,
12016
+ chainId
12017
+ });
12018
+ }
11327
12019
  });
11328
12020
  return {
11329
12021
  ...sent,
@@ -11342,7 +12034,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11342
12034
  const { walletClient, account, accountAddress } = requireWallet(config);
11343
12035
  const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
11344
12036
  const quote = await buildBuyRareQuote(publicClient, chain, addresses, params);
11345
- const txHash = await walletClient.writeContract({
12037
+ const targetTxHash = await walletClient.writeContract({
11346
12038
  address: router,
11347
12039
  abi: liquidRouterAbi,
11348
12040
  functionName: "buy",
@@ -11351,10 +12043,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
11351
12043
  chain: void 0,
11352
12044
  value: quote.ethAmount
11353
12045
  });
11354
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
12046
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
11355
12047
  return {
11356
- txHash,
11357
- receipt,
12048
+ txHash: targetTxHash,
12049
+ receipt: targetReceipt,
11358
12050
  estimatedRareOut: quote.estimatedRareOut,
11359
12051
  minRareOut: quote.minRareOut,
11360
12052
  commands: quote.commands,
@@ -11715,7 +12407,7 @@ function normalizeLazySovereignCollectionContractType(input) {
11715
12407
  );
11716
12408
  }
11717
12409
  function planCreateLazySovereignCollection(params) {
11718
- const contractType = params.contractType ?? "lazy";
12410
+ const contractType = normalizeLazySovereignCollectionContractType(params.contractType) ?? "lazy";
11719
12411
  return {
11720
12412
  name: params.name,
11721
12413
  symbol: params.symbol,
@@ -12542,10 +13234,8 @@ async function readReleaseCollectionOwner(publicClient, contract) {
12542
13234
  );
12543
13235
  }
12544
13236
  }
12545
- async function assertConfigurableReleaseContract(opts) {
13237
+ async function assertReleaseMinterCanMint(opts) {
12546
13238
  const { publicClient, contract, accountAddress, rareMinter } = opts;
12547
- const owner = await readReleaseCollectionOwner(publicClient, contract);
12548
- assertReleaseContractOwner({ contract, accountAddress, owner });
12549
13239
  try {
12550
13240
  await publicClient.simulateContract({
12551
13241
  address: contract,
@@ -12911,6 +13601,11 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
12911
13601
  currencyDecimals: currencyDecimals2,
12912
13602
  nowSeconds: currentUnixTimestamp3()
12913
13603
  });
13604
+ await assertCollectionOwnerForReleaseWrite({
13605
+ publicClient,
13606
+ contract: plan.contract,
13607
+ accountAddress
13608
+ });
12914
13609
  const approvalTxHash = await approveReleaseMinterIfNeeded({
12915
13610
  publicClient,
12916
13611
  walletClient,
@@ -12919,29 +13614,41 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
12919
13614
  minter: rareMinter,
12920
13615
  autoApprove: params.autoApprove
12921
13616
  });
12922
- await assertConfigurableReleaseContract({
12923
- publicClient,
12924
- contract: plan.contract,
12925
- accountAddress,
12926
- rareMinter
12927
- });
12928
- const txHash = await walletClient.writeContract({
12929
- address: rareMinter,
12930
- abi: rareMinterAbi,
12931
- functionName: "prepareMintDirectSale",
12932
- args: [
12933
- plan.contract,
12934
- plan.currencyAddress,
12935
- plan.price,
12936
- plan.startTime,
12937
- plan.maxMints,
12938
- plan.splitRecipients,
12939
- plan.splitRatios
12940
- ],
12941
- account,
12942
- chain: void 0
13617
+ const { txHash, receipt } = await runWithApprovalSideEffectAlert({
13618
+ operation: "release configure",
13619
+ approvals: [{
13620
+ type: "minter",
13621
+ approvalTxHash,
13622
+ target: plan.contract,
13623
+ minter: rareMinter
13624
+ }],
13625
+ run: async () => {
13626
+ await assertReleaseMinterCanMint({
13627
+ publicClient,
13628
+ contract: plan.contract,
13629
+ accountAddress,
13630
+ rareMinter
13631
+ });
13632
+ const configureTxHash = await walletClient.writeContract({
13633
+ address: rareMinter,
13634
+ abi: rareMinterAbi,
13635
+ functionName: "prepareMintDirectSale",
13636
+ args: [
13637
+ plan.contract,
13638
+ plan.currencyAddress,
13639
+ plan.price,
13640
+ plan.startTime,
13641
+ plan.maxMints,
13642
+ plan.splitRecipients,
13643
+ plan.splitRatios
13644
+ ],
13645
+ account,
13646
+ chain: void 0
13647
+ });
13648
+ const configureReceipt = await publicClient.waitForTransactionReceipt({ hash: configureTxHash });
13649
+ return { txHash: configureTxHash, receipt: configureReceipt };
13650
+ }
12943
13651
  });
12944
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
12945
13652
  return {
12946
13653
  txHash,
12947
13654
  receipt,
@@ -12990,26 +13697,38 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
12990
13697
  amount: mint.totalPrice,
12991
13698
  autoApprove: plan.autoApprove
12992
13699
  });
12993
- const txHash = await walletClient.writeContract({
12994
- address: rareMinter,
12995
- abi: rareMinterAbi,
12996
- functionName: "mintDirectSale",
12997
- args: [
12998
- mint.contract,
12999
- mint.currency,
13000
- mint.price,
13001
- mint.quantity,
13002
- mint.proof
13003
- ],
13004
- account,
13005
- chain: void 0,
13006
- value: payment.value
13007
- });
13008
- const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
13009
- const tokenRange = readMintDirectSaleTokenRange({
13010
- receipt,
13011
- contract: mint.contract,
13012
- buyer: accountAddress
13700
+ const { txHash, receipt, tokenRange } = await runWithApprovalSideEffectAlert({
13701
+ operation: "release mint",
13702
+ approvals: [{
13703
+ type: "erc20",
13704
+ approvalTxHash: payment.approvalTxHash,
13705
+ target: mint.currency,
13706
+ spender: rareMinter
13707
+ }],
13708
+ run: async () => {
13709
+ const targetTxHash = await walletClient.writeContract({
13710
+ address: rareMinter,
13711
+ abi: rareMinterAbi,
13712
+ functionName: "mintDirectSale",
13713
+ args: [
13714
+ mint.contract,
13715
+ mint.currency,
13716
+ mint.price,
13717
+ mint.quantity,
13718
+ mint.proof
13719
+ ],
13720
+ account,
13721
+ chain: void 0,
13722
+ value: payment.value
13723
+ });
13724
+ const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
13725
+ const mintedTokenRange = readMintDirectSaleTokenRange({
13726
+ receipt: targetReceipt,
13727
+ contract: mint.contract,
13728
+ buyer: accountAddress
13729
+ });
13730
+ return { txHash: targetTxHash, receipt: targetReceipt, tokenRange: mintedTokenRange };
13731
+ }
13013
13732
  });
13014
13733
  return {
13015
13734
  txHash,
@@ -14085,10 +14804,14 @@ function addressLeaf(address) {
14085
14804
  return hexBuffer(keccak2563(address));
14086
14805
  }
14087
14806
  function parseBytes32(value, field) {
14088
- if (!isHex5(value) || value.length !== 66) {
14807
+ if (!isHex5(value, { strict: true }) || value.length !== 66) {
14089
14808
  throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14090
14809
  }
14091
- return value;
14810
+ const normalized = value.toLowerCase();
14811
+ if (!isHex5(normalized, { strict: true }) || normalized.length !== 66) {
14812
+ throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14813
+ }
14814
+ return normalized;
14092
14815
  }
14093
14816
  function parseBytes32Array(values, field) {
14094
14817
  return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
@@ -14164,14 +14887,15 @@ function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
14164
14887
  const { tree, root } = buildBatchListingTree(
14165
14888
  artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
14166
14889
  );
14167
- if (root !== artifact.root) {
14890
+ const artifactRoot = parseBytes32(artifact.root, "artifact.root");
14891
+ if (root !== artifactRoot) {
14168
14892
  throw new Error(
14169
14893
  `Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
14170
14894
  );
14171
14895
  }
14172
14896
  const allowListProofFields = buildAllowListProofFields(artifact, buyer);
14173
14897
  return {
14174
- root: artifact.root,
14898
+ root: artifactRoot,
14175
14899
  contract: contractChecksum,
14176
14900
  tokenId: tokenIdBig.toString(),
14177
14901
  proof: getTokenProof(tree, contractChecksum, tokenIdBig),
@@ -14192,7 +14916,8 @@ function buildAllowListProofFields(artifact, buyer) {
14192
14916
  throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
14193
14917
  }
14194
14918
  const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
14195
- if (root !== artifact.allowList.root) {
14919
+ const artifactAllowListRoot = parseBytes32(artifact.allowList.root, "allowList.root");
14920
+ if (root !== artifactAllowListRoot) {
14196
14921
  throw new Error(
14197
14922
  `Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
14198
14923
  );
@@ -14208,7 +14933,7 @@ function assertRecord(value, field) {
14208
14933
  }
14209
14934
  }
14210
14935
  function assertHexRoot(value, field) {
14211
- if (typeof value !== "string" || !isHex5(value) || value.length !== 66) {
14936
+ if (typeof value !== "string" || !isHex5(value, { strict: true }) || value.length !== 66) {
14212
14937
  throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
14213
14938
  }
14214
14939
  }
@@ -14355,6 +15080,7 @@ function createRareClient(config) {
14355
15080
  contracts: {
14356
15081
  factory: addresses.factory,
14357
15082
  auction: addresses.auction,
15083
+ rareBridge: addresses.rareBridge,
14358
15084
  sovereignFactory: addresses.sovereignFactory,
14359
15085
  lazySovereignFactory: addresses.lazySovereignFactory,
14360
15086
  rareMinter: addresses.rareMinter,
@@ -14370,6 +15096,7 @@ function createRareClient(config) {
14370
15096
  v4Quoter: addresses.v4Quoter
14371
15097
  },
14372
15098
  liquidEdition: createLiquidNamespace(config, chain, addresses),
15099
+ bridge: createBridgeNamespace(publicClient, config, chain),
14373
15100
  swap: createSwapNamespace(config, chain, chainId, addresses),
14374
15101
  auction,
14375
15102
  offer,
@@ -18906,14 +19633,172 @@ function formatLongValue(value, maxLength = 160) {
18906
19633
  return value.length <= maxLength ? value : `${value.slice(0, maxLength - 3)}...`;
18907
19634
  }
18908
19635
 
19636
+ // src/commands/bridge.ts
19637
+ import { Command as Command18 } from "commander";
19638
+ import { formatEther as formatEther2 } from "viem";
19639
+
19640
+ // src/commands/options.ts
19641
+ import { getAddress as getAddress14, isAddress as isAddress11 } from "viem";
19642
+ var chainOptionDescription = "chain name (mainnet, sepolia, base, base-sepolia)";
19643
+ var chainIdOptionDescription = "chain ID (1, 11155111, 8453, 84532)";
19644
+ function addChainOptions(cmd) {
19645
+ return cmd.option("--chain <chain>", chainOptionDescription).option("--chain-id <id>", chainIdOptionDescription);
19646
+ }
19647
+
19648
+ // src/commands/bridge.ts
19649
+ function bridgeCommand() {
19650
+ const cmd = new Command18("bridge");
19651
+ cmd.description("Bridge RARE across supported CCIP routes");
19652
+ cmd.addCommand(bridgeQuoteCommand());
19653
+ cmd.addCommand(bridgeSendCommand());
19654
+ return cmd;
19655
+ }
19656
+ function bridgeQuoteCommand() {
19657
+ const cmd = new Command18("quote");
19658
+ cmd.description("Quote the native fee for bridging RARE");
19659
+ addBridgeRouteOptions(cmd).action(async (opts) => {
19660
+ const plan = parseBridgeRouteOptions(opts, "rare bridge quote");
19661
+ const publicClient = getPublicClient(plan.sourceChain);
19662
+ const rare = createRareClient({
19663
+ publicClient,
19664
+ account: getConfiguredAccountAddress(plan.sourceChain)
19665
+ });
19666
+ const quote = await rare.bridge.quote({
19667
+ amount: plan.amount,
19668
+ destinationChain: plan.destinationChain,
19669
+ recipient: plan.recipient
19670
+ });
19671
+ output(
19672
+ {
19673
+ sourceChain: quote.sourceChain,
19674
+ sourceChainId: quote.sourceChainId,
19675
+ destinationChain: quote.destinationChain,
19676
+ destinationChainId: quote.destinationChainId,
19677
+ sourceBridgeAddress: quote.sourceBridgeAddress,
19678
+ destinationBridgeAddress: quote.destinationBridgeAddress,
19679
+ rareTokenAddress: quote.rareTokenAddress,
19680
+ destinationCcipChainSelector: quote.destinationCcipChainSelector,
19681
+ amount: quote.amount,
19682
+ recipient: quote.recipient,
19683
+ nativeFee: quote.nativeFee,
19684
+ estimatedGas: quote.estimatedGas ?? null,
19685
+ distributionData: quote.distributionData
19686
+ },
19687
+ () => {
19688
+ printBridgeQuote(quote);
19689
+ }
19690
+ );
19691
+ });
19692
+ return cmd;
19693
+ }
19694
+ function bridgeSendCommand() {
19695
+ const cmd = new Command18("send");
19696
+ cmd.description("Bridge RARE to another supported chain");
19697
+ addBridgeRouteOptions(cmd).option("--yes", "yes to all prompts, including approval and transaction submission").action(async (opts) => {
19698
+ const plan = parseBridgeRouteOptions(opts, "rare bridge send");
19699
+ const publicClient = getPublicClient(plan.sourceChain);
19700
+ const { client } = getWalletClient(plan.sourceChain);
19701
+ const rare = createRareClient({ publicClient, walletClient: client });
19702
+ log(`Bridging RARE from ${plan.sourceChain} to ${plan.destinationChain}...`);
19703
+ log(` Source bridge: ${rare.contracts.rareBridge ?? "unavailable"}`);
19704
+ log(` Amount: ${plan.amount} RARE`);
19705
+ if (plan.recipient !== void 0) {
19706
+ log(` Recipient: ${plan.recipient}`);
19707
+ }
19708
+ const sendParams = {
19709
+ amount: plan.amount,
19710
+ destinationChain: plan.destinationChain,
19711
+ recipient: plan.recipient
19712
+ };
19713
+ const result = await runWithPaymentApprovalConsent({
19714
+ commandName: "rare bridge send",
19715
+ approvalMessage: "RARE approval is required before bridging.",
19716
+ runWithoutApproval: async () => rare.bridge.send({
19717
+ ...sendParams,
19718
+ autoApprove: opts.yes === true
19719
+ }),
19720
+ runWithApproval: async () => rare.bridge.send({
19721
+ ...sendParams,
19722
+ autoApprove: true
19723
+ })
19724
+ });
19725
+ if (result === void 0) {
19726
+ return;
19727
+ }
19728
+ output(
19729
+ {
19730
+ txHash: result.txHash,
19731
+ blockNumber: result.receipt.blockNumber.toString(),
19732
+ approvalTxHash: result.approvalTxHash ?? null,
19733
+ ccipExplorerUrl: result.ccipExplorerUrl,
19734
+ sourceChain: result.sourceChain,
19735
+ sourceChainId: result.sourceChainId,
19736
+ destinationChain: result.destinationChain,
19737
+ destinationChainId: result.destinationChainId,
19738
+ sourceBridgeAddress: result.sourceBridgeAddress,
19739
+ destinationBridgeAddress: result.destinationBridgeAddress,
19740
+ rareTokenAddress: result.rareTokenAddress,
19741
+ destinationCcipChainSelector: result.destinationCcipChainSelector,
19742
+ amount: result.amount,
19743
+ recipient: result.recipient,
19744
+ nativeFee: result.nativeFee,
19745
+ estimatedGas: result.estimatedGas ?? null,
19746
+ distributionData: result.distributionData
19747
+ },
19748
+ () => {
19749
+ if (result.approvalTxHash !== void 0) {
19750
+ console.log(`Approval tx sent: ${result.approvalTxHash}`);
19751
+ }
19752
+ console.log(`Transaction sent: ${result.txHash}`);
19753
+ console.log(`Confirmed in block ${result.receipt.blockNumber}`);
19754
+ console.log(`CCIP explorer: ${result.ccipExplorerUrl}`);
19755
+ }
19756
+ );
19757
+ });
19758
+ return cmd;
19759
+ }
19760
+ function addBridgeRouteOptions(cmd) {
19761
+ return addChainOptions(cmd).requiredOption("--amount <amount>", "RARE amount to bridge").requiredOption("--destination-chain <chain>", "destination chain (mainnet, base, sepolia, base-sepolia)").option("--recipient <address>", "destination recipient address");
19762
+ }
19763
+ function parseBridgeRouteOptions(opts, commandName) {
19764
+ if (opts.amount === void 0) {
19765
+ throw new Error(`${commandName} requires --amount.`);
19766
+ }
19767
+ if (opts.destinationChain === void 0) {
19768
+ throw new Error(`${commandName} requires --destination-chain.`);
19769
+ }
19770
+ return {
19771
+ sourceChain: getActiveChain(opts.chain, opts.chainId),
19772
+ destinationChain: parseDestinationChain(opts.destinationChain),
19773
+ amount: opts.amount,
19774
+ recipient: parseOptionalAddress(opts.recipient, "--recipient")
19775
+ };
19776
+ }
19777
+ function parseDestinationChain(value) {
19778
+ if (!isSupportedChain(value)) {
19779
+ throw new Error(`--destination-chain must be one of: ${supportedChains.join(", ")}`);
19780
+ }
19781
+ return value;
19782
+ }
19783
+ function printBridgeQuote(quote) {
19784
+ console.log(`
19785
+ RARE bridge quote: ${quote.sourceChain} -> ${quote.destinationChain}`);
19786
+ console.log(` Amount: ${formatEther2(quote.amount)} RARE`);
19787
+ console.log(` Recipient: ${quote.recipient}`);
19788
+ console.log(` Native fee: ${formatEther2(quote.nativeFee)} ETH`);
19789
+ console.log(` Estimated gas: ${quote.estimatedGas?.toString() ?? "unavailable"}`);
19790
+ console.log(` Source bridge: ${quote.sourceBridgeAddress}`);
19791
+ console.log(` Destination bridge: ${quote.destinationBridgeAddress}`);
19792
+ }
19793
+
18909
19794
  // src/commands/swap.ts
18910
19795
  import { readFile as readFile5 } from "fs/promises";
18911
19796
  import { createInterface as createInterface6 } from "readline/promises";
18912
- import { Command as Command18 } from "commander";
18913
- import { formatEther as formatEther3 } from "viem";
19797
+ import { Command as Command19 } from "commander";
19798
+ import { formatEther as formatEther4 } from "viem";
18914
19799
 
18915
19800
  // src/commands/swap-core.ts
18916
- import { formatEther as formatEther2, formatUnits as formatUnits9, getAddress as getAddress14, isHex as isHex7 } from "viem";
19801
+ import { formatEther as formatEther3, formatUnits as formatUnits9, getAddress as getAddress15, isHex as isHex7 } from "viem";
18917
19802
  function parseInputsJson(raw, label) {
18918
19803
  const parsed = parseJson4(raw, label);
18919
19804
  if (!Array.isArray(parsed)) {
@@ -18941,7 +19826,7 @@ function ensureHex(value, label) {
18941
19826
  }
18942
19827
  function parseAddress3(value, label) {
18943
19828
  try {
18944
- return getAddress14(value);
19829
+ return getAddress15(value);
18945
19830
  } catch {
18946
19831
  throw new Error(`${label} must be a valid EVM address.`);
18947
19832
  }
@@ -18967,15 +19852,15 @@ function formatBuyRareQuoteLines(params) {
18967
19852
  `Quote for buying RARE on ${params.chain}:`,
18968
19853
  ...params.router ? [` Router: ${params.router}`] : [],
18969
19854
  ` ETH in: ${params.eth}`,
18970
- ` Estimated RARE out: ${formatEther2(params.quote.estimatedRareOut)}`,
18971
- ` Min RARE out: ${formatEther2(params.quote.minRareOut)}`,
19855
+ ` Estimated RARE out: ${formatEther3(params.quote.estimatedRareOut)}`,
19856
+ ` Min RARE out: ${formatEther3(params.quote.minRareOut)}`,
18972
19857
  params.usedMinRareOutOverride ? " Min out source: manual override" : ` Slippage: ${params.quote.slippageBps} bps`,
18973
19858
  ...params.recipient ? [` Recipient: ${params.recipient}`] : []
18974
19859
  ];
18975
19860
  return lines;
18976
19861
  }
18977
19862
  function formatQuotedAmount(amount, decimals) {
18978
- return decimals === 18 ? formatEther2(amount) : formatUnits9(amount, decimals);
19863
+ return decimals === 18 ? formatEther3(amount) : formatUnits9(amount, decimals);
18979
19864
  }
18980
19865
  function formatTokenTradeQuoteLines(params) {
18981
19866
  const outputLabel = params.direction === "buy" ? "Estimated token out" : "Estimated ETH out";
@@ -19022,7 +19907,7 @@ async function confirmProceed() {
19022
19907
  }
19023
19908
  }
19024
19909
  function swapTokensCommand() {
19025
- const cmd = new Command18("tokens");
19910
+ const cmd = new Command19("tokens");
19026
19911
  cmd.alias("swap");
19027
19912
  cmd.description("Execute a raw router token swap");
19028
19913
  cmd.requiredOption("--token-in <address>", "input token address").requiredOption("--amount-in <amount>", "amount of the input token").requiredOption("--token-out <address>", "output token address").requiredOption("--min-amount-out <amount>", "minimum output token amount").requiredOption("--commands <hex>", "raw router commands hex").requiredOption("--inputs-file <path>", "JSON file containing router input calldata array").option("--recipient <address>", "recipient address").option("--deadline <seconds>", "deadline as a unix timestamp in seconds").option("--yes", "skip the interactive transaction confirmation").option("--chain <chain>", "chain to use (mainnet, sepolia)").option("--chain-id <id>", "chain ID (1, 11155111)").action(async (opts) => {
@@ -19068,7 +19953,7 @@ function swapTokensCommand() {
19068
19953
  return cmd;
19069
19954
  }
19070
19955
  function swapBuyTokenCommand() {
19071
- const cmd = new Command18("buy-token");
19956
+ const cmd = new Command19("buy-token");
19072
19957
  cmd.description("Buy a token with ETH using a canonical liquid route or Uniswap fallback");
19073
19958
  cmd.requiredOption("--token <address>", "token address to buy").requiredOption("--amount-in <amount>", "ETH amount to spend").option("--route <mode>", "route mode: auto, local, uniswap, raw (default: auto)").option("--slippage-bps <bps>", "slippage in basis points (default: 50)").option("--min-amount-out <amount>", "override minimum token amount out").option("--commands <hex>", "raw router commands hex when --route raw").option("--inputs-file <path>", "JSON file containing router input calldata array when --route raw").option("--quote-only", "show the quote without submitting a transaction").option("--yes", "submit the quoted swap and any required approvals without an interactive confirmation").option("--recipient <address>", "recipient address").option("--deadline <seconds>", "deadline as a unix timestamp in seconds").option("--chain <chain>", "chain to use").option("--chain-id <id>", "chain ID (1, 11155111, 8453, 84532)").action(async (opts) => {
19074
19959
  const quoteOnly = opts.quoteOnly === true;
@@ -19220,7 +20105,7 @@ function swapBuyTokenCommand() {
19220
20105
  return cmd;
19221
20106
  }
19222
20107
  function swapSellTokenCommand() {
19223
- const cmd = new Command18("sell-token");
20108
+ const cmd = new Command19("sell-token");
19224
20109
  cmd.description("Sell a token for ETH using a canonical liquid route or Uniswap fallback");
19225
20110
  cmd.requiredOption("--token <address>", "token address to sell").requiredOption("--amount-in <amount>", "token amount to sell").option("--route <mode>", "route mode: auto, local, uniswap, raw (default: auto)").option("--slippage-bps <bps>", "slippage in basis points (default: 50)").option("--min-amount-out <amount>", "override minimum ETH amount out").option("--commands <hex>", "raw router commands hex when --route raw").option("--inputs-file <path>", "JSON file containing router input calldata array when --route raw").option("--quote-only", "show the quote without submitting a transaction").option("--yes", "submit the quoted swap and any required approvals without an interactive confirmation").option("--recipient <address>", "recipient address").option("--deadline <seconds>", "deadline as a unix timestamp in seconds").option("--chain <chain>", "chain to use").option("--chain-id <id>", "chain ID (1, 11155111, 8453, 84532)").action(async (opts) => {
19226
20111
  const quoteOnly = opts.quoteOnly === true;
@@ -19278,7 +20163,7 @@ function swapSellTokenCommand() {
19278
20163
  },
19279
20164
  () => {
19280
20165
  console.log(`Transaction sent: ${result2.txHash}`);
19281
- console.log(`Min ETH out: ${formatEther3(result2.minAmountOut)}`);
20166
+ console.log(`Min ETH out: ${formatEther4(result2.minAmountOut)}`);
19282
20167
  }
19283
20168
  );
19284
20169
  return;
@@ -19366,15 +20251,15 @@ function swapSellTokenCommand() {
19366
20251
  },
19367
20252
  () => {
19368
20253
  console.log(`Transaction sent: ${result.txHash}`);
19369
- console.log(`Estimated ETH out: ${formatEther3(result.estimatedAmountOut)}`);
19370
- console.log(`Min ETH out: ${formatEther3(result.minAmountOut)}`);
20254
+ console.log(`Estimated ETH out: ${formatEther4(result.estimatedAmountOut)}`);
20255
+ console.log(`Min ETH out: ${formatEther4(result.minAmountOut)}`);
19371
20256
  }
19372
20257
  );
19373
20258
  });
19374
20259
  return cmd;
19375
20260
  }
19376
20261
  function swapBuyRareCommand() {
19377
- const cmd = new Command18("buy-rare");
20262
+ const cmd = new Command19("buy-rare");
19378
20263
  cmd.description("Buy RARE with ETH using the curated canonical route");
19379
20264
  cmd.requiredOption("--amount-in <amount>", "ETH amount to spend").option("--slippage-bps <bps>", "slippage in basis points (default: 50)").option("--min-amount-out <amount>", "override minimum RARE out").option("--quote-only", "show the quote without submitting a transaction").option("--yes", "submit the quoted swap without an interactive confirmation").option("--recipient <address>", "recipient address").option("--deadline <seconds>", "deadline as a unix timestamp in seconds").option("--chain <chain>", "chain to use (mainnet, sepolia)").option("--chain-id <id>", "chain ID (1, 11155111)").action(async (opts) => {
19380
20265
  const quoteOnly = opts.quoteOnly === true;
@@ -19450,15 +20335,15 @@ function swapBuyRareCommand() {
19450
20335
  },
19451
20336
  () => {
19452
20337
  console.log(`Transaction sent: ${result.txHash}`);
19453
- console.log(`Estimated RARE out: ${formatEther3(result.estimatedRareOut)}`);
19454
- console.log(`Min RARE out: ${formatEther3(result.minRareOut)}`);
20338
+ console.log(`Estimated RARE out: ${formatEther4(result.estimatedRareOut)}`);
20339
+ console.log(`Min RARE out: ${formatEther4(result.minRareOut)}`);
19455
20340
  }
19456
20341
  );
19457
20342
  });
19458
20343
  return cmd;
19459
20344
  }
19460
20345
  function swapCommand() {
19461
- const cmd = new Command18("swap");
20346
+ const cmd = new Command19("swap");
19462
20347
  cmd.description("Interact with token swap routes");
19463
20348
  cmd.addCommand(swapTokensCommand());
19464
20349
  cmd.addCommand(swapBuyTokenCommand());
@@ -19468,9 +20353,9 @@ function swapCommand() {
19468
20353
  }
19469
20354
 
19470
20355
  // src/commands/user.ts
19471
- import { Command as Command19 } from "commander";
20356
+ import { Command as Command20 } from "commander";
19472
20357
  function userCommand() {
19473
- const cmd = new Command19("user");
20358
+ const cmd = new Command20("user");
19474
20359
  cmd.description("Get RARE Protocol users");
19475
20360
  cmd.command("get").description("Get a user by wallet address").argument("<address>", "wallet address").action(async (address) => {
19476
20361
  const userAddress = parseAddress(address, "<address>");
@@ -19484,9 +20369,9 @@ function userCommand() {
19484
20369
  }
19485
20370
 
19486
20371
  // src/commands/utils.ts
19487
- import { Command as Command20 } from "commander";
20372
+ import { Command as Command21 } from "commander";
19488
20373
  function utilsCommand() {
19489
- const cmd = new Command20("utils");
20374
+ const cmd = new Command21("utils");
19490
20375
  cmd.description("Offline Merkle tree and proof utilities");
19491
20376
  cmd.addCommand(createUtilsTreeCommand());
19492
20377
  cmd.addCommand(createUtilsMerkleCommand());
@@ -19494,14 +20379,14 @@ function utilsCommand() {
19494
20379
  }
19495
20380
 
19496
20381
  // src/commands/mcp.ts
19497
- import { Command as Command21 } from "commander";
20382
+ import { Command as Command22 } from "commander";
19498
20383
 
19499
20384
  // src/mcp/server.ts
19500
20385
  import { readFile as readFile6 } from "fs/promises";
19501
20386
  import { basename as basename3 } from "path";
19502
20387
  import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
19503
20388
  import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
19504
- import { isAddress as isAddress11, isHex as isHex8 } from "viem";
20389
+ import { isAddress as isAddress12, isHex as isHex8 } from "viem";
19505
20390
  import { z } from "zod";
19506
20391
 
19507
20392
  // src/mcp/core.ts
@@ -19536,6 +20421,8 @@ var mcpToolSpecs = [
19536
20421
  sdkTool("write", "rare.swap.buy", "Execute a raw liquid-router token buy."),
19537
20422
  sdkTool("write", "rare.swap.sell", "Execute a raw liquid-router token sell."),
19538
20423
  sdkTool("write", "rare.swap.swapTokens", "Execute a raw liquid-router token swap."),
20424
+ sdkTool("read", "rare.bridge.quote", "Quote the native fee for bridging RARE."),
20425
+ sdkTool("write", "rare.bridge.send", "Bridge RARE to another supported chain."),
19539
20426
  sdkTool("read", "rare.swap.quoteBuyToken", "Quote buying a token with ETH."),
19540
20427
  sdkTool("write", "rare.swap.buyToken", "Buy a token with ETH."),
19541
20428
  sdkTool("read", "rare.swap.quoteSellToken", "Quote selling a token for ETH."),
@@ -19624,6 +20511,13 @@ var mcpToolNames = mcpToolSpecs.map((tool) => tool.name);
19624
20511
  function selectMcpToolNames(opts) {
19625
20512
  return opts.allowWrites ? [...mcpReadToolNames, ...mcpWriteToolNames] : [...mcpReadToolNames];
19626
20513
  }
20514
+ function shapeMcpToolAnnotations(access) {
20515
+ return {
20516
+ readOnlyHint: access === "read",
20517
+ destructiveHint: access === "write" ? true : void 0,
20518
+ openWorldHint: true
20519
+ };
20520
+ }
19627
20521
  function sdkPathToMcpToolName(sdkPath) {
19628
20522
  const path2 = sdkPath.startsWith("rare.") ? sdkPath.slice("rare.".length) : sdkPath;
19629
20523
  return path2.split(".").map(camelToSnake).join("_");
@@ -19692,7 +20586,7 @@ function isRecord10(value) {
19692
20586
  // src/mcp/server.ts
19693
20587
  var chainSchema = z.enum(supportedChains);
19694
20588
  var optionalChain = { chain: chainSchema.optional() };
19695
- var addressSchema = z.string().refine(isAddress11, "must be a valid 0x address");
20589
+ var addressSchema = z.string().refine(isAddress12, "must be a valid 0x address");
19696
20590
  var hexSchema = z.string().refine(isHex8, "must be a hex string");
19697
20591
  var integerSchema = z.union([z.string(), z.number()]);
19698
20592
  var amountSchema = z.union([z.string(), z.number()]);
@@ -19762,11 +20656,7 @@ function registerTool(server, spec) {
19762
20656
  server.registerTool(spec.name, {
19763
20657
  description: spec.description,
19764
20658
  inputSchema: tool.inputSchema,
19765
- annotations: {
19766
- readOnlyHint: spec.access === "read",
19767
- destructiveHint: spec.access === "write" ? false : void 0,
19768
- openWorldHint: true
19769
- }
20659
+ annotations: shapeMcpToolAnnotations(spec.access)
19770
20660
  }, async (args) => withToolErrors(async () => tool.handler(args)));
19771
20661
  }
19772
20662
  var toolHandlers = {
@@ -19863,6 +20753,14 @@ var toolHandlers = {
19863
20753
  inputSchema: { ...optionalChain, tokenIn: addressSchema, tokenOut: addressSchema, amountIn: amountSchema, ...rawRouteSchema, recipient: addressSchema.optional(), deadline: integerSchema.optional() },
19864
20754
  handler: ({ chain, ...args }) => callWrite(chain, async (rare) => txResult(await rare.swap.swapTokens(args)))
19865
20755
  },
20756
+ bridge_quote: {
20757
+ inputSchema: { ...optionalChain, amount: amountSchema, destinationChain: chainSchema, recipient: addressSchema.optional() },
20758
+ handler: ({ chain, ...args }) => callRead(chain, (rare) => rare.bridge.quote(args))
20759
+ },
20760
+ bridge_send: {
20761
+ inputSchema: { ...optionalChain, amount: amountSchema, destinationChain: chainSchema, recipient: addressSchema.optional(), ...autoApproveSchema },
20762
+ handler: ({ chain, ...args }) => callWrite(chain, async (rare) => txResult(await rare.bridge.send(args)))
20763
+ },
19866
20764
  swap_quote_buy_token: {
19867
20765
  inputSchema: { ...optionalChain, token: addressSchema, amountIn: amountSchema, minAmountOut: amountSchema.optional(), slippageBps: integerSchema.optional(), recipient: addressSchema.optional(), deadline: integerSchema.optional() },
19868
20766
  handler: ({ chain, ...args }) => callRead(chain, (rare) => rare.swap.quoteBuyToken(args))
@@ -20220,6 +21118,7 @@ function readRare(chain) {
20220
21118
  const selected = resolveChain(chain);
20221
21119
  return createRareClient({
20222
21120
  publicClient: getPublicClient(selected),
21121
+ account: getConfiguredAccountAddress(selected),
20223
21122
  resolveUniswapApiKey: () => getConfiguredUniswapApiKey(selected)
20224
21123
  });
20225
21124
  }
@@ -20301,7 +21200,7 @@ var McpToolError = class extends Error {
20301
21200
 
20302
21201
  // src/commands/mcp.ts
20303
21202
  function mcpCommand() {
20304
- const cmd = new Command21("mcp");
21203
+ const cmd = new Command22("mcp");
20305
21204
  cmd.description("Run MCP server integrations");
20306
21205
  cmd.command("serve").description("Start a stdio MCP server for agent-friendly RARE SDK access").option("--allow-writes", "register write-capable tools").action(async (opts) => {
20307
21206
  await serveMcp({ allowWrites: Boolean(opts.allowWrites) });
@@ -20339,7 +21238,7 @@ function requiresExplicitConfirmation(commandPath2) {
20339
21238
  // package.json
20340
21239
  var package_default = {
20341
21240
  name: "@rareprotocol/rare-cli",
20342
- version: "1.1.0",
21241
+ version: "1.2.0",
20343
21242
  description: "CLI tool for interacting with the RARE protocol smart contracts",
20344
21243
  type: "module",
20345
21244
  license: "MIT",
@@ -20453,7 +21352,7 @@ var package_default = {
20453
21352
 
20454
21353
  // src/program.ts
20455
21354
  function createRareProgram() {
20456
- const program2 = new Command22();
21355
+ const program2 = new Command23();
20457
21356
  program2.name("rare").description("CLI tool for interacting with the RARE protocol smart contracts").version(package_default.version).option("--json", "output results as JSON");
20458
21357
  program2.hook("preAction", async (_thisCommand, actionCommand) => {
20459
21358
  const decision = confirmationDecision(program2, actionCommand);
@@ -20482,6 +21381,7 @@ function createRareProgram() {
20482
21381
  program2.addCommand(collectionCommand());
20483
21382
  program2.addCommand(currenciesCommand());
20484
21383
  program2.addCommand(liquidEditionCommand());
21384
+ program2.addCommand(bridgeCommand());
20485
21385
  program2.addCommand(swapCommand());
20486
21386
  program2.addCommand(userCommand());
20487
21387
  program2.addCommand(utilsCommand());