@rareprotocol/rare-cli 1.1.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +22 -11
- package/dist/{addresses-BE3luaB3.d.ts → addresses-CcGI_7v1.d.ts} +5 -1
- package/dist/{batch-listing-Cu5Hoqxs.d.ts → batch-listing-C1CtPTD5.d.ts} +1 -1
- package/dist/client.d.ts +56 -5
- package/dist/client.js +1407 -654
- package/dist/contracts.d.ts +90 -2
- package/dist/contracts.js +140 -3
- package/dist/index.js +2003 -944
- package/dist/utils.d.ts +2 -2
- package/dist/utils.js +11 -5
- package/package.json +1 -1
package/dist/client.js
CHANGED
|
@@ -17,6 +17,7 @@ var contractAddresses = {
|
|
|
17
17
|
sepolia: {
|
|
18
18
|
factory: getAddress("0x3c7526a0975156299ceef369b8ff3c01cc670523"),
|
|
19
19
|
auction: getAddress("0xC8Edc7049b233641ad3723D6C60019D1c8771612"),
|
|
20
|
+
rareBridge: getAddress("0xdC168291658f6C5F1D0b33E573c4d289DCA9dD08"),
|
|
20
21
|
sovereignFactory: getAddress("0x46B2850ba7787734F648A6848b5eDE0815C1F8Bf"),
|
|
21
22
|
lazySovereignFactory: getAddress("0xc5B8Ad9003673a23d005A6448C74d8955a1a38fA"),
|
|
22
23
|
rareMinter: getAddress("0xd28Dc0B89104d7BBd902F338a0193fF063617ccE"),
|
|
@@ -34,6 +35,7 @@ var contractAddresses = {
|
|
|
34
35
|
mainnet: {
|
|
35
36
|
factory: getAddress("0xAe8E375a268Ed6442bEaC66C6254d6De5AeD4aB1"),
|
|
36
37
|
auction: getAddress("0x6D7c44773C52D396F43c2D511B81aa168E9a7a42"),
|
|
38
|
+
rareBridge: getAddress("0x88135dd0e7a8a2e42272dda89849a997ce2e83f7"),
|
|
37
39
|
sovereignFactory: getAddress("0xe980ec62378529d95ba446433f4deb6324129c59"),
|
|
38
40
|
lazySovereignFactory: getAddress("0xba798BD606d86D207ca2751510173532899117a1"),
|
|
39
41
|
rareMinter: getAddress("0x5fa112EFeD8297bec0010b312208d223E0cE891E"),
|
|
@@ -44,19 +46,27 @@ var contractAddresses = {
|
|
|
44
46
|
marketplaceSettings: getAddress("0x61DBF87164d33FD3695256DC8Ba74D3B1d304170"),
|
|
45
47
|
erc20ApprovalManager: getAddress("0xa837a7eAff154Ab837617Cf7250648D3Ec0A4436"),
|
|
46
48
|
erc721ApprovalManager: getAddress("0x4bb0Deea6d1A30C601338aAB776d394C2AE5c0F8"),
|
|
47
|
-
liquidFactory: getAddress("
|
|
49
|
+
liquidFactory: getAddress("0x25f993C222fE5e891128a782A5168f1C78629540"),
|
|
48
50
|
swapRouter: getAddress("0xEBd58EdA8408d9EA409f2c2bE8898BD9738f3583"),
|
|
49
51
|
v4Quoter: getAddress("0x52F0E24D1c21C8A0cB1e5a5dD6198556BD9E1203")
|
|
50
52
|
},
|
|
51
53
|
base: {
|
|
52
54
|
factory: getAddress("0xf776204233bfb52ba0ddff24810cbdbf3dbf94dd"),
|
|
53
|
-
auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2")
|
|
55
|
+
auction: getAddress("0x51c36ffb05e17ed80ee5c02fa83d7677c5613de2"),
|
|
56
|
+
rareBridge: getAddress("0x3b41e21094611d152a08d3691a70837f1a077dae")
|
|
54
57
|
},
|
|
55
58
|
"base-sepolia": {
|
|
56
59
|
factory: getAddress("0x2b181ae0f1aea6fed75591b04991b1a3f9868d51"),
|
|
57
|
-
auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2")
|
|
60
|
+
auction: getAddress("0x1f0c946f0ee87acb268d50ede6c9b4d010af65d2"),
|
|
61
|
+
rareBridge: getAddress("0xca491bb62A7730E97F500510132C47633DDD0229")
|
|
58
62
|
}
|
|
59
63
|
};
|
|
64
|
+
var ccipChainSelectors = {
|
|
65
|
+
mainnet: 5009297550715157269n,
|
|
66
|
+
sepolia: 16015286601757825753n,
|
|
67
|
+
base: 15971525489660198786n,
|
|
68
|
+
"base-sepolia": 10344971235874465080n
|
|
69
|
+
};
|
|
60
70
|
var canonicalV4Pools = {
|
|
61
71
|
sepolia: {
|
|
62
72
|
rareEthPool: {
|
|
@@ -206,6 +216,16 @@ function getCanonicalV4Pools(chain) {
|
|
|
206
216
|
}
|
|
207
217
|
return pools;
|
|
208
218
|
}
|
|
219
|
+
function getRareBridgeAddress(chain) {
|
|
220
|
+
const address = getContractAddresses(chain).rareBridge;
|
|
221
|
+
if (!address) {
|
|
222
|
+
throw new Error(`RareBridge is not configured on "${chain}". Supported RareBridge chains: mainnet, sepolia, base, base-sepolia.`);
|
|
223
|
+
}
|
|
224
|
+
return address;
|
|
225
|
+
}
|
|
226
|
+
function getCcipChainSelector(chain) {
|
|
227
|
+
return ccipChainSelectors[chain];
|
|
228
|
+
}
|
|
209
229
|
function isSupportedChain(value) {
|
|
210
230
|
return supportedChains.some((chain) => chain === value);
|
|
211
231
|
}
|
|
@@ -248,8 +268,12 @@ var RareApiError = class extends Error {
|
|
|
248
268
|
|
|
249
269
|
// src/data-access/base-url.ts
|
|
250
270
|
var DEFAULT_RARE_API_BASE_URL = "https://api.superrare.com";
|
|
271
|
+
function normalizeRareApiBaseUrlCandidate(baseUrl) {
|
|
272
|
+
const trimmedBaseUrl = baseUrl?.trim();
|
|
273
|
+
return trimmedBaseUrl === "" ? void 0 : trimmedBaseUrl;
|
|
274
|
+
}
|
|
251
275
|
function resolveRareApiBaseUrl(baseUrl) {
|
|
252
|
-
return process.env.RARE_API_BASE_URL ?? baseUrl ?? DEFAULT_RARE_API_BASE_URL;
|
|
276
|
+
return normalizeRareApiBaseUrlCandidate(process.env.RARE_API_BASE_URL) ?? normalizeRareApiBaseUrlCandidate(baseUrl) ?? DEFAULT_RARE_API_BASE_URL;
|
|
253
277
|
}
|
|
254
278
|
|
|
255
279
|
// src/data-access/client.ts
|
|
@@ -3481,6 +3505,50 @@ var auctionAbi = [
|
|
|
3481
3505
|
];
|
|
3482
3506
|
|
|
3483
3507
|
// src/sdk/approvals-shell.ts
|
|
3508
|
+
var ApprovalSideEffectError = class extends Error {
|
|
3509
|
+
operation;
|
|
3510
|
+
approvals;
|
|
3511
|
+
constructor(params) {
|
|
3512
|
+
super(
|
|
3513
|
+
`${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.`,
|
|
3514
|
+
{ cause: params.cause }
|
|
3515
|
+
);
|
|
3516
|
+
this.name = "ApprovalSideEffectError";
|
|
3517
|
+
this.operation = params.operation;
|
|
3518
|
+
this.approvals = params.approvals;
|
|
3519
|
+
}
|
|
3520
|
+
};
|
|
3521
|
+
async function runWithApprovalSideEffectAlert(params) {
|
|
3522
|
+
try {
|
|
3523
|
+
return await params.run();
|
|
3524
|
+
} catch (error) {
|
|
3525
|
+
const approvals = params.approvals.filter(hasApprovalTxHash);
|
|
3526
|
+
if (approvals.length === 0) {
|
|
3527
|
+
throw error;
|
|
3528
|
+
}
|
|
3529
|
+
throw new ApprovalSideEffectError({
|
|
3530
|
+
operation: params.operation,
|
|
3531
|
+
approvals,
|
|
3532
|
+
cause: error
|
|
3533
|
+
});
|
|
3534
|
+
}
|
|
3535
|
+
}
|
|
3536
|
+
function hasApprovalTxHash(approval) {
|
|
3537
|
+
return approval.approvalTxHash !== void 0;
|
|
3538
|
+
}
|
|
3539
|
+
function approvalSummary(approvals) {
|
|
3540
|
+
const [approval] = approvals;
|
|
3541
|
+
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(", ")}`;
|
|
3542
|
+
}
|
|
3543
|
+
function approvalDetails(approval) {
|
|
3544
|
+
if (approval.type === "erc20" || approval.type === "erc20-reset") {
|
|
3545
|
+
return `${approval.type}; token ${approval.target}; spender ${approval.spender ?? "unknown"}`;
|
|
3546
|
+
}
|
|
3547
|
+
if (approval.type === "minter") {
|
|
3548
|
+
return `minter; collection ${approval.target}; minter ${approval.minter ?? "unknown"}`;
|
|
3549
|
+
}
|
|
3550
|
+
return `nft; contract ${approval.target}; operator ${approval.operator ?? "unknown"}`;
|
|
3551
|
+
}
|
|
3484
3552
|
var approvalAbi = [
|
|
3485
3553
|
{
|
|
3486
3554
|
inputs: [{ name: "owner", type: "address" }, { name: "operator", type: "address" }],
|
|
@@ -3633,7 +3701,7 @@ async function toTokenAmount(publicClient, token, value, field) {
|
|
|
3633
3701
|
}
|
|
3634
3702
|
async function ensureTokenAllowance(publicClient, walletClient, account, owner, token, spender, amount) {
|
|
3635
3703
|
if (isAddressEqual4(token, ETH_ADDRESS) || amount === 0n) {
|
|
3636
|
-
return;
|
|
3704
|
+
return void 0;
|
|
3637
3705
|
}
|
|
3638
3706
|
const allowance = await publicClient.readContract({
|
|
3639
3707
|
address: token,
|
|
@@ -3642,7 +3710,7 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
|
|
|
3642
3710
|
args: [owner, spender]
|
|
3643
3711
|
});
|
|
3644
3712
|
if (allowance >= amount) {
|
|
3645
|
-
return;
|
|
3713
|
+
return void 0;
|
|
3646
3714
|
}
|
|
3647
3715
|
const approveTx = await walletClient.writeContract({
|
|
3648
3716
|
address: token,
|
|
@@ -3652,7 +3720,14 @@ async function ensureTokenAllowance(publicClient, walletClient, account, owner,
|
|
|
3652
3720
|
account,
|
|
3653
3721
|
chain: void 0
|
|
3654
3722
|
});
|
|
3655
|
-
await publicClient
|
|
3723
|
+
await confirmErc20Approval(publicClient, {
|
|
3724
|
+
approvalTxHash: approveTx,
|
|
3725
|
+
currency: token,
|
|
3726
|
+
accountAddress: owner,
|
|
3727
|
+
spenderAddress: spender,
|
|
3728
|
+
requiredAmount: amount
|
|
3729
|
+
});
|
|
3730
|
+
return approveTx;
|
|
3656
3731
|
}
|
|
3657
3732
|
var PaymentApprovalRequiredError = class extends Error {
|
|
3658
3733
|
requiredAmount;
|
|
@@ -3725,7 +3800,13 @@ async function preparePaymentAmountForSpender(opts) {
|
|
|
3725
3800
|
account,
|
|
3726
3801
|
chain: void 0
|
|
3727
3802
|
});
|
|
3728
|
-
await publicClient
|
|
3803
|
+
await confirmErc20Approval(publicClient, {
|
|
3804
|
+
approvalTxHash,
|
|
3805
|
+
currency,
|
|
3806
|
+
accountAddress,
|
|
3807
|
+
spenderAddress,
|
|
3808
|
+
requiredAmount
|
|
3809
|
+
});
|
|
3729
3810
|
return {
|
|
3730
3811
|
value: 0n,
|
|
3731
3812
|
requiredAmount,
|
|
@@ -3763,6 +3844,23 @@ async function readAllowance(publicClient, currency, accountAddress, spenderAddr
|
|
|
3763
3844
|
args: [accountAddress, spenderAddress]
|
|
3764
3845
|
});
|
|
3765
3846
|
}
|
|
3847
|
+
async function confirmErc20Approval(publicClient, params) {
|
|
3848
|
+
const receipt = await publicClient.waitForTransactionReceipt({ hash: params.approvalTxHash });
|
|
3849
|
+
if (receipt.status !== "success") {
|
|
3850
|
+
throw new Error(`ERC20 approval transaction ${params.approvalTxHash} did not succeed.`);
|
|
3851
|
+
}
|
|
3852
|
+
const allowance = await readAllowance(
|
|
3853
|
+
publicClient,
|
|
3854
|
+
params.currency,
|
|
3855
|
+
params.accountAddress,
|
|
3856
|
+
params.spenderAddress
|
|
3857
|
+
);
|
|
3858
|
+
if (allowance < params.requiredAmount) {
|
|
3859
|
+
throw new Error(
|
|
3860
|
+
`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.`
|
|
3861
|
+
);
|
|
3862
|
+
}
|
|
3863
|
+
}
|
|
3766
3864
|
|
|
3767
3865
|
// src/sdk/validation-core.ts
|
|
3768
3866
|
import { isHex } from "viem";
|
|
@@ -4207,6 +4305,11 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
|
|
|
4207
4305
|
accountAddress,
|
|
4208
4306
|
currentUnixTimestamp()
|
|
4209
4307
|
);
|
|
4308
|
+
const auctionType = await publicClient.readContract({
|
|
4309
|
+
address: addresses.auction,
|
|
4310
|
+
abi: auctionAbi,
|
|
4311
|
+
functionName: plan.auctionType === "scheduled" ? "SCHEDULED_AUCTION" : "COLDIE_AUCTION"
|
|
4312
|
+
});
|
|
4210
4313
|
const approvalTxHash = await approveNftContractIfNeeded({
|
|
4211
4314
|
publicClient,
|
|
4212
4315
|
walletClient,
|
|
@@ -4216,30 +4319,37 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
|
|
|
4216
4319
|
operator: addresses.auction,
|
|
4217
4320
|
autoApprove: params.autoApprove
|
|
4218
4321
|
});
|
|
4219
|
-
const
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4231
|
-
|
|
4232
|
-
|
|
4233
|
-
|
|
4234
|
-
|
|
4235
|
-
|
|
4236
|
-
|
|
4237
|
-
|
|
4238
|
-
|
|
4239
|
-
|
|
4240
|
-
|
|
4322
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4323
|
+
operation: "auction create",
|
|
4324
|
+
approvals: [{
|
|
4325
|
+
type: "nft",
|
|
4326
|
+
approvalTxHash,
|
|
4327
|
+
target: plan.nftAddress,
|
|
4328
|
+
operator: addresses.auction
|
|
4329
|
+
}],
|
|
4330
|
+
run: async () => {
|
|
4331
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4332
|
+
address: addresses.auction,
|
|
4333
|
+
abi: auctionAbi,
|
|
4334
|
+
functionName: "configureAuction",
|
|
4335
|
+
args: [
|
|
4336
|
+
auctionType,
|
|
4337
|
+
plan.nftAddress,
|
|
4338
|
+
plan.tokenId,
|
|
4339
|
+
plan.startingPrice,
|
|
4340
|
+
plan.currency,
|
|
4341
|
+
plan.duration,
|
|
4342
|
+
plan.startTime,
|
|
4343
|
+
plan.splitAddresses,
|
|
4344
|
+
plan.splitRatios
|
|
4345
|
+
],
|
|
4346
|
+
account,
|
|
4347
|
+
chain: void 0
|
|
4348
|
+
});
|
|
4349
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4350
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4351
|
+
}
|
|
4241
4352
|
});
|
|
4242
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4243
4353
|
return {
|
|
4244
4354
|
txHash,
|
|
4245
4355
|
receipt,
|
|
@@ -4265,22 +4375,34 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
|
|
|
4265
4375
|
amount: plan.amount,
|
|
4266
4376
|
autoApprove: params.autoApprove
|
|
4267
4377
|
});
|
|
4268
|
-
const txHash = await
|
|
4269
|
-
|
|
4270
|
-
|
|
4271
|
-
|
|
4272
|
-
|
|
4273
|
-
|
|
4274
|
-
|
|
4275
|
-
|
|
4378
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4379
|
+
operation: "auction bid",
|
|
4380
|
+
approvals: [{
|
|
4381
|
+
type: "erc20",
|
|
4382
|
+
approvalTxHash: payment.approvalTxHash,
|
|
4383
|
+
target: plan.currency,
|
|
4384
|
+
spender: addresses.auction
|
|
4385
|
+
}],
|
|
4386
|
+
run: async () => {
|
|
4387
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4388
|
+
address: addresses.auction,
|
|
4389
|
+
abi: auctionAbi,
|
|
4390
|
+
functionName: "bid",
|
|
4391
|
+
args: [params.contract, plan.tokenId, plan.currency, plan.amount],
|
|
4392
|
+
account,
|
|
4393
|
+
chain: void 0,
|
|
4394
|
+
value: payment.value
|
|
4395
|
+
});
|
|
4396
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4397
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4398
|
+
}
|
|
4276
4399
|
});
|
|
4277
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4278
4400
|
return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
|
|
4279
4401
|
},
|
|
4280
4402
|
async settle(params) {
|
|
4281
4403
|
const { walletClient, account } = requireWallet(config);
|
|
4282
4404
|
const plan = planAuctionTokenAction(params);
|
|
4283
|
-
const
|
|
4405
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4284
4406
|
address: addresses.auction,
|
|
4285
4407
|
abi: auctionAbi,
|
|
4286
4408
|
functionName: "settleAuction",
|
|
@@ -4288,13 +4410,13 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
|
|
|
4288
4410
|
account,
|
|
4289
4411
|
chain: void 0
|
|
4290
4412
|
});
|
|
4291
|
-
const
|
|
4292
|
-
return { txHash, receipt };
|
|
4413
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4414
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4293
4415
|
},
|
|
4294
4416
|
async cancel(params) {
|
|
4295
4417
|
const { walletClient, account } = requireWallet(config);
|
|
4296
4418
|
const plan = planAuctionTokenAction(params);
|
|
4297
|
-
const
|
|
4419
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4298
4420
|
address: addresses.auction,
|
|
4299
4421
|
abi: auctionAbi,
|
|
4300
4422
|
functionName: "cancelAuction",
|
|
@@ -4302,8 +4424,8 @@ function createAuctionNamespace(publicClient, config, chain, addresses) {
|
|
|
4302
4424
|
account,
|
|
4303
4425
|
chain: void 0
|
|
4304
4426
|
});
|
|
4305
|
-
const
|
|
4306
|
-
return { txHash, receipt };
|
|
4427
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4428
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4307
4429
|
},
|
|
4308
4430
|
async status(params) {
|
|
4309
4431
|
const plan = planAuctionTokenAction(params);
|
|
@@ -4380,23 +4502,35 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
|
|
|
4380
4502
|
amount: plan.amount,
|
|
4381
4503
|
autoApprove: params.autoApprove
|
|
4382
4504
|
});
|
|
4383
|
-
const txHash = await
|
|
4384
|
-
|
|
4385
|
-
|
|
4386
|
-
|
|
4387
|
-
|
|
4388
|
-
|
|
4389
|
-
|
|
4390
|
-
|
|
4505
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4506
|
+
operation: "offer create",
|
|
4507
|
+
approvals: [{
|
|
4508
|
+
type: "erc20",
|
|
4509
|
+
approvalTxHash: payment.approvalTxHash,
|
|
4510
|
+
target: plan.currency,
|
|
4511
|
+
spender: addresses.auction
|
|
4512
|
+
}],
|
|
4513
|
+
run: async () => {
|
|
4514
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4515
|
+
address: addresses.auction,
|
|
4516
|
+
abi: auctionAbi,
|
|
4517
|
+
functionName: "offer",
|
|
4518
|
+
args: [params.contract, plan.tokenId, plan.currency, plan.amount, false],
|
|
4519
|
+
account,
|
|
4520
|
+
chain: void 0,
|
|
4521
|
+
value: payment.value
|
|
4522
|
+
});
|
|
4523
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4524
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4525
|
+
}
|
|
4391
4526
|
});
|
|
4392
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4393
4527
|
return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
|
|
4394
4528
|
},
|
|
4395
4529
|
async cancel(params) {
|
|
4396
4530
|
const { walletClient, account } = requireWallet(config);
|
|
4397
4531
|
const currency = params.currency === void 0 ? ETH_ADDRESS : resolveCurrencyForSdk(params.currency, chain).address;
|
|
4398
4532
|
const plan = planOfferCancel({ ...params, currency });
|
|
4399
|
-
const
|
|
4533
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4400
4534
|
address: addresses.auction,
|
|
4401
4535
|
abi: auctionAbi,
|
|
4402
4536
|
functionName: "cancelOffer",
|
|
@@ -4404,8 +4538,8 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
|
|
|
4404
4538
|
account,
|
|
4405
4539
|
chain: void 0
|
|
4406
4540
|
});
|
|
4407
|
-
const
|
|
4408
|
-
return { txHash, receipt };
|
|
4541
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4542
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4409
4543
|
},
|
|
4410
4544
|
async accept(params) {
|
|
4411
4545
|
const { walletClient, account, accountAddress } = requireWallet(config);
|
|
@@ -4422,22 +4556,34 @@ function createOfferNamespace(publicClient, config, chain, addresses) {
|
|
|
4422
4556
|
operator: addresses.auction,
|
|
4423
4557
|
autoApprove: params.autoApprove
|
|
4424
4558
|
});
|
|
4425
|
-
const txHash = await
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4429
|
-
|
|
4430
|
-
params.contract,
|
|
4431
|
-
|
|
4432
|
-
|
|
4433
|
-
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4559
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4560
|
+
operation: "offer accept",
|
|
4561
|
+
approvals: [{
|
|
4562
|
+
type: "nft",
|
|
4563
|
+
approvalTxHash,
|
|
4564
|
+
target: params.contract,
|
|
4565
|
+
operator: addresses.auction
|
|
4566
|
+
}],
|
|
4567
|
+
run: async () => {
|
|
4568
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4569
|
+
address: addresses.auction,
|
|
4570
|
+
abi: auctionAbi,
|
|
4571
|
+
functionName: "acceptOffer",
|
|
4572
|
+
args: [
|
|
4573
|
+
params.contract,
|
|
4574
|
+
plan.tokenId,
|
|
4575
|
+
plan.currency,
|
|
4576
|
+
plan.amount,
|
|
4577
|
+
plan.splitAddresses,
|
|
4578
|
+
plan.splitRatios
|
|
4579
|
+
],
|
|
4580
|
+
account,
|
|
4581
|
+
chain: void 0
|
|
4582
|
+
});
|
|
4583
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4584
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4585
|
+
}
|
|
4439
4586
|
});
|
|
4440
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4441
4587
|
return { txHash, receipt, approvalTxHash };
|
|
4442
4588
|
},
|
|
4443
4589
|
async status(params) {
|
|
@@ -4502,29 +4648,41 @@ function createListingNamespace(publicClient, config, chain, addresses) {
|
|
|
4502
4648
|
operator: addresses.auction,
|
|
4503
4649
|
autoApprove: params.autoApprove
|
|
4504
4650
|
});
|
|
4505
|
-
const txHash = await
|
|
4506
|
-
|
|
4507
|
-
|
|
4508
|
-
|
|
4509
|
-
|
|
4510
|
-
plan.nftAddress,
|
|
4511
|
-
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
4519
|
-
|
|
4651
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4652
|
+
operation: "listing create",
|
|
4653
|
+
approvals: [{
|
|
4654
|
+
type: "nft",
|
|
4655
|
+
approvalTxHash,
|
|
4656
|
+
target: plan.nftAddress,
|
|
4657
|
+
operator: addresses.auction
|
|
4658
|
+
}],
|
|
4659
|
+
run: async () => {
|
|
4660
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4661
|
+
address: addresses.auction,
|
|
4662
|
+
abi: auctionAbi,
|
|
4663
|
+
functionName: "setSalePrice",
|
|
4664
|
+
args: [
|
|
4665
|
+
plan.nftAddress,
|
|
4666
|
+
plan.tokenId,
|
|
4667
|
+
plan.currency,
|
|
4668
|
+
plan.price,
|
|
4669
|
+
plan.target,
|
|
4670
|
+
plan.splitAddresses,
|
|
4671
|
+
plan.splitRatios
|
|
4672
|
+
],
|
|
4673
|
+
account,
|
|
4674
|
+
chain: void 0
|
|
4675
|
+
});
|
|
4676
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4677
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4678
|
+
}
|
|
4520
4679
|
});
|
|
4521
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4522
4680
|
return { txHash, receipt, approvalTxHash };
|
|
4523
4681
|
},
|
|
4524
4682
|
async cancel(params) {
|
|
4525
4683
|
const { walletClient, account } = requireWallet(config);
|
|
4526
4684
|
const plan = planListingCancel(params);
|
|
4527
|
-
const
|
|
4685
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4528
4686
|
address: addresses.auction,
|
|
4529
4687
|
abi: auctionAbi,
|
|
4530
4688
|
functionName: "removeSalePrice",
|
|
@@ -4532,8 +4690,8 @@ function createListingNamespace(publicClient, config, chain, addresses) {
|
|
|
4532
4690
|
account,
|
|
4533
4691
|
chain: void 0
|
|
4534
4692
|
});
|
|
4535
|
-
const
|
|
4536
|
-
return { txHash, receipt };
|
|
4693
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4694
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4537
4695
|
},
|
|
4538
4696
|
async buy(params) {
|
|
4539
4697
|
const { walletClient, account, accountAddress } = requireWallet(config);
|
|
@@ -4552,16 +4710,28 @@ function createListingNamespace(publicClient, config, chain, addresses) {
|
|
|
4552
4710
|
amount: plan.amount,
|
|
4553
4711
|
autoApprove: params.autoApprove
|
|
4554
4712
|
});
|
|
4555
|
-
const txHash = await
|
|
4556
|
-
|
|
4557
|
-
|
|
4558
|
-
|
|
4559
|
-
|
|
4560
|
-
|
|
4561
|
-
|
|
4562
|
-
|
|
4713
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
4714
|
+
operation: "listing buy",
|
|
4715
|
+
approvals: [{
|
|
4716
|
+
type: "erc20",
|
|
4717
|
+
approvalTxHash: payment.approvalTxHash,
|
|
4718
|
+
target: plan.currency,
|
|
4719
|
+
spender: addresses.auction
|
|
4720
|
+
}],
|
|
4721
|
+
run: async () => {
|
|
4722
|
+
const targetTxHash = await walletClient.writeContract({
|
|
4723
|
+
address: addresses.auction,
|
|
4724
|
+
abi: auctionAbi,
|
|
4725
|
+
functionName: "buy",
|
|
4726
|
+
args: [params.contract, plan.tokenId, plan.currency, plan.amount],
|
|
4727
|
+
account,
|
|
4728
|
+
chain: void 0,
|
|
4729
|
+
value: payment.value
|
|
4730
|
+
});
|
|
4731
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
4732
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
4733
|
+
}
|
|
4563
4734
|
});
|
|
4564
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
4565
4735
|
return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
|
|
4566
4736
|
},
|
|
4567
4737
|
async status(params) {
|
|
@@ -4579,7 +4749,7 @@ function createListingNamespace(publicClient, config, chain, addresses) {
|
|
|
4579
4749
|
}
|
|
4580
4750
|
|
|
4581
4751
|
// src/sdk/batch-listing.ts
|
|
4582
|
-
import { isAddressEqual as
|
|
4752
|
+
import { isAddressEqual as isAddressEqual10 } from "viem";
|
|
4583
4753
|
|
|
4584
4754
|
// src/contracts/abis/batch-listing.ts
|
|
4585
4755
|
var batchListingAbi = [
|
|
@@ -5284,10 +5454,158 @@ function uniqueRoots(roots) {
|
|
|
5284
5454
|
}
|
|
5285
5455
|
|
|
5286
5456
|
// src/sdk/batch-listing-core.ts
|
|
5287
|
-
import { isAddressEqual as
|
|
5457
|
+
import { isAddressEqual as isAddressEqual9 } from "viem";
|
|
5458
|
+
|
|
5459
|
+
// src/sdk/merkle-core.ts
|
|
5460
|
+
import { Buffer } from "buffer";
|
|
5461
|
+
import { MerkleTree } from "merkletreejs";
|
|
5462
|
+
import {
|
|
5463
|
+
encodePacked as encodePacked2,
|
|
5464
|
+
getAddress as getAddress6,
|
|
5465
|
+
isAddress as isAddress5,
|
|
5466
|
+
isAddressEqual as isAddressEqual8,
|
|
5467
|
+
isHex as isHex3,
|
|
5468
|
+
keccak256 as keccak2562
|
|
5469
|
+
} from "viem";
|
|
5470
|
+
function hexBuffer(hex) {
|
|
5471
|
+
return Buffer.from(hex.startsWith("0x") ? hex.slice(2) : hex, "hex");
|
|
5472
|
+
}
|
|
5473
|
+
function tokenLeaf(contract, tokenId) {
|
|
5474
|
+
const packed = encodePacked2(["address", "uint256"], [contract, tokenId]);
|
|
5475
|
+
return hexBuffer(keccak2562(packed));
|
|
5476
|
+
}
|
|
5477
|
+
function addressLeaf(address) {
|
|
5478
|
+
return hexBuffer(keccak2562(address));
|
|
5479
|
+
}
|
|
5480
|
+
function parseBytes32(value, field) {
|
|
5481
|
+
if (!isHex3(value, { strict: true }) || value.length !== 66) {
|
|
5482
|
+
throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
|
|
5483
|
+
}
|
|
5484
|
+
const normalized = value.toLowerCase();
|
|
5485
|
+
if (!isHex3(normalized, { strict: true }) || normalized.length !== 66) {
|
|
5486
|
+
throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
|
|
5487
|
+
}
|
|
5488
|
+
return normalized;
|
|
5489
|
+
}
|
|
5490
|
+
function parseBytes32Array(values, field) {
|
|
5491
|
+
return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
|
|
5492
|
+
}
|
|
5493
|
+
function compareTokenEntries(a, b) {
|
|
5494
|
+
if (!isAddressEqual8(a.contract, b.contract)) {
|
|
5495
|
+
return a.contract.localeCompare(b.contract);
|
|
5496
|
+
}
|
|
5497
|
+
return a.tokenId.localeCompare(b.tokenId);
|
|
5498
|
+
}
|
|
5499
|
+
function normalizeTokenEntry(token) {
|
|
5500
|
+
if (!isAddress5(token.contract)) {
|
|
5501
|
+
throw new Error(`Invalid token contract address: ${token.contract}`);
|
|
5502
|
+
}
|
|
5503
|
+
return {
|
|
5504
|
+
contract: getAddress6(token.contract),
|
|
5505
|
+
tokenId: String(token.tokenId),
|
|
5506
|
+
tokenIdBigInt: toInteger(token.tokenId, "tokenId")
|
|
5507
|
+
};
|
|
5508
|
+
}
|
|
5509
|
+
function buildBatchListingTree(tokens) {
|
|
5510
|
+
if (tokens.length < 2) {
|
|
5511
|
+
throw new Error("buildBatchListingTree requires at least two tokens");
|
|
5512
|
+
}
|
|
5513
|
+
const sorted = tokens.map(normalizeTokenEntry).sort(compareTokenEntries);
|
|
5514
|
+
const leaves = sorted.map((token) => tokenLeaf(token.contract, token.tokenIdBigInt));
|
|
5515
|
+
const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2562(data)), {
|
|
5516
|
+
sortPairs: true
|
|
5517
|
+
});
|
|
5518
|
+
return {
|
|
5519
|
+
root: parseBytes32(tree.getHexRoot(), "root"),
|
|
5520
|
+
tree,
|
|
5521
|
+
sortedTokens: sorted.map(({ contract, tokenId }) => ({ contract, tokenId }))
|
|
5522
|
+
};
|
|
5523
|
+
}
|
|
5524
|
+
function buildAllowListTree(addresses) {
|
|
5525
|
+
if (addresses.length < 2) {
|
|
5526
|
+
throw new Error("buildAllowListTree requires at least two addresses");
|
|
5527
|
+
}
|
|
5528
|
+
const sorted = addresses.map((address) => {
|
|
5529
|
+
if (!isAddress5(address)) throw new Error(`Invalid allowlist address: ${address}`);
|
|
5530
|
+
return getAddress6(address);
|
|
5531
|
+
}).sort((a, b) => a.localeCompare(b));
|
|
5532
|
+
const leaves = sorted.map(addressLeaf);
|
|
5533
|
+
const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2562(data)), {
|
|
5534
|
+
sortPairs: true
|
|
5535
|
+
});
|
|
5536
|
+
return {
|
|
5537
|
+
root: parseBytes32(tree.getHexRoot(), "root"),
|
|
5538
|
+
tree,
|
|
5539
|
+
sortedAddresses: sorted
|
|
5540
|
+
};
|
|
5541
|
+
}
|
|
5542
|
+
function getTokenProof(tree, contract, tokenId) {
|
|
5543
|
+
const leaf = tokenLeaf(getAddress6(contract), tokenId);
|
|
5544
|
+
return parseBytes32Array(tree.getHexProof(leaf), "proof");
|
|
5545
|
+
}
|
|
5546
|
+
function getAddressProof(tree, address) {
|
|
5547
|
+
const leaf = addressLeaf(getAddress6(address));
|
|
5548
|
+
return parseBytes32Array(tree.getHexProof(leaf), "proof");
|
|
5549
|
+
}
|
|
5550
|
+
function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
|
|
5551
|
+
const tokenIdBig = toInteger(tokenId, "tokenId");
|
|
5552
|
+
const contractChecksum = getAddress6(contract);
|
|
5553
|
+
const found = artifact.tokens.find(
|
|
5554
|
+
(token) => isAddressEqual8(token.contract, contractChecksum) && BigInt(token.tokenId) === tokenIdBig
|
|
5555
|
+
);
|
|
5556
|
+
if (found === void 0) {
|
|
5557
|
+
throw new Error(
|
|
5558
|
+
`Token ${contractChecksum}/${tokenIdBig.toString()} is not in this root artifact's token set`
|
|
5559
|
+
);
|
|
5560
|
+
}
|
|
5561
|
+
const { tree, root } = buildBatchListingTree(
|
|
5562
|
+
artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
|
|
5563
|
+
);
|
|
5564
|
+
const artifactRoot = parseBytes32(artifact.root, "artifact.root");
|
|
5565
|
+
if (root !== artifactRoot) {
|
|
5566
|
+
throw new Error(
|
|
5567
|
+
`Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
|
|
5568
|
+
);
|
|
5569
|
+
}
|
|
5570
|
+
const allowListProofFields = buildAllowListProofFields(artifact, buyer);
|
|
5571
|
+
return {
|
|
5572
|
+
root: artifactRoot,
|
|
5573
|
+
contract: contractChecksum,
|
|
5574
|
+
tokenId: tokenIdBig.toString(),
|
|
5575
|
+
proof: getTokenProof(tree, contractChecksum, tokenIdBig),
|
|
5576
|
+
...allowListProofFields ?? {}
|
|
5577
|
+
};
|
|
5578
|
+
}
|
|
5579
|
+
function buildAllowListProofFields(artifact, buyer) {
|
|
5580
|
+
if (artifact.allowList === void 0) return void 0;
|
|
5581
|
+
if (buyer === void 0) {
|
|
5582
|
+
throw new Error(
|
|
5583
|
+
"This root has an allowlist; pass buyer address to buildMerkleProofArtifact to include allowListProof"
|
|
5584
|
+
);
|
|
5585
|
+
}
|
|
5586
|
+
if (!isAddress5(buyer)) throw new Error(`Invalid buyer address: ${buyer}`);
|
|
5587
|
+
const buyerChecksum = getAddress6(buyer);
|
|
5588
|
+
const inAllowList = artifact.allowList.addresses.some((address) => isAddressEqual8(address, buyerChecksum));
|
|
5589
|
+
if (!inAllowList) {
|
|
5590
|
+
throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
|
|
5591
|
+
}
|
|
5592
|
+
const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
|
|
5593
|
+
const artifactAllowListRoot = parseBytes32(artifact.allowList.root, "allowList.root");
|
|
5594
|
+
if (root !== artifactAllowListRoot) {
|
|
5595
|
+
throw new Error(
|
|
5596
|
+
`Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
|
|
5597
|
+
);
|
|
5598
|
+
}
|
|
5599
|
+
return {
|
|
5600
|
+
allowListProof: getAddressProof(tree, buyerChecksum),
|
|
5601
|
+
allowListAddress: buyerChecksum
|
|
5602
|
+
};
|
|
5603
|
+
}
|
|
5604
|
+
|
|
5605
|
+
// src/sdk/batch-listing-core.ts
|
|
5288
5606
|
function uniqueAddresses(addresses) {
|
|
5289
5607
|
return addresses.reduce(
|
|
5290
|
-
(unique, address) => unique.some((existing) =>
|
|
5608
|
+
(unique, address) => unique.some((existing) => isAddressEqual9(existing, address)) ? unique : [...unique, address],
|
|
5291
5609
|
[]
|
|
5292
5610
|
);
|
|
5293
5611
|
}
|
|
@@ -5331,7 +5649,7 @@ function shapeBatchListingStatus(params) {
|
|
|
5331
5649
|
splitRecipients: [...params.listingConfig.splitRecipients],
|
|
5332
5650
|
splitRatios: [...params.listingConfig.splitRatios],
|
|
5333
5651
|
nonce: params.listingConfig.nonce,
|
|
5334
|
-
isEth:
|
|
5652
|
+
isEth: isAddressEqual9(params.listingConfig.currency, ETH_ADDRESS),
|
|
5335
5653
|
hasListing,
|
|
5336
5654
|
allowList: params.allowList,
|
|
5337
5655
|
...params.tokenStatus
|
|
@@ -5362,13 +5680,13 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5362
5680
|
functionName: "ownerOf",
|
|
5363
5681
|
args: [BigInt(token.tokenId)]
|
|
5364
5682
|
});
|
|
5365
|
-
if (!
|
|
5683
|
+
if (!isAddressEqual10(owner, accountAddress)) {
|
|
5366
5684
|
throw new Error(
|
|
5367
5685
|
`Token ${token.contract}/${token.tokenId} is owned by ${owner}, not the configured account ${accountAddress}. Re-check the token set before registering this batch listing.`
|
|
5368
5686
|
);
|
|
5369
5687
|
}
|
|
5370
5688
|
}
|
|
5371
|
-
const
|
|
5689
|
+
const nftApprovals = await approveNftContracts({
|
|
5372
5690
|
publicClient,
|
|
5373
5691
|
walletClient,
|
|
5374
5692
|
account,
|
|
@@ -5377,26 +5695,38 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5377
5695
|
nftAddresses: uniqueContracts,
|
|
5378
5696
|
autoApprove: params.autoApprove
|
|
5379
5697
|
});
|
|
5380
|
-
const txHash = await
|
|
5381
|
-
|
|
5382
|
-
|
|
5383
|
-
|
|
5384
|
-
|
|
5385
|
-
|
|
5386
|
-
|
|
5387
|
-
|
|
5388
|
-
|
|
5389
|
-
|
|
5390
|
-
|
|
5391
|
-
|
|
5392
|
-
|
|
5698
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
5699
|
+
operation: "batch listing create",
|
|
5700
|
+
approvals: nftApprovals.map((approval) => ({
|
|
5701
|
+
type: "nft",
|
|
5702
|
+
approvalTxHash: approval.txHash,
|
|
5703
|
+
target: approval.nftAddress,
|
|
5704
|
+
operator: addresses.erc721ApprovalManager
|
|
5705
|
+
})),
|
|
5706
|
+
run: async () => {
|
|
5707
|
+
const targetTxHash = await walletClient.writeContract({
|
|
5708
|
+
address: addresses.batchListing,
|
|
5709
|
+
abi: batchListingAbi,
|
|
5710
|
+
functionName: "registerSalePriceMerkleRoot",
|
|
5711
|
+
args: [
|
|
5712
|
+
artifact.root,
|
|
5713
|
+
artifact.currency,
|
|
5714
|
+
BigInt(artifact.amount),
|
|
5715
|
+
splitConfig.splitAddresses,
|
|
5716
|
+
splitConfig.splitRatios
|
|
5717
|
+
],
|
|
5718
|
+
account,
|
|
5719
|
+
chain: void 0
|
|
5720
|
+
});
|
|
5721
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
5722
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
5723
|
+
}
|
|
5393
5724
|
});
|
|
5394
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
5395
5725
|
return {
|
|
5396
5726
|
txHash,
|
|
5397
5727
|
receipt,
|
|
5398
5728
|
root: artifact.root,
|
|
5399
|
-
approvalTxHashes:
|
|
5729
|
+
approvalTxHashes: nftApprovals.length > 0 ? nftApprovals.map((approval) => approval.txHash) : void 0
|
|
5400
5730
|
};
|
|
5401
5731
|
},
|
|
5402
5732
|
async cancel(params) {
|
|
@@ -5409,7 +5739,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5409
5739
|
creator: accountAddress,
|
|
5410
5740
|
params
|
|
5411
5741
|
});
|
|
5412
|
-
const
|
|
5742
|
+
const targetTxHash = await walletClient.writeContract({
|
|
5413
5743
|
address: addresses.batchListing,
|
|
5414
5744
|
abi: batchListingAbi,
|
|
5415
5745
|
functionName: "cancelSalePriceMerkleRoot",
|
|
@@ -5417,8 +5747,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5417
5747
|
account,
|
|
5418
5748
|
chain: void 0
|
|
5419
5749
|
});
|
|
5420
|
-
const
|
|
5421
|
-
return { txHash, receipt, root };
|
|
5750
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
5751
|
+
return { txHash: targetTxHash, receipt: targetReceipt, root };
|
|
5422
5752
|
},
|
|
5423
5753
|
async buy(params) {
|
|
5424
5754
|
const { walletClient, account, accountAddress } = requireWallet(config);
|
|
@@ -5449,25 +5779,37 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5449
5779
|
amount,
|
|
5450
5780
|
autoApprove: params.autoApprove
|
|
5451
5781
|
});
|
|
5452
|
-
const txHash = await
|
|
5453
|
-
|
|
5454
|
-
|
|
5455
|
-
|
|
5456
|
-
|
|
5457
|
-
|
|
5458
|
-
|
|
5459
|
-
|
|
5460
|
-
|
|
5461
|
-
|
|
5462
|
-
|
|
5463
|
-
|
|
5464
|
-
|
|
5465
|
-
|
|
5466
|
-
|
|
5467
|
-
|
|
5468
|
-
|
|
5782
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
5783
|
+
operation: "batch listing buy",
|
|
5784
|
+
approvals: [{
|
|
5785
|
+
type: "erc20",
|
|
5786
|
+
approvalTxHash: payment.approvalTxHash,
|
|
5787
|
+
target: currency,
|
|
5788
|
+
spender: addresses.erc20ApprovalManager
|
|
5789
|
+
}],
|
|
5790
|
+
run: async () => {
|
|
5791
|
+
const targetTxHash = await walletClient.writeContract({
|
|
5792
|
+
address: addresses.batchListing,
|
|
5793
|
+
abi: batchListingAbi,
|
|
5794
|
+
functionName: "buyWithMerkleProof",
|
|
5795
|
+
args: [
|
|
5796
|
+
proofArtifact.contract,
|
|
5797
|
+
tokenIdBig,
|
|
5798
|
+
currency,
|
|
5799
|
+
amount,
|
|
5800
|
+
params.creator,
|
|
5801
|
+
proofArtifact.root,
|
|
5802
|
+
proofArtifact.proof,
|
|
5803
|
+
allowListProof
|
|
5804
|
+
],
|
|
5805
|
+
account,
|
|
5806
|
+
chain: void 0,
|
|
5807
|
+
value: payment.value
|
|
5808
|
+
});
|
|
5809
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
5810
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
5811
|
+
}
|
|
5469
5812
|
});
|
|
5470
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
5471
5813
|
return { txHash, receipt, approvalTxHash: payment.approvalTxHash };
|
|
5472
5814
|
},
|
|
5473
5815
|
async setAllowlist(params) {
|
|
@@ -5485,7 +5827,7 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5485
5827
|
requireInput(params.endTime ?? params.artifact?.allowList?.endTimestamp, "endTime"),
|
|
5486
5828
|
"endTime"
|
|
5487
5829
|
);
|
|
5488
|
-
const
|
|
5830
|
+
const targetTxHash = await walletClient.writeContract({
|
|
5489
5831
|
address: addresses.batchListing,
|
|
5490
5832
|
abi: batchListingAbi,
|
|
5491
5833
|
functionName: "setAllowListConfig",
|
|
@@ -5493,8 +5835,8 @@ function createBatchListingNamespace(publicClient, config, addresses) {
|
|
|
5493
5835
|
account,
|
|
5494
5836
|
chain: void 0
|
|
5495
5837
|
});
|
|
5496
|
-
const
|
|
5497
|
-
return { txHash, receipt, root, allowListRoot, endTime };
|
|
5838
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
5839
|
+
return { txHash: targetTxHash, receipt: targetReceipt, root, allowListRoot, endTime };
|
|
5498
5840
|
},
|
|
5499
5841
|
async status(params) {
|
|
5500
5842
|
const resolvedParams = await resolveBatchListingStatusParams({
|
|
@@ -5723,7 +6065,7 @@ function isHash(value) {
|
|
|
5723
6065
|
}
|
|
5724
6066
|
async function approveNftContracts(opts) {
|
|
5725
6067
|
return opts.nftAddresses.reduce(async (previous, nftAddress) => {
|
|
5726
|
-
const
|
|
6068
|
+
const approvals = await previous;
|
|
5727
6069
|
const txHash = await approveNftContractIfNeeded({
|
|
5728
6070
|
publicClient: opts.publicClient,
|
|
5729
6071
|
walletClient: opts.walletClient,
|
|
@@ -5733,7 +6075,7 @@ async function approveNftContracts(opts) {
|
|
|
5733
6075
|
operator: opts.operator,
|
|
5734
6076
|
autoApprove: opts.autoApprove
|
|
5735
6077
|
});
|
|
5736
|
-
return isHash(txHash) ? [...
|
|
6078
|
+
return isHash(txHash) ? [...approvals, { nftAddress, txHash }] : approvals;
|
|
5737
6079
|
}, Promise.resolve([]));
|
|
5738
6080
|
}
|
|
5739
6081
|
async function prepareBatchListingPayment(opts) {
|
|
@@ -5786,7 +6128,7 @@ async function readTokenStatus(publicClient, batchListingAddress, params) {
|
|
|
5786
6128
|
|
|
5787
6129
|
// src/sdk/batch-auction.ts
|
|
5788
6130
|
import {
|
|
5789
|
-
isAddressEqual as
|
|
6131
|
+
isAddressEqual as isAddressEqual12,
|
|
5790
6132
|
parseUnits as parseUnits3,
|
|
5791
6133
|
parseEventLogs as parseEventLogs3
|
|
5792
6134
|
} from "viem";
|
|
@@ -6018,7 +6360,7 @@ var batchAuctionHouseAbi = [
|
|
|
6018
6360
|
];
|
|
6019
6361
|
|
|
6020
6362
|
// src/sdk/batch-auction-core.ts
|
|
6021
|
-
import { isAddressEqual as
|
|
6363
|
+
import { isAddressEqual as isAddressEqual11 } from "viem";
|
|
6022
6364
|
var zeroAddress3 = ETH_ADDRESS;
|
|
6023
6365
|
var marketplaceFeePercentage = 3n;
|
|
6024
6366
|
function planBatchAuctionCreateLocalInputs(params, nowSeconds) {
|
|
@@ -6103,17 +6445,19 @@ function planBatchAuctionStatus(params) {
|
|
|
6103
6445
|
};
|
|
6104
6446
|
}
|
|
6105
6447
|
function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
|
|
6106
|
-
const hasAuction = details.startingTime > 0n && !
|
|
6107
|
-
const
|
|
6108
|
-
const
|
|
6448
|
+
const hasAuction = details.startingTime > 0n && !isAddressEqual11(details.seller, zeroAddress3);
|
|
6449
|
+
const hasCurrentRootConfig = rootContext !== void 0 && rootContext.config.duration > 0n && rootContext.rootNonce === rootContext.config.nonce;
|
|
6450
|
+
const currentRootConfig = hasCurrentRootConfig ? rootContext.config : void 0;
|
|
6451
|
+
const hasRootConfig = currentRootConfig !== void 0;
|
|
6452
|
+
const duration = hasAuction ? details.duration : currentRootConfig?.duration ?? 0n;
|
|
6109
6453
|
const startingTime = hasAuction ? details.startingTime : 0n;
|
|
6110
6454
|
const endTime = hasAuction ? startingTime + duration : null;
|
|
6111
6455
|
const ended = endTime !== null && nowSeconds >= endTime;
|
|
6112
|
-
const currentBidder = currentBid.amount > 0n && !
|
|
6456
|
+
const currentBidder = currentBid.amount > 0n && !isAddressEqual11(currentBid.bidder, zeroAddress3) ? currentBid.bidder : null;
|
|
6113
6457
|
const seller = hasAuction ? details.seller : rootContext?.creator ?? zeroAddress3;
|
|
6114
|
-
const currency = hasAuction ? details.currency :
|
|
6115
|
-
const reserveAmount = hasAuction ? details.reserveAmount :
|
|
6116
|
-
const tokenNonceConsumed = rootContext === void 0 ? null : rootContext.tokenNonce >= rootContext.config.nonce;
|
|
6458
|
+
const currency = hasAuction ? details.currency : currentRootConfig?.currency ?? ETH_ADDRESS;
|
|
6459
|
+
const reserveAmount = hasAuction ? details.reserveAmount : currentRootConfig?.reserveAmount ?? 0n;
|
|
6460
|
+
const tokenNonceConsumed = rootContext === void 0 ? null : !hasCurrentRootConfig || rootContext.tokenNonce >= rootContext.config.nonce;
|
|
6117
6461
|
return {
|
|
6118
6462
|
seller,
|
|
6119
6463
|
root: rootContext?.root ?? null,
|
|
@@ -6123,8 +6467,8 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
|
|
|
6123
6467
|
creationBlock: details.creationBlock,
|
|
6124
6468
|
startingTime,
|
|
6125
6469
|
endTime,
|
|
6126
|
-
splitAddresses: resolveStatusSplitAddresses(hasAuction, details,
|
|
6127
|
-
splitRatios: resolveStatusSplitRatios(hasAuction, details,
|
|
6470
|
+
splitAddresses: resolveStatusSplitAddresses(hasAuction, details, currentRootConfig),
|
|
6471
|
+
splitRatios: resolveStatusSplitRatios(hasAuction, details, currentRootConfig),
|
|
6128
6472
|
hasRootConfig,
|
|
6129
6473
|
rootNonce: rootContext?.rootNonce ?? null,
|
|
6130
6474
|
tokenNonce: rootContext?.tokenNonce ?? null,
|
|
@@ -6144,7 +6488,7 @@ function shapeBatchAuctionStatus(details, currentBid, rootContext, nowSeconds) {
|
|
|
6144
6488
|
hasRootConfig,
|
|
6145
6489
|
tokenNonceConsumed
|
|
6146
6490
|
}),
|
|
6147
|
-
isEth:
|
|
6491
|
+
isEth: isAddressEqual11(currency, ETH_ADDRESS)
|
|
6148
6492
|
};
|
|
6149
6493
|
}
|
|
6150
6494
|
function shapeBatchAuctionDetailsRead(details) {
|
|
@@ -6255,28 +6599,28 @@ function planSplitRecipients(splitAddresses, splitRatios, accountAddress) {
|
|
|
6255
6599
|
};
|
|
6256
6600
|
}
|
|
6257
6601
|
function uniqueAddresses2(addresses) {
|
|
6258
|
-
return addresses.reduce((unique, address) => unique.some((candidate) =>
|
|
6602
|
+
return addresses.reduce((unique, address) => unique.some((candidate) => isAddressEqual11(candidate, address)) ? unique : [...unique, address], []);
|
|
6259
6603
|
}
|
|
6260
6604
|
function addMinimumBidIncrease(amount) {
|
|
6261
6605
|
return amount + amount * marketplaceFeePercentage / 100n;
|
|
6262
6606
|
}
|
|
6263
|
-
function resolveStatusSplitAddresses(hasAuction, details,
|
|
6607
|
+
function resolveStatusSplitAddresses(hasAuction, details, rootConfig) {
|
|
6264
6608
|
if (hasAuction) {
|
|
6265
6609
|
return [...details.splitAddresses];
|
|
6266
6610
|
}
|
|
6267
|
-
if (
|
|
6611
|
+
if (rootConfig === void 0) {
|
|
6268
6612
|
return [];
|
|
6269
6613
|
}
|
|
6270
|
-
return [...
|
|
6614
|
+
return [...rootConfig.splitAddresses];
|
|
6271
6615
|
}
|
|
6272
|
-
function resolveStatusSplitRatios(hasAuction, details,
|
|
6616
|
+
function resolveStatusSplitRatios(hasAuction, details, rootConfig) {
|
|
6273
6617
|
if (hasAuction) {
|
|
6274
6618
|
return [...details.splitRatios];
|
|
6275
6619
|
}
|
|
6276
|
-
if (
|
|
6620
|
+
if (rootConfig === void 0) {
|
|
6277
6621
|
return [];
|
|
6278
6622
|
}
|
|
6279
|
-
return [...
|
|
6623
|
+
return [...rootConfig.splitRatios];
|
|
6280
6624
|
}
|
|
6281
6625
|
function resolveBatchAuctionState(params) {
|
|
6282
6626
|
if (params.hasAuction) {
|
|
@@ -6310,7 +6654,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6310
6654
|
currentUnixTimestamp2()
|
|
6311
6655
|
);
|
|
6312
6656
|
const erc721ApprovalManager = plan.approvalContracts.length === 0 ? void 0 : requireContractAddress(chain, "erc721ApprovalManager");
|
|
6313
|
-
const
|
|
6657
|
+
const nftApprovals = await approveNftContracts2({
|
|
6314
6658
|
publicClient,
|
|
6315
6659
|
account,
|
|
6316
6660
|
accountAddress,
|
|
@@ -6319,31 +6663,43 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6319
6663
|
nftAddresses: plan.approvalContracts,
|
|
6320
6664
|
autoApprove: params.autoApprove
|
|
6321
6665
|
});
|
|
6322
|
-
const txHash = await
|
|
6323
|
-
|
|
6324
|
-
|
|
6325
|
-
|
|
6326
|
-
|
|
6327
|
-
|
|
6328
|
-
|
|
6329
|
-
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6338
|
-
|
|
6339
|
-
|
|
6340
|
-
|
|
6341
|
-
|
|
6666
|
+
const { txHash, receipt, registered } = await runWithApprovalSideEffectAlert({
|
|
6667
|
+
operation: "batch auction create",
|
|
6668
|
+
approvals: nftApprovals.map((approval) => ({
|
|
6669
|
+
type: "nft",
|
|
6670
|
+
approvalTxHash: approval.txHash,
|
|
6671
|
+
target: approval.nftAddress,
|
|
6672
|
+
operator: erc721ApprovalManager
|
|
6673
|
+
})),
|
|
6674
|
+
run: async () => {
|
|
6675
|
+
const targetTxHash = await walletClient.writeContract({
|
|
6676
|
+
address: batchAuctionHouse,
|
|
6677
|
+
abi: batchAuctionHouseAbi,
|
|
6678
|
+
functionName: "registerAuctionMerkleRoot",
|
|
6679
|
+
args: [
|
|
6680
|
+
plan.root,
|
|
6681
|
+
plan.currency,
|
|
6682
|
+
plan.reserveAmount,
|
|
6683
|
+
plan.duration,
|
|
6684
|
+
plan.splitAddresses,
|
|
6685
|
+
plan.splitRatios
|
|
6686
|
+
],
|
|
6687
|
+
account,
|
|
6688
|
+
chain: void 0
|
|
6689
|
+
});
|
|
6690
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
6691
|
+
const logs = parseEventLogs3({
|
|
6692
|
+
abi: batchAuctionHouseAbi,
|
|
6693
|
+
logs: targetReceipt.logs,
|
|
6694
|
+
eventName: "AuctionMerkleRootRegistered"
|
|
6695
|
+
});
|
|
6696
|
+
const [registeredLog] = logs;
|
|
6697
|
+
if (!registeredLog) {
|
|
6698
|
+
throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
|
|
6699
|
+
}
|
|
6700
|
+
return { txHash: targetTxHash, receipt: targetReceipt, registered: registeredLog };
|
|
6701
|
+
}
|
|
6342
6702
|
});
|
|
6343
|
-
const [registered] = logs;
|
|
6344
|
-
if (!registered) {
|
|
6345
|
-
throw new Error("Batch auction create transaction succeeded but AuctionMerkleRootRegistered was not found in logs.");
|
|
6346
|
-
}
|
|
6347
6703
|
return {
|
|
6348
6704
|
txHash,
|
|
6349
6705
|
receipt,
|
|
@@ -6354,7 +6710,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6354
6710
|
reserveAmount: registered.args.startingAmount,
|
|
6355
6711
|
duration: registered.args.duration,
|
|
6356
6712
|
nonce: registered.args.nonce,
|
|
6357
|
-
approvalTxHashes
|
|
6713
|
+
approvalTxHashes: nftApprovals.map((approval) => approval.txHash)
|
|
6358
6714
|
};
|
|
6359
6715
|
},
|
|
6360
6716
|
async cancel(params) {
|
|
@@ -6367,7 +6723,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6367
6723
|
params
|
|
6368
6724
|
);
|
|
6369
6725
|
const plan = planBatchAuctionRoot(resolvedParams);
|
|
6370
|
-
const
|
|
6726
|
+
const targetTxHash = await walletClient.writeContract({
|
|
6371
6727
|
address: batchAuctionHouse,
|
|
6372
6728
|
abi: batchAuctionHouseAbi,
|
|
6373
6729
|
functionName: "cancelAuctionMerkleRoot",
|
|
@@ -6375,10 +6731,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6375
6731
|
account,
|
|
6376
6732
|
chain: void 0
|
|
6377
6733
|
});
|
|
6378
|
-
const
|
|
6734
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
6379
6735
|
const logs = parseEventLogs3({
|
|
6380
6736
|
abi: batchAuctionHouseAbi,
|
|
6381
|
-
logs:
|
|
6737
|
+
logs: targetReceipt.logs,
|
|
6382
6738
|
eventName: "AuctionMerkleRootCancelled"
|
|
6383
6739
|
});
|
|
6384
6740
|
const [cancelled] = logs;
|
|
@@ -6386,8 +6742,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6386
6742
|
throw new Error("Batch auction cancel transaction succeeded but AuctionMerkleRootCancelled was not found in logs.");
|
|
6387
6743
|
}
|
|
6388
6744
|
return {
|
|
6389
|
-
txHash,
|
|
6390
|
-
receipt,
|
|
6745
|
+
txHash: targetTxHash,
|
|
6746
|
+
receipt: targetReceipt,
|
|
6391
6747
|
batchAuctionHouse,
|
|
6392
6748
|
creator: cancelled.args.creator,
|
|
6393
6749
|
root: cancelled.args.merkleRoot
|
|
@@ -6417,7 +6773,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6417
6773
|
const price = requireInput(resolvedParams.price, "price");
|
|
6418
6774
|
const amount = typeof price === "bigint" ? price : parseUnits3(stringifyAmountInput(price, "price"), await resolveCurrencyDecimals(publicClient, chain, currency));
|
|
6419
6775
|
const plan = planBatchAuctionBid({ ...resolvedParams, currency, price: amount });
|
|
6420
|
-
const erc20ApprovalManager =
|
|
6776
|
+
const erc20ApprovalManager = isAddressEqual12(plan.currency, ETH_ADDRESS) ? batchAuctionHouse : requireContractAddress(chain, "erc20ApprovalManager");
|
|
6421
6777
|
const payment = await preparePaymentAmountForSpender({
|
|
6422
6778
|
publicClient,
|
|
6423
6779
|
walletClient,
|
|
@@ -6428,33 +6784,45 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6428
6784
|
requiredAmount: plan.requiredPayment,
|
|
6429
6785
|
autoApprove: params.autoApprove
|
|
6430
6786
|
});
|
|
6431
|
-
const txHash = await
|
|
6432
|
-
|
|
6433
|
-
|
|
6434
|
-
|
|
6435
|
-
|
|
6436
|
-
plan.currency,
|
|
6437
|
-
|
|
6438
|
-
|
|
6439
|
-
|
|
6440
|
-
|
|
6441
|
-
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
|
|
6445
|
-
|
|
6446
|
-
|
|
6447
|
-
|
|
6448
|
-
|
|
6449
|
-
|
|
6450
|
-
|
|
6451
|
-
|
|
6452
|
-
|
|
6787
|
+
const { txHash, receipt, bid } = await runWithApprovalSideEffectAlert({
|
|
6788
|
+
operation: "batch auction bid",
|
|
6789
|
+
approvals: [{
|
|
6790
|
+
type: "erc20",
|
|
6791
|
+
approvalTxHash: payment.approvalTxHash,
|
|
6792
|
+
target: plan.currency,
|
|
6793
|
+
spender: erc20ApprovalManager
|
|
6794
|
+
}],
|
|
6795
|
+
run: async () => {
|
|
6796
|
+
const targetTxHash = await walletClient.writeContract({
|
|
6797
|
+
address: batchAuctionHouse,
|
|
6798
|
+
abi: batchAuctionHouseAbi,
|
|
6799
|
+
functionName: "bidWithAuctionMerkleProof",
|
|
6800
|
+
args: [
|
|
6801
|
+
plan.currency,
|
|
6802
|
+
plan.contract,
|
|
6803
|
+
plan.tokenId,
|
|
6804
|
+
plan.creator,
|
|
6805
|
+
plan.root,
|
|
6806
|
+
plan.amount,
|
|
6807
|
+
plan.proof
|
|
6808
|
+
],
|
|
6809
|
+
account,
|
|
6810
|
+
chain: void 0,
|
|
6811
|
+
value: payment.value
|
|
6812
|
+
});
|
|
6813
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
6814
|
+
const logs = parseEventLogs3({
|
|
6815
|
+
abi: batchAuctionHouseAbi,
|
|
6816
|
+
logs: targetReceipt.logs,
|
|
6817
|
+
eventName: "AuctionMerkleBid"
|
|
6818
|
+
});
|
|
6819
|
+
const [bidLog] = logs;
|
|
6820
|
+
if (!bidLog) {
|
|
6821
|
+
throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
|
|
6822
|
+
}
|
|
6823
|
+
return { txHash: targetTxHash, receipt: targetReceipt, bid: bidLog };
|
|
6824
|
+
}
|
|
6453
6825
|
});
|
|
6454
|
-
const [bid] = logs;
|
|
6455
|
-
if (!bid) {
|
|
6456
|
-
throw new Error("Batch auction bid transaction succeeded but AuctionMerkleBid was not found in logs.");
|
|
6457
|
-
}
|
|
6458
6826
|
return {
|
|
6459
6827
|
txHash,
|
|
6460
6828
|
receipt,
|
|
@@ -6475,7 +6843,7 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6475
6843
|
const batchAuctionHouse = requireContractAddress(chain, "batchAuctionHouse");
|
|
6476
6844
|
const { walletClient, account } = requireWallet(config);
|
|
6477
6845
|
const plan = planBatchAuctionStatus(params);
|
|
6478
|
-
const
|
|
6846
|
+
const targetTxHash = await walletClient.writeContract({
|
|
6479
6847
|
address: batchAuctionHouse,
|
|
6480
6848
|
abi: batchAuctionHouseAbi,
|
|
6481
6849
|
functionName: "settleAuction",
|
|
@@ -6483,10 +6851,10 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6483
6851
|
account,
|
|
6484
6852
|
chain: void 0
|
|
6485
6853
|
});
|
|
6486
|
-
const
|
|
6854
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
6487
6855
|
const logs = parseEventLogs3({
|
|
6488
6856
|
abi: batchAuctionHouseAbi,
|
|
6489
|
-
logs:
|
|
6857
|
+
logs: targetReceipt.logs,
|
|
6490
6858
|
eventName: "AuctionSettled"
|
|
6491
6859
|
});
|
|
6492
6860
|
const [settled] = logs;
|
|
@@ -6494,8 +6862,8 @@ function createBatchAuctionNamespace(publicClient, config, chain) {
|
|
|
6494
6862
|
throw new Error("Batch auction settle transaction succeeded but AuctionSettled was not found in logs.");
|
|
6495
6863
|
}
|
|
6496
6864
|
return {
|
|
6497
|
-
txHash,
|
|
6498
|
-
receipt,
|
|
6865
|
+
txHash: targetTxHash,
|
|
6866
|
+
receipt: targetReceipt,
|
|
6499
6867
|
batchAuctionHouse,
|
|
6500
6868
|
seller: settled.args.seller,
|
|
6501
6869
|
bidder: settled.args.bidder,
|
|
@@ -6682,7 +7050,7 @@ async function approveNftContracts2(opts) {
|
|
|
6682
7050
|
}
|
|
6683
7051
|
const { walletClient, operator } = opts;
|
|
6684
7052
|
return opts.nftAddresses.reduce(async (previous, nftAddress) => {
|
|
6685
|
-
const
|
|
7053
|
+
const approvals = await previous;
|
|
6686
7054
|
const txHash = await approveNftContract({
|
|
6687
7055
|
publicClient: opts.publicClient,
|
|
6688
7056
|
walletClient,
|
|
@@ -6692,7 +7060,7 @@ async function approveNftContracts2(opts) {
|
|
|
6692
7060
|
nftAddress,
|
|
6693
7061
|
autoApprove: opts.autoApprove
|
|
6694
7062
|
});
|
|
6695
|
-
return txHash === void 0 ?
|
|
7063
|
+
return txHash === void 0 ? approvals : [...approvals, { nftAddress, txHash }];
|
|
6696
7064
|
}, Promise.resolve([]));
|
|
6697
7065
|
}
|
|
6698
7066
|
async function approveNftContract(opts) {
|
|
@@ -6764,7 +7132,7 @@ async function resolveRootContext(opts) {
|
|
|
6764
7132
|
|
|
6765
7133
|
// src/sdk/batch-offer.ts
|
|
6766
7134
|
import {
|
|
6767
|
-
isAddressEqual as
|
|
7135
|
+
isAddressEqual as isAddressEqual14,
|
|
6768
7136
|
parseUnits as parseUnits4,
|
|
6769
7137
|
parseEventLogs as parseEventLogs4
|
|
6770
7138
|
} from "viem";
|
|
@@ -6871,7 +7239,7 @@ var batchOfferAbi = [
|
|
|
6871
7239
|
];
|
|
6872
7240
|
|
|
6873
7241
|
// src/sdk/batch-offer-core.ts
|
|
6874
|
-
import { isAddressEqual as
|
|
7242
|
+
import { isAddressEqual as isAddressEqual13 } from "viem";
|
|
6875
7243
|
var zeroAddress4 = ETH_ADDRESS;
|
|
6876
7244
|
var zeroBytes322 = "0x0000000000000000000000000000000000000000000000000000000000000000";
|
|
6877
7245
|
function planBatchOfferCreateLocalInputs(params, nowSeconds) {
|
|
@@ -6928,7 +7296,7 @@ function planBatchOfferAccept(params, accountAddress) {
|
|
|
6928
7296
|
};
|
|
6929
7297
|
}
|
|
6930
7298
|
function shapeBatchOfferStatus(offer, expected, nowSeconds) {
|
|
6931
|
-
const hasOffer = !
|
|
7299
|
+
const hasOffer = !isAddressEqual13(offer.creator, zeroAddress4) && offer.rootHash !== zeroBytes322 && offer.amount > 0n;
|
|
6932
7300
|
const expired = hasOffer && offer.expiry <= nowSeconds;
|
|
6933
7301
|
const state = !hasOffer ? "NONE" : expired ? "EXPIRED" : "ACTIVE";
|
|
6934
7302
|
return {
|
|
@@ -6943,7 +7311,7 @@ function shapeBatchOfferStatus(offer, expected, nowSeconds) {
|
|
|
6943
7311
|
revoked: hasOffer ? false : null,
|
|
6944
7312
|
fillable: hasOffer && !expired,
|
|
6945
7313
|
state,
|
|
6946
|
-
isEth:
|
|
7314
|
+
isEth: isAddressEqual13(offer.currency, ETH_ADDRESS)
|
|
6947
7315
|
};
|
|
6948
7316
|
}
|
|
6949
7317
|
function shapeBatchOfferRead(value) {
|
|
@@ -7032,25 +7400,37 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7032
7400
|
amount: plan.amount,
|
|
7033
7401
|
autoApprove: params.autoApprove
|
|
7034
7402
|
});
|
|
7035
|
-
const txHash = await
|
|
7036
|
-
|
|
7037
|
-
|
|
7038
|
-
|
|
7039
|
-
|
|
7040
|
-
|
|
7041
|
-
|
|
7042
|
-
|
|
7043
|
-
|
|
7044
|
-
|
|
7045
|
-
|
|
7046
|
-
|
|
7047
|
-
|
|
7048
|
-
|
|
7403
|
+
const { txHash, receipt, created } = await runWithApprovalSideEffectAlert({
|
|
7404
|
+
operation: "batch offer create",
|
|
7405
|
+
approvals: [{
|
|
7406
|
+
type: "erc20",
|
|
7407
|
+
approvalTxHash: payment.approvalTxHash,
|
|
7408
|
+
target: plan.currency,
|
|
7409
|
+
spender: batchOfferCreator
|
|
7410
|
+
}],
|
|
7411
|
+
run: async () => {
|
|
7412
|
+
const targetTxHash = await walletClient.writeContract({
|
|
7413
|
+
address: batchOfferCreator,
|
|
7414
|
+
abi: batchOfferAbi,
|
|
7415
|
+
functionName: "createBatchOffer",
|
|
7416
|
+
args: [plan.root, plan.amount, plan.currency, plan.expiry],
|
|
7417
|
+
account,
|
|
7418
|
+
chain: void 0,
|
|
7419
|
+
value: payment.value
|
|
7420
|
+
});
|
|
7421
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
7422
|
+
const logs = parseEventLogs4({
|
|
7423
|
+
abi: batchOfferAbi,
|
|
7424
|
+
logs: targetReceipt.logs,
|
|
7425
|
+
eventName: "BatchOfferCreated"
|
|
7426
|
+
});
|
|
7427
|
+
const [createdLog] = logs;
|
|
7428
|
+
if (!createdLog) {
|
|
7429
|
+
throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
|
|
7430
|
+
}
|
|
7431
|
+
return { txHash: targetTxHash, receipt: targetReceipt, created: createdLog };
|
|
7432
|
+
}
|
|
7049
7433
|
});
|
|
7050
|
-
const [created] = logs;
|
|
7051
|
-
if (!created) {
|
|
7052
|
-
throw new Error("Batch offer create transaction succeeded but BatchOfferCreated was not found in logs.");
|
|
7053
|
-
}
|
|
7054
7434
|
return {
|
|
7055
7435
|
txHash,
|
|
7056
7436
|
receipt,
|
|
@@ -7076,7 +7456,7 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7076
7456
|
params
|
|
7077
7457
|
});
|
|
7078
7458
|
const plan = planBatchOfferRoot(resolvedParams);
|
|
7079
|
-
const
|
|
7459
|
+
const targetTxHash = await walletClient.writeContract({
|
|
7080
7460
|
address: batchOfferCreator,
|
|
7081
7461
|
abi: batchOfferAbi,
|
|
7082
7462
|
functionName: "revokeBatchOffer",
|
|
@@ -7084,10 +7464,10 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7084
7464
|
account,
|
|
7085
7465
|
chain: void 0
|
|
7086
7466
|
});
|
|
7087
|
-
const
|
|
7467
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
7088
7468
|
const logs = parseEventLogs4({
|
|
7089
7469
|
abi: batchOfferAbi,
|
|
7090
|
-
logs:
|
|
7470
|
+
logs: targetReceipt.logs,
|
|
7091
7471
|
eventName: "BatchOfferRevoked"
|
|
7092
7472
|
});
|
|
7093
7473
|
const [revoked] = logs;
|
|
@@ -7095,8 +7475,8 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7095
7475
|
throw new Error("Batch offer revoke transaction succeeded but BatchOfferRevoked was not found in logs.");
|
|
7096
7476
|
}
|
|
7097
7477
|
return {
|
|
7098
|
-
txHash,
|
|
7099
|
-
receipt,
|
|
7478
|
+
txHash: targetTxHash,
|
|
7479
|
+
receipt: targetReceipt,
|
|
7100
7480
|
batchOfferCreator,
|
|
7101
7481
|
creator: revoked.args.creator,
|
|
7102
7482
|
root: revoked.args.rootHash,
|
|
@@ -7121,7 +7501,7 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7121
7501
|
functionName: "ownerOf",
|
|
7122
7502
|
args: [plan.tokenId]
|
|
7123
7503
|
});
|
|
7124
|
-
if (!
|
|
7504
|
+
if (!isAddressEqual14(owner, accountAddress)) {
|
|
7125
7505
|
throw new Error(`Connected wallet ${accountAddress} does not own token ${plan.contract} #${plan.tokenId.toString()}.`);
|
|
7126
7506
|
}
|
|
7127
7507
|
const approvalTxHash = await approveNftContractIfNeeded({
|
|
@@ -7133,32 +7513,44 @@ function createBatchOfferNamespace(publicClient, config, chain) {
|
|
|
7133
7513
|
operator: batchOfferCreator,
|
|
7134
7514
|
autoApprove: plan.autoApprove
|
|
7135
7515
|
});
|
|
7136
|
-
const txHash = await
|
|
7137
|
-
|
|
7138
|
-
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
plan.
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7150
|
-
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7516
|
+
const { txHash, receipt, accepted } = await runWithApprovalSideEffectAlert({
|
|
7517
|
+
operation: "batch offer accept",
|
|
7518
|
+
approvals: [{
|
|
7519
|
+
type: "nft",
|
|
7520
|
+
approvalTxHash,
|
|
7521
|
+
target: plan.contract,
|
|
7522
|
+
operator: batchOfferCreator
|
|
7523
|
+
}],
|
|
7524
|
+
run: async () => {
|
|
7525
|
+
const targetTxHash = await walletClient.writeContract({
|
|
7526
|
+
address: batchOfferCreator,
|
|
7527
|
+
abi: batchOfferAbi,
|
|
7528
|
+
functionName: "acceptBatchOffer",
|
|
7529
|
+
args: [
|
|
7530
|
+
plan.creator,
|
|
7531
|
+
plan.proof,
|
|
7532
|
+
plan.root,
|
|
7533
|
+
plan.contract,
|
|
7534
|
+
plan.tokenId,
|
|
7535
|
+
plan.splitAddresses,
|
|
7536
|
+
plan.splitRatios
|
|
7537
|
+
],
|
|
7538
|
+
account,
|
|
7539
|
+
chain: void 0
|
|
7540
|
+
});
|
|
7541
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
7542
|
+
const logs = parseEventLogs4({
|
|
7543
|
+
abi: batchOfferAbi,
|
|
7544
|
+
logs: targetReceipt.logs,
|
|
7545
|
+
eventName: "BatchOfferAccepted"
|
|
7546
|
+
});
|
|
7547
|
+
const [acceptedLog] = logs;
|
|
7548
|
+
if (!acceptedLog) {
|
|
7549
|
+
throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
|
|
7550
|
+
}
|
|
7551
|
+
return { txHash: targetTxHash, receipt: targetReceipt, accepted: acceptedLog };
|
|
7552
|
+
}
|
|
7157
7553
|
});
|
|
7158
|
-
const [accepted] = logs;
|
|
7159
|
-
if (!accepted) {
|
|
7160
|
-
throw new Error("Batch offer accept transaction succeeded but BatchOfferAccepted was not found in logs.");
|
|
7161
|
-
}
|
|
7162
7554
|
return {
|
|
7163
7555
|
txHash,
|
|
7164
7556
|
receipt,
|
|
@@ -7779,6 +8171,7 @@ var liquidFactoryAbi = [
|
|
|
7779
8171
|
var TICK_BASE = 1.0001;
|
|
7780
8172
|
var TICK_LOG_BASE = Math.log(TICK_BASE);
|
|
7781
8173
|
var TOKEN_BASE_UNITS = 1e18;
|
|
8174
|
+
var SHARE_SCALE_UNITS = 10n ** 18n;
|
|
7782
8175
|
var RESERVE_TAIL_SHARES_PERCENT = 2;
|
|
7783
8176
|
var RESERVE_TAIL_END_PRICE_MULTIPLE = 100;
|
|
7784
8177
|
var SHARES_SUM_TOLERANCE = 1e-6;
|
|
@@ -7837,12 +8230,66 @@ function toValidNumber(value) {
|
|
|
7837
8230
|
if (typeof value !== "number" || !Number.isFinite(value)) return null;
|
|
7838
8231
|
return value;
|
|
7839
8232
|
}
|
|
7840
|
-
function
|
|
7841
|
-
|
|
7842
|
-
|
|
8233
|
+
function toNormalizedShare(value) {
|
|
8234
|
+
if (typeof value === "number") {
|
|
8235
|
+
if (!Number.isFinite(value) || value <= 0 || value > 1) {
|
|
8236
|
+
return null;
|
|
8237
|
+
}
|
|
8238
|
+
return parseShareDecimalString(expandFiniteNumber(value));
|
|
8239
|
+
}
|
|
8240
|
+
if (typeof value !== "string") {
|
|
7843
8241
|
return null;
|
|
7844
8242
|
}
|
|
7845
|
-
return
|
|
8243
|
+
return parseShareDecimalString(value);
|
|
8244
|
+
}
|
|
8245
|
+
function expandFiniteNumber(value) {
|
|
8246
|
+
const rawValue = value.toString();
|
|
8247
|
+
const [coefficient = "", exponentValue] = rawValue.toLowerCase().split("e");
|
|
8248
|
+
if (exponentValue === void 0) {
|
|
8249
|
+
return rawValue;
|
|
8250
|
+
}
|
|
8251
|
+
const exponent = Number(exponentValue);
|
|
8252
|
+
const [integerPart = "", fractionalPart = ""] = coefficient.split(".");
|
|
8253
|
+
const digits = `${integerPart}${fractionalPart}`;
|
|
8254
|
+
const decimalIndex = integerPart.length + exponent;
|
|
8255
|
+
if (decimalIndex <= 0) {
|
|
8256
|
+
return `0.${"0".repeat(Math.abs(decimalIndex))}${digits}`;
|
|
8257
|
+
}
|
|
8258
|
+
if (decimalIndex >= digits.length) {
|
|
8259
|
+
return `${digits}${"0".repeat(decimalIndex - digits.length)}`;
|
|
8260
|
+
}
|
|
8261
|
+
return `${digits.slice(0, decimalIndex)}.${digits.slice(decimalIndex)}`;
|
|
8262
|
+
}
|
|
8263
|
+
function parseShareDecimalString(value) {
|
|
8264
|
+
const normalized = value.trim();
|
|
8265
|
+
if (!/^(?:\d+\.?\d*|\.\d+)$/.test(normalized)) {
|
|
8266
|
+
return null;
|
|
8267
|
+
}
|
|
8268
|
+
const shareParts = normalized.startsWith(".") ? ["0", normalized.slice(1)] : normalized.split(".");
|
|
8269
|
+
const integerPart = shareParts[0] ?? "";
|
|
8270
|
+
const fractionalDigits = shareParts[1] ?? "";
|
|
8271
|
+
const excessFractionalDigits = fractionalDigits.slice(18);
|
|
8272
|
+
if (/[1-9]/.test(excessFractionalDigits)) {
|
|
8273
|
+
return null;
|
|
8274
|
+
}
|
|
8275
|
+
const integerUnits = BigInt(integerPart === "" ? "0" : integerPart);
|
|
8276
|
+
const fractionalUnits = BigInt(fractionalDigits.slice(0, 18).padEnd(18, "0"));
|
|
8277
|
+
const scaledUnits = integerUnits * SHARE_SCALE_UNITS + fractionalUnits;
|
|
8278
|
+
if (scaledUnits <= 0n || scaledUnits > SHARE_SCALE_UNITS) {
|
|
8279
|
+
return null;
|
|
8280
|
+
}
|
|
8281
|
+
return {
|
|
8282
|
+
decimal: formatScaledShareDecimal(scaledUnits),
|
|
8283
|
+
scaledUnits
|
|
8284
|
+
};
|
|
8285
|
+
}
|
|
8286
|
+
function formatScaledShareDecimal(scaledUnits) {
|
|
8287
|
+
const integerUnits = scaledUnits / SHARE_SCALE_UNITS;
|
|
8288
|
+
const fractionalUnits = scaledUnits % SHARE_SCALE_UNITS;
|
|
8289
|
+
if (fractionalUnits === 0n) {
|
|
8290
|
+
return integerUnits.toString();
|
|
8291
|
+
}
|
|
8292
|
+
return `${integerUnits}.${fractionalUnits.toString().padStart(18, "0").replace(/0+$/, "")}`;
|
|
7846
8293
|
}
|
|
7847
8294
|
function toApproxTokenAmount(value, label) {
|
|
7848
8295
|
const numeric = typeof value === "number" ? value : Number(value);
|
|
@@ -7991,8 +8438,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
|
|
|
7991
8438
|
if (invalidResult !== void 0) {
|
|
7992
8439
|
return invalidResult.result;
|
|
7993
8440
|
}
|
|
7994
|
-
const
|
|
7995
|
-
const totalPositions =
|
|
8441
|
+
const parsedEntries = normalizedResults.filter((result) => result.isValid).map((result) => result.entry);
|
|
8442
|
+
const totalPositions = parsedEntries.reduce((sum, entry) => sum + entry.segment.numPositions, 0);
|
|
7996
8443
|
if (totalPositions > MAX_TOTAL_POSITIONS) {
|
|
7997
8444
|
return {
|
|
7998
8445
|
isValid: false,
|
|
@@ -8000,8 +8447,8 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
|
|
|
8000
8447
|
errorMessage: `Total positions across all curves must not exceed ${MAX_TOTAL_POSITIONS}`
|
|
8001
8448
|
};
|
|
8002
8449
|
}
|
|
8003
|
-
const
|
|
8004
|
-
const hasGapOrOverlap =
|
|
8450
|
+
const sortedEntries = [...parsedEntries].sort((a, b) => a.segment.tickLower - b.segment.tickLower);
|
|
8451
|
+
const hasGapOrOverlap = sortedEntries.slice(1).some((current, index) => current.segment.tickLower !== sortedEntries[index]?.segment.tickUpper);
|
|
8005
8452
|
if (hasGapOrOverlap) {
|
|
8006
8453
|
return {
|
|
8007
8454
|
isValid: false,
|
|
@@ -8009,10 +8456,11 @@ function validateAndNormalizeSegments(rawSegments, totalCurveSupplyTokens, tickS
|
|
|
8009
8456
|
errorMessage: "Curve segments must be contiguous (no overlap or gaps)"
|
|
8010
8457
|
};
|
|
8011
8458
|
}
|
|
8012
|
-
const shareSum =
|
|
8013
|
-
if (
|
|
8459
|
+
const shareSum = sortedEntries.reduce((sum, entry) => sum + entry.shareScaledUnits, 0n);
|
|
8460
|
+
if (shareSum !== SHARE_SCALE_UNITS) {
|
|
8014
8461
|
return { isValid: false, error: "share-sum-invalid", errorMessage: "Curve share values must add up to 1" };
|
|
8015
8462
|
}
|
|
8463
|
+
const sortedSegments = sortedEntries.map((entry) => entry.segment);
|
|
8016
8464
|
const narrowSegment = sortedSegments.find((segment) => {
|
|
8017
8465
|
const minSpan = segment.numPositions * tickSpacing;
|
|
8018
8466
|
return segment.tickUpper - segment.tickLower < minSpan || computeGrossLiquidityAtFarTick(segment.tickLower, segment.tickUpper - segment.tickLower, segment.numPositions, Number(segment.shares), totalCurveSupplyTokens) > MAX_LIQUIDITY_PER_TICK;
|
|
@@ -8041,8 +8489,8 @@ function normalizeSegment(segment, tickSpacing) {
|
|
|
8041
8489
|
const tickLower = toValidNumber(segment.tickLower);
|
|
8042
8490
|
const tickUpper = toValidNumber(segment.tickUpper);
|
|
8043
8491
|
const numPositions = toValidNumber(segment.numPositions);
|
|
8044
|
-
const
|
|
8045
|
-
if (tickLower === null || tickUpper === null || numPositions === null ||
|
|
8492
|
+
const share = toNormalizedShare(segment.shares);
|
|
8493
|
+
if (tickLower === null || tickUpper === null || numPositions === null || share === null) {
|
|
8046
8494
|
return invalidSegmentResult();
|
|
8047
8495
|
}
|
|
8048
8496
|
if (!Number.isInteger(tickLower) || !Number.isInteger(tickUpper) || !Number.isInteger(numPositions) || numPositions <= 0) {
|
|
@@ -8059,11 +8507,14 @@ function normalizeSegment(segment, tickSpacing) {
|
|
|
8059
8507
|
}
|
|
8060
8508
|
return {
|
|
8061
8509
|
isValid: true,
|
|
8062
|
-
|
|
8063
|
-
|
|
8064
|
-
|
|
8065
|
-
|
|
8066
|
-
|
|
8510
|
+
entry: {
|
|
8511
|
+
segment: {
|
|
8512
|
+
tickLower,
|
|
8513
|
+
tickUpper,
|
|
8514
|
+
numPositions,
|
|
8515
|
+
shares: share.decimal
|
|
8516
|
+
},
|
|
8517
|
+
shareScaledUnits: share.scaledUnits
|
|
8067
8518
|
}
|
|
8068
8519
|
};
|
|
8069
8520
|
}
|
|
@@ -8430,9 +8881,23 @@ function missingLiquidEditionAddressError(txHash, receipt, cause) {
|
|
|
8430
8881
|
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.`;
|
|
8431
8882
|
return cause instanceof Error ? new Error(message, { cause }) : new Error(message);
|
|
8432
8883
|
}
|
|
8433
|
-
function
|
|
8884
|
+
function liquidEditionRevertedReceiptError(message, txHash, receipt) {
|
|
8434
8885
|
return new Error(
|
|
8435
|
-
|
|
8886
|
+
`${message} Transaction hash: ${txHash}. Block: ${receipt.blockNumber}.`
|
|
8887
|
+
);
|
|
8888
|
+
}
|
|
8889
|
+
function liquidEditionDeployRevertedError(txHash, receipt) {
|
|
8890
|
+
return liquidEditionRevertedReceiptError(
|
|
8891
|
+
"Liquid Edition deploy transaction reverted before emitting LiquidTokenCreated.",
|
|
8892
|
+
txHash,
|
|
8893
|
+
receipt
|
|
8894
|
+
);
|
|
8895
|
+
}
|
|
8896
|
+
function liquidEditionSetRenderContractRevertedError(txHash, receipt) {
|
|
8897
|
+
return liquidEditionRevertedReceiptError(
|
|
8898
|
+
'Liquid Edition setRenderContract transaction was confirmed with status "reverted".',
|
|
8899
|
+
txHash,
|
|
8900
|
+
receipt
|
|
8436
8901
|
);
|
|
8437
8902
|
}
|
|
8438
8903
|
async function waitForLiquidEditionAddress(publicClient, txHash) {
|
|
@@ -8518,7 +8983,13 @@ function createLiquidNamespace(config, chain, addresses) {
|
|
|
8518
8983
|
throw new Error(validation.errorMessage ?? "Invalid curve configuration");
|
|
8519
8984
|
}
|
|
8520
8985
|
const initialRareLiquidity = params.initialRareLiquidity !== void 0 ? await toTokenAmount(publicClient, factoryConfig.baseToken, params.initialRareLiquidity, "initialRareLiquidity") : 0n;
|
|
8521
|
-
|
|
8986
|
+
const curves = validation.curves.map((curve) => ({
|
|
8987
|
+
tickLower: curve.tickLower,
|
|
8988
|
+
tickUpper: curve.tickUpper,
|
|
8989
|
+
numPositions: curve.numPositions,
|
|
8990
|
+
shares: parseUnits6(curve.shares, 18)
|
|
8991
|
+
}));
|
|
8992
|
+
const approvalTxHash = await ensureTokenAllowance(
|
|
8522
8993
|
publicClient,
|
|
8523
8994
|
walletClient,
|
|
8524
8995
|
account,
|
|
@@ -8527,43 +8998,49 @@ function createLiquidNamespace(config, chain, addresses) {
|
|
|
8527
8998
|
liquidFactory,
|
|
8528
8999
|
initialRareLiquidity
|
|
8529
9000
|
);
|
|
8530
|
-
const
|
|
8531
|
-
|
|
8532
|
-
|
|
8533
|
-
|
|
8534
|
-
|
|
8535
|
-
|
|
8536
|
-
|
|
8537
|
-
|
|
8538
|
-
|
|
8539
|
-
|
|
8540
|
-
|
|
8541
|
-
|
|
8542
|
-
|
|
8543
|
-
|
|
8544
|
-
|
|
8545
|
-
|
|
8546
|
-
|
|
8547
|
-
|
|
8548
|
-
|
|
8549
|
-
|
|
8550
|
-
|
|
8551
|
-
|
|
8552
|
-
|
|
8553
|
-
|
|
8554
|
-
|
|
8555
|
-
|
|
8556
|
-
|
|
8557
|
-
|
|
8558
|
-
|
|
8559
|
-
|
|
8560
|
-
|
|
8561
|
-
|
|
8562
|
-
|
|
8563
|
-
|
|
8564
|
-
|
|
9001
|
+
const { txHash, receipt, contract } = await runWithApprovalSideEffectAlert({
|
|
9002
|
+
operation: "liquid edition deploy",
|
|
9003
|
+
approvals: [{
|
|
9004
|
+
type: "erc20",
|
|
9005
|
+
approvalTxHash,
|
|
9006
|
+
target: factoryConfig.baseToken,
|
|
9007
|
+
spender: liquidFactory
|
|
9008
|
+
}],
|
|
9009
|
+
run: async () => {
|
|
9010
|
+
const targetTxHash = customMaxTotalSupply === void 0 ? await walletClient.writeContract({
|
|
9011
|
+
address: liquidFactory,
|
|
9012
|
+
abi: liquidFactoryAbi,
|
|
9013
|
+
functionName: "createLiquidTokenMultiCurve",
|
|
9014
|
+
args: [
|
|
9015
|
+
accountAddress,
|
|
9016
|
+
params.tokenUri,
|
|
9017
|
+
params.name,
|
|
9018
|
+
params.symbol,
|
|
9019
|
+
initialRareLiquidity,
|
|
9020
|
+
curves
|
|
9021
|
+
],
|
|
9022
|
+
account,
|
|
9023
|
+
chain: void 0
|
|
9024
|
+
}) : await walletClient.writeContract({
|
|
9025
|
+
address: liquidFactory,
|
|
9026
|
+
abi: liquidFactoryAbi,
|
|
9027
|
+
functionName: "createLiquidTokenMultiCurveWithSupply",
|
|
9028
|
+
args: [
|
|
9029
|
+
accountAddress,
|
|
9030
|
+
params.tokenUri,
|
|
9031
|
+
params.name,
|
|
9032
|
+
params.symbol,
|
|
9033
|
+
initialRareLiquidity,
|
|
9034
|
+
curves,
|
|
9035
|
+
customMaxTotalSupply
|
|
9036
|
+
],
|
|
9037
|
+
account,
|
|
9038
|
+
chain: void 0
|
|
9039
|
+
});
|
|
9040
|
+
const deployed = await waitForLiquidEditionAddress(publicClient, targetTxHash);
|
|
9041
|
+
return { txHash: targetTxHash, receipt: deployed.receipt, contract: deployed.contract };
|
|
9042
|
+
}
|
|
8565
9043
|
});
|
|
8566
|
-
const { receipt, contract } = await waitForLiquidEditionAddress(publicClient, txHash);
|
|
8567
9044
|
return {
|
|
8568
9045
|
txHash,
|
|
8569
9046
|
receipt,
|
|
@@ -8598,6 +9075,9 @@ function createLiquidNamespace(config, chain, addresses) {
|
|
|
8598
9075
|
chain: void 0
|
|
8599
9076
|
});
|
|
8600
9077
|
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
9078
|
+
if (receipt.status === "reverted") {
|
|
9079
|
+
throw liquidEditionSetRenderContractRevertedError(txHash, receipt);
|
|
9080
|
+
}
|
|
8601
9081
|
return {
|
|
8602
9082
|
txHash,
|
|
8603
9083
|
receipt,
|
|
@@ -8704,6 +9184,312 @@ function createLiquidNamespace(config, chain, addresses) {
|
|
|
8704
9184
|
};
|
|
8705
9185
|
}
|
|
8706
9186
|
|
|
9187
|
+
// src/sdk/bridge.ts
|
|
9188
|
+
import { encodeFunctionData } from "viem";
|
|
9189
|
+
|
|
9190
|
+
// src/contracts/abis/rare-bridge.ts
|
|
9191
|
+
var rareBridgeAbi = [
|
|
9192
|
+
{
|
|
9193
|
+
type: "function",
|
|
9194
|
+
name: "getFee",
|
|
9195
|
+
inputs: [
|
|
9196
|
+
{
|
|
9197
|
+
name: "_destinationChainSelector",
|
|
9198
|
+
type: "uint64",
|
|
9199
|
+
internalType: "uint64"
|
|
9200
|
+
},
|
|
9201
|
+
{
|
|
9202
|
+
name: "_destinationChainRecipient",
|
|
9203
|
+
type: "address",
|
|
9204
|
+
internalType: "address"
|
|
9205
|
+
},
|
|
9206
|
+
{
|
|
9207
|
+
name: "_distributionData",
|
|
9208
|
+
type: "bytes",
|
|
9209
|
+
internalType: "bytes"
|
|
9210
|
+
},
|
|
9211
|
+
{
|
|
9212
|
+
name: "_extraArgs",
|
|
9213
|
+
type: "bytes",
|
|
9214
|
+
internalType: "bytes"
|
|
9215
|
+
},
|
|
9216
|
+
{
|
|
9217
|
+
name: "_payFeesInLink",
|
|
9218
|
+
type: "bool",
|
|
9219
|
+
internalType: "bool"
|
|
9220
|
+
}
|
|
9221
|
+
],
|
|
9222
|
+
outputs: [
|
|
9223
|
+
{
|
|
9224
|
+
name: "fee",
|
|
9225
|
+
type: "uint256",
|
|
9226
|
+
internalType: "uint256"
|
|
9227
|
+
}
|
|
9228
|
+
],
|
|
9229
|
+
stateMutability: "view"
|
|
9230
|
+
},
|
|
9231
|
+
{
|
|
9232
|
+
type: "function",
|
|
9233
|
+
name: "send",
|
|
9234
|
+
inputs: [
|
|
9235
|
+
{
|
|
9236
|
+
name: "_destinationChainSelector",
|
|
9237
|
+
type: "uint64",
|
|
9238
|
+
internalType: "uint64"
|
|
9239
|
+
},
|
|
9240
|
+
{
|
|
9241
|
+
name: "_destinationChainRecipient",
|
|
9242
|
+
type: "address",
|
|
9243
|
+
internalType: "address"
|
|
9244
|
+
},
|
|
9245
|
+
{
|
|
9246
|
+
name: "_distributionData",
|
|
9247
|
+
type: "bytes",
|
|
9248
|
+
internalType: "bytes"
|
|
9249
|
+
},
|
|
9250
|
+
{
|
|
9251
|
+
name: "_extraArgs",
|
|
9252
|
+
type: "bytes",
|
|
9253
|
+
internalType: "bytes"
|
|
9254
|
+
},
|
|
9255
|
+
{
|
|
9256
|
+
name: "_payFeesInLink",
|
|
9257
|
+
type: "bool",
|
|
9258
|
+
internalType: "bool"
|
|
9259
|
+
}
|
|
9260
|
+
],
|
|
9261
|
+
outputs: [],
|
|
9262
|
+
stateMutability: "payable"
|
|
9263
|
+
},
|
|
9264
|
+
{
|
|
9265
|
+
type: "event",
|
|
9266
|
+
name: "MessageSent",
|
|
9267
|
+
inputs: [
|
|
9268
|
+
{
|
|
9269
|
+
name: "messageId",
|
|
9270
|
+
type: "bytes32",
|
|
9271
|
+
indexed: true,
|
|
9272
|
+
internalType: "bytes32"
|
|
9273
|
+
},
|
|
9274
|
+
{
|
|
9275
|
+
name: "destinationChainSelector",
|
|
9276
|
+
type: "uint64",
|
|
9277
|
+
indexed: true,
|
|
9278
|
+
internalType: "uint64"
|
|
9279
|
+
},
|
|
9280
|
+
{
|
|
9281
|
+
name: "destinationChainRecipient",
|
|
9282
|
+
type: "address",
|
|
9283
|
+
indexed: true,
|
|
9284
|
+
internalType: "address"
|
|
9285
|
+
},
|
|
9286
|
+
{
|
|
9287
|
+
name: "fee",
|
|
9288
|
+
type: "uint256",
|
|
9289
|
+
indexed: false,
|
|
9290
|
+
internalType: "uint256"
|
|
9291
|
+
},
|
|
9292
|
+
{
|
|
9293
|
+
name: "payFeesInLink",
|
|
9294
|
+
type: "bool",
|
|
9295
|
+
indexed: false,
|
|
9296
|
+
internalType: "bool"
|
|
9297
|
+
}
|
|
9298
|
+
],
|
|
9299
|
+
anonymous: false
|
|
9300
|
+
}
|
|
9301
|
+
];
|
|
9302
|
+
|
|
9303
|
+
// src/sdk/bridge-core.ts
|
|
9304
|
+
import { encodeAbiParameters } from "viem";
|
|
9305
|
+
var allowedBridgePairs = [
|
|
9306
|
+
{ sourceChain: "mainnet", destinationChain: "base" },
|
|
9307
|
+
{ sourceChain: "base", destinationChain: "mainnet" },
|
|
9308
|
+
{ sourceChain: "sepolia", destinationChain: "base-sepolia" },
|
|
9309
|
+
{ sourceChain: "base-sepolia", destinationChain: "sepolia" }
|
|
9310
|
+
];
|
|
9311
|
+
function validateBridgeRoute(route) {
|
|
9312
|
+
const supported = allowedBridgePairs.some(
|
|
9313
|
+
(pair) => pair.sourceChain === route.sourceChain && pair.destinationChain === route.destinationChain
|
|
9314
|
+
);
|
|
9315
|
+
if (supported) {
|
|
9316
|
+
return { isValid: true };
|
|
9317
|
+
}
|
|
9318
|
+
return {
|
|
9319
|
+
isValid: false,
|
|
9320
|
+
error: "unsupported_bridge_route",
|
|
9321
|
+
errorMessage: `Unsupported RARE bridge route "${route.sourceChain}" -> "${route.destinationChain}". Supported routes: mainnet <-> base, sepolia <-> base-sepolia.`
|
|
9322
|
+
};
|
|
9323
|
+
}
|
|
9324
|
+
function getBridgeInfo(chain) {
|
|
9325
|
+
return {
|
|
9326
|
+
chain,
|
|
9327
|
+
chainId: chainIds[chain],
|
|
9328
|
+
rareBridgeAddress: getRareBridgeAddress(chain),
|
|
9329
|
+
rareTokenAddress: resolveCurrency("rare", chain),
|
|
9330
|
+
ccipChainSelector: getCcipChainSelector(chain)
|
|
9331
|
+
};
|
|
9332
|
+
}
|
|
9333
|
+
function encodeBridgeDistribution(params) {
|
|
9334
|
+
return encodeAbiParameters(
|
|
9335
|
+
[
|
|
9336
|
+
{ name: "recipients", type: "address[]" },
|
|
9337
|
+
{ name: "amounts", type: "uint256[]" }
|
|
9338
|
+
],
|
|
9339
|
+
[[params.recipient], [params.amount]]
|
|
9340
|
+
);
|
|
9341
|
+
}
|
|
9342
|
+
function buildBridgeSendArgs(params) {
|
|
9343
|
+
return [
|
|
9344
|
+
params.destinationBridgeInfo.ccipChainSelector,
|
|
9345
|
+
params.destinationBridgeInfo.rareBridgeAddress,
|
|
9346
|
+
params.distributionData,
|
|
9347
|
+
"0x",
|
|
9348
|
+
false
|
|
9349
|
+
];
|
|
9350
|
+
}
|
|
9351
|
+
function buildCcipExplorerUrl(txHash) {
|
|
9352
|
+
return `https://ccip.chain.link/tx/${txHash}`;
|
|
9353
|
+
}
|
|
9354
|
+
|
|
9355
|
+
// src/sdk/bridge.ts
|
|
9356
|
+
function createBridgeNamespace(publicClient, config, sourceChain) {
|
|
9357
|
+
return {
|
|
9358
|
+
async quote(params) {
|
|
9359
|
+
return buildBridgeQuote(publicClient, config, sourceChain, params);
|
|
9360
|
+
},
|
|
9361
|
+
async send(params) {
|
|
9362
|
+
return executeBridge(publicClient, config, sourceChain, params);
|
|
9363
|
+
}
|
|
9364
|
+
};
|
|
9365
|
+
}
|
|
9366
|
+
async function executeBridge(publicClient, config, sourceChain, params) {
|
|
9367
|
+
const { walletClient, account, accountAddress } = requireWallet(config);
|
|
9368
|
+
const quote = await buildBridgeQuote(publicClient, config, sourceChain, {
|
|
9369
|
+
...params,
|
|
9370
|
+
recipient: params.recipient ?? accountAddress
|
|
9371
|
+
}, {
|
|
9372
|
+
estimateGas: false
|
|
9373
|
+
});
|
|
9374
|
+
const approval = await preparePaymentAmountForSpender({
|
|
9375
|
+
publicClient,
|
|
9376
|
+
walletClient,
|
|
9377
|
+
account,
|
|
9378
|
+
accountAddress,
|
|
9379
|
+
spenderAddress: quote.sourceBridgeAddress,
|
|
9380
|
+
currency: quote.rareTokenAddress,
|
|
9381
|
+
requiredAmount: quote.amount,
|
|
9382
|
+
autoApprove: params.autoApprove
|
|
9383
|
+
});
|
|
9384
|
+
const sendArgs = buildBridgeSendArgs({
|
|
9385
|
+
destinationBridgeInfo: getBridgeInfo(quote.destinationChain),
|
|
9386
|
+
distributionData: quote.distributionData
|
|
9387
|
+
});
|
|
9388
|
+
const { txHash, receipt, estimatedGas } = await runWithApprovalSideEffectAlert({
|
|
9389
|
+
operation: "bridge send",
|
|
9390
|
+
approvals: [{
|
|
9391
|
+
type: "erc20",
|
|
9392
|
+
approvalTxHash: approval.approvalTxHash,
|
|
9393
|
+
target: quote.rareTokenAddress,
|
|
9394
|
+
spender: quote.sourceBridgeAddress
|
|
9395
|
+
}],
|
|
9396
|
+
run: async () => {
|
|
9397
|
+
const gas = await estimateBridgeGas(publicClient, {
|
|
9398
|
+
account: accountAddress,
|
|
9399
|
+
sourceBridgeAddress: quote.sourceBridgeAddress,
|
|
9400
|
+
args: sendArgs,
|
|
9401
|
+
nativeFee: quote.nativeFee
|
|
9402
|
+
});
|
|
9403
|
+
const targetTxHash = await walletClient.writeContract({
|
|
9404
|
+
address: quote.sourceBridgeAddress,
|
|
9405
|
+
abi: rareBridgeAbi,
|
|
9406
|
+
functionName: "send",
|
|
9407
|
+
args: sendArgs,
|
|
9408
|
+
value: quote.nativeFee,
|
|
9409
|
+
account,
|
|
9410
|
+
chain: void 0
|
|
9411
|
+
});
|
|
9412
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
9413
|
+
return { txHash: targetTxHash, receipt: targetReceipt, estimatedGas: gas };
|
|
9414
|
+
}
|
|
9415
|
+
});
|
|
9416
|
+
return {
|
|
9417
|
+
...quote,
|
|
9418
|
+
estimatedGas,
|
|
9419
|
+
txHash,
|
|
9420
|
+
receipt,
|
|
9421
|
+
approvalTxHash: approval.approvalTxHash,
|
|
9422
|
+
ccipExplorerUrl: buildCcipExplorerUrl(txHash)
|
|
9423
|
+
};
|
|
9424
|
+
}
|
|
9425
|
+
async function buildBridgeQuote(publicClient, config, sourceChain, params, options = {}) {
|
|
9426
|
+
const routeValidation = validateBridgeRoute({
|
|
9427
|
+
sourceChain,
|
|
9428
|
+
destinationChain: params.destinationChain
|
|
9429
|
+
});
|
|
9430
|
+
if (!routeValidation.isValid) {
|
|
9431
|
+
throw new Error(routeValidation.errorMessage);
|
|
9432
|
+
}
|
|
9433
|
+
const sourceBridgeInfo = getBridgeInfo(sourceChain);
|
|
9434
|
+
const destinationBridgeInfo = getBridgeInfo(params.destinationChain);
|
|
9435
|
+
const recipient = resolveRecipient(params.recipient, config);
|
|
9436
|
+
const amount = toPositiveWei(params.amount, "amount");
|
|
9437
|
+
const distributionData = encodeBridgeDistribution({ recipient, amount });
|
|
9438
|
+
const args = buildBridgeSendArgs({
|
|
9439
|
+
destinationBridgeInfo,
|
|
9440
|
+
distributionData
|
|
9441
|
+
});
|
|
9442
|
+
const nativeFee = await publicClient.readContract({
|
|
9443
|
+
address: sourceBridgeInfo.rareBridgeAddress,
|
|
9444
|
+
abi: rareBridgeAbi,
|
|
9445
|
+
functionName: "getFee",
|
|
9446
|
+
args
|
|
9447
|
+
});
|
|
9448
|
+
const estimatedGas = options.estimateGas === false ? void 0 : await estimateBridgeGas(publicClient, {
|
|
9449
|
+
account: getConfiguredAccountAddress(config),
|
|
9450
|
+
sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
|
|
9451
|
+
args,
|
|
9452
|
+
nativeFee
|
|
9453
|
+
});
|
|
9454
|
+
return {
|
|
9455
|
+
sourceChain,
|
|
9456
|
+
sourceChainId: sourceBridgeInfo.chainId,
|
|
9457
|
+
destinationChain: params.destinationChain,
|
|
9458
|
+
destinationChainId: destinationBridgeInfo.chainId,
|
|
9459
|
+
sourceBridgeAddress: sourceBridgeInfo.rareBridgeAddress,
|
|
9460
|
+
destinationBridgeAddress: destinationBridgeInfo.rareBridgeAddress,
|
|
9461
|
+
rareTokenAddress: sourceBridgeInfo.rareTokenAddress,
|
|
9462
|
+
destinationCcipChainSelector: destinationBridgeInfo.ccipChainSelector,
|
|
9463
|
+
amount,
|
|
9464
|
+
recipient,
|
|
9465
|
+
distributionData,
|
|
9466
|
+
nativeFee,
|
|
9467
|
+
estimatedGas
|
|
9468
|
+
};
|
|
9469
|
+
}
|
|
9470
|
+
function resolveRecipient(recipient, config) {
|
|
9471
|
+
const resolved = recipient ?? getConfiguredAccountAddress(config);
|
|
9472
|
+
if (resolved === void 0) {
|
|
9473
|
+
throw new Error("No recipient available for bridge quote. Pass params.recipient or provide config.account/walletClient with an account.");
|
|
9474
|
+
}
|
|
9475
|
+
return resolved;
|
|
9476
|
+
}
|
|
9477
|
+
async function estimateBridgeGas(publicClient, params) {
|
|
9478
|
+
if (params.account === void 0) {
|
|
9479
|
+
return void 0;
|
|
9480
|
+
}
|
|
9481
|
+
return publicClient.estimateGas({
|
|
9482
|
+
account: params.account,
|
|
9483
|
+
to: params.sourceBridgeAddress,
|
|
9484
|
+
data: encodeFunctionData({
|
|
9485
|
+
abi: rareBridgeAbi,
|
|
9486
|
+
functionName: "send",
|
|
9487
|
+
args: params.args
|
|
9488
|
+
}),
|
|
9489
|
+
value: params.nativeFee
|
|
9490
|
+
});
|
|
9491
|
+
}
|
|
9492
|
+
|
|
8707
9493
|
// src/contracts/abis/liquid-router.ts
|
|
8708
9494
|
var liquidRouterAbi = [
|
|
8709
9495
|
{
|
|
@@ -8754,7 +9540,7 @@ var liquidRouterAbi = [
|
|
|
8754
9540
|
];
|
|
8755
9541
|
|
|
8756
9542
|
// src/swap/known-pools.ts
|
|
8757
|
-
import { getAddress as
|
|
9543
|
+
import { getAddress as getAddress7 } from "viem";
|
|
8758
9544
|
|
|
8759
9545
|
// src/swap/pool-core.ts
|
|
8760
9546
|
function normalizeAddress(value) {
|
|
@@ -8773,10 +9559,10 @@ function inferBaseCurrencyAddress(poolKey, token) {
|
|
|
8773
9559
|
|
|
8774
9560
|
// src/swap/known-pools.ts
|
|
8775
9561
|
var wrappedEthAddresses = {
|
|
8776
|
-
mainnet:
|
|
8777
|
-
sepolia:
|
|
8778
|
-
base:
|
|
8779
|
-
"base-sepolia":
|
|
9562
|
+
mainnet: getAddress7("0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2"),
|
|
9563
|
+
sepolia: getAddress7("0xfFf9976782d46CC05630D1f6eBAb18b2324d6B14"),
|
|
9564
|
+
base: getAddress7("0x4200000000000000000000000000000000000006"),
|
|
9565
|
+
"base-sepolia": getAddress7("0x4200000000000000000000000000000000000006")
|
|
8780
9566
|
};
|
|
8781
9567
|
function poolToKey(pool) {
|
|
8782
9568
|
return {
|
|
@@ -9090,9 +9876,9 @@ async function quoteRouteSteps(publicClient, quoterAddress, routeSteps, currentA
|
|
|
9090
9876
|
|
|
9091
9877
|
// src/swap/route-encoding.ts
|
|
9092
9878
|
import {
|
|
9093
|
-
encodeAbiParameters,
|
|
9094
|
-
encodePacked as
|
|
9095
|
-
getAddress as
|
|
9879
|
+
encodeAbiParameters as encodeAbiParameters2,
|
|
9880
|
+
encodePacked as encodePacked3,
|
|
9881
|
+
getAddress as getAddress8,
|
|
9096
9882
|
parseAbiParameters
|
|
9097
9883
|
} from "viem";
|
|
9098
9884
|
var ROUTER_COMMANDS = {
|
|
@@ -9109,8 +9895,8 @@ var V4_ACTIONS = {
|
|
|
9109
9895
|
TAKE_ALL: 15
|
|
9110
9896
|
};
|
|
9111
9897
|
var ROUTER_RECIPIENTS = {
|
|
9112
|
-
msgSender:
|
|
9113
|
-
addressThis:
|
|
9898
|
+
msgSender: getAddress8("0x0000000000000000000000000000000000000001"),
|
|
9899
|
+
addressThis: getAddress8("0x0000000000000000000000000000000000000002")
|
|
9114
9900
|
};
|
|
9115
9901
|
var ROUTER_AMOUNT_CONSTANTS = {
|
|
9116
9902
|
openDelta: 0n,
|
|
@@ -9122,7 +9908,7 @@ function encodeRoute(quote, amountIn, currencyIn, currencyOut) {
|
|
|
9122
9908
|
}
|
|
9123
9909
|
const { commandBytes, inputs } = encodeRouteParts(quote, amountIn, currencyIn, currencyOut, 0);
|
|
9124
9910
|
return {
|
|
9125
|
-
commands:
|
|
9911
|
+
commands: encodePacked3(commandBytes.map(() => "uint8"), [...commandBytes]),
|
|
9126
9912
|
inputs
|
|
9127
9913
|
};
|
|
9128
9914
|
}
|
|
@@ -9202,13 +9988,13 @@ function getV4ExecutionMode(v4BlockStartIndex, nextIndex, routeLength) {
|
|
|
9202
9988
|
};
|
|
9203
9989
|
}
|
|
9204
9990
|
function encodeWrapEth(recipient, amount) {
|
|
9205
|
-
return
|
|
9991
|
+
return encodeAbiParameters2(
|
|
9206
9992
|
parseAbiParameters("address recipient, uint256 amount"),
|
|
9207
9993
|
[recipient, amount]
|
|
9208
9994
|
);
|
|
9209
9995
|
}
|
|
9210
9996
|
function encodeUnwrapWeth(recipient, amountMinimum) {
|
|
9211
|
-
return
|
|
9997
|
+
return encodeAbiParameters2(
|
|
9212
9998
|
parseAbiParameters("address recipient, uint256 amountMinimum"),
|
|
9213
9999
|
[recipient, amountMinimum]
|
|
9214
10000
|
);
|
|
@@ -9228,23 +10014,23 @@ function encodeV4ExactIn({
|
|
|
9228
10014
|
step.poolKey.hooks,
|
|
9229
10015
|
"0x"
|
|
9230
10016
|
]);
|
|
9231
|
-
const swapParams =
|
|
10017
|
+
const swapParams = encodeAbiParameters2(
|
|
9232
10018
|
parseAbiParameters("(address,(address,uint24,int24,address,bytes)[],uint128,uint128)"),
|
|
9233
10019
|
[[currencyIn, pathKeysArray, amountIn, minAmountOut]]
|
|
9234
10020
|
);
|
|
9235
10021
|
const settleAction = executionMode.inputSource === "user" ? V4_ACTIONS.SETTLE_ALL : V4_ACTIONS.SETTLE;
|
|
9236
|
-
const settleParams = executionMode.inputSource === "user" ?
|
|
10022
|
+
const settleParams = executionMode.inputSource === "user" ? encodeAbiParameters2(
|
|
9237
10023
|
parseAbiParameters("address currency, uint128 maxAmount"),
|
|
9238
10024
|
[currencyIn, amountIn]
|
|
9239
|
-
) :
|
|
10025
|
+
) : encodeAbiParameters2(
|
|
9240
10026
|
parseAbiParameters("address currency, uint256 amount, bool payerIsUser"),
|
|
9241
10027
|
[currencyIn, ROUTER_AMOUNT_CONSTANTS.contractBalance, false]
|
|
9242
10028
|
);
|
|
9243
10029
|
const takeAction = executionMode.outputTarget === "user" ? V4_ACTIONS.TAKE_ALL : V4_ACTIONS.TAKE;
|
|
9244
|
-
const takeParams = executionMode.outputTarget === "user" ?
|
|
10030
|
+
const takeParams = executionMode.outputTarget === "user" ? encodeAbiParameters2(
|
|
9245
10031
|
parseAbiParameters("address currency, uint128 minAmount"),
|
|
9246
10032
|
[currencyOut, minAmountOut]
|
|
9247
|
-
) :
|
|
10033
|
+
) : encodeAbiParameters2(
|
|
9248
10034
|
parseAbiParameters("address currency, address recipient, uint256 amount"),
|
|
9249
10035
|
[currencyOut, ROUTER_RECIPIENTS.addressThis, ROUTER_AMOUNT_CONSTANTS.openDelta]
|
|
9250
10036
|
);
|
|
@@ -9253,11 +10039,11 @@ function encodeV4ExactIn({
|
|
|
9253
10039
|
if (singleStep === void 0) {
|
|
9254
10040
|
throw new Error("Missing V4 exact input single step.");
|
|
9255
10041
|
}
|
|
9256
|
-
const actions2 =
|
|
10042
|
+
const actions2 = encodePacked3(
|
|
9257
10043
|
["uint8", "uint8", "uint8"],
|
|
9258
10044
|
[settleAction, V4_ACTIONS.SWAP_EXACT_IN_SINGLE, takeAction]
|
|
9259
10045
|
);
|
|
9260
|
-
return
|
|
10046
|
+
return encodeAbiParameters2(
|
|
9261
10047
|
parseAbiParameters("bytes actions, bytes[] params"),
|
|
9262
10048
|
[
|
|
9263
10049
|
actions2,
|
|
@@ -9269,11 +10055,11 @@ function encodeV4ExactIn({
|
|
|
9269
10055
|
]
|
|
9270
10056
|
);
|
|
9271
10057
|
}
|
|
9272
|
-
const actions =
|
|
10058
|
+
const actions = encodePacked3(
|
|
9273
10059
|
["uint8", "uint8", "uint8"],
|
|
9274
10060
|
[V4_ACTIONS.SWAP_EXACT_IN, settleAction, takeAction]
|
|
9275
10061
|
);
|
|
9276
|
-
return
|
|
10062
|
+
return encodeAbiParameters2(
|
|
9277
10063
|
parseAbiParameters("bytes actions, bytes[] params"),
|
|
9278
10064
|
[actions, [swapParams, settleParams, takeParams]]
|
|
9279
10065
|
);
|
|
@@ -9292,17 +10078,17 @@ function encodeV4ExactInSingle(step, amountIn, minAmountOut) {
|
|
|
9292
10078
|
minAmountOut,
|
|
9293
10079
|
"0x"
|
|
9294
10080
|
];
|
|
9295
|
-
return
|
|
10081
|
+
return encodeAbiParameters2(
|
|
9296
10082
|
parseAbiParameters("((address,address,uint24,int24,address),bool,uint128,uint128,bytes)"),
|
|
9297
10083
|
[swapExactInSingleTuple]
|
|
9298
10084
|
);
|
|
9299
10085
|
}
|
|
9300
10086
|
|
|
9301
10087
|
// src/swap/uniswap-api.ts
|
|
9302
|
-
import { getAddress as
|
|
10088
|
+
import { getAddress as getAddress9, isHex as isHex4 } from "viem";
|
|
9303
10089
|
|
|
9304
10090
|
// src/swap/trade-core.ts
|
|
9305
|
-
import { isAddressEqual as
|
|
10091
|
+
import { isAddressEqual as isAddressEqual15 } from "viem";
|
|
9306
10092
|
function toTradeInteger(value, field) {
|
|
9307
10093
|
if (typeof value === "bigint") return value;
|
|
9308
10094
|
if (typeof value === "number") {
|
|
@@ -9370,7 +10156,7 @@ function buildLiquidRouterTradeQuote(params) {
|
|
|
9370
10156
|
}
|
|
9371
10157
|
function getQuotedRecipientAmount(quote, recipient) {
|
|
9372
10158
|
const recipientOutput = quote.aggregatedOutputs?.find(
|
|
9373
|
-
(output) =>
|
|
10159
|
+
(output) => isAddressEqual15(output.recipient, recipient)
|
|
9374
10160
|
);
|
|
9375
10161
|
if (recipientOutput) {
|
|
9376
10162
|
return {
|
|
@@ -9389,7 +10175,7 @@ function assertSupportedUniswapRouting(routing) {
|
|
|
9389
10175
|
}
|
|
9390
10176
|
}
|
|
9391
10177
|
function assertRecipientSupportedForUniswapFallback(recipient, accountAddress) {
|
|
9392
|
-
if (recipient !== void 0 && !
|
|
10178
|
+
if (recipient !== void 0 && !isAddressEqual15(recipient, accountAddress)) {
|
|
9393
10179
|
throw new Error("recipient override is not supported for Uniswap API fallback routes.");
|
|
9394
10180
|
}
|
|
9395
10181
|
}
|
|
@@ -9469,7 +10255,7 @@ function parseNumber(value, field) {
|
|
|
9469
10255
|
function parseAddress2(value, field) {
|
|
9470
10256
|
const raw = parseString(value, field);
|
|
9471
10257
|
try {
|
|
9472
|
-
return
|
|
10258
|
+
return getAddress9(raw);
|
|
9473
10259
|
} catch {
|
|
9474
10260
|
throw new Error(`Uniswap API response field "${field}" must be a valid EVM address.`);
|
|
9475
10261
|
}
|
|
@@ -9479,7 +10265,7 @@ function parseOptionalAddress(value, field) {
|
|
|
9479
10265
|
}
|
|
9480
10266
|
function parseHex(value, field) {
|
|
9481
10267
|
const raw = parseString(value, field);
|
|
9482
|
-
if (!
|
|
10268
|
+
if (!isHex4(raw)) {
|
|
9483
10269
|
throw new Error(`Uniswap API response field "${field}" must be a hex string.`);
|
|
9484
10270
|
}
|
|
9485
10271
|
return raw;
|
|
@@ -9899,7 +10685,7 @@ async function executeRawRouterBuy(params) {
|
|
|
9899
10685
|
const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
|
|
9900
10686
|
const ethAmount = toWei(amountIn);
|
|
9901
10687
|
const minTokensOut = await toTokenAmount(params.publicClient, params.token, minAmountOutInput, "minAmountOut");
|
|
9902
|
-
const
|
|
10688
|
+
const targetTxHash = await walletClient.writeContract({
|
|
9903
10689
|
address: router,
|
|
9904
10690
|
abi: liquidRouterAbi,
|
|
9905
10691
|
functionName: "buy",
|
|
@@ -9908,8 +10694,8 @@ async function executeRawRouterBuy(params) {
|
|
|
9908
10694
|
chain: void 0,
|
|
9909
10695
|
value: ethAmount
|
|
9910
10696
|
});
|
|
9911
|
-
const
|
|
9912
|
-
return { txHash, receipt, minAmountOut: minTokensOut };
|
|
10697
|
+
const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
10698
|
+
return { txHash: targetTxHash, receipt: targetReceipt, minAmountOut: minTokensOut };
|
|
9913
10699
|
}
|
|
9914
10700
|
async function executeRawRouterSell(params) {
|
|
9915
10701
|
const { walletClient, account, accountAddress } = requireWallet(params.config);
|
|
@@ -9919,25 +10705,37 @@ async function executeRawRouterSell(params) {
|
|
|
9919
10705
|
const minAmountOutInput = requireInput(params.minAmountOut, "minAmountOut");
|
|
9920
10706
|
const tokenAmount = await toTokenAmount(params.publicClient, params.token, amountIn, "amountIn");
|
|
9921
10707
|
const minEthOut = toWei(minAmountOutInput);
|
|
9922
|
-
await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
|
|
9923
|
-
const txHash = await
|
|
9924
|
-
|
|
9925
|
-
|
|
9926
|
-
|
|
9927
|
-
|
|
9928
|
-
params.token,
|
|
9929
|
-
|
|
9930
|
-
|
|
9931
|
-
|
|
9932
|
-
|
|
9933
|
-
|
|
9934
|
-
|
|
9935
|
-
|
|
9936
|
-
|
|
9937
|
-
|
|
10708
|
+
const approvalTxHash = await ensureTokenAllowance(params.publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
|
|
10709
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
10710
|
+
operation: "swap sell",
|
|
10711
|
+
approvals: [{
|
|
10712
|
+
type: "erc20",
|
|
10713
|
+
approvalTxHash,
|
|
10714
|
+
target: params.token,
|
|
10715
|
+
spender: router
|
|
10716
|
+
}],
|
|
10717
|
+
run: async () => {
|
|
10718
|
+
const targetTxHash = await walletClient.writeContract({
|
|
10719
|
+
address: router,
|
|
10720
|
+
abi: liquidRouterAbi,
|
|
10721
|
+
functionName: "sell",
|
|
10722
|
+
args: [
|
|
10723
|
+
params.token,
|
|
10724
|
+
tokenAmount,
|
|
10725
|
+
params.recipient ?? accountAddress,
|
|
10726
|
+
minEthOut,
|
|
10727
|
+
params.commands,
|
|
10728
|
+
[...params.inputs],
|
|
10729
|
+
resolveDeadline(params.deadline)
|
|
10730
|
+
],
|
|
10731
|
+
account,
|
|
10732
|
+
chain: void 0
|
|
10733
|
+
});
|
|
10734
|
+
const targetReceipt = await params.publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
10735
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
10736
|
+
}
|
|
9938
10737
|
});
|
|
9939
|
-
|
|
9940
|
-
return { txHash, receipt, minAmountOut: minEthOut, tokenAmount };
|
|
10738
|
+
return { txHash, receipt, minAmountOut: minEthOut, tokenAmount, approvalTxHash };
|
|
9941
10739
|
}
|
|
9942
10740
|
function isRawTokenTradeParams(params) {
|
|
9943
10741
|
return params.route === "raw";
|
|
@@ -9981,28 +10779,38 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
9981
10779
|
validateRouterPayload(params.commands, params.inputs);
|
|
9982
10780
|
const amountIn = await toTokenAmount(publicClient, params.tokenIn, params.amountIn, "amountIn");
|
|
9983
10781
|
const minAmountOut = await toTokenAmount(publicClient, params.tokenOut, params.minAmountOut, "minAmountOut");
|
|
9984
|
-
|
|
9985
|
-
|
|
9986
|
-
|
|
9987
|
-
|
|
9988
|
-
|
|
9989
|
-
|
|
9990
|
-
|
|
9991
|
-
|
|
9992
|
-
|
|
9993
|
-
|
|
9994
|
-
|
|
9995
|
-
|
|
9996
|
-
|
|
9997
|
-
|
|
9998
|
-
|
|
9999
|
-
|
|
10000
|
-
|
|
10001
|
-
|
|
10002
|
-
|
|
10003
|
-
|
|
10782
|
+
const approvalTxHash = params.tokenIn === ETH_ADDRESS ? void 0 : await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.tokenIn, router, amountIn);
|
|
10783
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
10784
|
+
operation: "swap tokens",
|
|
10785
|
+
approvals: [{
|
|
10786
|
+
type: "erc20",
|
|
10787
|
+
approvalTxHash,
|
|
10788
|
+
target: params.tokenIn,
|
|
10789
|
+
spender: router
|
|
10790
|
+
}],
|
|
10791
|
+
run: async () => {
|
|
10792
|
+
const targetTxHash = await walletClient.writeContract({
|
|
10793
|
+
address: router,
|
|
10794
|
+
abi: liquidRouterAbi,
|
|
10795
|
+
functionName: "swap",
|
|
10796
|
+
args: [
|
|
10797
|
+
params.tokenIn,
|
|
10798
|
+
amountIn,
|
|
10799
|
+
params.tokenOut,
|
|
10800
|
+
params.recipient ?? accountAddress,
|
|
10801
|
+
minAmountOut,
|
|
10802
|
+
params.commands,
|
|
10803
|
+
[...params.inputs],
|
|
10804
|
+
resolveDeadline(params.deadline)
|
|
10805
|
+
],
|
|
10806
|
+
account,
|
|
10807
|
+
chain: void 0,
|
|
10808
|
+
value: params.tokenIn === ETH_ADDRESS ? amountIn : void 0
|
|
10809
|
+
});
|
|
10810
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
10811
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
10812
|
+
}
|
|
10004
10813
|
});
|
|
10005
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
10006
10814
|
return { txHash, receipt };
|
|
10007
10815
|
},
|
|
10008
10816
|
async quoteBuyToken(params) {
|
|
@@ -10069,7 +10877,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10069
10877
|
});
|
|
10070
10878
|
if (quoteDetails.kind === "local") {
|
|
10071
10879
|
const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
|
|
10072
|
-
const
|
|
10880
|
+
const targetTxHash = await walletClient.writeContract({
|
|
10073
10881
|
address: router,
|
|
10074
10882
|
abi: liquidRouterAbi,
|
|
10075
10883
|
functionName: "buy",
|
|
@@ -10085,10 +10893,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10085
10893
|
chain: void 0,
|
|
10086
10894
|
value: quoteDetails.quote.amountIn
|
|
10087
10895
|
});
|
|
10088
|
-
const
|
|
10896
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
10089
10897
|
return {
|
|
10090
|
-
txHash,
|
|
10091
|
-
receipt,
|
|
10898
|
+
txHash: targetTxHash,
|
|
10899
|
+
receipt: targetReceipt,
|
|
10092
10900
|
estimatedAmountOut: quoteDetails.quote.estimatedAmountOut,
|
|
10093
10901
|
minAmountOut: quoteDetails.quote.minAmountOut,
|
|
10094
10902
|
routeSource: quoteDetails.quote.routeSource,
|
|
@@ -10180,24 +10988,36 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10180
10988
|
const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
|
|
10181
10989
|
const amountIn = requireInput(params.amountIn, "amountIn");
|
|
10182
10990
|
const tokenAmount = await toTokenAmount(publicClient, params.token, amountIn, "amountIn");
|
|
10183
|
-
await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
|
|
10184
|
-
const txHash = await
|
|
10185
|
-
|
|
10186
|
-
|
|
10187
|
-
|
|
10188
|
-
|
|
10189
|
-
params.token,
|
|
10190
|
-
|
|
10191
|
-
|
|
10192
|
-
|
|
10193
|
-
|
|
10194
|
-
|
|
10195
|
-
|
|
10196
|
-
|
|
10197
|
-
|
|
10198
|
-
|
|
10991
|
+
const approvalTxHash2 = await ensureTokenAllowance(publicClient, walletClient, account, accountAddress, params.token, router, tokenAmount);
|
|
10992
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
10993
|
+
operation: "sell token",
|
|
10994
|
+
approvals: [{
|
|
10995
|
+
type: "erc20",
|
|
10996
|
+
approvalTxHash: approvalTxHash2,
|
|
10997
|
+
target: params.token,
|
|
10998
|
+
spender: router
|
|
10999
|
+
}],
|
|
11000
|
+
run: async () => {
|
|
11001
|
+
const targetTxHash = await walletClient.writeContract({
|
|
11002
|
+
address: router,
|
|
11003
|
+
abi: liquidRouterAbi,
|
|
11004
|
+
functionName: "sell",
|
|
11005
|
+
args: [
|
|
11006
|
+
params.token,
|
|
11007
|
+
tokenAmount,
|
|
11008
|
+
params.recipient ?? accountAddress,
|
|
11009
|
+
quoteDetails.quote.minAmountOut,
|
|
11010
|
+
quoteDetails.quote.commands,
|
|
11011
|
+
[...quoteDetails.quote.inputs],
|
|
11012
|
+
resolveDeadline(params.deadline)
|
|
11013
|
+
],
|
|
11014
|
+
account,
|
|
11015
|
+
chain: void 0
|
|
11016
|
+
});
|
|
11017
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
11018
|
+
return { txHash: targetTxHash, receipt: targetReceipt };
|
|
11019
|
+
}
|
|
10199
11020
|
});
|
|
10200
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
10201
11021
|
return {
|
|
10202
11022
|
txHash,
|
|
10203
11023
|
receipt,
|
|
@@ -10206,7 +11026,8 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10206
11026
|
routeSource: quoteDetails.quote.routeSource,
|
|
10207
11027
|
execution: quoteDetails.quote.execution,
|
|
10208
11028
|
commands: quoteDetails.quote.commands,
|
|
10209
|
-
inputs: quoteDetails.quote.inputs
|
|
11029
|
+
inputs: quoteDetails.quote.inputs,
|
|
11030
|
+
approvalTxHash: approvalTxHash2
|
|
10210
11031
|
};
|
|
10211
11032
|
}
|
|
10212
11033
|
const approval = await requestUniswapApproval({
|
|
@@ -10225,14 +11046,33 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10225
11046
|
accountAddress,
|
|
10226
11047
|
chainId
|
|
10227
11048
|
})).txHash : void 0;
|
|
10228
|
-
const
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
|
|
10235
|
-
|
|
11049
|
+
const sent = await runWithApprovalSideEffectAlert({
|
|
11050
|
+
operation: "sell token",
|
|
11051
|
+
approvals: [
|
|
11052
|
+
{
|
|
11053
|
+
type: "erc20-reset",
|
|
11054
|
+
approvalTxHash: approvalResetTxHash,
|
|
11055
|
+
target: params.token,
|
|
11056
|
+
spender: approval.cancel?.to
|
|
11057
|
+
},
|
|
11058
|
+
{
|
|
11059
|
+
type: "erc20",
|
|
11060
|
+
approvalTxHash,
|
|
11061
|
+
target: params.token,
|
|
11062
|
+
spender: approval.approval?.to
|
|
11063
|
+
}
|
|
11064
|
+
],
|
|
11065
|
+
run: async () => {
|
|
11066
|
+
const swapResponse = await requestUniswapSwap({
|
|
11067
|
+
apiKey: quoteDetails.apiKey,
|
|
11068
|
+
quote: quoteDetails.rawQuote,
|
|
11069
|
+
deadline: uniswapDeadline
|
|
11070
|
+
});
|
|
11071
|
+
return sendPreparedTransaction(publicClient, walletClient, account, swapResponse.swap, {
|
|
11072
|
+
accountAddress,
|
|
11073
|
+
chainId
|
|
11074
|
+
});
|
|
11075
|
+
}
|
|
10236
11076
|
});
|
|
10237
11077
|
return {
|
|
10238
11078
|
...sent,
|
|
@@ -10251,7 +11091,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10251
11091
|
const { walletClient, account, accountAddress } = requireWallet(config);
|
|
10252
11092
|
const router = requireConfiguredAddress(addresses.swapRouter, "Liquid router", chain);
|
|
10253
11093
|
const quote = await buildBuyRareQuote(publicClient, chain, addresses, params);
|
|
10254
|
-
const
|
|
11094
|
+
const targetTxHash = await walletClient.writeContract({
|
|
10255
11095
|
address: router,
|
|
10256
11096
|
abi: liquidRouterAbi,
|
|
10257
11097
|
functionName: "buy",
|
|
@@ -10260,10 +11100,10 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10260
11100
|
chain: void 0,
|
|
10261
11101
|
value: quote.ethAmount
|
|
10262
11102
|
});
|
|
10263
|
-
const
|
|
11103
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
10264
11104
|
return {
|
|
10265
|
-
txHash,
|
|
10266
|
-
receipt,
|
|
11105
|
+
txHash: targetTxHash,
|
|
11106
|
+
receipt: targetReceipt,
|
|
10267
11107
|
estimatedRareOut: quote.estimatedRareOut,
|
|
10268
11108
|
minRareOut: quote.minRareOut,
|
|
10269
11109
|
commands: quote.commands,
|
|
@@ -10277,7 +11117,7 @@ function createSwapNamespace(config, chain, chainId, addresses) {
|
|
|
10277
11117
|
import {
|
|
10278
11118
|
erc20Abi as erc20Abi2,
|
|
10279
11119
|
hexToBigInt as hexToBigInt2,
|
|
10280
|
-
isAddressEqual as
|
|
11120
|
+
isAddressEqual as isAddressEqual17,
|
|
10281
11121
|
parseEventLogs as parseEventLogs6
|
|
10282
11122
|
} from "viem";
|
|
10283
11123
|
|
|
@@ -10599,9 +11439,32 @@ var rareMinterAbi = [
|
|
|
10599
11439
|
];
|
|
10600
11440
|
|
|
10601
11441
|
// src/sdk/collection-core.ts
|
|
11442
|
+
var lazySovereignCollectionContractTypes = [
|
|
11443
|
+
"lazy",
|
|
11444
|
+
"lazy-royalty-guard",
|
|
11445
|
+
"lazy-deadman-royalty-guard"
|
|
11446
|
+
];
|
|
10602
11447
|
var defaultRoyaltyInfoSalePrice = 10000n;
|
|
11448
|
+
function normalizeLazySovereignCollectionContractType(input) {
|
|
11449
|
+
if (input === void 0) {
|
|
11450
|
+
return void 0;
|
|
11451
|
+
}
|
|
11452
|
+
const normalized = input.trim().toLowerCase();
|
|
11453
|
+
if (normalized === "lazy" || normalized === "standard" || normalized === "lazy-sovereign" || normalized === "lazy-sovereign-nft") {
|
|
11454
|
+
return "lazy";
|
|
11455
|
+
}
|
|
11456
|
+
if (normalized === "lazy-royalty-guard" || normalized === "royalty-guard") {
|
|
11457
|
+
return "lazy-royalty-guard";
|
|
11458
|
+
}
|
|
11459
|
+
if (normalized === "lazy-deadman-royalty-guard" || normalized === "lazy-royalty-guard-deadman" || normalized === "deadman-royalty-guard" || normalized === "royalty-guard-deadman" || normalized === "deadman") {
|
|
11460
|
+
return "lazy-deadman-royalty-guard";
|
|
11461
|
+
}
|
|
11462
|
+
throw new Error(
|
|
11463
|
+
`Unsupported Lazy Sovereign collection contract type "${input}". Supported: ${lazySovereignCollectionContractTypes.join(", ")}.`
|
|
11464
|
+
);
|
|
11465
|
+
}
|
|
10603
11466
|
function planCreateLazySovereignCollection(params) {
|
|
10604
|
-
const contractType = params.contractType ?? "lazy";
|
|
11467
|
+
const contractType = normalizeLazySovereignCollectionContractType(params.contractType) ?? "lazy";
|
|
10605
11468
|
return {
|
|
10606
11469
|
name: params.name,
|
|
10607
11470
|
symbol: params.symbol,
|
|
@@ -10759,11 +11622,11 @@ function toRoyaltyPercentage(value) {
|
|
|
10759
11622
|
|
|
10760
11623
|
// src/sdk/release-core.ts
|
|
10761
11624
|
import {
|
|
10762
|
-
getAddress as
|
|
10763
|
-
isAddress as
|
|
10764
|
-
isAddressEqual as
|
|
10765
|
-
isHex as
|
|
10766
|
-
keccak256 as
|
|
11625
|
+
getAddress as getAddress10,
|
|
11626
|
+
isAddress as isAddress6,
|
|
11627
|
+
isAddressEqual as isAddressEqual16,
|
|
11628
|
+
isHex as isHex5,
|
|
11629
|
+
keccak256 as keccak2563,
|
|
10767
11630
|
parseEther as parseEther2,
|
|
10768
11631
|
parseUnits as parseUnits7
|
|
10769
11632
|
} from "viem";
|
|
@@ -10780,7 +11643,7 @@ function requireRareMinterAddress(address) {
|
|
|
10780
11643
|
}
|
|
10781
11644
|
function assertReleaseContractOwner(opts) {
|
|
10782
11645
|
const { contract, accountAddress, owner } = opts;
|
|
10783
|
-
if (!
|
|
11646
|
+
if (!isAddressEqual16(owner, accountAddress)) {
|
|
10784
11647
|
throw new Error(
|
|
10785
11648
|
`Connected wallet ${accountAddress} is not the owner of collection ${contract}. Contract owner is ${owner}.`
|
|
10786
11649
|
);
|
|
@@ -10969,7 +11832,7 @@ function parseReleaseAllowlistCsv(input) {
|
|
|
10969
11832
|
throw new Error("CSV allowlist is empty.");
|
|
10970
11833
|
}
|
|
10971
11834
|
const headerColumn = findAllowlistAddressColumn(firstRow.fields);
|
|
10972
|
-
if (headerColumn === -1 && !
|
|
11835
|
+
if (headerColumn === -1 && !isAddress6(firstRow.fields[0]?.trim() ?? "")) {
|
|
10973
11836
|
throw new Error("CSV allowlist must put wallet addresses in the first column or include an address/wallet header.");
|
|
10974
11837
|
}
|
|
10975
11838
|
const addressColumn = headerColumn === -1 ? 0 : headerColumn;
|
|
@@ -11028,27 +11891,27 @@ function buildReleaseAllowlistArtifact(wallets) {
|
|
|
11028
11891
|
};
|
|
11029
11892
|
}
|
|
11030
11893
|
function getReleaseAllowlistProof(opts) {
|
|
11031
|
-
const address =
|
|
11894
|
+
const address = getAddress10(opts.address);
|
|
11032
11895
|
return opts.artifact.wallets.find((entry) => addressesEqual(entry.address, address)) ?? null;
|
|
11033
11896
|
}
|
|
11034
11897
|
function verifyReleaseAllowlistProof(opts) {
|
|
11035
11898
|
const root = normalizeBytes322(opts.root, "allowlist root");
|
|
11036
11899
|
const hash = opts.proof.reduce(
|
|
11037
11900
|
(current, sibling) => hashMerklePair(current, normalizeBytes322(sibling, "allowlist proof item")),
|
|
11038
|
-
hashAllowlistAddress(
|
|
11901
|
+
hashAllowlistAddress(getAddress10(opts.address))
|
|
11039
11902
|
);
|
|
11040
11903
|
return hexEquals(hash, root);
|
|
11041
11904
|
}
|
|
11042
11905
|
function preflightReleaseDirectSaleMint(params) {
|
|
11043
11906
|
const { status, plan, buyer, nowSeconds } = params;
|
|
11044
11907
|
const quantity = BigInt(plan.quantity);
|
|
11045
|
-
if (!
|
|
11908
|
+
if (!isAddressEqual16(status.contract, plan.contract)) {
|
|
11046
11909
|
throw new Error(`Release status is for ${status.contract}, but mint plan is for ${plan.contract}.`);
|
|
11047
11910
|
}
|
|
11048
11911
|
if (!status.configured) {
|
|
11049
11912
|
throw new Error("RareMinter direct sale is not configured for this contract.");
|
|
11050
11913
|
}
|
|
11051
|
-
if (plan.recipient !== void 0 && !
|
|
11914
|
+
if (plan.recipient !== void 0 && !isAddressEqual16(plan.recipient, buyer)) {
|
|
11052
11915
|
throw new Error("RareMinter direct sale mint does not support a separate recipient; it mints to the connected wallet.");
|
|
11053
11916
|
}
|
|
11054
11917
|
if (status.startTime > nowSeconds) {
|
|
@@ -11072,7 +11935,7 @@ function preflightReleaseDirectSaleMint(params) {
|
|
|
11072
11935
|
throw new Error("buyer has reached the per-wallet transaction limit.");
|
|
11073
11936
|
}
|
|
11074
11937
|
}
|
|
11075
|
-
if (plan.currency !== void 0 && !
|
|
11938
|
+
if (plan.currency !== void 0 && !isAddressEqual16(plan.currency, status.currencyAddress)) {
|
|
11076
11939
|
throw new Error(`expected currency ${plan.currency} does not match configured currency ${status.currencyAddress}.`);
|
|
11077
11940
|
}
|
|
11078
11941
|
const price = plan.price === void 0 ? status.price : normalizeReleasePrice({
|
|
@@ -11206,11 +12069,11 @@ function requireReleaseAccountCounter(value, label) {
|
|
|
11206
12069
|
return value;
|
|
11207
12070
|
}
|
|
11208
12071
|
function normalizeBytes322(value, field) {
|
|
11209
|
-
if (typeof value !== "string" || !
|
|
12072
|
+
if (typeof value !== "string" || !isHex5(value) || value.length !== 66) {
|
|
11210
12073
|
throw new Error(`${field} must be a 32-byte hex string.`);
|
|
11211
12074
|
}
|
|
11212
12075
|
const normalized = value.toLocaleLowerCase();
|
|
11213
|
-
if (!
|
|
12076
|
+
if (!isHex5(normalized) || normalized.length !== 66) {
|
|
11214
12077
|
throw new Error(`${field} must be a 32-byte hex string.`);
|
|
11215
12078
|
}
|
|
11216
12079
|
return normalized;
|
|
@@ -11280,11 +12143,11 @@ function normalizeAllowlistRows(rows) {
|
|
|
11280
12143
|
throw new Error(`Invalid allowlist address at ${row.label}: expected a string.`);
|
|
11281
12144
|
}
|
|
11282
12145
|
const raw = row.value.trim();
|
|
11283
|
-
if (!
|
|
12146
|
+
if (!isAddress6(raw)) {
|
|
11284
12147
|
throw new Error(`Invalid allowlist address at ${row.label}: "${raw}".`);
|
|
11285
12148
|
}
|
|
11286
|
-
const address =
|
|
11287
|
-
const duplicate = state.seen.find((seen) =>
|
|
12149
|
+
const address = getAddress10(raw);
|
|
12150
|
+
const duplicate = state.seen.find((seen) => isAddressEqual16(seen.address, address));
|
|
11288
12151
|
if (duplicate !== void 0) {
|
|
11289
12152
|
throw new Error(`Duplicate allowlist address at ${row.label}: "${address}" duplicates ${duplicate.label}.`);
|
|
11290
12153
|
}
|
|
@@ -11340,11 +12203,11 @@ function getMerkleRoot(layers) {
|
|
|
11340
12203
|
return root;
|
|
11341
12204
|
}
|
|
11342
12205
|
function hashAllowlistAddress(address) {
|
|
11343
|
-
return
|
|
12206
|
+
return keccak2563(address);
|
|
11344
12207
|
}
|
|
11345
12208
|
function hashMerklePair(a, b) {
|
|
11346
12209
|
const [left, right] = compareHex(a, b) <= 0 ? [a, b] : [b, a];
|
|
11347
|
-
return
|
|
12210
|
+
return keccak2563(`0x${left.slice(2)}${right.slice(2)}`);
|
|
11348
12211
|
}
|
|
11349
12212
|
function compareAddress(a, b) {
|
|
11350
12213
|
return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase());
|
|
@@ -11353,7 +12216,7 @@ function compareHex(a, b) {
|
|
|
11353
12216
|
return a.toLocaleLowerCase().localeCompare(b.toLocaleLowerCase());
|
|
11354
12217
|
}
|
|
11355
12218
|
function addressesEqual(a, b) {
|
|
11356
|
-
return
|
|
12219
|
+
return isAddressEqual16(a, b);
|
|
11357
12220
|
}
|
|
11358
12221
|
function hexEquals(a, b) {
|
|
11359
12222
|
return a.toLocaleLowerCase() === b.toLocaleLowerCase();
|
|
@@ -11428,10 +12291,8 @@ async function readReleaseCollectionOwner(publicClient, contract) {
|
|
|
11428
12291
|
);
|
|
11429
12292
|
}
|
|
11430
12293
|
}
|
|
11431
|
-
async function
|
|
12294
|
+
async function assertReleaseMinterCanMint(opts) {
|
|
11432
12295
|
const { publicClient, contract, accountAddress, rareMinter } = opts;
|
|
11433
|
-
const owner = await readReleaseCollectionOwner(publicClient, contract);
|
|
11434
|
-
assertReleaseContractOwner({ contract, accountAddress, owner });
|
|
11435
12296
|
try {
|
|
11436
12297
|
await publicClient.simulateContract({
|
|
11437
12298
|
address: contract,
|
|
@@ -11610,7 +12471,7 @@ function readMintDirectSaleTokenRange(opts) {
|
|
|
11610
12471
|
eventName: "MintDirectSale",
|
|
11611
12472
|
logs: opts.receipt.logs
|
|
11612
12473
|
}).filter(
|
|
11613
|
-
(log) =>
|
|
12474
|
+
(log) => isAddressEqual17(log.args._contractAddress, opts.contract) && isAddressEqual17(log.args._buyer, opts.buyer)
|
|
11614
12475
|
);
|
|
11615
12476
|
if (event === void 0) {
|
|
11616
12477
|
throw new Error(`MintDirectSale event was not found for ${opts.contract} and buyer ${opts.buyer}.`);
|
|
@@ -11797,6 +12658,11 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
|
|
|
11797
12658
|
currencyDecimals: currencyDecimals2,
|
|
11798
12659
|
nowSeconds: currentUnixTimestamp3()
|
|
11799
12660
|
});
|
|
12661
|
+
await assertCollectionOwnerForReleaseWrite({
|
|
12662
|
+
publicClient,
|
|
12663
|
+
contract: plan.contract,
|
|
12664
|
+
accountAddress
|
|
12665
|
+
});
|
|
11800
12666
|
const approvalTxHash = await approveReleaseMinterIfNeeded({
|
|
11801
12667
|
publicClient,
|
|
11802
12668
|
walletClient,
|
|
@@ -11805,29 +12671,41 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
|
|
|
11805
12671
|
minter: rareMinter,
|
|
11806
12672
|
autoApprove: params.autoApprove
|
|
11807
12673
|
});
|
|
11808
|
-
await
|
|
11809
|
-
|
|
11810
|
-
|
|
11811
|
-
|
|
11812
|
-
|
|
11813
|
-
|
|
11814
|
-
|
|
11815
|
-
|
|
11816
|
-
|
|
11817
|
-
|
|
11818
|
-
|
|
11819
|
-
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
|
|
11823
|
-
|
|
11824
|
-
|
|
11825
|
-
|
|
11826
|
-
|
|
11827
|
-
|
|
11828
|
-
|
|
12674
|
+
const { txHash, receipt } = await runWithApprovalSideEffectAlert({
|
|
12675
|
+
operation: "release configure",
|
|
12676
|
+
approvals: [{
|
|
12677
|
+
type: "minter",
|
|
12678
|
+
approvalTxHash,
|
|
12679
|
+
target: plan.contract,
|
|
12680
|
+
minter: rareMinter
|
|
12681
|
+
}],
|
|
12682
|
+
run: async () => {
|
|
12683
|
+
await assertReleaseMinterCanMint({
|
|
12684
|
+
publicClient,
|
|
12685
|
+
contract: plan.contract,
|
|
12686
|
+
accountAddress,
|
|
12687
|
+
rareMinter
|
|
12688
|
+
});
|
|
12689
|
+
const configureTxHash = await walletClient.writeContract({
|
|
12690
|
+
address: rareMinter,
|
|
12691
|
+
abi: rareMinterAbi,
|
|
12692
|
+
functionName: "prepareMintDirectSale",
|
|
12693
|
+
args: [
|
|
12694
|
+
plan.contract,
|
|
12695
|
+
plan.currencyAddress,
|
|
12696
|
+
plan.price,
|
|
12697
|
+
plan.startTime,
|
|
12698
|
+
plan.maxMints,
|
|
12699
|
+
plan.splitRecipients,
|
|
12700
|
+
plan.splitRatios
|
|
12701
|
+
],
|
|
12702
|
+
account,
|
|
12703
|
+
chain: void 0
|
|
12704
|
+
});
|
|
12705
|
+
const configureReceipt = await publicClient.waitForTransactionReceipt({ hash: configureTxHash });
|
|
12706
|
+
return { txHash: configureTxHash, receipt: configureReceipt };
|
|
12707
|
+
}
|
|
11829
12708
|
});
|
|
11830
|
-
const receipt = await publicClient.waitForTransactionReceipt({ hash: txHash });
|
|
11831
12709
|
return {
|
|
11832
12710
|
txHash,
|
|
11833
12711
|
receipt,
|
|
@@ -11876,26 +12754,38 @@ function createReleaseNamespace(publicClient, config, chain, addresses) {
|
|
|
11876
12754
|
amount: mint.totalPrice,
|
|
11877
12755
|
autoApprove: plan.autoApprove
|
|
11878
12756
|
});
|
|
11879
|
-
const txHash = await
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
mint.
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
|
|
11894
|
-
|
|
11895
|
-
|
|
11896
|
-
|
|
11897
|
-
|
|
11898
|
-
|
|
12757
|
+
const { txHash, receipt, tokenRange } = await runWithApprovalSideEffectAlert({
|
|
12758
|
+
operation: "release mint",
|
|
12759
|
+
approvals: [{
|
|
12760
|
+
type: "erc20",
|
|
12761
|
+
approvalTxHash: payment.approvalTxHash,
|
|
12762
|
+
target: mint.currency,
|
|
12763
|
+
spender: rareMinter
|
|
12764
|
+
}],
|
|
12765
|
+
run: async () => {
|
|
12766
|
+
const targetTxHash = await walletClient.writeContract({
|
|
12767
|
+
address: rareMinter,
|
|
12768
|
+
abi: rareMinterAbi,
|
|
12769
|
+
functionName: "mintDirectSale",
|
|
12770
|
+
args: [
|
|
12771
|
+
mint.contract,
|
|
12772
|
+
mint.currency,
|
|
12773
|
+
mint.price,
|
|
12774
|
+
mint.quantity,
|
|
12775
|
+
mint.proof
|
|
12776
|
+
],
|
|
12777
|
+
account,
|
|
12778
|
+
chain: void 0,
|
|
12779
|
+
value: payment.value
|
|
12780
|
+
});
|
|
12781
|
+
const targetReceipt = await publicClient.waitForTransactionReceipt({ hash: targetTxHash });
|
|
12782
|
+
const mintedTokenRange = readMintDirectSaleTokenRange({
|
|
12783
|
+
receipt: targetReceipt,
|
|
12784
|
+
contract: mint.contract,
|
|
12785
|
+
buyer: accountAddress
|
|
12786
|
+
});
|
|
12787
|
+
return { txHash: targetTxHash, receipt: targetReceipt, tokenRange: mintedTokenRange };
|
|
12788
|
+
}
|
|
11899
12789
|
});
|
|
11900
12790
|
return {
|
|
11901
12791
|
txHash,
|
|
@@ -12949,146 +13839,6 @@ function contractSupportError(operation, contract, cause) {
|
|
|
12949
13839
|
);
|
|
12950
13840
|
}
|
|
12951
13841
|
|
|
12952
|
-
// src/sdk/merkle-core.ts
|
|
12953
|
-
import { Buffer } from "buffer";
|
|
12954
|
-
import { MerkleTree } from "merkletreejs";
|
|
12955
|
-
import {
|
|
12956
|
-
encodePacked as encodePacked3,
|
|
12957
|
-
getAddress as getAddress10,
|
|
12958
|
-
isAddress as isAddress6,
|
|
12959
|
-
isAddressEqual as isAddressEqual17,
|
|
12960
|
-
isHex as isHex5,
|
|
12961
|
-
keccak256 as keccak2563
|
|
12962
|
-
} from "viem";
|
|
12963
|
-
function hexBuffer(hex) {
|
|
12964
|
-
return Buffer.from(hex.startsWith("0x") ? hex.slice(2) : hex, "hex");
|
|
12965
|
-
}
|
|
12966
|
-
function tokenLeaf(contract, tokenId) {
|
|
12967
|
-
const packed = encodePacked3(["address", "uint256"], [contract, tokenId]);
|
|
12968
|
-
return hexBuffer(keccak2563(packed));
|
|
12969
|
-
}
|
|
12970
|
-
function addressLeaf(address) {
|
|
12971
|
-
return hexBuffer(keccak2563(address));
|
|
12972
|
-
}
|
|
12973
|
-
function parseBytes32(value, field) {
|
|
12974
|
-
if (!isHex5(value) || value.length !== 66) {
|
|
12975
|
-
throw new Error(`${field} must be a 0x-prefixed bytes32 hex string`);
|
|
12976
|
-
}
|
|
12977
|
-
return value;
|
|
12978
|
-
}
|
|
12979
|
-
function parseBytes32Array(values, field) {
|
|
12980
|
-
return values.map((value, index) => parseBytes32(value, `${field}[${index}]`));
|
|
12981
|
-
}
|
|
12982
|
-
function compareTokenEntries(a, b) {
|
|
12983
|
-
if (!isAddressEqual17(a.contract, b.contract)) {
|
|
12984
|
-
return a.contract.localeCompare(b.contract);
|
|
12985
|
-
}
|
|
12986
|
-
return a.tokenId.localeCompare(b.tokenId);
|
|
12987
|
-
}
|
|
12988
|
-
function normalizeTokenEntry(token) {
|
|
12989
|
-
if (!isAddress6(token.contract)) {
|
|
12990
|
-
throw new Error(`Invalid token contract address: ${token.contract}`);
|
|
12991
|
-
}
|
|
12992
|
-
return {
|
|
12993
|
-
contract: getAddress10(token.contract),
|
|
12994
|
-
tokenId: String(token.tokenId),
|
|
12995
|
-
tokenIdBigInt: toInteger(token.tokenId, "tokenId")
|
|
12996
|
-
};
|
|
12997
|
-
}
|
|
12998
|
-
function buildBatchListingTree(tokens) {
|
|
12999
|
-
if (tokens.length < 2) {
|
|
13000
|
-
throw new Error("buildBatchListingTree requires at least two tokens");
|
|
13001
|
-
}
|
|
13002
|
-
const sorted = tokens.map(normalizeTokenEntry).sort(compareTokenEntries);
|
|
13003
|
-
const leaves = sorted.map((token) => tokenLeaf(token.contract, token.tokenIdBigInt));
|
|
13004
|
-
const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2563(data)), {
|
|
13005
|
-
sortPairs: true
|
|
13006
|
-
});
|
|
13007
|
-
return {
|
|
13008
|
-
root: parseBytes32(tree.getHexRoot(), "root"),
|
|
13009
|
-
tree,
|
|
13010
|
-
sortedTokens: sorted.map(({ contract, tokenId }) => ({ contract, tokenId }))
|
|
13011
|
-
};
|
|
13012
|
-
}
|
|
13013
|
-
function buildAllowListTree(addresses) {
|
|
13014
|
-
if (addresses.length < 2) {
|
|
13015
|
-
throw new Error("buildAllowListTree requires at least two addresses");
|
|
13016
|
-
}
|
|
13017
|
-
const sorted = addresses.map((address) => {
|
|
13018
|
-
if (!isAddress6(address)) throw new Error(`Invalid allowlist address: ${address}`);
|
|
13019
|
-
return getAddress10(address);
|
|
13020
|
-
}).sort((a, b) => a.localeCompare(b));
|
|
13021
|
-
const leaves = sorted.map(addressLeaf);
|
|
13022
|
-
const tree = new MerkleTree(leaves, (data) => hexBuffer(keccak2563(data)), {
|
|
13023
|
-
sortPairs: true
|
|
13024
|
-
});
|
|
13025
|
-
return {
|
|
13026
|
-
root: parseBytes32(tree.getHexRoot(), "root"),
|
|
13027
|
-
tree,
|
|
13028
|
-
sortedAddresses: sorted
|
|
13029
|
-
};
|
|
13030
|
-
}
|
|
13031
|
-
function getTokenProof(tree, contract, tokenId) {
|
|
13032
|
-
const leaf = tokenLeaf(getAddress10(contract), tokenId);
|
|
13033
|
-
return parseBytes32Array(tree.getHexProof(leaf), "proof");
|
|
13034
|
-
}
|
|
13035
|
-
function getAddressProof(tree, address) {
|
|
13036
|
-
const leaf = addressLeaf(getAddress10(address));
|
|
13037
|
-
return parseBytes32Array(tree.getHexProof(leaf), "proof");
|
|
13038
|
-
}
|
|
13039
|
-
function buildMerkleProofArtifact(artifact, contract, tokenId, buyer) {
|
|
13040
|
-
const tokenIdBig = toInteger(tokenId, "tokenId");
|
|
13041
|
-
const contractChecksum = getAddress10(contract);
|
|
13042
|
-
const found = artifact.tokens.find(
|
|
13043
|
-
(token) => isAddressEqual17(token.contract, contractChecksum) && BigInt(token.tokenId) === tokenIdBig
|
|
13044
|
-
);
|
|
13045
|
-
if (found === void 0) {
|
|
13046
|
-
throw new Error(
|
|
13047
|
-
`Token ${contractChecksum}/${tokenIdBig.toString()} is not in this root artifact's token set`
|
|
13048
|
-
);
|
|
13049
|
-
}
|
|
13050
|
-
const { tree, root } = buildBatchListingTree(
|
|
13051
|
-
artifact.tokens.map((token) => ({ contract: token.contract, tokenId: token.tokenId }))
|
|
13052
|
-
);
|
|
13053
|
-
if (root !== artifact.root) {
|
|
13054
|
-
throw new Error(
|
|
13055
|
-
`Recomputed NFT tree root (${root}) does not match artifact root (${artifact.root}). Artifact is corrupt or tree encoding has drifted.`
|
|
13056
|
-
);
|
|
13057
|
-
}
|
|
13058
|
-
const allowListProofFields = buildAllowListProofFields(artifact, buyer);
|
|
13059
|
-
return {
|
|
13060
|
-
root: artifact.root,
|
|
13061
|
-
contract: contractChecksum,
|
|
13062
|
-
tokenId: tokenIdBig.toString(),
|
|
13063
|
-
proof: getTokenProof(tree, contractChecksum, tokenIdBig),
|
|
13064
|
-
...allowListProofFields ?? {}
|
|
13065
|
-
};
|
|
13066
|
-
}
|
|
13067
|
-
function buildAllowListProofFields(artifact, buyer) {
|
|
13068
|
-
if (artifact.allowList === void 0) return void 0;
|
|
13069
|
-
if (buyer === void 0) {
|
|
13070
|
-
throw new Error(
|
|
13071
|
-
"This root has an allowlist; pass buyer address to buildMerkleProofArtifact to include allowListProof"
|
|
13072
|
-
);
|
|
13073
|
-
}
|
|
13074
|
-
if (!isAddress6(buyer)) throw new Error(`Invalid buyer address: ${buyer}`);
|
|
13075
|
-
const buyerChecksum = getAddress10(buyer);
|
|
13076
|
-
const inAllowList = artifact.allowList.addresses.some((address) => isAddressEqual17(address, buyerChecksum));
|
|
13077
|
-
if (!inAllowList) {
|
|
13078
|
-
throw new Error(`Buyer ${buyerChecksum} is not in the allowlist`);
|
|
13079
|
-
}
|
|
13080
|
-
const { tree, root } = buildAllowListTree(artifact.allowList.addresses);
|
|
13081
|
-
if (root !== artifact.allowList.root) {
|
|
13082
|
-
throw new Error(
|
|
13083
|
-
`Recomputed allowlist root (${root}) does not match artifact (${artifact.allowList.root})`
|
|
13084
|
-
);
|
|
13085
|
-
}
|
|
13086
|
-
return {
|
|
13087
|
-
allowListProof: getAddressProof(tree, buyerChecksum),
|
|
13088
|
-
allowListAddress: buyerChecksum
|
|
13089
|
-
};
|
|
13090
|
-
}
|
|
13091
|
-
|
|
13092
13842
|
// src/sdk/utils.ts
|
|
13093
13843
|
function createUtilsNamespace() {
|
|
13094
13844
|
return {
|
|
@@ -13179,6 +13929,7 @@ function createRareClient(config) {
|
|
|
13179
13929
|
contracts: {
|
|
13180
13930
|
factory: addresses.factory,
|
|
13181
13931
|
auction: addresses.auction,
|
|
13932
|
+
rareBridge: addresses.rareBridge,
|
|
13182
13933
|
sovereignFactory: addresses.sovereignFactory,
|
|
13183
13934
|
lazySovereignFactory: addresses.lazySovereignFactory,
|
|
13184
13935
|
rareMinter: addresses.rareMinter,
|
|
@@ -13194,6 +13945,7 @@ function createRareClient(config) {
|
|
|
13194
13945
|
v4Quoter: addresses.v4Quoter
|
|
13195
13946
|
},
|
|
13196
13947
|
liquidEdition: createLiquidNamespace(config, chain, addresses),
|
|
13948
|
+
bridge: createBridgeNamespace(publicClient, config, chain),
|
|
13197
13949
|
swap: createSwapNamespace(config, chain, chainId, addresses),
|
|
13198
13950
|
auction,
|
|
13199
13951
|
offer,
|
|
@@ -13277,6 +14029,7 @@ function isRecord5(value) {
|
|
|
13277
14029
|
return typeof value === "object" && value !== null;
|
|
13278
14030
|
}
|
|
13279
14031
|
export {
|
|
14032
|
+
ApprovalSideEffectError,
|
|
13280
14033
|
NftApprovalRequiredError,
|
|
13281
14034
|
PaymentApprovalRequiredError,
|
|
13282
14035
|
createRareClient
|