@lifestonelabs/tokensales 1.0.4 → 1.0.6

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/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
  ______________________________________________________________
3
+ ## [1.0.6] - 2026-02-09
4
+ ### Changed
5
+ - `buyNFT` & `burn` made ticketMasterUtxo param optional. They now fetch the correct TokenSale UTXO from the contract if one is not provided.
6
+ Lets the frontend manage the contract UTXO fetching themselves if they want to limit the amount of electrum calls.
7
+ ______________________________________________________________
8
+ ## [1.0.5] - 2026-02-09
9
+ ### Changed
10
+ - `buyNFT` fixed logic so that a MintingNFT owner for the categoryID can purchase tickets for 1000sats rather than paying full price.
11
+ Also adjusted miner fee up to 1700sats
12
+ ______________________________________________________________
3
13
  ## [1.0.4] - 2026-02-08
4
14
  ### Changed
5
15
  - `listAvailableTickets` removed blockheight check so this will always return the NFTs of the requested categoryID on the contract.
package/README.md CHANGED
@@ -5,7 +5,7 @@ A TypeScript library for interacting with TokenSales contracts on Bitcoin Cash.
5
5
  ## Installation
6
6
 
7
7
  ```bash
8
- npm install tokensales
8
+ npm install @lifestonelabs/tokensales
9
9
  ```
10
10
 
11
11
  ## Signing Transactions
