@0xslots/sdk 0.10.0 → 0.10.2

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.
@@ -3,7 +3,16 @@ import { metadataModuleAbi, getSlotsHubAddress, slotAbi, slotFactoryAbi } from '
3
3
  import { gql as gql$1, GraphQLClient } from 'graphql-request';
4
4
  import { encodeFunctionData, erc20Abi } from 'viem';
5
5
 
6
- // src/generated/graphql.ts
6
+ // src/errors.ts
7
+ var SlotsError = class extends Error {
8
+ constructor(operation, cause) {
9
+ const msg = cause instanceof Error ? cause.message : String(cause);
10
+ super(`${operation}: ${msg}`);
11
+ this.operation = operation;
12
+ this.name = "SlotsError";
13
+ this.cause = cause;
14
+ }
15
+ };
7
16
  var AccountFieldsFragmentDoc = gql`
8
17
  fragment AccountFields on Account {
9
18
  id
@@ -899,17 +908,6 @@ function getSdk(client, withWrapper = defaultWrapper) {
899
908
  }
900
909
  };
901
910
  }
902
-
903
- // src/errors.ts
904
- var SlotsError = class extends Error {
905
- constructor(operation, cause) {
906
- const msg = cause instanceof Error ? cause.message : String(cause);
907
- super(`${operation}: ${msg}`);
908
- this.operation = operation;
909
- this.name = "SlotsError";
910
- this.cause = cause;
911
- }
912
- };
913
911
  var EXPECTED_MODULE_NAME = "MetadataModule";
914
912
  var MetadataModuleClient = class {
915
913
  constructor(opts) {
@@ -1052,13 +1050,11 @@ var META_QUERY = gql$1`
1052
1050
  var SlotsChain = /* @__PURE__ */ ((SlotsChain2) => {
1053
1051
  SlotsChain2[SlotsChain2["BASE"] = 8453] = "BASE";
1054
1052
  SlotsChain2[SlotsChain2["BASE_SEPOLIA"] = 84532] = "BASE_SEPOLIA";
1055
- SlotsChain2[SlotsChain2["ARBITRUM"] = 42161] = "ARBITRUM";
1056
1053
  return SlotsChain2;
1057
1054
  })(SlotsChain || {});
1058
1055
  var SUBGRAPH_URLS = {
1059
1056
  [84532 /* BASE_SEPOLIA */]: "https://gateway.thegraph.com/api/subgraphs/id/Z361DLoMdPh9WAopH7shJP8WoXYAB9XeKrLUCTYjdZR",
1060
- [8453 /* BASE */]: "https://gateway.thegraph.com/api/subgraphs/id/4sZrdv1SFzN4KzE9jiWDRuUyM4CnCrmvQ54Rv1s65qUq",
1061
- [42161 /* ARBITRUM */]: "https://api.studio.thegraph.com/query/958/0-x-slots-arb/version/latest"
1057
+ [8453 /* BASE */]: "https://gateway.thegraph.com/api/subgraphs/id/4sZrdv1SFzN4KzE9jiWDRuUyM4CnCrmvQ54Rv1s65qUq"
1062
1058
  };
