bch-slpjs
Version:
Simple Ledger Protocol (SLP) JavaScript Library
261 lines (212 loc) • 10.1 kB
text/typescript
import { Utils } from './utils';
import BigNumber from 'bignumber.js';
export class SlpTokenType1 {
static get lokadIdHex() { return "534c5000" }
static buildGenesisOpReturn(ticker: string|null, name: string|null, documentUri:string|null, documentHashHex: string|null, decimals: number, batonVout:number|null, initialQuantity:BigNumber) {
let script: (number|number[])[] = [];
// OP Return Prefix
script.push(0x6a)
// Lokad Id
let lokadId = Buffer.from(this.lokadIdHex, 'hex')
script.push(Utils.getPushDataOpcode(lokadId))
lokadId.forEach((item) => script.push(item))
// Token Version/Type
let tokenVersionType = 0x01
script.push(Utils.getPushDataOpcode([tokenVersionType]))
script.push(tokenVersionType)
// Transaction Type
let transactionType = Buffer.from('GENESIS')
script.push(Utils.getPushDataOpcode(transactionType))
transactionType.forEach((item) => script.push(item))
// Ticker
if (ticker !== null && typeof ticker !== 'string'){
throw Error("ticker must be a string")
} else if (ticker === null || ticker.length === 0) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else {
let tickerBuf = Buffer.from(ticker, 'utf8')
script.push(Utils.getPushDataOpcode(tickerBuf))
tickerBuf.forEach((item) => script.push(item))
}
// Name
if (name !== null && typeof name !== 'string') {
throw Error("name must be a string")
} else if (name == null || name.length === 0) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else {
let nameBuf = Buffer.from(name, 'utf8')
script.push(Utils.getPushDataOpcode(nameBuf))
nameBuf.forEach((item) => script.push(item))
}
// Document URL
if (documentUri !== null && typeof documentUri !== 'string') {
throw Error("documentUri must be a string")
} else if (documentUri == null || documentUri.length === 0) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else {
let documentUriBuf = Buffer.from(documentUri, 'ascii')
script.push(Utils.getPushDataOpcode(documentUriBuf))
documentUriBuf.forEach((item) => script.push(item))
}
// check Token Document Hash should be hexademical chracters.
var re = /^[0-9a-fA-F]+$/;
// Document Hash
if (documentHashHex == null || documentHashHex.length === 0) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else if (documentHashHex.length === 64 && re.test(documentHashHex)) {
let documentHashBuf = Buffer.from(documentHashHex, 'hex')
script.push(Utils.getPushDataOpcode(documentHashBuf))
documentHashBuf.forEach((item) => script.push(item))
} else {
throw Error("Document hash must be provided as a 64 character hex string")
}
// Decimals
if (decimals === null || decimals < 0 || decimals > 9) {
throw Error("Decimals property must be in range 0 to 9")
} else {
script.push(Utils.getPushDataOpcode([decimals]))
script.push(decimals)
}
// Baton Vout
if (batonVout == null) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else {
if (batonVout < 2 || batonVout > 255 || !(typeof batonVout == 'number'))
throw Error("Baton vout must a number and greater than 1 and less than 256.")
script.push(Utils.getPushDataOpcode([batonVout]))
script.push(batonVout)
}
// Initial Quantity
let MAX_QTY = new BigNumber('18446744073709551615');
try {
initialQuantity.absoluteValue()
} catch(_) {
throw Error("Amount must be an instance of BigNumber");
}
if (initialQuantity.isGreaterThan(MAX_QTY))
throw new Error("Maximum genesis value exceeded. Reduce input quantity below 18446744073709551615.");
if (initialQuantity.isLessThan(0))
throw Error("Genesis quantity must be greater than 0.");
if (!initialQuantity.modulo(1).isEqualTo(new BigNumber(0)))
throw Error("Genesis quantity must be a whole number.");
let initialQuantityBuf = Utils.int2FixedBuffer(initialQuantity)
script.push(Utils.getPushDataOpcode(initialQuantityBuf))
initialQuantityBuf.forEach((item) => script.push(item))
let encodedScript = Utils.encodeScript(script)
if (encodedScript.length > 223) {
throw Error("Script too long, must be less than 223 bytes.")
}
return encodedScript
}
static buildSendOpReturn(tokenIdHex: string, outputQtyArray: BigNumber[]) {
let script: (number|number[])[] = [];
// OP Return Prefix
script.push(0x6a)
// Lokad Id
let lokadId = Buffer.from(this.lokadIdHex, 'hex')
script.push(Utils.getPushDataOpcode(lokadId))
lokadId.forEach((item) => script.push(item))
// Token Version/Type
let tokenVersionType = 0x01
script.push(Utils.getPushDataOpcode([tokenVersionType]))
script.push(tokenVersionType)
// Transaction Type
let transactionType = Buffer.from('SEND')
script.push(Utils.getPushDataOpcode(transactionType))
transactionType.forEach((item) => script.push(item))
// Token Id
// check Token Id should be hexademical chracters.
let re = /^([A-Fa-f0-9]{2}){32,32}$/;
if (typeof tokenIdHex !== 'string' || !re.test(tokenIdHex)) {
throw Error("TokenIdHex must be provided as a 64 character hex string.")
}
let tokenId = Buffer.from(tokenIdHex, 'hex')
script.push(Utils.getPushDataOpcode(tokenId))
tokenId.forEach((item) => script.push(item))
// Output Quantities
if (outputQtyArray.length > 19) {
throw Error("Cannot have more than 19 SLP token outputs.")
}
if (outputQtyArray.length < 1) {
throw Error("Cannot have less than 1 SLP token output.")
}
outputQtyArray.forEach((outputQty) => {
try {
outputQty.absoluteValue()
} catch(_) {
throw Error("Amount must be an instance of BigNumber");
}
let MAX_QTY = new BigNumber('18446744073709551615');
if (outputQty.isGreaterThan(MAX_QTY))
throw new Error("Maximum value exceeded. Reduce input quantity below 18446744073709551615.");
if (outputQty.isLessThan(0))
throw Error("All Send outputs must be greater than 0.");
if (!outputQty.modulo(1).isEqualTo(new BigNumber(0)))
throw Error("All Send outputs must be a whole number.");
let qtyBuffer = Utils.int2FixedBuffer(outputQty)
script.push(Utils.getPushDataOpcode(qtyBuffer))
qtyBuffer.forEach((item) => script.push(item))
})
let encodedScript = Utils.encodeScript(script)
if (encodedScript.length > 223) {
throw Error("Script too long, must be less than 223 bytes.")
}
return encodedScript
}
static buildMintOpReturn(tokenIdHex: string, batonVout: number|null, mintQuantity: BigNumber) {
let script: (number|number[])[] = [];
// OP Return Prefix
script.push(0x6a)
// Lokad Id
let lokadId = Buffer.from(this.lokadIdHex, 'hex')
script.push(Utils.getPushDataOpcode(lokadId))
lokadId.forEach((item) => script.push(item))
// Token Version/Type
let tokenVersionType = 0x01
script.push(Utils.getPushDataOpcode([tokenVersionType]))
script.push(tokenVersionType)
// Transaction Type
let transactionType = Buffer.from('MINT')
script.push(Utils.getPushDataOpcode(transactionType))
transactionType.forEach((item) => script.push(item))
// Token Id
// check Token Id should be hexademical chracters.
let re = /^([A-Fa-f0-9]{2}){32,32}$/;
if (typeof tokenIdHex !== 'string' || !re.test(tokenIdHex)) {
throw Error("TokenIdHex must be provided as a 64 character hex string.")
}
let tokenId = Buffer.from(tokenIdHex, 'hex')
script.push(Utils.getPushDataOpcode(tokenId))
tokenId.forEach((item) => script.push(item))
// Baton Vout
if (batonVout == null) {
[0x4c, 0x00].forEach((item) => script.push(item))
} else {
if (batonVout < 2 || batonVout > 255 || !(typeof batonVout == 'number'))
throw Error("Baton vout must a number and greater than 1 and less than 256.")
script.push(Utils.getPushDataOpcode([batonVout]))
script.push(batonVout)
}
// Initial Quantity
let MAX_QTY = new BigNumber('18446744073709551615');
try {
mintQuantity.absoluteValue()
} catch(_) {
throw Error("Amount must be an instance of BigNumber");
}
if (mintQuantity.isGreaterThan(MAX_QTY))
throw new Error("Maximum mint value exceeded. Reduce input quantity below 18446744073709551615.");
if (mintQuantity.isLessThan(0))
throw Error("Mint quantity must be greater than 0.");
if (!mintQuantity.modulo(1).isEqualTo(new BigNumber(0)))
throw Error("Mint quantity must be a whole number.");
let initialQuantityBuf = Utils.int2FixedBuffer(mintQuantity)
script.push(Utils.getPushDataOpcode(initialQuantityBuf))
initialQuantityBuf.forEach((item) => script.push(item))
let encodedScript = Utils.encodeScript(script)
if (encodedScript.length > 223) {
throw Error("Script too long, must be less than 223 bytes.")
}
return encodedScript
}
}