UNPKG

sensible-sdk

Version:

Sensible-SDK

261 lines (260 loc) 11.2 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getQuerySensibleID = exports.getQueryGenesis = exports.getQueryCodehash = exports.updateScript = exports.parseDataPart = exports.newDataPart = exports.getNewTokenScript = exports.getDataPart = exports.getContractCodeHash = exports.getContractCode = exports.getTokenName = exports.getTokenSymbol = exports.getGenesisFlag = exports.getDecimalNum = exports.getTokenAddress = exports.getGenesisHash = exports.getRabinPubKeyHashArrayHash = exports.getSensibleID = exports.getTokenID = exports.getTokenAmount = exports.getHeaderLen = exports.GENESIS_FLAG = exports.FT_OP_TYPE = exports.OP_UNLOCK_FROM_CONTRACT = exports.OP_TRANSFER = exports.nonGenesisFlag = exports.EMPTY_ADDRESS = exports.GENESIS_TOKEN_ID = exports.SIGNER_VERIFY_NUM = exports.SIGNER_NUM = exports.PROTO_VERSION = void 0; const BN = require("../../bn.js"); const bsv = require("../../bsv"); const proto = require("../../common/protoheader"); const Utils = require("../../common/utils"); const scryptlib_1 = require("../../scryptlib"); exports.PROTO_VERSION = 1; exports.SIGNER_NUM = 5; exports.SIGNER_VERIFY_NUM = 3; // token specific //<type specific data> = <token_name (20 bytes)> + <token_symbol (10 bytes)> + <is_genesis(1 byte)> + <decimal_num(1 byte)> + <public key hash(20 bytes)> + <token value(8 bytes)> + <tokenid(36 bytes)> + <proto header> const TOKEN_ID_LEN = 20; const SENSIBLE_ID_LEN = 36; const RABIN_PUBKEY_HASH_ARRAY_HASH_LEN = 20; const GENESIS_HASH_LEN = 20; const TOKEN_AMOUNT_LEN = 8; const TOKEN_ADDRESS_LEN = 20; const DECIMAL_NUM_LEN = 1; const GENESIS_FLAG_LEN = 1; const TOKEN_SYMBOL_LEN = 10; const TOKEN_NAME_LEN = 20; const SENSIBLE_ID_OFFSET = SENSIBLE_ID_LEN + proto.getHeaderLen(); const RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET = SENSIBLE_ID_OFFSET + RABIN_PUBKEY_HASH_ARRAY_HASH_LEN; const GENESIS_HASH_OFFSET = RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET + GENESIS_HASH_LEN; const TOKEN_AMOUNT_OFFSET = GENESIS_HASH_OFFSET + TOKEN_AMOUNT_LEN; const TOKEN_ADDRESS_OFFSET = TOKEN_AMOUNT_OFFSET + TOKEN_ADDRESS_LEN; const DECIMAL_NUM_OFFSET = TOKEN_ADDRESS_OFFSET + DECIMAL_NUM_LEN; const GENESIS_FLAG_OFFSET = DECIMAL_NUM_OFFSET + GENESIS_FLAG_LEN; const TOKEN_SYMBOL_OFFSET = GENESIS_FLAG_OFFSET + TOKEN_SYMBOL_LEN; const TOKEN_NAME_OFFSET = TOKEN_SYMBOL_OFFSET + TOKEN_NAME_LEN; const TOKEN_HEADER_LEN = TOKEN_NAME_OFFSET; exports.GENESIS_TOKEN_ID = Buffer.alloc(TOKEN_ID_LEN, 0); exports.EMPTY_ADDRESS = Buffer.alloc(TOKEN_ADDRESS_LEN, 0); exports.nonGenesisFlag = Buffer.alloc(1, 0); exports.OP_TRANSFER = 1; exports.OP_UNLOCK_FROM_CONTRACT = 2; var FT_OP_TYPE; (function (FT_OP_TYPE) { FT_OP_TYPE[FT_OP_TYPE["TRANSFER"] = 1] = "TRANSFER"; FT_OP_TYPE[FT_OP_TYPE["UNLOCK_FROM_CONTRACT"] = 2] = "UNLOCK_FROM_CONTRACT"; })(FT_OP_TYPE = exports.FT_OP_TYPE || (exports.FT_OP_TYPE = {})); var GENESIS_FLAG; (function (GENESIS_FLAG) { GENESIS_FLAG[GENESIS_FLAG["FALSE"] = 0] = "FALSE"; GENESIS_FLAG[GENESIS_FLAG["TRUE"] = 1] = "TRUE"; })(GENESIS_FLAG = exports.GENESIS_FLAG || (exports.GENESIS_FLAG = {})); function getHeaderLen() { return TOKEN_HEADER_LEN; } exports.getHeaderLen = getHeaderLen; function getTokenAmount(script) { if (script.length < TOKEN_AMOUNT_OFFSET) return BN.Zero; return BN.fromBuffer(script.slice(script.length - TOKEN_AMOUNT_OFFSET, script.length - TOKEN_AMOUNT_OFFSET + TOKEN_AMOUNT_LEN), { endian: "little" }); } exports.getTokenAmount = getTokenAmount; function getTokenID(script) { return bsv.crypto.Hash.sha256ripemd160(script.slice(script.length - GENESIS_HASH_OFFSET, script.length - proto.getHeaderLen())); } exports.getTokenID = getTokenID; function getSensibleID(script0) { if (script0.length < SENSIBLE_ID_OFFSET) return { txid: "", index: 0 }; let script = Buffer.from(script0); let sensibleIDBuf = script.slice(script.length - SENSIBLE_ID_OFFSET, script.length - SENSIBLE_ID_OFFSET + SENSIBLE_ID_LEN); let txid = sensibleIDBuf.slice(0, 32).reverse().toString("hex"); //reverse会改变原对象 let index = sensibleIDBuf.readUIntLE(32, 4); let sensibleID = { txid, index }; return sensibleID; } exports.getSensibleID = getSensibleID; function getRabinPubKeyHashArrayHash(script) { return script .slice(script.length - RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET, script.length - RABIN_PUBKEY_HASH_ARRAY_HASH_OFFSET + RABIN_PUBKEY_HASH_ARRAY_HASH_LEN) .toString("hex"); } exports.getRabinPubKeyHashArrayHash = getRabinPubKeyHashArrayHash; function getGenesisHash(script) { return script .slice(script.length - GENESIS_HASH_OFFSET, script.length - GENESIS_HASH_OFFSET + GENESIS_HASH_LEN) .toString("hex"); } exports.getGenesisHash = getGenesisHash; function getTokenAddress(script) { if (script.length < TOKEN_ADDRESS_OFFSET) return ""; return script .slice(script.length - TOKEN_ADDRESS_OFFSET, script.length - TOKEN_ADDRESS_OFFSET + TOKEN_ADDRESS_LEN) .toString("hex"); } exports.getTokenAddress = getTokenAddress; function getDecimalNum(script) { if (script.length < DECIMAL_NUM_OFFSET) return 0; return script.readUIntLE(script.length - DECIMAL_NUM_OFFSET, DECIMAL_NUM_LEN); } exports.getDecimalNum = getDecimalNum; function getGenesisFlag(script) { if (script.length < GENESIS_FLAG_OFFSET) return 0; return script.readUIntLE(script.length - GENESIS_FLAG_OFFSET, GENESIS_FLAG_LEN); } exports.getGenesisFlag = getGenesisFlag; function getTokenSymbol(script) { if (script.length < TOKEN_SYMBOL_OFFSET) return ""; let buf = script.slice(script.length - TOKEN_SYMBOL_OFFSET, script.length - TOKEN_SYMBOL_OFFSET + TOKEN_SYMBOL_LEN); return buf.toString(); } exports.getTokenSymbol = getTokenSymbol; function getTokenName(script) { if (script.length < TOKEN_NAME_OFFSET) return ""; let buf = script.slice(script.length - TOKEN_NAME_OFFSET, script.length - TOKEN_NAME_OFFSET + TOKEN_NAME_LEN); return buf.toString(); } exports.getTokenName = getTokenName; function getContractCode(script) { return script.slice(0, script.length - TOKEN_HEADER_LEN - Utils.getVarPushdataHeader(TOKEN_HEADER_LEN).length); } exports.getContractCode = getContractCode; function getContractCodeHash(script) { return bsv.crypto.Hash.sha256ripemd160(getContractCode(script)); } exports.getContractCodeHash = getContractCodeHash; function getDataPart(script) { return script.slice(script.length - TOKEN_HEADER_LEN, script.length); } exports.getDataPart = getDataPart; function getNewTokenScript(scriptBuf, address, tokenAmount) { const amountBuf = tokenAmount.toBuffer({ endian: "little", size: 8 }); const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_ADDRESS_OFFSET); const newScript = Buffer.concat([ firstBuf, address, amountBuf, scriptBuf.slice(scriptBuf.length - GENESIS_HASH_OFFSET, scriptBuf.length), ]); return newScript; } exports.getNewTokenScript = getNewTokenScript; function newDataPart({ tokenName, tokenSymbol, genesisFlag, decimalNum, tokenAddress, tokenAmount, genesisHash, rabinPubKeyHashArrayHash, sensibleID, protoVersion, protoType, }) { const tokenNameBuf = Buffer.alloc(TOKEN_NAME_LEN, 0); if (tokenName) { tokenNameBuf.write(tokenName); } const tokenSymbolBuf = Buffer.alloc(TOKEN_SYMBOL_LEN, 0); if (tokenSymbol) { tokenSymbolBuf.write(tokenSymbol); } const decimalBuf = Buffer.alloc(DECIMAL_NUM_LEN, 0); if (decimalNum) { decimalBuf.writeUInt8(decimalNum); } const genesisFlagBuf = Buffer.alloc(GENESIS_FLAG_LEN, 0); if (genesisFlag) { genesisFlagBuf.writeUInt8(genesisFlag); } const tokenAddressBuf = Buffer.alloc(TOKEN_ADDRESS_LEN, 0); if (tokenAddress) { tokenAddressBuf.write(tokenAddress, "hex"); } let tokenAmountBuf = Buffer.alloc(TOKEN_AMOUNT_LEN, 0); if (tokenAmount) { tokenAmountBuf = tokenAmount .toBuffer({ endian: "little", size: TOKEN_AMOUNT_LEN }) .slice(0, TOKEN_AMOUNT_LEN); } const genesisHashBuf = Buffer.alloc(GENESIS_HASH_LEN, 0); if (genesisHash) { genesisHashBuf.write(genesisHash, "hex"); } const rabinPubKeyHashArrayHashBuf = Buffer.alloc(RABIN_PUBKEY_HASH_ARRAY_HASH_LEN, 0); if (rabinPubKeyHashArrayHash) { rabinPubKeyHashArrayHashBuf.write(rabinPubKeyHashArrayHash, "hex"); } let sensibleIDBuf = Buffer.alloc(SENSIBLE_ID_LEN, 0); if (sensibleID) { const txidBuf = Buffer.from(sensibleID.txid, "hex").reverse(); const indexBuf = Buffer.alloc(4, 0); indexBuf.writeUInt32LE(sensibleID.index); sensibleIDBuf = Buffer.concat([txidBuf, indexBuf]); } const protoTypeBuf = Buffer.alloc(proto.PROTO_TYPE_LEN, 0); if (protoType) { protoTypeBuf.writeUInt32LE(protoType); } const protoVersionBuf = Buffer.alloc(proto.PROTO_VERSION_LEN); if (protoVersion) { protoVersionBuf.writeUInt32LE(protoVersion); } return Buffer.concat([ tokenNameBuf, tokenSymbolBuf, genesisFlagBuf, decimalBuf, tokenAddressBuf, tokenAmountBuf, genesisHashBuf, rabinPubKeyHashArrayHashBuf, sensibleIDBuf, protoVersionBuf, protoTypeBuf, proto.PROTO_FLAG, ]); } exports.newDataPart = newDataPart; function parseDataPart(scriptBuf) { let tokenName = getTokenName(scriptBuf); let tokenSymbol = getTokenSymbol(scriptBuf); let decimalNum = getDecimalNum(scriptBuf); let genesisFlag = getGenesisFlag(scriptBuf); let tokenAddress = getTokenAddress(scriptBuf); let tokenAmount = getTokenAmount(scriptBuf); let genesisHash = getGenesisHash(scriptBuf); let rabinPubKeyHashArrayHash = getRabinPubKeyHashArrayHash(scriptBuf); let sensibleID = getSensibleID(scriptBuf); let protoVersion = proto.getProtoVersioin(scriptBuf); let protoType = proto.getProtoType(scriptBuf); return { tokenName, tokenSymbol, decimalNum, genesisFlag, tokenAddress, tokenAmount, genesisHash, rabinPubKeyHashArrayHash, sensibleID, protoVersion, protoType, }; } exports.parseDataPart = parseDataPart; function updateScript(scriptBuf, dataPartObj) { const firstBuf = scriptBuf.slice(0, scriptBuf.length - TOKEN_HEADER_LEN); const dataPart = newDataPart(dataPartObj); return Buffer.concat([firstBuf, dataPart]); } exports.updateScript = updateScript; function getQueryCodehash(script) { return (0, scryptlib_1.toHex)(getContractCodeHash(script)); } exports.getQueryCodehash = getQueryCodehash; function getQueryGenesis(script) { return (0, scryptlib_1.toHex)(getTokenID(script)); } exports.getQueryGenesis = getQueryGenesis; function getQuerySensibleID(script0) { let script = Buffer.from(script0); let sensibleIDBuf = script.slice(script.length - SENSIBLE_ID_OFFSET, script.length - SENSIBLE_ID_OFFSET + SENSIBLE_ID_LEN); return (0, scryptlib_1.toHex)(sensibleIDBuf); } exports.getQuerySensibleID = getQuerySensibleID;