UNPKG

@ecash/lib

Version:

Library for eCash transaction building

172 lines 6.73 kB
"use strict"; // Copyright (c) 2024 The Bitcoin developers // Distributed under the MIT software license, see the accompanying // file COPYING or http://www.opensource.org/licenses/mit-license.php. Object.defineProperty(exports, "__esModule", { value: true }); exports.slpAmount = exports.slpBurn = exports.slpSend = exports.slpMintVault = exports.slpMint = exports.slpGenesis = exports.SLP_NFT1_GROUP = exports.SLP_NFT1_CHILD = exports.SLP_MINT_VAULT = exports.SLP_FUNGIBLE = exports.SLP_LOKAD_ID = void 0; const hex_js_1 = require("../io/hex.js"); const str_js_1 = require("../io/str.js"); const op_js_1 = require("../op.js"); const opcode_js_1 = require("../opcode.js"); const script_js_1 = require("../script.js"); const common_js_1 = require("./common.js"); /** LOKAD ID for SLP */ exports.SLP_LOKAD_ID = (0, str_js_1.strToBytes)('SLP\0'); /** SLP fungible token type number */ exports.SLP_FUNGIBLE = 1; /** SLP MINT Vault token type number */ exports.SLP_MINT_VAULT = 2; /** SLP NFT1 Child token type number */ exports.SLP_NFT1_CHILD = 0x41; /** SLP NFT1 Group token type number */ exports.SLP_NFT1_GROUP = 0x81; /** Build an SLP GENESIS OP_RETURN, creating a new SLP token */ function slpGenesis(tokenType, genesisInfo, initialQuantity, mintBatonOutIdx) { verifyTokenType(tokenType); const data = []; data.push(exports.SLP_LOKAD_ID); data.push(new Uint8Array([tokenType])); data.push(common_js_1.GENESIS); data.push((0, str_js_1.strToBytes)(genesisInfo.tokenTicker ?? '')); data.push((0, str_js_1.strToBytes)(genesisInfo.tokenName ?? '')); data.push((0, str_js_1.strToBytes)(genesisInfo.url ?? '')); data.push(genesisInfo.hash ? (0, hex_js_1.fromHex)(genesisInfo.hash) : new Uint8Array()); data.push(new Uint8Array([genesisInfo.decimals ?? 0])); if (tokenType == exports.SLP_MINT_VAULT) { if (genesisInfo.mintVaultScripthash === undefined) { throw new Error('Must set mintVaultScripthash for MINT VAULT'); } data.push((0, hex_js_1.fromHex)(genesisInfo.mintVaultScripthash)); } else { if (mintBatonOutIdx !== undefined) { if (mintBatonOutIdx < 2) { throw new Error('mintBatonOutIdx must be >= 2'); } data.push(new Uint8Array([mintBatonOutIdx])); } else { data.push(new Uint8Array()); } } data.push(slpAmount(initialQuantity)); return script_js_1.Script.fromOps([opcode_js_1.OP_RETURN].concat(data.map(pushdataOpSlp))); } exports.slpGenesis = slpGenesis; /** * Build an SLP MINT pushdata section, creating new SLP tokens and mint batons * of the given token ID. **/ function slpMint(tokenId, tokenType, additionalQuantity, mintBatonOutIdx) { verifyTokenType(tokenType); verifyTokenId(tokenId); return script_js_1.Script.fromOps([ opcode_js_1.OP_RETURN, pushdataOpSlp(exports.SLP_LOKAD_ID), pushdataOpSlp(new Uint8Array([tokenType])), pushdataOpSlp(common_js_1.MINT), pushdataOpSlp((0, hex_js_1.fromHex)(tokenId)), pushdataOpSlp(new Uint8Array(mintBatonOutIdx !== undefined ? [mintBatonOutIdx] : [])), pushdataOpSlp(slpAmount(additionalQuantity)), ]); } exports.slpMint = slpMint; /** * Build an SLP MINT VAULT pushdata section, creating new SLP tokens and mint batons * of the given token ID. **/ function slpMintVault(tokenId, additionalQuantities) { verifyTokenId(tokenId); verifySendAmounts(additionalQuantities); return script_js_1.Script.fromOps([ opcode_js_1.OP_RETURN, pushdataOpSlp(exports.SLP_LOKAD_ID), pushdataOpSlp(new Uint8Array([exports.SLP_MINT_VAULT])), pushdataOpSlp(common_js_1.MINT), pushdataOpSlp((0, hex_js_1.fromHex)(tokenId)), ].concat(additionalQuantities.map(qty => pushdataOpSlp(slpAmount(qty))))); } exports.slpMintVault = slpMintVault; /** * Build an SLP SEND pushdata section, moving SLP tokens to different outputs **/ function slpSend(tokenId, tokenType, sendAmounts) { verifyTokenType(tokenType); verifyTokenId(tokenId); verifySendAmounts(sendAmounts); return script_js_1.Script.fromOps([ opcode_js_1.OP_RETURN, pushdataOpSlp(exports.SLP_LOKAD_ID), pushdataOpSlp(new Uint8Array([tokenType])), pushdataOpSlp(common_js_1.SEND), pushdataOpSlp((0, hex_js_1.fromHex)(tokenId)), ].concat(sendAmounts.map(qty => pushdataOpSlp(slpAmount(qty))))); } exports.slpSend = slpSend; /** * Build an SLP BURN pushdata section, intentionally burning SLP tokens. * See https://github.com/badger-cash/slp-self-mint-protocol/blob/master/token-type1-burn.md **/ function slpBurn(tokenId, tokenType, burnAmount) { verifyTokenType(tokenType); verifyTokenId(tokenId); return script_js_1.Script.fromOps([ opcode_js_1.OP_RETURN, pushdataOpSlp(exports.SLP_LOKAD_ID), pushdataOpSlp(new Uint8Array([tokenType])), pushdataOpSlp(common_js_1.BURN), pushdataOpSlp((0, hex_js_1.fromHex)(tokenId)), pushdataOpSlp(slpAmount(burnAmount)), ]); } exports.slpBurn = slpBurn; function verifyTokenType(tokenType) { switch (tokenType) { case exports.SLP_FUNGIBLE: case exports.SLP_MINT_VAULT: case exports.SLP_NFT1_GROUP: case exports.SLP_NFT1_CHILD: return; default: throw new Error(`Unknown token type ${tokenType}`); } } function verifyTokenId(tokenId) { if (tokenId.length != 64) { throw new Error(`Token ID must be 64 hex characters in length, but got ${tokenId.length}`); } } function verifySendAmounts(sendAmounts) { if (sendAmounts.length == 0) { throw new Error('Send amount cannot be empty'); } if (sendAmounts.length > 19) { throw new Error(`Cannot use more than 19 amounts, but got ${sendAmounts.length}`); } } function pushdataOpSlp(pushdata) { if (pushdata.length == 0) { return { opcode: opcode_js_1.OP_PUSHDATA1, data: pushdata, }; } if (pushdata.length < opcode_js_1.OP_PUSHDATA1) { return { opcode: pushdata.length, data: pushdata, }; } return (0, op_js_1.pushBytesOp)(pushdata); } function slpAmount(amount) { if (amount < 0 || BigInt(amount) > 0xffffffffffffffffn) { throw new Error(`Amount out of range: ${amount}`); } const amountBytes = new Uint8Array(8); const view = new DataView(amountBytes.buffer, amountBytes.byteOffset, amountBytes.byteLength); view.setBigUint64(0, BigInt(amount), /*little endian=*/ false); return amountBytes; } exports.slpAmount = slpAmount; //# sourceMappingURL=slp.js.map