@lifestonelabs/tokensales 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/config.d.ts +2 -2
- package/dist/constants/values.d.ts +2 -2
- package/dist/constants/values.d.ts.map +1 -1
- package/dist/functions/listActiveSales.d.ts +9 -0
- package/dist/functions/listActiveSales.d.ts.map +1 -0
- package/dist/functions/listAllSales.d.ts +8 -0
- package/dist/functions/listAllSales.d.ts.map +1 -0
- package/dist/functions/listAvailableTickets.d.ts +2 -2
- package/dist/functions/listAvailableTickets.d.ts.map +1 -1
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.esm.js +123 -59
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +124 -58
- package/dist/index.js.map +1 -1
- package/dist/types/index.d.ts +24 -0
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/artifacts/TokenSales.cash +6 -5
- package/src/artifacts/TokenSales.json +39 -39
- package/src/artifacts/TokenSales_old1.cash +238 -0
- package/src/artifacts/TokenSales_old1.json +290 -0
- package/src/constants/values.ts +8 -3
package/dist/config.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const DEFAULT_CONTRACT_ADDRESSES: {
|
|
2
|
-
readonly contract: "bitcoincash:
|
|
3
|
-
readonly token: "bitcoincash:
|
|
2
|
+
readonly contract: "bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt";
|
|
3
|
+
readonly token: "bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq";
|
|
4
4
|
};
|
|
5
5
|
/**
|
|
6
6
|
* Get contract address
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export declare const AddressTicketMaster = "bitcoincash:
|
|
2
|
-
export declare const AddressTicketMasterToken = "bitcoincash:
|
|
1
|
+
export declare const AddressTicketMaster = "bitcoincash:pdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2m4afvzlt";
|
|
2
|
+
export declare const AddressTicketMasterToken = "bitcoincash:rdmta0t3lmeufrhjlmyxkx3ye648lvr08cdwmy36eqtkj4wzpagg2fxpg4rxq";
|
|
3
3
|
export declare const TICKET_LEVEL_DESCRIPTIONS: {
|
|
4
4
|
'01': {
|
|
5
5
|
name: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/constants/values.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"values.d.ts","sourceRoot":"","sources":["../../src/constants/values.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,mBAAmB,8EAA8E,CAAC;AAC/G,eAAO,MAAM,wBAAwB,8EAA8E,CAAC;AAIpH,eAAO,MAAM,yBAAyB;;;;;;;;;;;;;CAarC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ListActiveSalesParams, TokenSaleUtxo } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* List active TokenSale NFTs (minting capability, 39-byte commitment, sale not ended)
|
|
4
|
+
* A sale is active when current blockheight > endSale commitment field
|
|
5
|
+
* @param params - ListActiveSalesParams object containing the electrum provider
|
|
6
|
+
* @returns Promise resolving to array of active TokenSale UTXOs with parsed commitment data
|
|
7
|
+
*/
|
|
8
|
+
export declare function listActiveSales(params: ListActiveSalesParams): Promise<TokenSaleUtxo[]>;
|
|
9
|
+
//# sourceMappingURL=listActiveSales.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { ListAllSalesParams, TokenSaleUtxo } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* List all TokenSale NFTs (minting capability & 39-byte commitment)
|
|
4
|
+
* @param params - ListAllSalesParams object containing the electrum provider
|
|
5
|
+
* @returns Promise resolving to array of TokenSale UTXOs with parsed commitment data
|
|
6
|
+
*/
|
|
7
|
+
export declare function listAllSales(params: ListAllSalesParams): Promise<TokenSaleUtxo[]>;
|
|
8
|
+
//# sourceMappingURL=listAllSales.d.ts.map
|
|
@@ -0,0 +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"}
|
|
@@ -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)
|
|
5
6
|
* @param params - ListAvailableTicketsParams object containing all required parameters
|
|
6
|
-
* @returns Promise resolving to array of ticket UTXOs
|
|
7
|
-
* @throws Error if validation fails or TokenSale is not found/active
|
|
7
|
+
* @returns Promise resolving to array of ticket UTXOs (excluding the TokenSale NFT)
|
|
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,EAA2B,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"listAvailableTickets.d.ts","sourceRoot":"","sources":["../../src/functions/listAvailableTickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAA2B,MAAM,YAAY,CAAC;AAC3D,OAAO,EAAE,0BAA0B,EAAE,MAAM,UAAU,CAAC;AAItD;;;;;GAKG;AACH,wBAAsB,oBAAoB,CAAC,MAAM,EAAE,0BAA0B,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CA4C9F"}
|
package/dist/index.d.ts
CHANGED
|
@@ -8,6 +8,9 @@ export { burn } from './functions/burn';
|
|
|
8
8
|
export { addSatoshis } from './functions/addSatoshis';
|
|
9
9
|
export { createListing } from './functions/createListing';
|
|
10
10
|
export { listAvailableTickets } from './functions/listAvailableTickets';
|
|
11
|
+
export { listAllSales } from './functions/listAllSales';
|
|
12
|
+
export { listActiveSales } from './functions/listActiveSales';
|
|
13
|
+
export * from './types';
|
|
11
14
|
export { parseTicketMasterCommitment, formatBCH, isTicketMaster, isTicket } from './utils/ticketMaster';
|
|
12
15
|
export { default as toTokenAddress } from './utils/toTokenAddress';
|
|
13
16
|
export { ensureAddressPrefix, hexToUint8Array, toLittleEndianHexString } from './utils';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAGH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAC5C,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,OAAO,EAAE,YAAY,EAAE,MAAM,0BAA0B,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAG9D,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,2BAA2B,EAAE,SAAS,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AACxG,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,wBAAwB,CAAC;AACnE,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAExF,OAAO,EAAE,qBAAqB,EAAE,MAAM,yBAAyB,CAAC;AAGhE,cAAc,SAAS,CAAC;AAGxB,OAAO,EAAE,0BAA0B,EAAE,oBAAoB,EAAE,kBAAkB,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAGjH,OAAO,EAAE,mBAAmB,EAAE,wBAAwB,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.esm.js
CHANGED
|
@@ -257,11 +257,11 @@ var abi = [
|
|
|
257
257
|
]
|
|
258
258
|
}
|
|
259
259
|
];
|
|
260
|
-
var bytecode = "OP_DUP OP_0 OP_NUMEQUAL OP_IF OP_0 OP_UTXOBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 13 OP_SPLIT OP_DROP OP_15 OP_SPLIT OP_NIP OP_TXLOCKTIME OP_SWAP OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_TXINPUTCOUNT OP_3 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_4 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_0 OP_3 OP_PICK OP_1 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_5 OP_SPLIT OP_DROP OP_1 OP_UTXOTOKENCOMMITMENT OP_1 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_NIP OP_ELSE OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_10 OP_SPLIT OP_DROP OP_5 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_2 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ELSE OP_3 OP_PICK OP_3 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT OP_15 OP_SPLIT OP_DROP OP_10 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_3 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ENDIF OP_ENDIF OP_1 OP_OUTPUTTOKENCOMMITMENT OP_ROT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_EQUAL OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUAL OP_DUP OP_ROT OP_BOOLOR OP_VERIFY OP_DUP OP_IF OP_TXOUTPUTCOUNT OP_4 OP_NUMEQUALVERIFY OP_ENDIF OP_IF e803 OP_NIP OP_ENDIF OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP 76a914 OP_SWAP OP_CAT 88ac OP_CAT OP_2 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_2 OP_UTXOVALUE
|
|
261
|
-
var source = "pragma cashscript ^0.12.0;\r\n\r\ncontract TokenSales() {\r\n// Single-contract NFT Marketplace on Bitcoin Cash\r\n// \r\n// 1. Sale owner creates a `TokenSale` MintingNFT of the same category as the NFTs to be sold. The TokenSale MintingNFT must have its commitment setup as:\r\n//\r\n /* --- State `TokenSale` Minting NFT ---\r\n bytes5 priceType1\r\n bytes5 priceType2\r\n bytes5 priceType3\r\n bytes4 endSale \r\n bytes20 adminPubKeyHash\r\n */\r\n//\r\n// 2. Sale owner sends the immutableNFTs to be sold of the same categoory to this contract. (mutableNFT's will be stuck in the contract until they are reclaim()'d)\r\n// 3. Users can purchase any NFT and can choose what `type` the NFT will be, paying the appropriate price.\r\n// Purchases require the sale is active (endSale block has not yet been reached).\r\n// Up to 3 NFT types with different prices can be set. If a types price is set to 0 the type will not be available for purchase.\r\n// 4. Each sales BCH price is sent to the adminPubKeyHash address.\r\n// 5. Admin can perform the following actions at any time:\r\n// - Change the price of the three NFT types.\r\n// - Change the endSale block number, including stopping a currently-active sale, re-starting a stopped sale, and extending a sale.\r\n// - Burn the TokenSaleNFT ('the sale') and any remaining NFTs of the same category.\r\n// - Purchase a NFT for 1000sats by providing another MintingNFT of the same category. (so adminsPubKeyHash address will have an entry for all sold NFTs, even those that admin took for 'free')\r\n//\r\n// Additionally, a reclaim() function is provided to reclaim the satoshis from UTXOs on this contract that have been abandoned for 2 years.\r\n// This is a workaround for any stray UTXOs that are sent to or left on the contract (e.g. if NFT's are not included in the burnTokenSale() function)\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////////// Purchase a NFT ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// User purchases a NFT. Must include a MintingNFT of the same category (`TokenSale`). \r\n// Updates NFT commitment with the type of NFT purchased. \r\n// Enforces any change back to user.\r\n// Admin can provide another MintingNFT (with BCH on it) of the same category instead of a BCH UTXO to buy an NFT of any type for free.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 NFT [NFT] (from TokenSale contract)\r\n// [2 userUTXO [BCH] (from user)\r\n// OR] adminUTXO [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract)\r\n// 1 NFT [NFT] (to user)\r\n// 2 payment [BCH] (to adminPkh)\r\n// [3 {optional} change [BCH] (to user)\r\n// OR] adminUTXO [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function purchaseNFT(byte nftType) {\r\n // verify input0 is the MintingNFT from this contract. (also forces TokenSaleNFT as input0 rather than an adminNFT)\r\n require(tx.inputs[0].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[0].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify NFT is for this tokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tokenSaleCategoryID);\r\n\r\n // require sale has not ended\r\n bytes endSale = tx.inputs[0].nftCommitment.slice(15,19);\r\n require(tx.locktime < int(endSale));\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 3);\r\n require(tx.outputs.length <= 4);\r\n\r\n bytes newNFTCommitment = 0x;\r\n int nftPrice = 0;\r\n // buy NFT based on type \r\n if (nftType == 0x01) {\r\n bytes5 priceType1 = tx.inputs[0].nftCommitment.split(5)[0];\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x01;\r\n nftPrice = int(priceType1);\r\n } else if (nftType == 0x02) {\r\n bytes5 priceType2 = tx.inputs[0].nftCommitment.slice(5,10);\r\n require(priceType2 != 0x000000000000);\r\n nftPrice = int(priceType2);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x02;\r\n } else {\r\n require(nftType == 0x03);\r\n bytes5 priceType3 = tx.inputs[0].nftCommitment.slice(10,15);\r\n require(priceType3 != 0x000000000000);\r\n nftPrice = int(priceType3);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x03;\r\n }\r\n\r\n // send NFT to user with updated type\r\n require(tx.outputs[1].nftCommitment == newNFTCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value == tx.inputs[1].value);\r\n\r\n // verify user providing either pure BCH or adminNFT\r\n bool isPureBCH = tx.inputs[2].tokenCategory == 0x;\r\n bool isAdmin = tx.inputs[2].tokenCategory == tx.inputs[0].tokenCategory;\r\n require(isAdmin || isPureBCH);\r\n\r\n // if admin, set nftPrice to 0 and prevent accidental burning of adminNFT\r\n if (isAdmin) require(tx.outputs.length == 4);\r\n if (isAdmin) nftPrice = 1000;\r\n \r\n // send payment to adminPkh\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n bytes adminAddress = new LockingBytecodeP2PKH(adminPkh); \r\n require(tx.outputs[2].lockingBytecode == adminAddress);\r\n require(tx.outputs[2].tokenCategory == 0x);\r\n require(tx.outputs[2].value == nftPrice);\r\n\r\n // recreate TokenSale MintingNFT\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount); \r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n\r\n // determine how much change exists after reserving up to 10_000 sats for miner fee\r\n int change = max((tx.inputs[2].value - (tx.outputs[0].value - tx.inputs[0].value) - 10000), 0);\r\n // return change to user\r\n if (change > 1000) {\r\n require(tx.outputs[3].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[3].tokenCategory == tx.inputs[2].tokenCategory);\r\n require(tx.outputs[3].nftCommitment == tx.inputs[2].nftCommitment);\r\n require(tx.outputs[3].value >= change);\r\n }\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////// Modify TokenSale NFT //////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can change the `TokenSale` NFT type prices and endSale block number.\r\n// Requires 2000sats extra on the adminNFT to cover tx fee.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 adminNFT [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract) \r\n// 1 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n//parameters:\r\n// priceType1: the price of a type1 NFT (in satoshis)\r\n// priceType2: the price of a type2 NFT (in satoshis)\r\n// priceType3: the price of a type3 NFT (in satoshis)\r\n// endSale: the block number to end sale at\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function modifyTokenSale(bytes5 priceType1, bytes5 priceType2, bytes5 priceType3, bytes4 endSale) {\r\n // verify input0 is a MintingNFT from this contract\r\n require(this.activeInputIndex == 0);\r\n\r\n // verify adminNFT is for this TokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tx.inputs[0].tokenCategory);\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 2);\r\n require(tx.outputs.length == 2); \r\n\r\n // verify parameters are correct lengths\r\n require(priceType1.length == 5);\r\n require(priceType2.length == 5);\r\n require(priceType3.length == 5);\r\n require(endSale.length == 4);\r\n\r\n // recreate TokenSale\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n require(tx.outputs[0].nftCommitment == priceType1 + priceType2 + priceType3 + endSale + adminPkh);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[1].nftCommitment == tx.inputs[1].nftCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value >= tx.inputs[1].value - 10000);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n /////////////////////////////// Burn TokenSale ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can burn the `TokenSale` NFT and any remaining NFTs of this category.\r\n// No other inputs besides NFTs of this category are permitted for inputs2+.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 adminNFT [NFT]-Minting (from admin)\r\n// 1 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// N NFTs [NFT] (from TokenSale contract)\r\n//outputs:\r\n// 0 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function burnTokenSale() {\r\n // verify input1 is a MintingNFT\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[1].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify adminNFT is for this TokenSale\r\n require(tx.inputs[0].tokenCategory == tx.inputs[1].tokenCategory);\r\n\r\n //require next input is a NFT of this category\r\n int nextIndex = this.activeInputIndex + 1;\r\n if (tx.inputs.length > nextIndex) {\r\n require(tx.inputs[nextIndex].tokenCategory == tokenSaleCategoryID);\r\n }\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value >= tx.inputs[0].value - 10000);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n //////////////////////////// Reclaim Expired Inputs /////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Anyone can reclaim the satoshis from utxos on this contract that have been abandoned for 2 years.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0+ UTXO [Any] (from TokenSale contract)\r\n//outputs:\r\n// 0 UTXO [BCH] (to anyone)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function reclaim() {\r\n require(this.age >= 105420);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n\r\n // enforce output\r\n require(tx.outputs[0].tokenCategory == 0x);\r\n\r\n }\r\n}";
|
|
260
|
+
var bytecode = "OP_DUP OP_0 OP_NUMEQUAL OP_IF OP_0 OP_UTXOBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 13 OP_SPLIT OP_DROP OP_15 OP_SPLIT OP_NIP OP_TXLOCKTIME OP_SWAP OP_BIN2NUM OP_LESSTHAN OP_VERIFY OP_TXINPUTCOUNT OP_3 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_4 OP_LESSTHANOREQUAL OP_VERIFY OP_0 OP_0 OP_3 OP_PICK OP_1 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_5 OP_SPLIT OP_DROP OP_1 OP_UTXOTOKENCOMMITMENT OP_1 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_NIP OP_ELSE OP_3 OP_PICK OP_2 OP_EQUAL OP_IF OP_0 OP_UTXOTOKENCOMMITMENT OP_10 OP_SPLIT OP_DROP OP_5 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_2 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ELSE OP_3 OP_PICK OP_3 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT OP_15 OP_SPLIT OP_DROP OP_10 OP_SPLIT OP_NIP OP_DUP 000000000000 OP_EQUAL OP_NOT OP_VERIFY OP_DUP OP_BIN2NUM OP_ROT OP_DROP OP_SWAP OP_1 OP_UTXOTOKENCOMMITMENT OP_3 OP_CAT OP_3 OP_ROLL OP_DROP OP_SWAP OP_TOALTSTACK OP_SWAP OP_FROMALTSTACK OP_DROP OP_ENDIF OP_ENDIF OP_1 OP_OUTPUTTOKENCOMMITMENT OP_ROT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_EQUAL OP_2 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUAL OP_DUP OP_ROT OP_BOOLOR OP_VERIFY OP_DUP OP_IF OP_TXOUTPUTCOUNT OP_4 OP_NUMEQUALVERIFY OP_ENDIF OP_IF e803 OP_NIP OP_ENDIF OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP 76a914 OP_SWAP OP_CAT 88ac OP_CAT OP_2 OP_OUTPUTBYTECODE OP_EQUALVERIFY OP_2 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUALVERIFY OP_2 OP_OUTPUTVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_2 OP_UTXOVALUE 1027 OP_SUB OP_0 OP_MAX OP_DUP e803 OP_GREATERTHAN OP_IF OP_3 OP_OUTPUTBYTECODE OP_2 OP_UTXOBYTECODE OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCATEGORY OP_2 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_3 OP_OUTPUTTOKENCOMMITMENT OP_2 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_3 OP_OUTPUTVALUE OP_OVER OP_GREATERTHANOREQUAL OP_VERIFY OP_ENDIF OP_2DROP OP_DROP OP_1 OP_ELSE OP_DUP OP_1 OP_NUMEQUAL OP_IF OP_INPUTINDEX OP_0 OP_NUMEQUALVERIFY OP_1 OP_UTXOTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_TXINPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_TXOUTPUTCOUNT OP_2 OP_NUMEQUALVERIFY OP_OVER OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_2 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_3 OP_PICK OP_SIZE OP_NIP OP_5 OP_NUMEQUALVERIFY OP_4 OP_PICK OP_SIZE OP_NIP OP_4 OP_NUMEQUALVERIFY OP_0 OP_UTXOTOKENCOMMITMENT 27 OP_SPLIT OP_DROP 13 OP_SPLIT OP_NIP OP_0 OP_OUTPUTTOKENCOMMITMENT OP_3 OP_ROLL OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_4 OP_ROLL OP_CAT OP_ROT OP_CAT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE OP_NUMEQUALVERIFY OP_1 OP_OUTPUTTOKENCOMMITMENT OP_1 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_1 OP_OUTPUTBYTECODE OP_1 OP_UTXOBYTECODE OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_1 OP_OUTPUTTOKENAMOUNT OP_1 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_1 OP_OUTPUTVALUE OP_1 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_NIP OP_ELSE OP_DUP OP_2 OP_NUMEQUAL OP_IF OP_1 OP_UTXOTOKENCATEGORY 20 OP_SPLIT OP_2 OP_EQUALVERIFY OP_0 OP_UTXOTOKENCATEGORY OP_1 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_INPUTINDEX OP_1ADD OP_TXINPUTCOUNT OP_OVER OP_GREATERTHAN OP_IF OP_DUP OP_UTXOTOKENCATEGORY OP_2 OP_PICK OP_EQUALVERIFY OP_ENDIF OP_0 OP_OUTPUTTOKENCOMMITMENT OP_0 OP_UTXOTOKENCOMMITMENT OP_EQUALVERIFY OP_0 OP_OUTPUTBYTECODE OP_0 OP_UTXOBYTECODE OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_UTXOTOKENCATEGORY OP_EQUALVERIFY OP_0 OP_OUTPUTTOKENAMOUNT OP_0 OP_UTXOTOKENAMOUNT OP_NUMEQUALVERIFY OP_0 OP_OUTPUTVALUE OP_0 OP_UTXOVALUE 1027 OP_SUB OP_GREATERTHANOREQUAL OP_VERIFY OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUAL OP_NIP OP_NIP OP_NIP OP_ELSE OP_3 OP_NUMEQUALVERIFY cc9b01 OP_CHECKSEQUENCEVERIFY OP_DROP OP_TXOUTPUTCOUNT OP_1 OP_NUMEQUALVERIFY OP_0 OP_OUTPUTTOKENCATEGORY OP_0 OP_EQUAL OP_ENDIF OP_ENDIF OP_ENDIF";
|
|
261
|
+
var source = "pragma cashscript ^0.12.0;\r\n\r\ncontract TokenSales() {\r\n// Single-contract NFT Marketplace on Bitcoin Cash\r\n// \r\n// 1. Sale owner creates a `TokenSale` MintingNFT of the same category as the NFTs to be sold. The TokenSale MintingNFT must have its commitment setup as:\r\n//\r\n /* --- State `TokenSale` Minting NFT ---\r\n bytes5 priceType1\r\n bytes5 priceType2\r\n bytes5 priceType3\r\n bytes4 endSale \r\n bytes20 adminPubKeyHash\r\n */\r\n//\r\n// 2. Sale owner sends the immutableNFTs to be sold of the same categoory to this contract. (mutableNFT's will be stuck in the contract until they are reclaim()'d)\r\n// 3. Users can purchase any NFT and can choose what `type` the NFT will be, paying the appropriate price.\r\n// Purchases require the sale is active (endSale block has not yet been reached).\r\n// Up to 3 NFT types with different prices can be set. If a types price is set to 0 the type will not be available for purchase.\r\n// 4. Each sales BCH price is sent to the adminPubKeyHash address.\r\n// 5. Admin can perform the following actions at any time:\r\n// - Change the price of the three NFT types.\r\n// - Change the endSale block number, including stopping a currently-active sale, re-starting a stopped sale, and extending a sale.\r\n// - Burn the TokenSaleNFT ('the sale') and any remaining NFTs of the same category.\r\n// - Purchase a NFT for 1000sats by providing another MintingNFT of the same category. (so adminsPubKeyHash address will have an entry for all sold NFTs, even those that admin took for 'free')\r\n//\r\n// Additionally, a reclaim() function is provided to reclaim the satoshis from UTXOs on this contract that have been abandoned for 2 years.\r\n// This is a workaround for any stray UTXOs that are sent to or left on the contract (e.g. if NFT's are not included in the burnTokenSale() function)\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////////// Purchase a NFT ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// User purchases a NFT. Must include a MintingNFT of the same category (`TokenSale`). \r\n// Updates NFT commitment with the type of NFT purchased. \r\n// Enforces any change back to user.\r\n// Admin can provide another MintingNFT (with BCH on it) of the same category instead of a BCH UTXO to buy an NFT of any type for free.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 NFT [NFT] (from TokenSale contract)\r\n// [2 userUTXO [BCH] (from user)\r\n// OR] adminUTXO [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract)\r\n// 1 NFT [NFT] (to user)\r\n// 2 payment [BCH] (to adminPkh)\r\n// [3 {optional} change [BCH] (to user)\r\n// OR] adminUTXO [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function purchaseNFT(byte nftType) {\r\n // verify input0 is the MintingNFT from this contract. (also forces TokenSaleNFT as input0 rather than an adminNFT)\r\n require(tx.inputs[0].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[0].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify NFT is for this tokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tokenSaleCategoryID);\r\n\r\n // require sale has not ended\r\n bytes endSale = tx.inputs[0].nftCommitment.slice(15,19);\r\n require(tx.locktime < int(endSale));\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 3);\r\n require(tx.outputs.length <= 4);\r\n\r\n bytes newNFTCommitment = 0x;\r\n int nftPrice = 0;\r\n // buy NFT based on type \r\n if (nftType == 0x01) {\r\n bytes5 priceType1 = tx.inputs[0].nftCommitment.split(5)[0];\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x01;\r\n nftPrice = int(priceType1);\r\n } else if (nftType == 0x02) {\r\n bytes5 priceType2 = tx.inputs[0].nftCommitment.slice(5,10);\r\n require(priceType2 != 0x000000000000);\r\n nftPrice = int(priceType2);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x02;\r\n } else {\r\n require(nftType == 0x03);\r\n bytes5 priceType3 = tx.inputs[0].nftCommitment.slice(10,15);\r\n require(priceType3 != 0x000000000000);\r\n nftPrice = int(priceType3);\r\n newNFTCommitment = tx.inputs[1].nftCommitment + 0x03;\r\n }\r\n\r\n // send NFT to user with updated type\r\n require(tx.outputs[1].nftCommitment == newNFTCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value == tx.inputs[1].value);\r\n\r\n // verify user providing either pure BCH or adminNFT\r\n bool isPureBCH = tx.inputs[2].tokenCategory == 0x;\r\n bool isAdmin = tx.inputs[2].tokenCategory == tx.inputs[0].tokenCategory;\r\n require(isAdmin || isPureBCH);\r\n\r\n // if admin, set nftPrice to 0 and prevent accidental burning of adminNFT\r\n if (isAdmin) require(tx.outputs.length == 4);\r\n if (isAdmin) nftPrice = 1000;\r\n \r\n // send payment to adminPkh\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n bytes adminAddress = new LockingBytecodeP2PKH(adminPkh); \r\n require(tx.outputs[2].lockingBytecode == adminAddress);\r\n require(tx.outputs[2].tokenCategory == 0x);\r\n require(tx.outputs[2].value == nftPrice);\r\n\r\n // recreate TokenSale MintingNFT\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount); \r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n\r\n // determine how much change exists after reserving up to 10_000 sats for miner fee\r\n int change = max((tx.inputs[2].value - 10000), 0);\r\n // return change to user\r\n if (change > 1000) {\r\n require(tx.outputs[3].lockingBytecode == tx.inputs[2].lockingBytecode);\r\n require(tx.outputs[3].tokenCategory == tx.inputs[2].tokenCategory);\r\n require(tx.outputs[3].nftCommitment == tx.inputs[2].nftCommitment);\r\n require(tx.outputs[3].value >= change);\r\n }\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n ////////////////////////////// Modify TokenSale NFT //////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can change the `TokenSale` NFT type prices and endSale block number.\r\n// Requires 2000sats extra on the adminNFT to cover tx fee.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// 1 adminNFT [NFT]-Minting (from admin)\r\n//outputs:\r\n// 0 TokenSale [NFT]-Minting (to TokenSale contract) \r\n// 1 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n//parameters:\r\n// priceType1: the price of a type1 NFT (in satoshis)\r\n// priceType2: the price of a type2 NFT (in satoshis)\r\n// priceType3: the price of a type3 NFT (in satoshis)\r\n// endSale: the block number to end sale at\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function modifyTokenSale(bytes5 priceType1, bytes5 priceType2, bytes5 priceType3, bytes4 endSale) {\r\n // verify input0 is from this contract\r\n require(this.activeInputIndex == 0);\r\n\r\n // verify adminNFT is for this TokenSaleCategoryID\r\n require(tx.inputs[1].tokenCategory == tx.inputs[0].tokenCategory);\r\n\r\n // verify tx limits\r\n require(tx.inputs.length == 2);\r\n require(tx.outputs.length == 2); \r\n\r\n // verify parameters are correct lengths\r\n require(priceType1.length == 5);\r\n require(priceType2.length == 5);\r\n require(priceType3.length == 5);\r\n require(endSale.length == 4);\r\n\r\n // recreate TokenSale. Implicitly enforces that input0 is not an immutableNFT\r\n bytes20 adminPkh = tx.inputs[0].nftCommitment.slice(19,39);\r\n require(tx.outputs[0].nftCommitment == priceType1 + priceType2 + priceType3 + endSale + adminPkh);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value == tx.inputs[0].value);\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[1].nftCommitment == tx.inputs[1].nftCommitment);\r\n require(tx.outputs[1].lockingBytecode == tx.inputs[1].lockingBytecode);\r\n require(tx.outputs[1].tokenCategory == tx.inputs[1].tokenCategory);\r\n require(tx.outputs[1].tokenAmount == tx.inputs[1].tokenAmount);\r\n require(tx.outputs[1].value >= tx.inputs[1].value - 10000);\r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n /////////////////////////////// Burn TokenSale ///////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Admin can burn the `TokenSale` NFT and any remaining NFTs of this category.\r\n// No other inputs besides NFTs of this category are permitted for inputs2+.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0 adminNFT [NFT]-Minting (from admin)\r\n// 1 TokenSale [NFT]-Minting (from TokenSale contract)\r\n// N NFTs [NFT] (from TokenSale contract)\r\n//outputs:\r\n// 0 adminNFT [NFT]-Minting (to admin)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function burnTokenSale() {\r\n // verify input1 is a MintingNFT\r\n bytes tokenSaleCategoryID, bytes tokenSaleCapability = tx.inputs[1].tokenCategory.split(32);\r\n require(tokenSaleCapability == 0x02);\r\n\r\n // verify adminNFT is for this TokenSale\r\n require(tx.inputs[0].tokenCategory == tx.inputs[1].tokenCategory);\r\n\r\n //require next input is a NFT of this category\r\n int nextIndex = this.activeInputIndex + 1;\r\n if (tx.inputs.length > nextIndex) {\r\n require(tx.inputs[nextIndex].tokenCategory == tokenSaleCategoryID);\r\n }\r\n\r\n // recreate adminNFT\r\n require(tx.outputs[0].nftCommitment == tx.inputs[0].nftCommitment);\r\n require(tx.outputs[0].lockingBytecode == tx.inputs[0].lockingBytecode);\r\n require(tx.outputs[0].tokenCategory == tx.inputs[0].tokenCategory);\r\n require(tx.outputs[0].tokenAmount == tx.inputs[0].tokenAmount);\r\n require(tx.outputs[0].value >= tx.inputs[0].value - 10000);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n }\r\n\r\n //////////////////////////////////////////////////////////////////////////////////////////\r\n //////////////////////////// Reclaim Expired Inputs /////////////////////////////////\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n// Anyone can reclaim the satoshis from utxos on this contract that have been abandoned for 2 years.\r\n// ------------------------------------------------------------------------------------\r\n//inputs: \r\n// 0+ UTXO [Any] (from TokenSale contract)\r\n//outputs:\r\n// 0 UTXO [BCH] (to anyone)\r\n//////////////////////////////////////////////////////////////////////////////////////////\r\n function reclaim() {\r\n require(this.age >= 105420);\r\n\r\n // verify tx limits\r\n require(tx.outputs.length == 1); \r\n\r\n // enforce output\r\n require(tx.outputs[0].tokenCategory == 0x);\r\n\r\n }\r\n}";
|
|
262
262
|
var debug = {
|
|
263
|
-
bytecode: "
|
|
264
|
-
sourceMap: "50:4:126:4;;;;52:26:52:27;:16::44:1;:58::59:0;:48::76:1;:8::78;53:73:53:74:0;:63::89:1;:96::98:0;:63::99:1;54:39:54:43:0;:8::45:1;57:26:57:27:0;:16::42:1;:8::67;60:34:60:35:0;:24::50:1;:60::62:0;:24::63:1;;:57::59:0;:24::63:1;;61:16:61:27:0;:34::41;:30::42:1;:16;:8::44;64:16:64:32:0;:36::37;:8::39:1;65:16:65:33:0;:37::38;:16:::1;:8::40;67:33:67:35:0;68:23:68:24;70:12:70:19;;:23::27;:12:::1;:29:74:9:0;71:42:71:43;:32::58:1;:65::66:0;:32::67:1;:::70;72:41:72:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;73:27:73:37:0;:23::38:1;:12::39;;70:29:74:9;74:15:85::0;:19:74:26;;:30::34;:19:::1;:36:79:9:0;75:42:75:43;:32::58:1;:67::69:0;:32::70:1;;:65::66:0;:32::70:1;;76:20:76:30:0;:34::48;:20:::1;;:12::50;77:27:77:37:0;:23::38:1;:12::39;;;78:41:78:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;74:36:79:9;79:15:85::0;80:20:80:27;;:31::35;:12::37:1;81:42:81:43:0;:32::58:1;:68::70:0;:32::71:1;;:65::67:0;:32::71:1;;82:20:82:30:0;:34::48;:20:::1;;:12::50;83:27:83:37:0;:23::38:1;:12::39;;;84:41:84:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;79:15:85:9;;74;88:27:88:28:0;:16::43:1;:47::63:0;:8::65:1;89:27:89:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;90:27:90:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;91:27:91:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;92:27:92:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;95:35:95:36:0;:25::51:1;:55::57:0;:25:::1;96:33:96:34:0;:23::49:1;:63::64:0;:53::79:1;:23;97:16:97:23:0;:27::36;:16:::1;:8::38;100:12:100:19:0;:21::53;:29::46;:50::51;:21::53:1;;101::101:37:0;:32::36;:21::37:1;;104:37:104:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;105:29:105:63:0;:54::62;:29::63:1;;;106:27:106:28:0;:16::45:1;:8::63;107:27:107:28:0;:16::43:1;:47::49:0;:8::51:1;108:27:108:28:0;:16::35:1;:8::49;111:27:111:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;112:27:112:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;113:27:113:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;114:27:114:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;115:27:115:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;118:36:118:37:0;:26::44:1;:
|
|
263
|
+
bytecode: "76009c6300c751c78800ce01207f528851ce8800cf01137f755f7f77c57c819f69c3539dc454a1690000537951876300cf557f7551cf517e537a757c6b7c6c76817b757767537952876300cf5a7f75557f77760600000000000087916976817b757c51cf527e537a757c6b7c6c75675379538800cf5f7f755a7f77760600000000000087916976817b757c51cf537e537a757c6b7c6c75686851d27b8851cd52c78851d151ce8851d351d09d51cc51c69d52ce008752ce00ce87767b9b697663c4549d686302e803776800cf01277f7501137f770376a9147c7e0288ac7e52cd8852d1008852cc9d00cc00c69d00cd00c78800d100ce8800d300d09d00d200cf8852c60210279400a47602e803a06353cd52c78853d152ce8853d252cf8853cc78a269686d75516776519c63c0009d51ce00ce88c3529dc4529d788277559d52798277559d53798277559d54798277549d00cf01277f7501137f7700d2537a547a7e547a7e547a7e7b7e8800cd00c78800d100ce8800d300d09d00cc00c69d51d251cf8851cd51c78851d151ce8851d351d09d51cc51c602102794a2776776529c6351ce01207f528800ce51ce88c08bc378a06376ce5279886800d200cf8800cd00c78800d100ce8800d300d09d00cc00c602102794a269c4519c77777767539d03cc9b01b275c4519d00d10087686868",
|
|
264
|
+
sourceMap: "50:4:126:4;;;;52:26:52:27;:16::44:1;:58::59:0;:48::76:1;:8::78;53:73:53:74:0;:63::89:1;:96::98:0;:63::99:1;54:39:54:43:0;:8::45:1;57:26:57:27:0;:16::42:1;:8::67;60:34:60:35:0;:24::50:1;:60::62:0;:24::63:1;;:57::59:0;:24::63:1;;61:16:61:27:0;:34::41;:30::42:1;:16;:8::44;64:16:64:32:0;:36::37;:8::39:1;65:16:65:33:0;:37::38;:16:::1;:8::40;67:33:67:35:0;68:23:68:24;70:12:70:19;;:23::27;:12:::1;:29:74:9:0;71:42:71:43;:32::58:1;:65::66:0;:32::67:1;:::70;72:41:72:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;73:27:73:37:0;:23::38:1;:12::39;;70:29:74:9;74:15:85::0;:19:74:26;;:30::34;:19:::1;:36:79:9:0;75:42:75:43;:32::58:1;:67::69:0;:32::70:1;;:65::66:0;:32::70:1;;76:20:76:30:0;:34::48;:20:::1;;:12::50;77:27:77:37:0;:23::38:1;:12::39;;;78:41:78:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;74:36:79:9;79:15:85::0;80:20:80:27;;:31::35;:12::37:1;81:42:81:43:0;:32::58:1;:68::70:0;:32::71:1;;:65::67:0;:32::71:1;;82:20:82:30:0;:34::48;:20:::1;;:12::50;83:27:83:37:0;:23::38:1;:12::39;;;84:41:84:42:0;:31::57:1;:60::64:0;:31:::1;:12::65;;;;;;;79:15:85:9;;74;88:27:88:28:0;:16::43:1;:47::63:0;:8::65:1;89:27:89:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;90:27:90:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;91:27:91:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;92:27:92:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;95:35:95:36:0;:25::51:1;:55::57:0;:25:::1;96:33:96:34:0;:23::49:1;:63::64:0;:53::79:1;:23;97:16:97:23:0;:27::36;:16:::1;:8::38;100:12:100:19:0;:21::53;:29::46;:50::51;:21::53:1;;101::101:37:0;:32::36;:21::37:1;;104:37:104:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;105:29:105:63:0;:54::62;:29::63:1;;;106:27:106:28:0;:16::45:1;:8::63;107:27:107:28:0;:16::43:1;:47::49:0;:8::51:1;108:27:108:28:0;:16::35:1;:8::49;111:27:111:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;112:27:112:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;113:27:113:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;114:27:114:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;115:27:115:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;118:36:118:37:0;:26::44:1;:47::52:0;:26:::1;:55::56:0;:21::57:1;120:12:120:18:0;:21::25;:12:::1;:27:125:9:0;121:31:121:32;:20::49:1;:63::64:0;:53::81:1;:12::83;122:31:122:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;123:31:123:32:0;:20::47:1;:61::62:0;:51::77:1;:12::79;124:31:124:32:0;:20::39:1;:43::49:0;:20:::1;:12::51;120:27:125:9;50:4:126:4;;;;147::178:5:0;;;;149:16:149:37;:41::42;:8::44:1;152:26:152:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;155:16:155:32:0;:36::37;:8::39:1;156:16:156:33:0;:37::38;:8::40:1;159:16:159:26:0;:::33:1;;:37::38:0;:8::40:1;160:16:160:26:0;;:::33:1;;:37::38:0;:8::40:1;161:16:161:26:0;;:::33:1;;:37::38:0;:8::40:1;162:16:162:23:0;;:::30:1;;:34::35:0;:8::37:1;165:37:165:38:0;:27::53:1;:63::65:0;:27::66:1;;:60::62:0;:27::66:1;;166::166:28:0;:16::43:1;:47::57:0;;:60::70;;:47:::1;:73::83:0;;:47:::1;:86::93:0;;:47:::1;:96::104:0;:47:::1;:8::106;167:27:167:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;168:27:168:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;169:27:169:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;170:27:170:28:0;:16::35:1;:49::50:0;:39::57:1;:8::59;173:27:173:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;174:27:174:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;175:27:175:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;176:27:176:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;177:27:177:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:8::67;147:4:178:5;;193::216::0;;;;195:73:195:74;:63::89:1;:96::98:0;:63::99:1;196:39:196:43:0;:8::45:1;199:26:199:27:0;:16::42:1;:56::57:0;:46::72:1;:8::74;202:24:202:45:0;:::49:1;203:12:203:28:0;:31::40;:12:::1;:42:205:9:0;204:30:204:39;:20::54:1;:58::77:0;;:12::79:1;203:42:205:9;208:27:208:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;209:27:209:28:0;:16::45:1;:59::60:0;:49::77:1;:8::79;210:27:210:28:0;:16::43:1;:57::58:0;:47::73:1;:8::75;211:27:211:28:0;:16::41:1;:55::56:0;:45::69:1;:8::71;212:27:212:28:0;:16::35:1;:49::50:0;:39::57:1;:60::65:0;:39:::1;:16;:8::67;215:16:215:33:0;:37::38;:8::40:1;193:4:216:5;;;;228::237::0;;229:28:229:34;:8::36:1;;232:16:232:33:0;:37::38;:8::40:1;235:27:235:28:0;:16::43:1;:47::49:0;:8::51:1;3:0:238:1;;",
|
|
265
265
|
logs: [
|
|
266
266
|
],
|
|
267
267
|
requires: [
|
|
@@ -362,139 +362,139 @@ var debug = {
|
|
|
362
362
|
line: 115
|
|
363
363
|
},
|
|
364
364
|
{
|
|
365
|
-
ip:
|
|
365
|
+
ip: 248,
|
|
366
366
|
line: 121
|
|
367
367
|
},
|
|
368
368
|
{
|
|
369
|
-
ip:
|
|
369
|
+
ip: 253,
|
|
370
370
|
line: 122
|
|
371
371
|
},
|
|
372
372
|
{
|
|
373
|
-
ip:
|
|
373
|
+
ip: 258,
|
|
374
374
|
line: 123
|
|
375
375
|
},
|
|
376
376
|
{
|
|
377
|
-
ip:
|
|
377
|
+
ip: 263,
|
|
378
378
|
line: 124
|
|
379
379
|
},
|
|
380
380
|
{
|
|
381
|
-
ip:
|
|
381
|
+
ip: 275,
|
|
382
382
|
line: 149
|
|
383
383
|
},
|
|
384
384
|
{
|
|
385
|
-
ip:
|
|
385
|
+
ip: 280,
|
|
386
386
|
line: 152
|
|
387
387
|
},
|
|
388
388
|
{
|
|
389
|
-
ip:
|
|
389
|
+
ip: 283,
|
|
390
390
|
line: 155
|
|
391
391
|
},
|
|
392
392
|
{
|
|
393
|
-
ip:
|
|
393
|
+
ip: 286,
|
|
394
394
|
line: 156
|
|
395
395
|
},
|
|
396
396
|
{
|
|
397
|
-
ip:
|
|
397
|
+
ip: 291,
|
|
398
398
|
line: 159
|
|
399
399
|
},
|
|
400
400
|
{
|
|
401
|
-
ip:
|
|
401
|
+
ip: 297,
|
|
402
402
|
line: 160
|
|
403
403
|
},
|
|
404
404
|
{
|
|
405
|
-
ip:
|
|
405
|
+
ip: 303,
|
|
406
406
|
line: 161
|
|
407
407
|
},
|
|
408
408
|
{
|
|
409
|
-
ip:
|
|
409
|
+
ip: 309,
|
|
410
410
|
line: 162
|
|
411
411
|
},
|
|
412
412
|
{
|
|
413
|
-
ip:
|
|
413
|
+
ip: 333,
|
|
414
414
|
line: 166
|
|
415
415
|
},
|
|
416
416
|
{
|
|
417
|
-
ip:
|
|
417
|
+
ip: 338,
|
|
418
418
|
line: 167
|
|
419
419
|
},
|
|
420
420
|
{
|
|
421
|
-
ip:
|
|
421
|
+
ip: 343,
|
|
422
422
|
line: 168
|
|
423
423
|
},
|
|
424
424
|
{
|
|
425
|
-
ip:
|
|
425
|
+
ip: 348,
|
|
426
426
|
line: 169
|
|
427
427
|
},
|
|
428
428
|
{
|
|
429
|
-
ip:
|
|
429
|
+
ip: 353,
|
|
430
430
|
line: 170
|
|
431
431
|
},
|
|
432
432
|
{
|
|
433
|
-
ip:
|
|
433
|
+
ip: 358,
|
|
434
434
|
line: 173
|
|
435
435
|
},
|
|
436
436
|
{
|
|
437
|
-
ip:
|
|
437
|
+
ip: 363,
|
|
438
438
|
line: 174
|
|
439
439
|
},
|
|
440
440
|
{
|
|
441
|
-
ip:
|
|
441
|
+
ip: 368,
|
|
442
442
|
line: 175
|
|
443
443
|
},
|
|
444
444
|
{
|
|
445
|
-
ip:
|
|
445
|
+
ip: 373,
|
|
446
446
|
line: 176
|
|
447
447
|
},
|
|
448
448
|
{
|
|
449
|
-
ip:
|
|
449
|
+
ip: 381,
|
|
450
450
|
line: 177
|
|
451
451
|
},
|
|
452
452
|
{
|
|
453
|
-
ip:
|
|
453
|
+
ip: 392,
|
|
454
454
|
line: 196
|
|
455
455
|
},
|
|
456
456
|
{
|
|
457
|
-
ip:
|
|
457
|
+
ip: 397,
|
|
458
458
|
line: 199
|
|
459
459
|
},
|
|
460
460
|
{
|
|
461
|
-
ip:
|
|
461
|
+
ip: 408,
|
|
462
462
|
line: 204
|
|
463
463
|
},
|
|
464
464
|
{
|
|
465
|
-
ip:
|
|
465
|
+
ip: 414,
|
|
466
466
|
line: 208
|
|
467
467
|
},
|
|
468
468
|
{
|
|
469
|
-
ip:
|
|
469
|
+
ip: 419,
|
|
470
470
|
line: 209
|
|
471
471
|
},
|
|
472
472
|
{
|
|
473
|
-
ip:
|
|
473
|
+
ip: 424,
|
|
474
474
|
line: 210
|
|
475
475
|
},
|
|
476
476
|
{
|
|
477
|
-
ip:
|
|
477
|
+
ip: 429,
|
|
478
478
|
line: 211
|
|
479
479
|
},
|
|
480
480
|
{
|
|
481
|
-
ip:
|
|
481
|
+
ip: 437,
|
|
482
482
|
line: 212
|
|
483
483
|
},
|
|
484
484
|
{
|
|
485
|
-
ip:
|
|
485
|
+
ip: 441,
|
|
486
486
|
line: 215
|
|
487
487
|
},
|
|
488
488
|
{
|
|
489
|
-
ip:
|
|
489
|
+
ip: 448,
|
|
490
490
|
line: 229
|
|
491
491
|
},
|
|
492
492
|
{
|
|
493
|
-
ip:
|
|
493
|
+
ip: 452,
|
|
494
494
|
line: 232
|
|
495
495
|
},
|
|
496
496
|
{
|
|
497
|
-
ip:
|
|
497
|
+
ip: 457,
|
|
498
498
|
line: 235
|
|
499
499
|
}
|
|
500
500
|
]
|
|
@@ -503,7 +503,7 @@ var compiler = {
|
|
|
503
503
|
name: "cashc",
|
|
504
504
|
version: "0.12.1"
|
|
505
505
|
};
|
|
506
|
-
var updatedAt = "2026-
|
|
506
|
+
var updatedAt = "2026-02-07T09:19:09.786Z";
|
|
507
507
|
var contractArtifact = {
|
|
508
508
|
contractName: contractName,
|
|
509
509
|
constructorInputs: constructorInputs,
|
|
@@ -1262,9 +1262,12 @@ async function addSatoshis(params) {
|
|
|
1262
1262
|
return wcTransactionObj;
|
|
1263
1263
|
}
|
|
1264
1264
|
|
|
1265
|
-
//
|
|
1266
|
-
const AddressTicketMaster = 'bitcoincash:pvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryszkdd99zq';
|
|
1267
|
-
const AddressTicketMasterToken = 'bitcoincash:rvh0yat7d2r9nf228fpns3mypydvstq9arftt9qlmma42xeq2eryss93vuymt';
|
|
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';
|
|
1268
1271
|
// Ticket Level Descriptions
|
|
1269
1272
|
const TICKET_LEVEL_DESCRIPTIONS = {
|
|
1270
1273
|
'01': {
|
|
@@ -1455,9 +1458,9 @@ function getContractAddresses() {
|
|
|
1455
1458
|
|
|
1456
1459
|
/**
|
|
1457
1460
|
* List available tickets for purchase from a TokenSale
|
|
1461
|
+
* Returns ALL UTXOs matching the categoryID, excluding the TokenSale NFT (minting capability)
|
|
1458
1462
|
* @param params - ListAvailableTicketsParams object containing all required parameters
|
|
1459
|
-
* @returns Promise resolving to array of ticket UTXOs
|
|
1460
|
-
* @throws Error if validation fails or TokenSale is not found/active
|
|
1463
|
+
* @returns Promise resolving to array of ticket UTXOs (excluding the TokenSale NFT)
|
|
1461
1464
|
*/
|
|
1462
1465
|
async function listAvailableTickets(params) {
|
|
1463
1466
|
const { electrumProvider, categoryID } = params;
|
|
@@ -1481,33 +1484,94 @@ async function listAvailableTickets(params) {
|
|
|
1481
1484
|
if (!tokenSaleUtxo) {
|
|
1482
1485
|
throw new Error(`No active TokenSale found for category ${categoryID}`);
|
|
1483
1486
|
}
|
|
1484
|
-
//
|
|
1485
|
-
const
|
|
1486
|
-
|
|
1487
|
-
|
|
1488
|
-
|
|
1487
|
+
// Return all UTXOs EXCEPT the TokenSale NFT (minting capability)
|
|
1488
|
+
const availableTickets = categoryUtxos.filter((utxo) => !isTicketMaster(utxo));
|
|
1489
|
+
return availableTickets;
|
|
1490
|
+
}
|
|
1491
|
+
|
|
1492
|
+
/**
|
|
1493
|
+
* List all TokenSale NFTs (minting capability & 39-byte commitment)
|
|
1494
|
+
* @param params - ListAllSalesParams object containing the electrum provider
|
|
1495
|
+
* @returns Promise resolving to array of TokenSale UTXOs with parsed commitment data
|
|
1496
|
+
*/
|
|
1497
|
+
async function listAllSales(params) {
|
|
1498
|
+
const { electrumProvider } = params;
|
|
1499
|
+
if (!electrumProvider) {
|
|
1500
|
+
throw new Error('Electrum provider not available');
|
|
1501
|
+
}
|
|
1502
|
+
// Get the contract token address
|
|
1503
|
+
const contractTokenAddress = getTokenAddress();
|
|
1504
|
+
// Get all UTXOs from the contract token address
|
|
1505
|
+
const contractUtxos = await electrumProvider.getUtxos(contractTokenAddress);
|
|
1506
|
+
// Filter to only TokenSale NFTs (minting capability with 39-byte commitment)
|
|
1507
|
+
const tokenSaleUtxos = [];
|
|
1508
|
+
for (const utxo of contractUtxos) {
|
|
1509
|
+
if (isTicketMaster(utxo)) {
|
|
1510
|
+
const commitment = utxo.token?.nft?.commitment || '';
|
|
1511
|
+
const tokenSaleData = parseTicketMasterCommitment(commitment);
|
|
1512
|
+
if (tokenSaleData) {
|
|
1513
|
+
tokenSaleUtxos.push({
|
|
1514
|
+
...utxo,
|
|
1515
|
+
tokenSaleData
|
|
1516
|
+
});
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
}
|
|
1520
|
+
return tokenSaleUtxos;
|
|
1521
|
+
}
|
|
1522
|
+
|
|
1523
|
+
/**
|
|
1524
|
+
* List active TokenSale NFTs (minting capability, 39-byte commitment, sale not ended)
|
|
1525
|
+
* A sale is active when current blockheight > endSale commitment field
|
|
1526
|
+
* @param params - ListActiveSalesParams object containing the electrum provider
|
|
1527
|
+
* @returns Promise resolving to array of active TokenSale UTXOs with parsed commitment data
|
|
1528
|
+
*/
|
|
1529
|
+
async function listActiveSales(params) {
|
|
1530
|
+
const { electrumProvider } = params;
|
|
1531
|
+
if (!electrumProvider) {
|
|
1532
|
+
throw new Error('Electrum provider not available');
|
|
1489
1533
|
}
|
|
1490
1534
|
// Get current block height
|
|
1491
|
-
// ElectrumNetworkProvider may expose getBlockHeight directly, or we need to use performRequest
|
|
1492
1535
|
let currentBlockHeight;
|
|
1493
1536
|
if (typeof electrumProvider.getBlockHeight === 'function') {
|
|
1494
1537
|
currentBlockHeight = await electrumProvider.getBlockHeight();
|
|
1495
1538
|
}
|
|
1496
1539
|
else if (typeof electrumProvider.performRequest === 'function') {
|
|
1497
|
-
|
|
1498
|
-
|
|
1540
|
+
try {
|
|
1541
|
+
const header = await electrumProvider.performRequest('blockchain.headers.subscribe');
|
|
1542
|
+
currentBlockHeight = header?.height || header;
|
|
1543
|
+
}
|
|
1544
|
+
catch (e) {
|
|
1545
|
+
// Fallback: try to get block height from getUtxos call
|
|
1546
|
+
throw new Error('Unable to get block height from provider');
|
|
1547
|
+
}
|
|
1499
1548
|
}
|
|
1500
1549
|
else {
|
|
1501
1550
|
throw new Error('Unable to get block height from provider');
|
|
1502
1551
|
}
|
|
1503
|
-
//
|
|
1504
|
-
|
|
1505
|
-
|
|
1552
|
+
// Get the contract token address
|
|
1553
|
+
const contractTokenAddress = getTokenAddress();
|
|
1554
|
+
// Get all UTXOs from the contract token address
|
|
1555
|
+
const contractUtxos = await electrumProvider.getUtxos(contractTokenAddress);
|
|
1556
|
+
// Filter to only active TokenSale NFTs (sale not ended)
|
|
1557
|
+
const activeSales = [];
|
|
1558
|
+
for (const utxo of contractUtxos) {
|
|
1559
|
+
if (isTicketMaster(utxo)) {
|
|
1560
|
+
const commitment = utxo.token?.nft?.commitment || '';
|
|
1561
|
+
const tokenSaleData = parseTicketMasterCommitment(commitment);
|
|
1562
|
+
if (tokenSaleData) {
|
|
1563
|
+
// Sale is active when current blockheight > endSale
|
|
1564
|
+
if (currentBlockHeight < tokenSaleData.endSale) {
|
|
1565
|
+
activeSales.push({
|
|
1566
|
+
...utxo,
|
|
1567
|
+
tokenSaleData
|
|
1568
|
+
});
|
|
1569
|
+
}
|
|
1570
|
+
}
|
|
1571
|
+
}
|
|
1506
1572
|
}
|
|
1507
|
-
|
|
1508
|
-
const availableTickets = categoryUtxos.filter((utxo) => isTicket(utxo, categoryID));
|
|
1509
|
-
return availableTickets;
|
|
1573
|
+
return activeSales;
|
|
1510
1574
|
}
|
|
1511
1575
|
|
|
1512
|
-
export { AddressTicketMaster, AddressTicketMasterToken, DEFAULT_CONTRACT_ADDRESSES, TICKET_LEVEL_DESCRIPTIONS, addSatoshis, burn, buyNFT, createListing, createSignTransaction, ensureAddressPrefix, formatBCH, getContractAddress, getContractAddresses, getTokenAddress, hexToUint8Array, isTicket, isTicketMaster, listAvailableTickets, modifyTokenSale, parseTicketMasterCommitment, toLittleEndianHexString, toTokenAddress };
|
|
1576
|
+
export { AddressTicketMaster, AddressTicketMasterToken, DEFAULT_CONTRACT_ADDRESSES, TICKET_LEVEL_DESCRIPTIONS, addSatoshis, burn, buyNFT, createListing, createSignTransaction, ensureAddressPrefix, formatBCH, getContractAddress, getContractAddresses, getTokenAddress, hexToUint8Array, isTicket, isTicketMaster, listActiveSales, listAllSales, listAvailableTickets, modifyTokenSale, parseTicketMasterCommitment, toLittleEndianHexString, toTokenAddress };
|
|
1513
1577
|
//# sourceMappingURL=index.esm.js.map
|