UNPKG

mnee

Version:

Legacy package for interacting with MNEE USD stablecoin. Includes experimental features.

3 lines (2 loc) 47.6 kB
import{Utils as t,LockingScript as e,OP as r,TransactionSignature as s,Hash as n,UnlockingScript as i,Transaction as o,PrivateKey as a,PublicKey as c,Script as u,P2PKH as d,Mnemonic as h,HD as l}from"@bsv/sdk";import*as f from"bip39";function p(){return p=Object.assign?Object.assign.bind():function(t){for(var e=1;e<arguments.length;e++){var r=arguments[e];for(var s in r)({}).hasOwnProperty.call(r,s)&&(t[s]=r[s])}return t},p.apply(null,arguments)}function m(t){const e=new Error(t);return e.stack=void 0,e}class g{lock(s,n){let i=[];if("string"==typeof s){const e=t.fromBase58Check(s);if(0!==e.prefix[0]&&111!==e.prefix[0])throw m("only P2PKH is supported");i=e.data}else i=s;const o=new e;return o.writeOpCode(r.OP_DUP).writeOpCode(r.OP_HASH160).writeBin(i).writeOpCode(r.OP_EQUALVERIFY).writeOpCode(r.OP_CHECKSIGVERIFY).writeBin(n.encode(!0)).writeOpCode(r.OP_CHECKSIG),o}userUnlock(t,e="all",r=!1,o,a){return{sign:async function(c,u){var d,h,l;let f=s.SIGHASH_FORKID;"all"===e&&(f|=s.SIGHASH_ALL),"none"===e&&(f|=s.SIGHASH_NONE),"single"===e&&(f|=s.SIGHASH_SINGLE),r&&(f|=s.SIGHASH_ANYONECANPAY);const p=c.inputs[u],g=c.inputs.filter((t,e)=>e!==u),v=p.sourceTXID?p.sourceTXID:null==(d=p.sourceTransaction)?void 0:d.id("hex");if(!v)throw m("The input sourceTXID or sourceTransaction is required for transaction signing.");if(o||(o=null==(h=p.sourceTransaction)?void 0:h.outputs[p.sourceOutputIndex].satoshis),!o)throw m("The sourceSatoshis or input sourceTransaction is required for transaction signing.");if(a||(a=null==(l=p.sourceTransaction)?void 0:l.outputs[p.sourceOutputIndex].lockingScript),!a)throw m("The lockingScript or input sourceTransaction is required for transaction signing.");const w=s.format({sourceTXID:v,sourceOutputIndex:p.sourceOutputIndex,sourceSatoshis:o,transactionVersion:c.version,otherInputs:g,inputIndex:u,outputs:c.outputs,inputSequence:p.sequence||4294967295,subscript:a,lockTime:c.lockTime,scope:f}),y=t.sign(n.sha256(w)),A=new s(y.r,y.s,f),I=new i;return I.writeBin(A.toChecksigFormat()),I.writeBin(t.toPublicKey().encode(!0)),I},estimateLength:async function(){return 182}}}unlock(t,e,r="all",o=!1,a,c){return{sign:async function(u,d){var h,l,f;let p=s.SIGHASH_FORKID;"all"===r&&(p|=s.SIGHASH_ALL),"none"===r&&(p|=s.SIGHASH_NONE),"single"===r&&(p|=s.SIGHASH_SINGLE),o&&(p|=s.SIGHASH_ANYONECANPAY);const g=u.inputs[d],v=u.inputs.filter((t,e)=>e!==d),w=g.sourceTXID?g.sourceTXID:null==(h=g.sourceTransaction)?void 0:h.id("hex");if(!w)throw m("The input sourceTXID or sourceTransaction is required for transaction signing.");if(a||(a=null==(l=g.sourceTransaction)?void 0:l.outputs[g.sourceOutputIndex].satoshis),!a)throw m("The sourceSatoshis or input sourceTransaction is required for transaction signing.");if(c||(c=null==(f=g.sourceTransaction)?void 0:f.outputs[g.sourceOutputIndex].lockingScript),!c)throw m("The lockingScript or input sourceTransaction is required for transaction signing.");const y=s.format({sourceTXID:w,sourceOutputIndex:g.sourceOutputIndex,sourceSatoshis:a,transactionVersion:u.version,otherInputs:v,inputIndex:d,outputs:u.outputs,inputSequence:g.sequence||4294967295,subscript:c,lockTime:u.lockTime,scope:p}),A=t.sign(n.sha256(y)),I=new s(A.r,A.s,p),x=new i;return x.writeBin(I.toChecksigFormat()),x.writeScript(e),x},estimateLength:async function(){return 182}}}}const v=t=>Buffer.from(t).toString("hex"),w=(t,r,s,n=!1)=>{let i="";if(void 0!==(null==r?void 0:r.dataB64)&&void 0!==(null==r?void 0:r.contentType)){const t=v("ord"),e=Buffer.from(r.dataB64,"base64").toString("hex").trim();if(!e)throw m("Invalid file data");const s=v(r.contentType);if(!s)throw m("Invalid media type");i=`OP_0 OP_IF ${t} OP_1 ${s} OP_0 ${e} OP_ENDIF`}let o=`${i?`${i} ${n?"OP_CODESEPARATOR ":""}`:""}${t.toASM()}`;if(s&&(!s.app||!s.type))throw m("MAP.app and MAP.type are required fields");if(null!=s&&s.app&&null!=s&&s.type){o=`${o?`${o} `:""}OP_RETURN ${v("1PuQa7K62MiKCtssSLKy1kh56WWU7MtUR5")} ${v("SET")}`;for(const[t,e]of Object.entries(s))"cmd"!==t&&(o=`${o} ${v(t)} ${v(e)}`)}return e.fromASM(o)},y=1e-5,A="ae59f3b898ec61acbdb6cc7a245fabeded0c094bf046f35206a3aec60ef88127_0",I="1inHbiwj2jrEcZPiSYnfgJ8FmS1Bmk4Dh",x="833a7720966a2a435db28d967385e8aa7284b6150ebb39482cc5228b73e1703f_0",b="1AZNdbFYBDFTAEgzZMfPzANxyNrpGJZAUY",T=e=>{var s,i;let o;for(let s=0;s<e.chunks.length;s++){var a;const n=e.chunks[s];s>=2&&3===(null==(a=n.data)?void 0:a.length)&&"ord"==t.toUTF8(n.data)&&e.chunks[s-1].op==r.OP_IF&&e.chunks[s-2].op==r.OP_FALSE&&(o=s+1)}if(void 0===o)return;const c={file:{hash:"",size:0,type:""},fields:{}};for(let a=o;a<e.chunks.length;a+=2){var u,d;const o=e.chunks[a];if(o.op==r.OP_ENDIF)break;if(o.op>r.OP_16)return;const h=e.chunks[a+1];if(h.op>r.OP_PUSHDATA4)return;if(null!=(u=o.data)&&u.length)continue;let l=0;switch(o.op>r.OP_PUSHDATA4&&o.op<=r.OP_16?l=o.op-80:null!=(d=o.data)&&d.length&&(l=o.data[0]),l){case 0:if(c.file.size=(null==(s=h.data)?void 0:s.length)||0,null==(i=h.data)||!i.length)break;c.file.hash=t.toBase64(n.sha256(h.data)),c.file.content=h.data;break;case 1:c.file.type=Buffer.from(h.data||[]).toString()}}return c},S=e=>e.map(e=>{const s=e.chunks;for(let e=0;e<=s.length-4;e++){var n,i,o;if(s.length>e+6&&s[0+e].op===r.OP_DUP&&s[1+e].op===r.OP_HASH160&&20===(null==(n=s[2+e].data)?void 0:n.length)&&s[3+e].op===r.OP_EQUALVERIFY&&s[4+e].op===r.OP_CHECKSIGVERIFY&&33===(null==(i=s[5+e].data)?void 0:i.length)&&s[6+e].op===r.OP_CHECKSIG)return{cosigner:t.toHex(s[5+e].data||[]),address:t.toBase58Check(s[2+e].data||[],[0])};if(s[0+e].op===r.OP_DUP&&s[1+e].op===r.OP_HASH160&&20===(null==(o=s[2+e].data)?void 0:o.length)&&s[3+e].op===r.OP_EQUALVERIFY&&s[4+e].op===r.OP_CHECKSIG)return{cosigner:"",address:t.toBase58Check(s[2+e].data||[],[0])}}}).filter(t=>void 0!==t),k=(e,r,s)=>{const n=e.senders.includes(r)?"send":"receive",i=e.height>0?"confirmed":"unconfirmed";if(!e.rawtx)return null;const a=t.toArray(e.rawtx,"base64"),c=t.toHex(a),u=o.fromHex(c).outputs.map(t=>t.lockingScript),d=S(u),h=u.map(T),l=d.map(t=>t.address),f=l.indexOf(s.feeAddress),p=e.senders[0];let m=0;const g=new Map;h.forEach((e,n)=>{var i;const o=null==e||null==(i=e.file)?void 0:i.content;if(!o)return;const a=t.toUTF8(o);if(!a)return;let c;try{c=JSON.parse(a)}catch(t){return void console.error("Failed to parse inscription JSON:",t)}if("bsv-20"!==c.p||c.id!==s.tokenId)return;const u=parseInt(c.amt,10);if(Number.isNaN(u))return;if(f===n&&p===r)return void(m+=u);const d=l[n],h=g.get(d)||0;g.set(d,h+u)});const v=g.get(r)||0;if("send"===n){const t=g.get(p)||0;g.set(p,t-v)}let w=[];w="receive"===n?[{address:p,amount:v}]:Array.from(g.entries()).map(([t,e])=>({address:t,amount:e})).filter(t=>t.address!==r&&t.address!==s.feeAddress&&t.amount>0);const y=w.reduce((t,e)=>t+e.amount,0);return{txid:e.txid,height:e.height,type:n,status:i,amount:y,fee:m,score:e.score,counterparties:w}},$=e=>{try{const r=t.fromBase58Check(e),s=r.prefix[0];if("number"!=typeof s||![0].includes(s))throw m(`Invalid address prefix: ${s}`);if(20!==r.data.length)throw m(`Invalid address payload length: ${r.data.length}`);return!0}catch(t){return!1}},O=t=>{try{return{isValid:!0,privateKey:a.fromWif(t)}}catch(t){if(t instanceof Error){const e=t.message.toLowerCase();if(e.includes("invalid base58 character"))return{isValid:!1,error:"Invalid WIF key: contains invalid characters"};if(e.includes("invalid checksum"))return{isValid:!1,error:"Invalid WIF key: checksum verification failed"};if(e.includes("expected base58 string"))return{isValid:!1,error:"Invalid WIF key: must be a valid base58 encoded string"}}return{isValid:!1,error:"Invalid WIF key provided"}}};class E extends Error{constructor(t){super(t.message),this.code=void 0,this.hostname=void 0,this.originalError=void 0,this.name="NetworkError",this.code=t.code,this.hostname=t.hostname,this.originalError=t.originalError}}function C(t){var e,r,s;if(!t)return!1;const n=["ENOTFOUND","ECONNREFUSED","ETIMEDOUT","ECONNRESET","ENETUNREACH","EHOSTUNREACH","EPIPE","ECONNABORTED"];return!!n.includes(t.code)||!(!t.cause||!n.includes(null==(e=t.cause)?void 0:e.code))||!!(null!=(r=t.message)&&r.includes("fetch failed")||null!=(s=t.message)&&s.includes("getaddrinfo"))}function P(t,e){if(C(t)){const r=function(t){if(t.cause&&t.cause.code){const e=t.cause;let r="Network connection failed";switch(e.code){case"ENOTFOUND":r="Unable to connect to MNEE network. Please check your internet connection.";break;case"ECONNREFUSED":r="Connection refused by MNEE server. The service may be temporarily unavailable.";break;case"ETIMEDOUT":r="Request timed out. Please check your internet connection and try again.";break;case"ECONNRESET":r="Connection was reset. Please try again.";break;case"ENETUNREACH":case"EHOSTUNREACH":r="Network unreachable. Please check your internet connection.";break;default:r=`Network error: ${e.code}. Please check your connection and try again.`}return new E({code:e.code,message:r,hostname:e.hostname,originalError:t})}if(t.code){let e="Network error occurred";switch(t.code){case"ENOTFOUND":e="Unable to connect to MNEE network. Please check your internet connection.";break;case"ECONNREFUSED":e="Connection refused by MNEE server. The service may be temporarily unavailable.";break;case"ETIMEDOUT":e="Request timed out. Please check your internet connection and try again.";break;default:e=`Network error: ${t.code}. Please check your connection and try again.`}return new E({code:t.code,message:e,hostname:t.hostname,originalError:t})}return new E({code:"NETWORK_ERROR",message:"Network error occurred. Please check your internet connection and try again.",originalError:t})}(t);return console.error(`Network error during ${e}: ${r.message}`),r.message}console.error(`Failed to ${e}:`,t)}const N=["parseOptions"];class H{constructor(t){this.service=void 0,this.service=t}async getUtxos(t,e={}){var r=this;if(!Array.isArray(t))throw m("Input must be an array of addresses");const s=[],n=await this.processBatch(t,async function(t){const n=[],i=[];for(const e of t)e&&"string"==typeof e&&""!==e.trim()?/^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$|^bc1[a-z0-9]{39,59}$/.test(e)?n.push(e):(i.push(e),s.push({items:[e],error:{message:`Invalid address format: ${e}`},retryCount:0})):(i.push(e),s.push({items:[e],error:{message:"Invalid address: empty or not a string"},retryCount:0}));if(!e.continueOnError&&i.length>0)throw new Error(s[0].error.message);if(0===n.length)return[];const o=await r.service.getUtxos(n);return t.map(t=>({address:t,utxos:n.includes(t)?o.filter(e=>e.owners.includes(t)):[]}))},e);return p({},n,{errors:[...n.errors,...s],totalErrors:n.errors.length+s.length})}async getBalances(t,e={}){var r=this;if(!Array.isArray(t))throw m("Input must be an array of addresses");return this.processBatch(t,async function(t){return r.service.getBalances(t)},e)}async getTxHistories(t,e={}){var r=this;if(!Array.isArray(t))throw m("Input must be an array of address history parameters");return this.processBatch(t,async function(t){return r.service.getRecentTxHistories(t)},e,t=>t.address)}async parseTx(t,e={}){var r=this;if(!Array.isArray(t))throw m("Input must be an array of transaction IDs");const{parseOptions:s}=e,n=function(t,e){if(null==t)return{};var r={};for(var s in t)if({}.hasOwnProperty.call(t,s)){if(-1!==e.indexOf(s))continue;r[s]=t[s]}return r}(e,N),i=[],o=await this.processBatch(t,async function(t){const e=await Promise.allSettled(t.map(async function(t){if(!t||"string"!=typeof t||""===t.trim())throw new Error("Invalid transaction ID: empty or not a string");if(!/^[a-fA-F0-9]{64}$/.test(t))throw new Error(`Invalid transaction ID format: ${t}`);return{txid:t,parsed:await r.service.parseTx(t,s)}})),o=[];if(e.forEach((e,r)=>{const s=t[r];if("fulfilled"===e.status)o.push(e.value);else{const t=e.reason instanceof Error?e.reason.message:String(e.reason);i.push({items:[s],error:{message:t},retryCount:n.maxRetries||3})}}),!n.continueOnError&&i.length>0)throw new Error(i[0].error.message);return o},n);return p({},o,{errors:[...o.errors,...i],totalErrors:o.errors.length+i.length})}async processBatch(t,e,r,s){var n=this;const{chunkSize:i=20,continueOnError:o=!1,onProgress:a,maxRetries:c=3,retryDelay:u=1e3,requestsPerSecond:d=3}=r,h=i>0?i:20,l=d>0?d:3,f=Math.ceil(1e3/l),p=Math.max(1,Math.floor(l)),m=new M(p,f);if(0===t.length)return{results:[],errors:[],totalProcessed:0,totalErrors:0};const g=[],v=[];let w=0;const y=this.chunkArray(t,h),A=y.length,I=y.map(async function(t){try{const r=await n.processWithRetry(()=>e(t),c,u,m);return g.push(...r),w++,a&&a(w,A,v.length),r}catch(r){if(!o)throw r;const i=[],d=[];for(const r of t)try{const t=await n.processWithRetry(()=>e([r]),c,u,m);t.length>0&&i.push(...t)}catch(t){const e=t instanceof Error?t:new Error(String(t));d.push({item:r,error:e})}if(g.push(...i),d.length>0){const t=d.map(({item:t})=>s?s(t):t),e=d[0].error;v.push({items:t,error:{message:e.message,code:e.code},retryCount:c})}return w++,a&&a(w,A,v.length),i}});return await Promise.all(I),{results:g,errors:v,totalProcessed:w,totalErrors:v.length}}async processWithRetry(t,e,r,s){let n;for(let i=0;i<e;i++)try{return await s.execute(t)}catch(t){n=t,i<e-1&&await this.delay(r*(i+1))}throw n||new Error("Max retries exceeded")}chunkArray(t,e){const r=[],s=Math.max(1,e);for(let e=0;e<t.length;e+=s)r.push(t.slice(e,e+s));return r}delay(t){return new Promise(e=>setTimeout(e,t))}}class M{constructor(t,e){this.maxConcurrent=void 0,this.minDelay=void 0,this.queue=[],this.running=0,this.maxConcurrent=t,this.minDelay=e}async execute(t){await this.waitForSlot();try{this.running++;const e=Date.now(),r=await t(),s=Date.now()-e;return s<this.minDelay&&await this.delay(this.minDelay-s),r}finally{this.running--,this.processQueue()}}waitForSlot(){return this.running<this.maxConcurrent?Promise.resolve():new Promise(t=>{this.queue.push(t)})}processQueue(){if(this.queue.length>0&&this.running<this.maxConcurrent){const t=this.queue.shift();t&&t()}}delay(t){return new Promise(e=>setTimeout(e,t))}}class F{constructor(t){if(this.mneeApiKey=void 0,this.mneeConfig=void 0,this.mneeApi=void 0,"production"!==t.environment&&"sandbox"!==t.environment)throw m('Invalid environment. Must be either "production" or "sandbox"');const e="production"===t.environment;if(""===(null==t?void 0:t.apiKey))throw m("MNEE API key cannot be an empty string");this.mneeApiKey=null!=t&&t.apiKey?t.apiKey:e?"92982ec1c0975f31979da515d46bae9f":"54f1fd1688ba66a58a67675b82feb93e",this.mneeApi=e?"https://proxy-api.mnee.net":"https://sandbox-proxy-api.mnee.net",this.getCosignerConfig().catch(()=>{})}async getCosignerConfig(){try{const t=await fetch(`${this.mneeApi}/v1/config?auth_token=${this.mneeApiKey}`,{method:"GET"});if(401===t.status||403===t.status)throw m("Invalid API key");if(!t.ok)throw m(`HTTP error! status: ${t.status}`);const e=await t.json();return this.mneeConfig=e,e}catch(t){throw C(t)&&P(t,"fetch config"),t}}toAtomicAmount(t){return Math.round(t*10**5)}fromAtomicAmount(t){return t/10**5}async createInscriptionOutput(t,e,r){const s={p:"bsv-20",op:"transfer",id:r.tokenId,amt:e.toString()};return{lockingScript:w((new g).lock(t,c.fromString(r.approver)),{dataB64:Buffer.from(JSON.stringify(s)).toString("base64"),contentType:"application/bsv-20"}),satoshis:1}}async getUtxos(t,e,r,s){try{if(!t)throw m("Address is required");if("string"==typeof t){if(!$(t))throw m(`Invalid Bitcoin address: ${t}`);const n=[t],i=await fetch(`${this.mneeApi}/v2/utxos?auth_token=${this.mneeApiKey}${void 0!==e?`&page=${e}`:""}${void 0!==r?`&size=${r}`:""}${s?`&order=${s}`:""}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(401===i.status||403===i.status)throw m("Invalid API key");if(!i.ok)throw m(`HTTP error! status: ${i.status}`);const o=await i.json(),a=["transfer","deploy+mint"];return o.filter(t=>a.includes(t.data.bsv21.op.toLowerCase()))}if(Array.isArray(t)){const n=t.filter(t=>"string"==typeof t&&$(t));if(0===n.length)throw m("No valid Bitcoin addresses provided");const i=t.filter(t=>"string"!=typeof t||!$(t));i.length>0&&console.warn(`${i.length} invalid bitcoin addresses will be ignored`);const o=await fetch(`${this.mneeApi}/v2/utxos?auth_token=${this.mneeApiKey}${void 0!==e?`&page=${e}`:""}${void 0!==r?`&size=${r}`:""}${s?`&order=${s}`:""}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(401===o.status||403===o.status)throw m("Invalid API key");if(!o.ok)throw m(`HTTP error! status: ${o.status}`);const a=await o.json(),c=["transfer","deploy+mint"];return a.filter(t=>c.includes(t.data.bsv21.op.toLowerCase()))}throw m("Invalid input type for address")}catch(t){throw C(t)&&P(t,"fetch UTXOs"),t}}async fetchSourceTransaction(t,e=3){for(let r=0;r<=e;r++)try{const s=await fetch(`${this.mneeApi}/v1/tx/${t}?auth_token=${this.mneeApiKey}`);if(404===s.status)throw m("Transaction not found");if(401===s.status||403===s.status)throw m("Invalid API key");if(429===s.status&&r<e){const t=Math.min(500*Math.pow(2,r),2e3);await new Promise(e=>setTimeout(e,t));continue}if(200!==s.status)throw m(`${s.status} - Failed to fetch rawtx for txid: ${t}`);const{rawtx:n}=await s.json();return o.fromHex(Buffer.from(n,"base64").toString("hex"))}catch(t){if(r===e)return void(C(t)&&P(t,"fetch transaction"));await new Promise(t=>setTimeout(t,200))}}async generateSignatures(e,r){try{const i=65;let a;switch(e.format){case"beef":a=o.fromHexBEEF(e.rawtx);break;case"ef":a=o.fromHexEF(e.rawtx);break;default:a=o.fromHex(e.rawtx)}const c=e.sigRequests.flatMap(e=>[r].map(r=>{const o=s.format({sourceTXID:e.prevTxid,sourceOutputIndex:e.outputIndex,sourceSatoshis:e.satoshis,transactionVersion:a.version,otherInputs:a.inputs.filter((t,r)=>r!==e.inputIndex),inputIndex:e.inputIndex,outputs:a.outputs,inputSequence:a.inputs[e.inputIndex].sequence||0,subscript:e.script?u.fromHex(e.script):(new d).lock(r.toPublicKey().toAddress()),lockTime:a.lockTime,scope:e.sigHashType||i}),c=r.sign(n.sha256(o)),h=new s(c.r,c.s,e.sigHashType||i);return{sig:t.toHex(h.toChecksigFormat()),pubKey:r.toPublicKey().toString(),inputIndex:e.inputIndex,sigHashType:e.sigHashType||i,csIdx:e.csIdx}}));return Promise.resolve({sigResponses:c})}catch(t){var i;return C(t)&&P(t,"get signatures"),{error:{message:null!=(i=t.message)?i:"unknown",cause:t.cause}}}}async getEnoughUtxos(t,e){const r=this.mneeConfig||await this.getCosignerConfig();if(!r)throw m("Config not fetched");const s=r.fees.find(t=>e>=t.min&&e<=t.max);if(!s)throw m("Fee not found");const n=s.fee,i=e+n,o=await this.getBalance(t);if(o.amount<i)throw m(`Insufficient MNEE balance. Max transfer amount: ${this.fromAtomicAmount(o.amount-n)}`);let a=1,c=[],u=0;for(;u<i;){const e=await this.getUtxos(t,a,25);if(0===e.length)throw m(`Insufficient MNEE balance. Max transfer amount: ${this.fromAtomicAmount(u-n)}`);if(c.push(...e),u=c.reduce((t,e)=>t+e.data.bsv21.amt,0),u>=i)break;a++}c.sort((t,e)=>e.data.bsv21.amt-t.data.bsv21.amt);let d=[],h=0;for(const t of c)if(d.push(t),h+=t.data.bsv21.amt,h>=i)break;return d}async getAllUtxos(t){let e=1,r=[];for(;;){const s=await this.getUtxos(t,e,100);if(0===s.length)break;r.push(...s),e++}return r}async transfer(t,e,r){try{var s;const n=this.mneeConfig||await this.getCosignerConfig();if(!n)throw m("Config not fetched");const{isValid:a,totalAmount:c,privateKey:u,error:d}=((t,e)=>{const{isValid:r,error:s,privateKey:n}=O(e);if(0===t.length)return{isValid:!1,error:"Empty transfer options provided. Please provide at least one recipient."};if(!r)return{isValid:!1,error:s||"Invalid WIF key provided"};if(!n)return{isValid:!1,error:"Private key not found"};let i=0;for(const e of t){if(!$(e.address))return{isValid:!1,error:`Invalid recipient address: ${e.address}`};if("number"!=typeof e.amount||isNaN(e.amount)||!isFinite(e.amount))return{isValid:!1,error:`Invalid amount for ${e.address}: amount must be a valid number`};if(e.amount<y)return{isValid:!1,error:`Invalid amount for ${e.address}: minimum transfer amount is 0.00001 MNEE`};i+=e.amount}return i<=0?{isValid:!1,error:"Invalid amount: total must be greater than 0"}:{isValid:!0,totalAmount:i,privateKey:n}})(t,e);if(!a)throw m(d||"Invalid transfer options");if(!u)throw m("Private key not found");if(!c)throw m("Invalid amount");const h=this.toAtomicAmount(c),l=u.toAddress(),f=await this.getEnoughUtxos(l,h),p=void 0!==t.find(t=>t.address===n.burnAddress)?0:null==(s=n.fees.find(t=>h>=t.min&&h<=t.max))?void 0:s.fee;if(void 0===p)throw m("Fee ranges inadequate");const g=new o(1,[],[],0);let v=0,w="";for(;v<h+p;){const t=f.shift();if(!t){const t=await this.getBalance(l);throw m("Insufficient MNEE balance. Max transfer amount is "+this.fromAtomicAmount(t.amount-p))}const e=await this.fetchSourceTransaction(t.txid);if(!e)throw m(`Failed to fetch source transaction: ${t.txid}_${t.vout}`);w=w||t.owners[0],g.addInput({sourceTXID:t.txid,sourceOutputIndex:t.vout,sourceTransaction:e,unlockingScript:new i}),v+=t.data.bsv21.amt}for(const e of t)g.addOutput(await this.createInscriptionOutput(e.address,this.toAtomicAmount(e.amount),n));p>0&&g.addOutput(await this.createInscriptionOutput(n.feeAddress,p,n));const A=v-h-p;A>0&&g.addOutput(await this.createInscriptionOutput(w,A,n));const I=new Map;for(let t=0;t<g.inputs.length;t++)I.set(t,u);const x=await this.signAllInputs(g,I);if(x.error)throw m(x.error);const b=g.toHex();if(!1===(null==r?void 0:r.broadcast))return{rawtx:b};const{ticketId:T}=await this.submitRawTx(b,r);if(!T)throw m("Failed to broadcast transaction");return{ticketId:T}}catch(t){throw C(t)&&P(t,"transfer tokens"),t}}async submitRawTx(e,r={broadcast:!0,callbackUrl:void 0}){try{var s,n,i,a;if(!1!==(null==(s=r)?void 0:s.broadcast)&&(r=p({},r,{broadcast:!0})),null!=(n=r)&&n.callbackUrl&&!1===(null==(i=r)?void 0:i.broadcast))throw m("Callback URL cannot be provided when broadcast is false");if(!e)throw m("Raw transaction is required");const c=o.fromHex(e);if(null==(a=r)||!a.broadcast)return{rawtx:c.toHex()};const u=t.toBase64(c.toBinary()),d=JSON.stringify(r?{rawtx:u,callback_url:r.callbackUrl}:{rawtx:u}),h=await fetch(`${this.mneeApi}/v2/transfer?auth_token=${this.mneeApiKey}`,{method:"POST",headers:{"Content-Type":"application/json"},body:d});if(!h.ok)throw m(`Failed to submit transaction: ${h.status}`);return{ticketId:await h.text()}}catch(t){throw C(t)&&P(t,"submit raw transaction"),t}}async getTxStatus(t){try{if(!t)throw m("Ticket ID is required");const e=await fetch(`${this.mneeApi}/v2/ticket?ticketID=${t}&auth_token=${this.mneeApiKey}`,{method:"GET",headers:{"Content-Type":"application/json"}});if(!e.ok)throw m(`Failed to get transaction status: ${e.status}`);return await e.json()}catch(t){throw C(t)&&P(t,"get transaction status"),t}}async getBalance(t){if(!$(t))throw m(`Invalid Bitcoin address: ${t}`);try{if(!this.mneeConfig&&!await this.getCosignerConfig())throw m("Config not fetched");const e=await fetch(`${this.mneeApi}/v2/balance?auth_token=${this.mneeApiKey}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify([t])});if(!e.ok)throw m(`Failed to get transaction status: ${e.status}`);const r=await e.json();return r&&0!==r.length?{address:r[0].address,amount:r[0].amt,decimalAmount:r[0].precised}:{address:t,amount:0,decimalAmount:0}}catch(t){throw C(t)&&P(t,"fetch balance"),t}}async getBalances(t){if(!Array.isArray(t))throw m("Addresses must be an array");const e=t.filter(t=>$(t));if(0===e.length)throw m("You must pass at least 1 valid address");const r=t.length-e.length;r>0&&console.warn(`${r} invalid bitcoin addresses will be ignored`);try{if(!this.mneeConfig&&!await this.getCosignerConfig())throw m("Config not fetched");const t=await fetch(`${this.mneeApi}/v2/balance?auth_token=${this.mneeApiKey}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)});if(!t.ok)throw m(`Failed to get transaction status: ${t.status}`);const r=await t.json();if(!r||0===r.length)return e.map(t=>({address:t,amount:0,decimalAmount:0}));const s=new Map;return r.forEach(t=>{s.set(t.address,{address:t.address,amount:t.amt,decimalAmount:t.precised})}),e.map(t=>s.has(t)?s.get(t):{address:t,amount:0,decimalAmount:0})}catch(t){throw C(t)&&P(t,"fetch balances"),t}}processMneeValidation(e,r,s){try{const n=e.id("hex")===r.tokenId.split("_")[0],i=e.outputs.map(t=>t.lockingScript),o=S(i),a=e.outputs.map((e,r)=>{var s;const n=o[r],i=T(e.lockingScript);let a=null;if(null!=i&&null!=(s=i.file)&&s.content)try{const e=t.toUTF8(i.file.content);e&&(a=JSON.parse(e))}catch(t){}return{index:r,address:null==n?void 0:n.address,cosigner:null==n?void 0:n.cosigner,inscription:a}}),c=a.some(t=>t.cosigner===r.approver);if(a.find(t=>""!==t.cosigner&&t.cosigner!==r.approver))throw m("Invalid cosigner detected");const u=a.filter(t=>{if(!t.inscription)return!1;const e=t.inscription;if("bsv-20"!==e.p)return!1;if(!n&&e.id!==r.tokenId)throw m(`Invalid token ID: ${e.id}`);const s=parseInt(e.amt,10);if(isNaN(s)||s<=0)throw m(`Invalid MNEE amount: ${e.amt}`);return!0});if(0===u.length)throw m("No valid MNEE inscriptions found in transaction");const d=new Set(u.map(t=>t.inscription.op)),h=d.has("burn"),l=u.some(t=>{var e;return"transfer"===t.inscription.op&&"redeem"===(null==(e=t.inscription.metadata)?void 0:e.action)}),f=l&&a.some(t=>t.address===b||t.address===I);if((d.has("transfer")&&!l||h||l&&!f)&&!c)throw m("Cosigner not found in transaction with transfer/burn/redeem operation");const p=u.filter(t=>{const e=t.inscription;return"transfer"===e.op||"burn"===e.op||"deploy+mint"===e.op});if(s){const t=[...p];for(const e of s){const r=t.findIndex(t=>t.address===e.address&&t.inscription.amt===this.toAtomicAmount(e.amount).toString());if(-1===r)throw m(`No matching output found for ${e.address} with amount ${e.amount}`);t.splice(r,1)}}return!0}catch(t){return C(t)&&P(t,"validate Mnee transaction"),!1}}async validateMneeTx(t,e){try{const r=this.mneeConfig||await this.getCosignerConfig();if(!r)throw m("Config not fetched");const s=o.fromHex(t);if(!this.processMneeValidation(s,r,e))return!1;if(s.id("hex")!==r.tokenId.split("_")[0]){const t=await this.processTransactionInputs(s,r),e=this.processTransactionOutputs(s,r);if(t.total!==e.total)return!1}return!0}catch(t){return C(t)&&P(t,"validate Mnee transaction"),!1}}async getMneeSyncs(t,e,r,s){try{const n=Array.isArray(t)?t:[t],i=await fetch(`${this.mneeApi}/v1/sync?auth_token=${this.mneeApiKey}${e?`&from=${e}`:""}${r?`&limit=${r}`:""}${s?`&order=${s}`:""}`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(n)});if(401===i.status||403===i.status)throw m("Invalid API key");if(!i.ok)throw m(`HTTP error! status: ${i.status}`);const o=await i.json();return n.map(t=>{const e=o.filter(e=>e.senders.includes(t)||e.receivers.includes(t));return{address:t,syncs:e}})}catch(t){throw C(t)&&P(t,"fetch syncs"),t}}async getRecentTxHistory(t,e,r,s){if(!$(t))throw m(`Invalid Bitcoin address: ${t}`);if(void 0!==e&&("number"!=typeof e||e<0||!Number.isFinite(e)))throw m(`Invalid fromScore: ${e}. Must be a positive number or 0`);if(void 0!==r&&("number"!=typeof r||r<=0||!Number.isInteger(r)))throw m(`Invalid limit: ${r}. Must be a positive integer`);if(void 0!==s&&"asc"!==s&&"desc"!==s)throw m(`Invalid order: ${s}. Must be 'asc' or 'desc'`);try{const n=this.mneeConfig||await this.getCosignerConfig();if(!n)throw m("Config not fetched");const i=await this.getMneeSyncs(t,e,r,s),{syncs:o}=i[0];if(!o||0===o.length)return{address:t,history:[],nextScore:e||0};const a=[];for(const e of o){const r=k(e,t,n);r&&a.push(r)}const c=a.length>0?a[a.length-1].score:e||0;return r&&a.length>r?{address:t,history:a.slice(0,r),nextScore:c}:{address:t,history:a,nextScore:c}}catch(t){throw C(t)&&P(t,"fetch transaction history"),t}}async getRecentTxHistories(t){var e=this;if(!Array.isArray(t))throw m("Parameters must be an array");if(0===t.length)throw m("You must pass at least 1 address parameter");const r=t.filter(t=>t&&t.address&&$(t.address));if(0===r.length)throw m("You must pass at least 1 valid address");const s=t.length-r.length;s>0&&console.warn(`${s} invalid bitcoin addresses will be ignored`);for(const t of r){if(void 0!==t.fromScore&&("number"!=typeof t.fromScore||t.fromScore<0||!Number.isFinite(t.fromScore)))throw m(`Invalid fromScore for address ${t.address}: ${t.fromScore}. Must be a positive number or 0`);if(void 0!==t.limit&&("number"!=typeof t.limit||t.limit<=0||!Number.isInteger(t.limit)))throw m(`Invalid limit for address ${t.address}: ${t.limit}. Must be a positive integer`);if(void 0!==t.order&&"asc"!==t.order&&"desc"!==t.order)throw m(`Invalid order for address ${t.address}: ${t.order}. Must be 'asc' or 'desc'`)}try{const t=this.mneeConfig||await this.getCosignerConfig();if(!t)throw m("Config not fetched");const s={};r.forEach(t=>{const e=`${t.fromScore||0}:${t.limit||100}:${t.order||"default"}`;s[e]||(s[e]=[]),s[e].push(t)});const n=Object.entries(s).map(async function([r,s]){const[n,i,o]=r.split(":"),a=Number(n),c=Number(i),u="default"===o?void 0:o,d=s.map(t=>t.address);return(await e.getMneeSyncs(d,a,c,u)).map(({address:e,syncs:r})=>{const n=s.find(t=>t.address===e);if(!r||0===r.length)return{address:e,history:[],nextScore:(null==n?void 0:n.fromScore)||0};const i=[],o=new Set;for(const s of r){const r=k(s,e,t);r&&!o.has(r.txid)&&(o.add(r.txid),i.push(r))}const a=i.length>0?i[i.length-1].score:(null==n?void 0:n.fromScore)||0,c=null==n?void 0:n.limit;return c&&i.length>c?{address:e,history:i.slice(0,c),nextScore:a}:{address:e,history:i,nextScore:a}})});return(await Promise.all(n)).flat()}catch(t){throw C(t)&&P(t,"fetch transaction histories"),t}}parseInscriptionData(e){try{var r;const s=T(e),n=null==s||null==(r=s.file)?void 0:r.content;if(!n)return null;const i=t.toUTF8(n);return i?JSON.parse(i):null}catch(t){return C(t)&&P(t,"parse inscription data"),null}}determineEnvironment(t,e,r,s){return t===A.split("_")[0]?"production":t===x.split("_")[0]?"sandbox":e===A&&"020a177d6a5e6f3a8689acd2e313bd1cf0dcf5a243d1cc67b7218602aee9e04b2f"===r?"production":e===x&&"02bed35e894cc41cc9879b4002ad03d33533b615c1b476068c8dd6822a09f93f6c"===r?"sandbox":""===r&&s===I?"production":"sandbox"}determineTransactionType(t,e,r,s,n){return"burn"===t?"burn":"deploy+mint"===t||e===s?r===n.split("_")[0]?"deploy":"mint":e===I||e===b?"mint":"transfer"}async processTransactionInputs(t,e){var r=this;const s=t.id("hex"),n=new Array(t.inputs.length);let i,o,a=BigInt(0);const c=new M(3,334),u=t.inputs.map(async function(t,e){if(!t.sourceTXID)return{index:e,sourceTx:null};try{return{index:e,sourceTx:await c.execute(()=>r.fetchSourceTransaction(t.sourceTXID))}}catch(t){return C(t)&&P(t,"fetch source transaction"),{index:e,sourceTx:null}}}),d=await Promise.all(u);for(const{index:r,sourceTx:c}of d){const u=t.inputs[r];if(!c||!u.sourceTXID){n[r]={address:void 0,amount:0,satoshis:0,inscription:null,cosigner:void 0};continue}const d=c.outputs[u.sourceOutputIndex],h=S([d.lockingScript])[0],l=this.parseInscriptionData(d.lockingScript),f={address:null==h?void 0:h.address,amount:l?parseInt(l.amt):0,satoshis:Number(d.satoshis),inscription:l,cosigner:h};n[r]=f,l&&h&&(a+=BigInt(l.amt),i||(i=this.determineEnvironment(s,l.id,h.cosigner||"",h.address||"")),o||(o=this.determineTransactionType(l.op,h.address||"",s,e.mintAddress,e.tokenId)))}return{inputs:n,total:a,environment:i,type:o}}processTransactionOutputs(t,e){const r=t.id("hex"),s=[];let n,i,o=BigInt(0);for(let a=0;a<t.outputs.length;a++){const c=t.outputs[a],u=S([c.lockingScript])[0],d=this.parseInscriptionData(c.lockingScript),h={address:null==u?void 0:u.address,amount:d?parseInt(d.amt):0,satoshis:Number(c.satoshis),inscription:d,cosigner:u};if(s.push(h),d&&u){o+=BigInt(d.amt),n=this.determineEnvironment(r,d.id,u.cosigner||"",u.address||"");const t=this.determineTransactionType(d.op,u.address||"",r,e.mintAddress,e.tokenId);"burn"===t||"deploy"===t?i=t:i||(i=t)}}return{outputs:s,total:o,environment:n,type:i}}validateTransaction(t,e,r,s,n){return!!this.processMneeValidation(e,t)&&("deploy"===r||s===n)}buildParseResponse(t,e,r,s,n,i,o,a){const c={txid:t,environment:e,type:r,inputs:s.inputs.filter(t=>t.inscription&&t.address).map(t=>({address:t.address,amount:t.amount})),outputs:n.outputs.filter(t=>t.inscription&&t.address).map(t=>({address:t.address,amount:t.amount})),isValid:i,inputTotal:s.total.toString(),outputTotal:n.total.toString()};return null!=a&&a.includeRaw?p({},c,{raw:{txHex:o.toHex(),inputs:o.inputs.map((t,e)=>{var r;const n=s.inputs[e];return{txid:t.sourceTXID||"",vout:t.sourceOutputIndex,scriptSig:(null==(r=t.unlockingScript)?void 0:r.toHex())||"",sequence:t.sequence||4294967295,address:null==n?void 0:n.address,satoshis:(null==n?void 0:n.satoshis)||0,tokenData:null!=n&&n.inscription?{amount:n.amount}:void 0}}),outputs:o.outputs.map((t,e)=>{const r=n.outputs[e];return{value:Number(t.satoshis),scriptPubKey:t.lockingScript.toHex(),address:null==r?void 0:r.address,tokenData:null!=r&&r.inscription?{amount:r.amount}:void 0}})}}):c}async parseTransaction(t,e,r){const s=t.id("hex"),n=await this.processTransactionInputs(t,e),i=this.processTransactionOutputs(t,e),o=i.environment||n.environment||"sandbox";let a=i.type||n.type||"transfer";"transfer"===a&&n.inputs.some(t=>t.inscription&&(t.address===I||t.address===b))&&(a="mint"),"transfer"!==a&&"mint"!==a||i.outputs.some(t=>{var e;return"redeem"===(null==(e=t.inscription)||null==(e=e.metadata)?void 0:e.action)})&&(a="redeem"),0===n.inputs.filter(t=>t.inscription).length&&n.inputs.length>0&&(a="deploy");const c=this.validateTransaction(e,t,a,n.total,i.total);return this.buildParseResponse(s,o,a,n,i,c,t,r)}async parseTx(t,e){if(!t||"string"!=typeof t||""===t.trim()||!/^[a-fA-F0-9]{64}$/.test(t))throw m("A valid transaction ID is required");const r=this.mneeConfig||await this.getCosignerConfig();if(!r)throw m("Config not fetched");const s=await this.fetchSourceTransaction(t);if(!s)throw m("Failed to fetch transaction");return await this.parseTransaction(s,r,e)}async parseTxFromRawTx(t,e){if(!t||"string"!=typeof t||""===t.trim())throw m("A valid raw transaction is required");if(!(t=>{try{return o.fromHex(t),!0}catch(t){return!1}})(t))throw m("Invalid raw transaction hex");const r=o.fromHex(t),s=this.mneeConfig||await this.getCosignerConfig();if(!s)throw m("Config not fetched");return await this.parseTransaction(r,s,e)}parseInscription(t){return T(t)}parseCosignerScripts(t){return S(t)}validateUniqueInputs(t){const e=new Set;for(const r of t){const t=`${r.txid}:${r.vout}`;if(e.has(t))return{error:`Duplicate input detected: ${t}. Each UTXO can only be spent once.`};e.add(t)}return{}}async addInputsToTransaction(t,e,r){let s=0;for(let n=0;n<e.length;n++){const o=e[n],c=await this.fetchSourceTransaction(o.txid);if(!c)return{tokensIn:0,error:`Failed to fetch source transaction: ${o.txid}_${o.vout}`};const u=c.outputs[o.vout];if(!u)return{tokensIn:0,error:`Output ${o.vout} not found in transaction ${o.txid}`};const d=this.parseInscriptionData(u.lockingScript);if(!d)return{tokensIn:0,error:`No inscription found in output ${o.txid}:${o.vout}`};s+=parseInt(d.amt),r.set(n,a.fromWif(o.wif)),t.addInput({sourceTXID:o.txid,sourceOutputIndex:o.vout,sourceTransaction:c,unlockingScript:new i})}return{tokensIn:s}}calculateTransferMultiFee(t,e,r,s,n,i){let o=0,a=-1;for(;o!==a;){var c;a=o;const u=t-e-o;let d=0;if(u>0)if("string"==typeof r)s.has(r)||(d=u);else if(Array.isArray(r))for(const t of r){const e=this.toAtomicAmount(t.amount);s.has(t.address)||(d+=e)}else d=0;const h=e+d,l=void 0!==i.find(t=>t.address===n.burnAddress)?0:null==(c=n.fees.find(t=>h>=t.min&&h<=t.max))?void 0:c.fee;if(void 0===l)return{fee:0,error:"Fee ranges inadequate"};o=l}return{fee:o}}async addChangeOutputs(t,e,r,s,n,i,o,a){if(e<=0)return{};if("string"==typeof r)t.addOutput(await this.createInscriptionOutput(r,e,n));else if(Array.isArray(r)){if(0===r.length)return{error:"Change address array cannot be empty. Provide at least one change output or use a single address string."};const s=r.map(t=>({address:t.address,amount:this.toAtomicAmount(t.amount)})),c=s.reduce((t,e)=>t+e.amount,0);if(c!==e){const t=this.fromAtomicAmount(e),r=this.fromAtomicAmount(c);return{error:`Change amounts must sum to ${t} (${e} atomic units). Total inputs: ${this.fromAtomicAmount(i)} - total outputs: ${this.fromAtomicAmount(o)} - fee: ${this.fromAtomicAmount(a)} = ${t}. Your change outputs sum to ${r} (${c} atomic units).`}}for(const t of r)if(t.amount<=0)return{error:`Invalid change amount: ${t.amount}. Must be positive.`};for(const e of s)t.addOutput(await this.createInscriptionOutput(e.address,e.amount,n))}else{const r=s.get(0).toAddress();t.addOutput(await this.createInscriptionOutput(r,e,n))}return{}}createSignatureRequests(t){return t.inputs.map((t,e)=>{var r,n;if(!t.sourceTXID)throw m("Source TXID is undefined");return{prevTxid:t.sourceTXID,outputIndex:t.sourceOutputIndex,inputIndex:e,address:"",script:null==(r=t.sourceTransaction)?void 0:r.outputs[t.sourceOutputIndex].lockingScript.toHex(),satoshis:(null==(n=t.sourceTransaction)?void 0:n.outputs[t.sourceOutputIndex].satoshis)||1,sigHashType:s.SIGHASH_ALL|s.SIGHASH_ANYONECANPAY|s.SIGHASH_FORKID}})}async signAllInputs(e,r){const s=this.createSignatureRequests(e);s.forEach((t,e)=>{t.address=r.get(e).toAddress()});const n=e.toHex(),i=[];for(const[t,e]of r.entries()){const r=s[t],o=await this.generateSignatures({rawtx:n,sigRequests:[r]},e);if(null==o||!o.sigResponses)return{error:`Failed to get signatures for input ${t}`};i.push(...o.sigResponses)}for(const r of i)e.inputs[r.inputIndex].unlockingScript=(new u).writeBin(t.toArray(r.sig,"hex")).writeBin(t.toArray(r.pubKey,"hex"));return{}}applySignatures(e,r){for(const s of r)e.inputs[s.inputIndex].unlockingScript=(new u).writeBin(t.toArray(s.sig,"hex")).writeBin(t.toArray(s.pubKey,"hex"));return e}async buildUnsignedMneeTransaction(t){var e;const r=this.mneeConfig||await this.getCosignerConfig();if(!r)throw m("Config not fetched");const s=t.recipients.reduce((t,e)=>t+e.amount,0);if(s<=0)throw m("Invalid amount");const n=this.toAtomicAmount(s),a=new o(1,[],[],0),c=new Map;let u=0;for(let e=0;e<t.inputs.length;e++){const r=t.inputs[e],s=await this.fetchSourceTransaction(r.txid);if(!s)throw m(`Failed to fetch source transaction: ${r.txid}_${r.vout}`);const n=s.outputs[r.vout];if(!n)throw m(`Output ${r.vout} not found in transaction ${r.txid}`);const o=this.parseInscriptionData(n.lockingScript);if(!o)throw m(`No inscription found in output ${r.txid}:${r.vout}`);u+=parseInt(o.amt),c.set(e,s),a.addInput({sourceTXID:r.txid,sourceOutputIndex:r.vout,sourceTransaction:s,unlockingScript:new i})}const d=void 0!==t.recipients.find(t=>t.address===r.burnAddress)?0:null==(e=r.fees.find(t=>n>=t.min&&n<=t.max))?void 0:e.fee;if(void 0===d)throw m("Fee ranges inadequate");if(u<n+d)throw m(`Insufficient tokens. Have: ${this.fromAtomicAmount(u)}, Need: ${this.fromAtomicAmount(n+d)} (including fee: ${this.fromAtomicAmount(d)})`);for(const e of t.recipients)a.addOutput(await this.createInscriptionOutput(e.address,this.toAtomicAmount(e.amount),r));d>0&&a.addOutput(await this.createInscriptionOutput(r.feeAddress,d,r));const h=u-n-d;if(h>0)if(t.changeAddress){if("string"==typeof t.changeAddress)a.addOutput(await this.createInscriptionOutput(t.changeAddress,h,r));else if(Array.isArray(t.changeAddress)){const e=t.changeAddress.map(t=>({address:t.address,amount:this.toAtomicAmount(t.amount)})),s=e.reduce((t,e)=>t+e.amount,0);if(s!==h)throw m(`Change amounts must sum to ${this.fromAtomicAmount(h)}. Your change outputs sum to ${this.fromAtomicAmount(s)}`);for(const t of e)a.addOutput(await this.createInscriptionOutput(t.address,t.amount,r))}}else{const e=t.inputs[0],s=c.get(0),n=S([s.outputs[e.vout].lockingScript])[0];if(null==n||!n.address)throw m("Could not determine change address from input");a.addOutput(await this.createInscriptionOutput(n.address,h,r))}return{transaction:a,sigRequests:this.createSignatureRequests(a),sourceTransactions:c}}validateTokenConservation(t,e){let r=0;for(let e=0;e<t.outputs.length;e++){const s=this.parseInscriptionData(t.outputs[e].lockingScript);s&&(r+=parseInt(s.amt))}return e!==r?{error:`Token conservation violation! Inputs (${this.fromAtomicAmount(e)}) do not equal outputs (${this.fromAtomicAmount(r)}). This would ${e>r?"burn":"create"} ${this.fromAtomicAmount(Math.abs(e-r))} tokens.`}:{}}async transferMulti(t,e){try{const r=this.mneeConfig||await this.getCosignerConfig();if(!r)throw m("Config not fetched");const{isValid:s,error:n}=(t=>{for(const e of t.recipients){if(!e.address||!e.amount)return{isValid:!1,error:`Invalid recipient: ${JSON.stringify(e)}. Missing required fields: address, amount`};if("number"!=typeof e.amount||isNaN(e.amount)||!isFinite(e.amount))return{isValid:!1,error:`Invalid amount for ${e.address}: amount must be a valid number`};if(e.amount<y)return{isValid:!1,error:`Invalid amount for ${e.address}: minimum transfer amount is 0.00001 MNEE`};if(!$(e.address))return{isValid:!1,error:`Invalid recipient address: ${e.address}`}}for(const e of t.inputs){if(!e.txid||"number"!=typeof e.vout||!e.wif)return{isValid:!1,error:`Invalid input: ${JSON.stringify(e)}. Missing required fields: txid, vout, wif`};const t=O(e.wif);if(!t.isValid)return{isValid:!1,error:`Invalid WIF key: ${e.wif} for input ${e.txid}:${e.vout}`};const r=t.privateKey.toAddress();if(!$(r))return{isValid:!1,error:`Invalid input address: ${r}`}}if(t.changeAddress&&Array.isArray(t.changeAddress))for(const e of t.changeAddress){if(e.amount<y)return{isValid:!1,error:`Invalid amount for ${e.address}: minimum transfer amount is 0.00001 MNEE`};if(!$(e.address))return{isValid:!1,error:`Invalid change address: ${e.address}`}}return{isValid:!0}})(t);if(!s)throw m(n||"Invalid transfer options");const i=t.recipients.reduce((t,e)=>t+e.amount,0);if(i<=0)throw m("Invalid amount");const c=this.toAtomicAmount(i),u=this.validateUniqueInputs(t.inputs);if(u.error)throw m(u.error);const d=new o(1,[],[],0),h=new Map,l=await this.addInputsToTransaction(d,t.inputs,h);if(l.error)throw m(l.error);const f=l.tokensIn,p=new Set;for(let e=0;e<t.inputs.length;e++){const r=a.fromWif(t.inputs[e].wif);p.add(r.toAddress())}const g=this.calculateTransferMultiFee(f,c,t.changeAddress,p,r,t.recipients);if(g.error)throw m(g.error);const v=g.fee;if(f<c+v)throw m(`Insufficient tokens. Have: ${this.fromAtomicAmount(f)}, Need: ${this.fromAtomicAmount(c+v)} (including fee: ${this.fromAtomicAmount(v)})`);for(const e of t.recipients)d.addOutput(await this.createInscriptionOutput(e.address,this.toAtomicAmount(e.amount),r));v>0&&d.addOutput(await this.createInscriptionOutput(r.feeAddress,v,r));const w=f-c-v,A=await this.addChangeOutputs(d,w,t.changeAddress,h,r,f,c,v);if(A.error)throw m(A.error);const I=await this.signAllInputs(d,h);if(I.error)throw m(I.error);const x=this.validateTokenConservation(d,f);if(x.error)throw m(x.error);const b=d.toHex();if(null==e||!e.broadcast)return{rawtx:b};const{ticketId:T}=await this.submitRawTx(b,e);if(!T)throw m("Failed to broadcast transaction");return{ticketId:T}}catch(t){throw C(t)&&P(t,"multi-source transfer"),t}}}class D{constructor(t,e){if(this.masterKey=void 0,this.derivationPath=void 0,this.cacheSize=void 0,this.cache=void 0,!f.validateMnemonic(t))throw m("Invalid mnemonic phrase");const r=h.fromString(t).toSeed();this.masterKey=l.fromSeed(r),this.derivationPath=e.derivationPath,this.cacheSize=e.cacheSize||1e3,this.cache=new Map}static generateMnemonic(){return f.generateMnemonic()}static isValidMnemonic(t){return f.validateMnemonic(t)}deriveAddress(t,e=!1){const r=`${this.derivationPath}/${e?1:0}/${t}`;if(this.cache.has(r))return this.cache.get(r);const s=this.masterKey.derive(r).privKey;if(!s)throw m(`Failed to derive private key for path: ${r}`);const n={address:s.toAddress(),privateKey:s.toWif(),path:r};return this.cache.size<this.cacheSize&&this.cache.set(r,n),n}async deriveAddresses(t,e,r=!1){const s=[];for(let n=0;n<e;n++){const e=this.deriveAddress(t+n,r);s.push(e)}return s}getPrivateKeysForAddresses(t,e){const r=(null==e?void 0:e.maxScanReceive)||1e4,s=(null==e?void 0:e.maxScanChange)||1e4,n=(null==e?void 0:e.scanStrategy)||"parallel",i={},o={},a=new Set(t);for(const[t,e]of this.cache)a.has(e.address)&&(i[e.address]=e.privateKey,o[e.address]=e.path,a.delete(e.address));if(0===a.size)return{privateKeys:i,paths:o};if("sequential"===n){for(let t=0;t<r&&a.size>0;t++){const e=this.deriveAddress(t,!1);a.has(e.address)&&(i[e.address]=e.privateKey,o[e.address]=e.path,a.delete(e.address))}for(let t=0;t<s&&a.size>0;t++){const e=this.deriveAddress(t,!0);a.has(e.address)&&(i[e.address]=e.privateKey,o[e.address]=e.path,a.delete(e.address))}}else{const t=Math.max(r,s);for(let e=0;e<t&&a.size>0;e++){if(e<r){const t=this.deriveAddress(e,!1);a.has(t.address)&&(i[t.address]=t.privateKey,o[t.address]=t.path,a.delete(t.address))}if(e<s){const t=this.deriveAddress(e,!0);a.has(t.address)&&(i[t.address]=t.privateKey,o[t.address]=t.path,a.delete(t.address))}}}if(a.size>0){const t=Array.from(a);throw m(`Could not find private keys for ${t.length} address(es): ${t.join(", ")}. Scanned up to index ${r} for receive addresses and ${s} for change addresses.`)}return{privateKeys:i,paths:o}}getPrivateKeys(t,e){return this.getPrivateKeysForAddresses(t,e).privateKeys}async scanAddressesWithGapLimit(t,e){const r=(null==e?void 0:e.gapLimit)||20,s=!1!==(null==e?void 0:e.scanChange),n=(null==e?void 0:e.maxScan)||1e4,i={receive:[],change:[]};let o=0;for(let e=0;e<n&&o<r;e++){const r=this.deriveAddress(e,!1);await t(r.address)?(i.receive.push(r),o=0):o++}if(s){o=0;for(let e=0;e<n&&o<r;e++){const r=this.deriveAddress(e,!0);await t(r.address)?(i.change.push(r),o=0):o++}}return i}clearCache(){this.cache.clear()}getCacheSize(){return this.cache.size}}class _{constructor(t){this.service=void 0,this._batch=void 0,this.service=new F(t)}async validateMneeTx(t,e){return this.service.validateMneeTx(t,e)}toAtomicAmount(t){return this.service.toAtomicAmount(t)}fromAtomicAmount(t){return this.service.fromAtomicAmount(t)}async config(){return this.service.getCosignerConfig()}async balance(t){return this.service.getBalance(t)}async balances(t){return this.service.getBalances(t)}async getUtxos(t,e,r,s){return this.service.getUtxos(t,e,r,s)}async getEnoughUtxos(t,e){return this.service.getEnoughUtxos(t,e)}async getAllUtxos(t){return this.service.getAllUtxos(t)}async transfer(t,e,r){return this.service.transfer(t,e,r)}async transferMulti(t,e){return this.service.transferMulti(t,e)}async submitRawTx(t,e){return this.service.submitRawTx(t,e)}async getTxStatus(t){return this.service.getTxStatus(t)}async recentTxHistory(t,e,r,s){return this.service.getRecentTxHistory(t,e,r,s)}async recentTxHistories(t){return this.service.getRecentTxHistories(t)}async parseTx(t,e){return this.service.parseTx(t,e)}async parseTxFromRawTx(t,e){return this.service.parseTxFromRawTx(t,e)}parseInscription(t){return this.service.parseInscription(t)}parseCosignerScripts(t){return this.service.parseCosignerScripts(t)}HDWallet(t,e){return new D(t,e)}batch(){return this._batch||(this._batch=new H(this.service)),this._batch}createInscriptionOutput(t,e,r){return this.service.createInscriptionOutput(t,e,r)}fetchSourceTransaction(t,e){return this.service.fetchSourceTransaction(t,e)}generateSignatures(t,e){return this.service.generateSignatures(t,e)}createSignatureRequests(t){return this.service.createSignatureRequests(t)}applySignatures(t,e){return this.service.applySignatures(t,e)}buildUnsignedMneeTransaction(t){return this.service.buildUnsignedMneeTransaction(t)}}_.HDWallet=D;export{_ as default}; //# sourceMappingURL=index.modern.js.map