1063
1059
  var SlotsClient = class {
1064
1060
  constructor(config) {
@@ -1142,11 +1138,17 @@ var SlotsClient = class {
1142
1138
  }
1143
1139
  /** Fetch all slots owned by a given recipient address. */
1144
1140
  getSlotsByRecipient(...args) {
1145
- return this.query("getSlotsByRecipient", () => this.sdk.GetSlotsByRecipient(...args));
1141
+ return this.query(
1142
+ "getSlotsByRecipient",
1143
+ () => this.sdk.GetSlotsByRecipient(...args)
1144
+ );
1146
1145
  }
1147
1146
  /** Fetch all slots currently occupied by a given address. */
1148
1147
  getSlotsByOccupant(...args) {
1149
- return this.query("getSlotsByOccupant", () => this.sdk.GetSlotsByOccupant(...args));
1148
+ return this.query(
1149
+ "getSlotsByOccupant",
1150
+ () => this.sdk.GetSlotsByOccupant(...args)
1151
+ );
1150
1152
  }
1151
1153
  // Factory queries
1152
1154
  /** Fetch factory configuration. */
@@ -1160,27 +1162,45 @@ var SlotsClient = class {
1160
1162
  // Event queries
1161
1163
  /** Fetch slot deployed events with optional filters. */
1162
1164
  getSlotDeployedEvents(...args) {
1163
- return this.query("getSlotDeployedEvents", () => this.sdk.GetSlotDeployedEvents(...args));
1165
+ return this.query(
1166
+ "getSlotDeployedEvents",
1167
+ () => this.sdk.GetSlotDeployedEvents(...args)
1168
+ );
1164
1169
  }
1165
1170
  /** Fetch bought events with optional filters. */
1166
1171
  getBoughtEvents(...args) {
1167
- return this.query("getBoughtEvents", () => this.sdk.GetBoughtEvents(...args));
1172
+ return this.query(
1173
+ "getBoughtEvents",
1174
+ () => this.sdk.GetBoughtEvents(...args)
1175
+ );
1168
1176
  }
1169
1177
  /** Fetch settled events with optional filters. */
1170
1178
  getSettledEvents(...args) {
1171
- return this.query("getSettledEvents", () => this.sdk.GetSettledEvents(...args));
1179
+ return this.query(
1180
+ "getSettledEvents",
1181
+ () => this.sdk.GetSettledEvents(...args)
1182
+ );
1172
1183
  }
1173
1184
  /** Fetch tax-collected events with optional filters. */
1174
1185
  getTaxCollectedEvents(...args) {
1175
- return this.query("getTaxCollectedEvents", () => this.sdk.GetTaxCollectedEvents(...args));
1186
+ return this.query(
1187
+ "getTaxCollectedEvents",
1188
+ () => this.sdk.GetTaxCollectedEvents(...args)
1189
+ );
1176
1190
  }
1177
1191
  /** Fetch all activity for a specific slot (all event types). */
1178
1192
  getSlotActivity(...args) {
1179
- return this.query("getSlotActivity", () => this.sdk.GetSlotActivity(...args));
1193
+ return this.query(
1194
+ "getSlotActivity",
1195
+ () => this.sdk.GetSlotActivity(...args)
1196
+ );
1180
1197
  }
1181
1198
  /** Fetch the most recent events across all slots. */
1182
1199
  getRecentEvents(...args) {
1183
- return this.query("getRecentEvents", () => this.sdk.GetRecentEvents(...args));
1200
+ return this.query(
1201
+ "getRecentEvents",
1202
+ () => this.sdk.GetRecentEvents(...args)
1203
+ );
1184
1204
  }
1185
1205
  // Account queries
1186
1206
  /** Fetch a single account by address. */
@@ -1194,28 +1214,46 @@ var SlotsClient = class {
1194
1214
  // Individual event queries
1195
1215
  /** Fetch released events with optional filters. */
1196
1216
  getReleasedEvents(...args) {
1197
- return this.query("getReleasedEvents", () => this.sdk.GetReleasedEvents(...args));
1217
+ return this.query(
1218
+ "getReleasedEvents",
1219
+ () => this.sdk.GetReleasedEvents(...args)
1220
+ );
1198
1221
  }
1199
1222
  /** Fetch liquidated events with optional filters. */
1200
1223
  getLiquidatedEvents(...args) {
1201
- return this.query("getLiquidatedEvents", () => this.sdk.GetLiquidatedEvents(...args));
1224
+ return this.query(
1225
+ "getLiquidatedEvents",
1226
+ () => this.sdk.GetLiquidatedEvents(...args)
1227
+ );
1202
1228
  }
1203
1229
  /** Fetch deposited events with optional filters. */
1204
1230
  getDepositedEvents(...args) {
1205
- return this.query("getDepositedEvents", () => this.sdk.GetDepositedEvents(...args));
1231
+ return this.query(
1232
+ "getDepositedEvents",
1233
+ () => this.sdk.GetDepositedEvents(...args)
1234
+ );
1206
1235
  }
1207
1236
  /** Fetch withdrawn events with optional filters. */
1208
1237
  getWithdrawnEvents(...args) {
1209
- return this.query("getWithdrawnEvents", () => this.sdk.GetWithdrawnEvents(...args));
1238
+ return this.query(
1239
+ "getWithdrawnEvents",
1240
+ () => this.sdk.GetWithdrawnEvents(...args)
1241
+ );
1210
1242
  }
1211
1243
  /** Fetch price-updated events with optional filters. */
1212
1244
  getPriceUpdatedEvents(...args) {
1213
- return this.query("getPriceUpdatedEvents", () => this.sdk.GetPriceUpdatedEvents(...args));
1245
+ return this.query(
1246
+ "getPriceUpdatedEvents",
1247
+ () => this.sdk.GetPriceUpdatedEvents(...args)
1248
+ );
1214
1249
  }
1215
1250
  // Meta
1216
1251
  /** Fetch subgraph indexing metadata (latest block, indexing errors). */
1217
1252
  getMeta() {
1218
- return this.query("getMeta", () => this.gqlClient.request(META_QUERY));
1253
+ return this.query(
1254
+ "getMeta",
1255
+ () => this.gqlClient.request(META_QUERY)
1256
+ );
1219
1257
  }
1220
1258
  // ═══════════════════════════════════════════════════════════════════════════
1221
1259
  // READ — On-chain (RPC)
@@ -1249,7 +1287,12 @@ var SlotsClient = class {
1249
1287
  address: this.factory,
1250
1288
  abi: slotFactoryAbi,
1251
1289
  functionName: "createSlot",
1252
- args: [params.recipient, params.currency, params.config, params.initParams],
1290
+ args: [
1291
+ params.recipient,
1292
+ params.currency,
1293
+ params.config,
1294
+ params.initParams
1295
+ ],
1253
1296
  account: this.account,
1254
1297
  chain: this.chain
1255
1298
  });
@@ -1264,7 +1307,13 @@ var SlotsClient = class {
1264
1307
  address: this.factory,
1265
1308
  abi: slotFactoryAbi,
1266
1309
  functionName: "createSlots",
1267
- args: [params.recipient, params.currency, params.config, params.initParams, params.count],
1310
+ args: [
1311
+ params.recipient,
1312
+ params.currency,
1313
+ params.config,
1314
+ params.initParams,
1315
+ params.count
1316
+ ],
1268
1317
  account: this.account,
1269
1318
  chain: this.chain
1270
1319
  });
@@ -1281,7 +1330,13 @@ var SlotsClient = class {
1281
1330
  async buy(params) {
1282
1331
  this.assertPositive(params.depositAmount, "depositAmount");
1283
1332
  this.assertPositive(params.selfAssessedPrice, "selfAssessedPrice");
1284
- return this.withAllowance(params.slot, params.depositAmount, {
1333
+ const currentPrice = await this.publicClient.readContract({
1334
+ address: params.slot,
1335
+ abi: slotAbi,
1336
+ functionName: "price"
1337
+ });
1338
+ const approvalAmount = currentPrice + params.depositAmount;
1339
+ return this.withAllowance(params.slot, approvalAmount, {
1285
1340
  to: params.slot,
1286
1341
  abi: slotAbi,
1287
1342
  functionName: "buy",
@@ -1437,7 +1492,8 @@ var SlotsClient = class {
1437
1492
  * @throws {SlotsError} If newBps is outside 0-10000, or the transaction fails.
1438
1493
  */
1439
1494
  async setLiquidationBounty(slot, newBps) {
1440
- if (newBps < 0n || newBps > 10000n) throw new SlotsError("setLiquidationBounty", "newBps must be 0-10000");
1495
+ if (newBps < 0n || newBps > 10000n)
1496
+ throw new SlotsError("setLiquidationBounty", "newBps must be 0-10000");
1441
1497
  return this.wallet.writeContract({
1442
1498
  address: slot,
1443
1499
  abi: slotAbi,
@@ -1458,7 +1514,8 @@ var SlotsClient = class {
1458
1514
  * @throws {SlotsError} If calls array is empty, or the transaction fails.
1459
1515
  */
1460
1516
  async multicall(slot, calls) {
1461
- if (calls.length === 0) throw new SlotsError("multicall", "calls array must not be empty");
1517
+ if (calls.length === 0)
1518
+ throw new SlotsError("multicall", "calls array must not be empty");
1462
1519
  const data = calls.map(
1463
1520
  (call) => encodeFunctionData({
1464
1521
  abi: slotAbi,
@@ -1476,46 +1533,9 @@ var SlotsClient = class {
1476
1533
  });
1477
1534
  }
1478
1535
  // ─── Internals ──────────────────────────────────────────────────────────────
1479
- /** Check if wallet supports atomic batch calls (EIP-5792). */
1480
- async supportsAtomicBatch() {
1481
- if (this._atomicSupport !== void 0) return this._atomicSupport;
1482
- try {
1483
- const capabilities = await this.wallet.getCapabilities?.();
1484
- if (!capabilities) {
1485
- this._atomicSupport = false;
1486
- return false;
1487
- }
1488
- const chainId = this.chain.id;
1489
- const chainCaps = capabilities[chainId] || capabilities[`0x${chainId.toString(16)}`];
1490
- const atomic = chainCaps?.atomicBatch ?? chainCaps?.atomic;
1491
- const status = atomic && typeof atomic === "object" && "status" in atomic ? atomic.status : void 0;
1492
- this._atomicSupport = status === "supported" || status === "ready";
1493
- } catch {
1494
- this._atomicSupport = false;
1495
- }
1496
- return this._atomicSupport;
1497
- }
1498
- /** Poll EIP-5792 getCallsStatus until the batch settles, then return a tx hash. */
1499
- async pollBatchReceipt(id) {
1500
- const MAX_ATTEMPTS = 60;
1501
- const INTERVAL = 1500;
1502
- for (let i = 0; i < MAX_ATTEMPTS; i++) {
1503
- const result = await this.wallet.getCallsStatus({ id });
1504
- if (result.status === "success") {
1505
- const receipts = result.receipts ?? [];
1506
- return receipts[receipts.length - 1]?.transactionHash ?? id;
1507
- }
1508
- if (result.status === "failure") {
1509
- throw new Error("Batch transaction reverted");
1510
- }
1511
- await new Promise((r) => setTimeout(r, INTERVAL));
1512
- }
1513
- throw new Error("Batch transaction timed out");
1514
- }
1515
1536
  /**
1516
- * Execute a contract call that needs ERC-20 allowance.
1517
- * If wallet supports atomic batch (EIP-5792): sends approve + action as one atomic call.
1518
- * Otherwise: chains approve tx (if needed) then action tx.
1537
+ * Approve confirm on-chain execute call sequentially.
1538
+ * Skips approval if the existing allowance already covers the amount.
1519
1539
  */
1520
1540
  async withAllowance(spender, amount, call) {
1521
1541
  const currency = await this.publicClient.readContract({
@@ -1529,31 +1549,8 @@ var SlotsClient = class {
1529
1549
  functionName: "allowance",
1530
1550
  args: [this.account, spender]
1531
1551
  });
1532
- const needsApproval = allowance < amount;
1533
- if (needsApproval && await this.supportsAtomicBatch()) {
1534
- const approveData = encodeFunctionData({
1535
- abi: erc20Abi,
1536
- functionName: "approve",
1537
- args: [spender, amount]
1538
- });
1539
- const actionData = encodeFunctionData({
1540
- abi: call.abi,
1541
- functionName: call.functionName,
1542
- args: call.args
1543
- });
1544
- const id = await this.wallet.sendCalls({
1545
- account: this.account,
1546
- chain: this.chain,
1547
- calls: [
1548
- { to: currency, data: approveData },
1549
- { to: call.to, data: actionData }
1550
- ]
1551
- });
1552
- const txHash = await this.pollBatchReceipt(id);
1553
- return txHash;
1554
- }
1555
- if (needsApproval) {
1556
- const hash = await this.wallet.writeContract({
1552
+ if (allowance < amount) {
1553
+ const approveTx = await this.wallet.writeContract({
1557
1554
  address: currency,
1558
1555
  abi: erc20Abi,
1559
1556
  functionName: "approve",
@@ -1561,7 +1558,22 @@ var SlotsClient = class {
1561
1558
  account: this.account,
1562
1559
  chain: this.chain
1563
1560
  });
1564
- await this.publicClient.waitForTransactionReceipt({ hash });
1561
+ await this.publicClient.waitForTransactionReceipt({ hash: approveTx });
1562
+ const confirmed = await this.pollUntil(
1563
+ () => this.publicClient.readContract({
1564
+ address: currency,
1565
+ abi: erc20Abi,
1566
+ functionName: "allowance",
1567
+ args: [this.account, spender]
1568
+ }),
1569
+ (value) => value >= amount
1570
+ );
1571
+ if (confirmed < amount) {
1572
+ throw new SlotsError(
1573
+ "withAllowance",
1574
+ "Approval confirmed but on-chain allowance is still insufficient after retries"
1575
+ );
1576
+ }
1565
1577
  }
1566
1578
  return this.wallet.writeContract({
1567
1579
  address: call.to,
@@ -1572,11 +1584,20 @@ var SlotsClient = class {
1572
1584
  chain: this.chain
1573
1585
  });
1574
1586
  }
1587
+ /** Poll `check` every `delayMs` until it returns a truthy value or `maxAttempts` is exhausted. */
1588
+ async pollUntil(check, predicate, { maxAttempts = 10, delayMs = 500 } = {}) {
1589
+ let value = await check();
1590
+ for (let i = 1; i < maxAttempts && !predicate(value); i++) {
1591
+ await new Promise((res) => setTimeout(res, delayMs));
1592
+ value = await check();
1593
+ }
1594
+ return value;
1595
+ }
1575
1596
  };
1576
1597
  function createSlotsClient(config) {
1577
1598
  return new SlotsClient(config);
1578
1599
  }
1579
1600
 
1580
1601
  export { AccountFieldsFragmentDoc, CurrencyFieldsFragmentDoc, GetAccountDocument, GetAccountsDocument, GetBoughtEventsDocument, GetDepositedEventsDocument, GetFactoryDocument, GetLiquidatedEventsDocument, GetMetadataSlotDocument, GetMetadataSlotsByRecipientDocument, GetMetadataSlotsDocument, GetMetadataUpdatedEventsDocument, GetModulesDocument, GetPriceUpdatedEventsDocument, GetRecentEventsDocument, GetReleasedEventsDocument, GetSettledEventsDocument, GetSlotActivityDocument, GetSlotDeployedEventsDocument, GetSlotDocument, GetSlotsByOccupantDocument, GetSlotsByRecipientDocument, GetSlotsDocument, GetTaxCollectedEventsDocument, GetWithdrawnEventsDocument, MetadataModuleClient, MetadataSlotFieldsFragmentDoc, SUBGRAPH_URLS, SlotFieldsFragmentDoc, SlotsChain, SlotsClient, SlotsError, createSlotsClient, getSdk };
1581
- //# sourceMappingURL=chunk-KRJINGNH.js.map
1582
- //# sourceMappingURL=chunk-KRJINGNH.js.map
1602
+ //# sourceMappingURL=chunk-PZ2PG636.js.map
1603
+ //# sourceMappingURL=chunk-PZ2PG636.js.map