@@ -1 +1 @@
1
- {"version":3,"file":"burn.d.ts","sourceRoot":"","sources":["../../src/functions/burn.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAItE;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAkLtF"}
1
+ {"version":3,"file":"burn.d.ts","sourceRoot":"","sources":["../../src/functions/burn.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,UAAU,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAKtE;;;;;GAKG;AACH,wBAAsB,IAAI,CAAC,MAAM,EAAE,UAAU,GAAG,OAAO,CAAC,8BAA8B,CAAC,CA+MtF"}
@@ -1 +1 @@
1
- {"version":3,"file":"buyNFT.d.ts","sourceRoot":"","sources":["../../src/functions/buyNFT.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAIxE;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAoT1F"}
1
+ {"version":3,"file":"buyNFT.d.ts","sourceRoot":"","sources":["../../src/functions/buyNFT.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,8BAA8B,EAAE,MAAM,UAAU,CAAC;AAKxE;;;;;GAKG;AACH,wBAAsB,MAAM,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,8BAA8B,CAAC,CAwV1F"}
@@ -1 +1 @@
1
- {"version":3,"file":"listActiveSales.d.ts","sourceRoot":"","sources":["../../src/functions/listActiveSales.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIhE;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAkD7F"}
1
+ {"version":3,"file":"listActiveSales.d.ts","sourceRoot":"","sources":["../../src/functions/listActiveSales.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAIhE;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,qBAAqB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CAkD7F"}
@@ -1 +1 @@
1
- {"version":3,"file":"listAllSales.d.ts","sourceRoot":"","sources":["../../src/functions/listAllSales.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI7D;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA+BvF"}
1
+ {"version":3,"file":"listAllSales.d.ts","sourceRoot":"","sources":["../../src/functions/listAllSales.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAI7D;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,aAAa,EAAE,CAAC,CA+BvF"}
@@ -2,9 +2,9 @@ import { Utxo } from 'cashscript';
2
2
  import { ListAvailableTicketsParams } from '../types';
3
3
  /**
4
4
  * List available tickets for purchase from a TokenSale
5
- * Returns ALL UTXOs matching the categoryID, excluding the TokenSale NFT (minting capability)
6
5
  * @param params - ListAvailableTicketsParams object containing all required parameters
7
- * @returns Promise resolving to array of ticket UTXOs (excluding the TokenSale NFT)
6
+ * @returns Promise resolving to array of ticket UTXOs that are available for purchase
7
+ * @throws Error if validation fails or TokenSale is not found/active
8
8
  */
9
9
  export declare function listAvailableTickets(params: ListAvailableTicketsParams): Promise<Utxo[]>;
10
10
  //# sourceMappingURL=listAvailableTickets.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"listAvailableTickets.d.ts","sourceRoot":"","sources":["../../src/functions/listAvailableTickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CA4C9F"}
1
+ {"version":3,"file":"listAvailableTickets.d.ts","sourceRoot":"","sources":["../../src/functions/listAvailableTickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,YAAY,CAAC;AAClC,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAoD9F"}
package/dist/index.esm.js CHANGED
@@ -212,6 +212,61 @@ function toLittleEndianHexString(number, byteCount) {
212
212
  return hex.match(/../g)?.reverse().join('') ?? '';
213
213
  }
214
214
 
215
+ // TokenSales_old1 contract addresses
216
+ //export const AddressTicketMaster = 'bitcoincash:pvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryszkdd99zq'; //address hash: 2ef2757e6a8659a54a3a43384764091ac82c05e8d2b5941fdefb551b20564648
217
+ //export const AddressTicketMasterToken = 'bitcoincash:rvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryss93vuymt';
218
+ // TokenSales contract addresses | simplified change fee calculation in purchaseNFT()
219
+ const AddressTicketMaster = 'bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt'; //address hash: 76bebd71fef3c48ef2fec86b1a24ceaa7fb06f3e1aed923ac8176955c20f5085
220
+ const AddressTicketMasterToken = 'bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq';
221
+ // Ticket Level Descriptions
222
+ const TICKET_LEVEL_DESCRIPTIONS = {
223
+ '01': {
224
+ name: 'Regular',
225
+ description: 'Regular tickets provide standard access to the event. This is the base level ticket option.'
226
+ },
227
+ '02': {
228
+ name: 'VIP',
229
+ description: 'VIP tickets offer enhanced benefits including priority access, exclusive areas, and additional perks.'
230
+ },
231
+ '03': {
232
+ name: 'Premium',
233
+ description: 'Premium tickets provide the highest level of access with all VIP benefits plus additional exclusive features.'
234
+ }
235
+ };
236
+
237
+ /**
238
+ * TokenSales contract addresses
239
+ * These are the addresses for the TokenSales (TicketMaster) contract
240
+ */
241
+ const DEFAULT_CONTRACT_ADDRESSES = {
242
+ contract: AddressTicketMaster,
243
+ token: AddressTicketMasterToken
244
+ };
245
+ /**
246
+ * Get contract address
247
+ * @returns Contract address
248
+ */
249
+ function getContractAddress() {
250
+ return AddressTicketMaster;
251
+ }
252
+ /**
253
+ * Get token address
254
+ * @returns Token address
255
+ */
256
+ function getTokenAddress() {
257
+ return AddressTicketMasterToken;
258
+ }
259
+ /**
260
+ * Get contract addresses
261
+ * @returns Object with contract and token addresses
262
+ */
263
+ function getContractAddresses() {
264
+ return {
265
+ contract: AddressTicketMaster,
266
+ token: AddressTicketMasterToken
267
+ };
268
+ }
269
+
215
270
  var contractName = "TokenSales";
216
271
  var constructorInputs = [
217
272
  ];
@@ -522,7 +577,7 @@ var contractArtifact = {
522
577
  * @throws Error if validation fails or transaction building fails
523
578
  */
524
579
  async function buyNFT(params) {
525
- const { electrumProvider, usersAddress, ticketMasterUtxo, ticketUtxo, ticketType, isAdmin } = params;
580
+ const { electrumProvider, usersAddress, ticketMasterUtxo: providedTicketMasterUtxo, ticketUtxo, ticketType, isAdmin } = params;
526
581
  if (!electrumProvider) {
527
582
  throw new Error('Electrum provider not available');
528
583
  }
@@ -531,6 +586,28 @@ async function buyNFT(params) {
531
586
  provider: electrumProvider,
532
587
  addressType: 'p2sh32'
533
588
  });
589
+ // If ticketMasterUtxo is not provided or is not a valid Utxo, fetch it from the contract
590
+ let ticketMasterUtxo;
591
+ if (providedTicketMasterUtxo?.token?.category === ticketUtxo.token?.category
592
+ && providedTicketMasterUtxo?.token?.nft?.capability === 'minting') {
593
+ ticketMasterUtxo = providedTicketMasterUtxo;
594
+ }
595
+ else {
596
+ // Get the contract token address
597
+ const contractTokenAddress = getTokenAddress();
598
+ // Get all UTXOs from the contract token address
599
+ const contractUtxos = await electrumProvider.getUtxos(contractTokenAddress);
600
+ // Filter to find the TicketMaster UTXO with matching category ID
601
+ const matchingCategoryId = ticketUtxo.token?.category;
602
+ if (!matchingCategoryId) {
603
+ throw new Error('ticketUtxo must have a token category');
604
+ }
605
+ ticketMasterUtxo = contractUtxos.find(utxo => utxo.token?.category === matchingCategoryId &&
606
+ utxo.token?.nft?.capability === 'minting');
607
+ if (!ticketMasterUtxo) {
608
+ throw new Error(`No TicketMaster UTXO found for category ${matchingCategoryId}`);
609
+ }
610
+ }
534
611
  // Parse TicketMaster commitment to get price and admin address
535
612
  const commitment = ticketMasterUtxo.token?.nft?.commitment || '';
536
613
  if (commitment.length !== 78) {
@@ -668,16 +745,24 @@ async function buyNFT(params) {
668
745
  commitment: ticketUtxo.token?.nft?.commitment + ticketType // ticketType appended to commitment
669
746
  }
670
747
  },
671
- })
672
- // Ticket price is sent to admin address
673
- .addOutput({
674
- to: adminAddress,
675
- amount: ticketPrice,
676
748
  });
749
+ // Ticket price is sent to admin address
750
+ if (isAdmin) {
751
+ transaction.addOutput({
752
+ to: adminAddress,
753
+ amount: 1000n,
754
+ });
755
+ }
756
+ else {
757
+ transaction.addOutput({
758
+ to: adminAddress,
759
+ amount: ticketPrice,
760
+ });
761
+ }
677
762
  if (isAdmin) {
678
763
  transaction.addOutput({
679
764
  to: userTokenAddress,
680
- amount: userUTXO.satoshis - 2000n,
765
+ amount: userUTXO.satoshis - 2700n,
681
766
  token: {
682
767
  amount: userUTXO.token?.amount,
683
768
  category: userUTXO.token?.category,
@@ -690,7 +775,7 @@ async function buyNFT(params) {
690
775
  }
691
776
  else {
692
777
  // Calculate change amount (userUTXO - ticketPrice - miner fee)
693
- const changeAmount = userUTXO.satoshis - ticketPrice - 2000n;
778
+ const changeAmount = userUTXO.satoshis - ticketPrice - 1700n;
694
779
  if (changeAmount > 1000n) { // Dust limit
695
780
  transaction.addOutput({
696
781
  to: normalizedUserAddress,
@@ -967,7 +1052,7 @@ async function modifyTokenSale(params) {
967
1052
  * @throws Error if validation fails or transaction building fails
968
1053
  */
969
1054
  async function burn(params) {
970
- const { electrumProvider, usersAddress, ticketMasterUtxo, userMintingNFT, tickets } = params;
1055
+ const { electrumProvider, usersAddress, ticketMasterUtxo: providedTicketMasterUtxo, userMintingNFT, tickets } = params;
971
1056
  if (!electrumProvider) {
972
1057
  throw new Error('Electrum provider not available');
973
1058
  }
@@ -976,6 +1061,28 @@ async function burn(params) {
976
1061
  provider: electrumProvider,
977
1062
  addressType: 'p2sh32'
978
1063
  });
1064
+ // If ticketMasterUtxo is not provided or is not a valid Utxo, fetch it from the contract
1065
+ let ticketMasterUtxo;
1066
+ if (providedTicketMasterUtxo?.token?.category === userMintingNFT.token?.category
1067
+ && providedTicketMasterUtxo?.token?.nft?.capability === 'minting') {
1068
+ ticketMasterUtxo = providedTicketMasterUtxo;
1069
+ }
1070
+ else {
1071
+ // Get the contract token address
1072
+ const contractTokenAddress = getTokenAddress();
1073
+ // Get all UTXOs from the contract token address
1074
+ const contractUtxos = await electrumProvider.getUtxos(contractTokenAddress);
1075
+ // Filter to find the TicketMaster UTXO with matching category ID
1076
+ const matchingCategoryId = userMintingNFT.token?.category;
1077
+ if (!matchingCategoryId) {
1078
+ throw new Error('userMintingNFT must have a token category');
1079
+ }
1080
+ ticketMasterUtxo = contractUtxos.find(utxo => utxo.token?.category === matchingCategoryId &&
1081
+ utxo.token?.nft?.capability === 'minting');
1082
+ if (!ticketMasterUtxo) {
1083
+ throw new Error(`No TicketMaster UTXO found for category ${matchingCategoryId}`);
1084
+ }
1085
+ }
979
1086
  // Get contract address from compiled contract
980
1087
  const contractAddr = ticketMasterContract.address;
981
1088
  // Creating lockingBytecode for contract address
@@ -1262,28 +1369,6 @@ async function addSatoshis(params) {
1262
1369
  return wcTransactionObj;
1263
1370
  }
1264
1371
 
1265
- // TokenSales_old1 contract addresses
1266
- //export const AddressTicketMaster = 'bitcoincash:pvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryszkdd99zq'; //address hash: 2ef2757e6a8659a54a3a43384764091ac82c05e8d2b5941fdefb551b20564648
1267
- //export const AddressTicketMasterToken = 'bitcoincash:rvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryss93vuymt';
1268
- // TokenSales contract addresses | simplified change fee calculation in purchaseNFT()
1269
- const AddressTicketMaster = 'bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt'; //address hash: 76bebd71fef3c48ef2fec86b1a24ceaa7fb06f3e1aed923ac8176955c20f5085
1270
- const AddressTicketMasterToken = 'bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq';
1271
- // Ticket Level Descriptions
1272
- const TICKET_LEVEL_DESCRIPTIONS = {
1273
- '01': {
1274
- name: 'Regular',
1275
- description: 'Regular tickets provide standard access to the event. This is the base level ticket option.'
1276
- },
1277
- '02': {
1278
- name: 'VIP',
1279
- description: 'VIP tickets offer enhanced benefits including priority access, exclusive areas, and additional perks.'
1280
- },
1281
- '03': {
1282
- name: 'Premium',
1283
- description: 'Premium tickets provide the highest level of access with all VIP benefits plus additional exclusive features.'
1284
- }
1285
- };
1286
-
1287
1372
  /**
1288
1373
  * Create a new TicketMaster listing
1289
1374
  * @param params - CreateListingParams object containing all required parameters
@@ -1423,44 +1508,11 @@ async function createListing(params) {
1423
1508
  return wcTransactionObj;
1424
1509
  }
1425
1510
 
1426
- /**
1427
- * TokenSales contract addresses
1428
- * These are the addresses for the TokenSales (TicketMaster) contract
1429
- */
1430
- const DEFAULT_CONTRACT_ADDRESSES = {
1431
- contract: AddressTicketMaster,
1432
- token: AddressTicketMasterToken
1433
- };
1434
- /**
1435
- * Get contract address
1436
- * @returns Contract address
1437
- */
1438
- function getContractAddress() {
1439
- return AddressTicketMaster;
1440
- }
1441
- /**
1442
- * Get token address
1443
- * @returns Token address
1444
- */
1445
- function getTokenAddress() {
1446
- return AddressTicketMasterToken;
1447
- }
1448
- /**
1449
- * Get contract addresses
1450
- * @returns Object with contract and token addresses
1451
- */
1452
- function getContractAddresses() {
1453
- return {
1454
- contract: AddressTicketMaster,
1455
- token: AddressTicketMasterToken
1456
- };
1457
- }
1458
-
1459
1511
  /**
1460
1512
  * List available tickets for purchase from a TokenSale
1461
- * Returns ALL UTXOs matching the categoryID, excluding the TokenSale NFT (minting capability)
1462
1513
  * @param params - ListAvailableTicketsParams object containing all required parameters
1463
- * @returns Promise resolving to array of ticket UTXOs (excluding the TokenSale NFT)
1514
+ * @returns Promise resolving to array of ticket UTXOs that are available for purchase
1515
+ * @throws Error if validation fails or TokenSale is not found/active
1464
1516
  */
1465
1517
  async function listAvailableTickets(params) {
1466
1518
  const { electrumProvider, categoryID } = params;
@@ -1484,8 +1536,14 @@ async function listAvailableTickets(params) {
1484
1536
  if (!tokenSaleUtxo) {
1485
1537
  throw new Error(`No active TokenSale found for category ${categoryID}`);
1486
1538
  }
1487
- // Return all UTXOs EXCEPT the TokenSale NFT (minting capability)
1488
- const availableTickets = categoryUtxos.filter((utxo) => !isTicketMaster(utxo));
1539
+ // Parse the TokenSale commitment to get endSale block height
1540
+ const commitment = tokenSaleUtxo.token?.nft?.commitment || '';
1541
+ const tokenSaleData = parseTicketMasterCommitment(commitment);
1542
+ if (!tokenSaleData) {
1543
+ throw new Error('Failed to parse TokenSale commitment');
1544
+ }
1545
+ // Filter to only ticket UTXOs (capability === 'none')
1546
+ const availableTickets = categoryUtxos.filter((utxo) => isTicket(utxo, categoryID));
1489
1547
  return availableTickets;
1490
1548
  }
1491
1549