Settings

Blockchain
Network
Unit
Language
Theme
Sound New Block

Transaction

40f66e5d2d44367591f8a1111e5909dbb72fbdf85be717827bc83c16c1c9cba8
Timestamp (utc)
2021-06-07 07:35:46
Fee Paid
0.00007498 BSV
(
0.00043281 BSV
-
0.00035783 BSV
)
Fee Rate
500.1 sat/KB
Version
1
Confirmations
295,934
Size Stats
14,993 B

6 Outputs

Total Output:
0.00035783 BSV
  • jrunM39{"in":0,"ref":["native://Jig","f97d4ac2a3d6f5ed09fad4a4f341619dc5a3773d9844ff95c99c5d4f8388de2f_o1"],"out":["e93e093bf3c9b561b3ceb9c6033bc76b9dfb6c69fdec0102cb035c7a0de50d9f","e38fa6427fffd176764ecd95b9eee129b1da4e1e1ed7e77653fa09352bb9443e","9778ed0e7699a32a5773737b96e890932e78e75a8289a5bf62f045125c325198","3a5e67af9f889c87d2070875413c4745bac4d8bb10794dd835b8efc9b4b33aef"],"del":[],"cre":["mzrgrGpxHoKgWB7b5g3Dj8GRS1V1Qtjywn","mzrgrGpxHoKgWB7b5g3Dj8GRS1V1Qtjywn","mzrgrGpxHoKgWB7b5g3Dj8GRS1V1Qtjywn","mzrgrGpxHoKgWB7b5g3Dj8GRS1V1Qtjywn"],"exec":[{"op":"DEPLOY","data":["class MLBasicJig extends Jig {\n init(opts) {\n super.init()\n this.className = \"MLBasicJig\";\n this.name = opts.name || \"\";\n this.setTitle(opts.title, opts.description);\n }\n id(){ return this.origin; }\n setTitle(t, d){\n this.title = t || \"\";\n this.description = d || \"\";\n }\n deposit(val){\n this.satoshis += val || 0;\n }\n withdraw(val){\n this.satoshis -= val || 0;\n }\n balance(){\n return this.satoshis || 0;\n }\n send(to){\n this.owner = to;\n }\n}",{"deps":{"Jig":{"$jig":0}},"title":"MLBasicJig","version":"0.0.1"},"class MLJigger1 extends MLBasicJig {\n init(opts) {\n super.init(opts);\n this.className = \"MLJigger1\";\n this.children = [];\n this._c_at = opts.c_at || -1;\n this._dstr_at = -1;\n }\n newChild(opts, dsp_to){\n const jig = new MLJigger2(opts, dsp_to || opts.dsp_to || \"\");\n this.children.push(jig)\n return jig;\n }\n\n getChild(idx){\n return this.children[idx];\n }\n\n debugChild(idx) {\n console.log(\"MLJigger1 debug child: \", idx);\n this.children[idx].debug();\n }\n\n\n getCanA(){ return this.children.filter(c=>c.canA()) }\n cntCanA(){ return (this.getCanA() || []).length; }\n\n getCanDsp(){ return this.children.filter(c=>c.canDsp()) }\n cntCanDsp(){ return (this.getCanDsp() || []).length; }\n\n getCanP(){ return this.children.filter(c=>c.canP()) }\n cntCanP(){ return (this.getCanP() || []).length; }\n\n getX(){ return this.children.filter(c=>c.isX()) }\n cntX(){ return (this.getX() || []).length; }\n\n getVld(){ return this.children.filter(c=>c.isVld()) }\n cntVld(){ return (this.getVld() || []).length; }\n\n send() {\n throw new Error(\"transfer can corrupt ownership\")\n }\n\n deposit() {\n throw new Error(\"cant deposit\")\n }\n\n withdraw() {\n throw new Error(\"cant withdraw\")\n }\n\n destroy(cdt){\n expect(this.cntVld()).toBe(0, \"Can not destroy a bucket with valid licenses.\")\n this._dstr_at = cdt;\n super.destroy(cdt);\n }\n\n debug() {\n console.log(\"MLJigger1 debug\");\n console.log(\"caller\", caller);\n console.log(\"getCanA\", this.getCanA());\n console.log(\"cntCanA\", this.cntCanA());\n console.log(\"getCanDsp\", this.getCanDsp());\n console.log(\"cntCanDsp\", this.cntCanDsp());\n console.log(\"getCanP\", this.getCanP());\n console.log(\"cntCanP\", this.cntCanP());\n console.log(\"getX\", this.getX());\n console.log(\"cntX\", this.cntX());\n console.log(\"getVld\", this.getVld());\n console.log(\"cntVld\", this.cntVld());\n }\n}",{"deps":{"MLBasicJig":{"$jig":2},"MLJigger2":{"$jig":4},"expect":{"$jig":1}},"title":"MLJigger1","version":"0.0.1"},"class MLJigger2 extends MLBasicJig {\n init(opts, dsp_to) {\n opts = opts || {};\n super.init(opts);\n\n // Constants\n this.className = \"MLJigger2\";\n\n // Expectations\n expect(caller).toBeInstanceOf(MLJigger1)\n expect(opts.c_at).toBeInteger(\"not integer\")\n\n //\n this.parent = {\n origin: caller.origin,\n location: caller.location,\n owner: caller.owner\n };\n\n // Configurations\n this.cnf(opts);\n\n // Privates\n this._c_at = opts.c_at;\n this._a_at = -1;\n this._d_at = -1;\n this._dstr_at = -1;\n this._cnc_at = -1;\n this._vrf_at = -1;\n this._c_cnt = 0;\n this._p_h = [];\n this._p_l_a = -1;\n this._p_c_x_at = -1;\n this._x_at = -1;\n \n if (dsp_to > \"\") this.dispatch(opts.c_at, dsp_to);\n\n }\n\n cnf(opts){\n // Validations\n if (!opts.c_id) throw new Error(\"Missing c_id\");\n if (!opts.p_ad) throw new Error(\"Missing p_ad\");\n if (!Array.isArray(opts.p_ad)) throw new Error(\"p_ad array\");\n \n // Configuration\n this.setTitle(opts.title, opts.description);\n this.c_id = opts.c_id || \"\";\n this.c_lft = opts.c_lft || -1;\n this.cclb = opts.cclb === false ? false : true;\n this.trsf = opts.trsf === false ? false : true;\n this.verfbl = opts.verfbl === true ? true : false;\n //\n this.p_ad = opts.p_ad || [\"\", 1.0];\n this.p_c_max = opts.p_c_max || -1;\n this.p_c_tu = opts.p_c_tu || 60 * 60;\n this.p_c_pr = opts.p_c_pr || 1000;\n this.p_c_min = opts.p_c_min || 1;\n\n this.pld = opts.pld || {};\n }\n\n exp(){\n return {\n name: this.name,\n title: this.title,\n description: this.description,\n c_id: this.c_id,\n c_lft: this.c_lft,\n cclb: this.cclb,\n trsf: this.trsf,\n p_ad: this.p_ad,\n p_c_max: this.p_c_max,\n p_c_tu: this.p_c_tu,\n p_c_pr: this.p_c_pr,\n p_c_min: this.p_c_min,\n pld: this.pld,\n verfbl: this.verfbl\n }\n }\n\n // Values\n minDep() { return this.p_c_min * this.p_c_pr; }\n minTuSz() { return this.p_c_min * this.p_c_tu; }\n reqMinDep() {\n const dbt = (this.p_c_min - this._c_cnt) * this.p_c_pr;\n return ( dbt < 0 ) ? 0 : dbt;\n }\n dbtSz() {\n const dpsz = !this.isA() ? this.reqMinDep() - this.satoshis : this.p_c_pr - this.satoshis;\n return dpsz < 0 ? 0 : dpsz;\n }\n lifeTm() { \n const mts = this.minTuSz();\n return (this.c_lft > mts) ? this.c_lft : mts; \n }\n lifeTmLft(cdt) { \n const lf = this._x_at - cdt; \n return (lf < 0) ? 0 : lf;\n }\n lifeLft(cdt) { \n const lf = this._p_c_x_at - cdt; \n return (lf < 0) ? 0 : lf;\n }\n\n // Conditions\n isParOwn() { return this.owner == this.parent.owner; }\n isA() { return this._a_at > 0; }\n isCnc() { return this._cnc_at > 0; }\n isD() { return this._d_at > 0; }\n isDstr() { return this.owner == null; }\n isX(cdt) { return (this._x_at > 0 && this._x_at < cdt) || (this.isPCX(cdt) && this._c_cnt == this.p_c_max); }\n isPCX(cdt) { return this._p_c_x_at > 0 && this._p_c_x_at < cdt; }\n isGteMin() { return this._c_cnt >= this.p_c_min; }\n isLtMax() { return this.p_c_max <= 0 || this._c_cnt < this.p_c_max; }\n isLteMax() { return this.p_c_max <= 0 || this._c_cnt <= this.p_c_max; }\n hasLifeTmNext(cdt){ \n return this._x_at == -1 || (this.lifeTmLft(cdt) >= (this.lifeLft(cdt) + this.p_c_tu)); \n }\n\n hasPayBal() {\n return this.isA() ? this.satoshis >= this.p_c_pr : this.satoshis >= this.minDep();\n }\n canA(){\n return this.isD() && !this.isA() && !this.isParOwn() && !this.isCnc();\n }\n canP() {\n return !this.isParOwn()\n && this.isA()\n && !this.isX()\n && this.isLtMax()\n && this.hasPayBal();\n }\n canCnc(){\n return !this.isDstr()\n && (\n (this.isParOwn() && (!this.isD() || (this.isD() && this.isCnc())))\n || (\n this.cclb \n && (\n !this.isA()\n || \n (this.isA() && !this.isX() && this.isGteMin())\n )\n )\n );\n }\n canDsp(){\n return this.isParOwn() && !this.isA() && !this.isCnc() && !this.isX();\n }\n canS(){\n return this.trsf && !this.isParOwn() && !this.isX() && !this.isCnc();\n }\n canDep(){\n return !this.isParOwn() && !this.isX() && !this.isCnc();\n }\n canW(){\n return this.satoshis > 0\n && (\n this.isParOwn() \n || !this.isA()\n || (!this.isX() && !this.isCnc())\n );\n }\n canDstr(){\n return !this.isDstr() && this.isParOwn();\n }\n isVld(cdt){\n return this.isA() && !this.isX(cdt) && !this.isPCX(cdt) && this.isLteMax();\n }\n \n _ensureNotPCX(cdt, msg) { if (this.isPCX(cdt)) throw new Error(msg || \"c exp\"); }\n _ensureNotX(cdt, msg) { if (this.isX(cdt)) throw new Error(msg || \"exp\"); }\n _ensureNotCnc(msg) { if (this.isCnc()) throw new Error(msg || \"canceled\"); }\n _ensureGteMin(msg) { if (!this.isGteMin()) throw new Error(msg || \"lic\"); }\n _ensureLtMax(msg) { if (!this.isLtMax()) throw new Error(msg || \"pax pay r\"); }\n \n _next(st) { \n this._ensureLtMax();\n this._c_cnt += st || 1;\n }\n\n //\n \n dispatch(cdt, newOwner) {\n expect(this.isParOwn()).toBe(true, \"only creator\")\n expect(this.isA()).toBe(false, \"cant dispatch\")\n this.owner = newOwner;\n this._d_at = cdt;\n this._cnc_at = -1;\n }\n\n //\n \n deposit(cdt, val) {\n expect(this.isParOwn()).toBe(false, \"owner cant deposit\")\n this._ensureNotX(cdt);\n this.satoshis += val;\n }\n \n withdraw() {\n if (this.satoshis == 0) throw new Error(\"No balance\");\n if (this.isParOwn()){\n this.satoshis = 0;\n return;\n } else if (!this.isA()){\n this.satoshis = 0;\n return;\n }\n const dsz = this.reqMinDep();\n if (this.satoshis <= dsz) {\n throw new Error(\"Balance equal or below minimum\");\n }\n this.satoshis = (dsz > 0) ? dsz : 0;\n }\n\n activate(cdt, pld) {\n expect(this.isParOwn()).toBe(false, \"own cant activate\")\n this._ensureNotX(cdt);\n expect(this.isA()).toBe(false, \"already activated\")\n if (this.dbtSz() > 0) throw new Error(\"needs minimum deposit\");\n \n this._payExec(cdt, this.reqMinDep(), \"Activation payment\");\n \n this._a_at = cdt;\n if (this.c_lft > 0){\n this._x_at = cdt + this.lifeTm();\n }\n this._p_c_x_at = cdt + this.minTuSz();\n this.pld = pld || this.pld;\n \n this._next(this.p_c_min);\n }\n\n pay(cdt) {\n expect(this.isParOwn()).toBe(false, \"owner cant pay\")\n expect(this.isA()).toBe(true, \"can only pay activated\")\n this._ensureNotX(cdt);\n this._ensureLtMax(\"cant pay max reach\");\n expect(this.hasLifeTmNext(cdt)).toBe(true, \"contract to close to expire\")\n\n this._payExec(cdt, this.p_c_pr, \"Recycle payment\");\n \n if (this._p_c_x_at < cdt)\n this._p_c_x_at = cdt + this.p_c_tu;\n else\n this._p_c_x_at += this.p_c_tu;\n\n this._next(1);\n }\n\n _payExec(cdt, value, title) {\n if (!this.hasPayBal()) throw new Error(\"no balance\")\n this._p_h.push([cdt, this.p_c_pr]);\n this._p_l_a = cdt;\n new MLPayJigger(this.parent.owner, value, title, this.title + \" - \" + this.description)\n this.satoshis -= value;\n }\n\n send(cdt, addr) {\n expect(this.isParOwn()).toBe(false, \"use dispatch\")\n this._ensureNotX(cdt);\n this._ensureNotCnc(\"Can not send cancelled\");\n if (!this.trsf) throw new Error(\"no transf\");\n this.owner = addr;\n if (this.verfbl) this._vrf_at = -1;\n }\n\n cancel(cdt) {\n if (this.isParOwn() && (!this.isD() || (this.isD() && this.isCnc()))) {\n this.destroy(cdt)\n return;\n }\n expect(this.cclb).toBe(true, \"non cclb\");\n if (!this.isA()){\n this.satoshis = 0;\n // apply penalties if there are any\n this.returnOwner(cdt);\n return;\n }\n this._ensureNotX(cdt);\n this._ensureGteMin(\"cant cnc not min\");\n let penaltyFee = parseInt((this.satoshis / 2).toString().split(\".\")[0],10);\n new MLPayJigger(this.parent.owner, penaltyFee, \"Cancel penalty\")\n this.satoshis = 0;\n this.returnOwner(cdt);\n }\n\n returnOwner(cdt) {\n expect(this.owner).not.toBe(null, \"is destroyed\");\n expect(this.owner).not.toBe(this.parent.owner, \"already owned\");\n this.owner = this.parent.owner;\n this._cnc_at = cdt;\n }\n \n destroy(cdt){\n expect(this.isParOwn()).toBe(true, \"only parents can burn\")\n // throw new Error(\"Cant destroy jigger2\")\n this._dstr_at = cdt;\n super.destroy(cdt);\n }\n\n debug() {\n console.log(\"MLJigger2 DEBUG1\", this)\n console.log(\"caller\", caller);\n console.log(\"this\", this);\n console.log(\"parent\", this.parent);\n }\n\n debug2(cdt){\n console.log(\"MLJigger2 DEBUG2\", this.name, this)\n console.log(\"CDT\", cdt);\n console.log(this.title, this.description)\n console.log(\"balance\",this.satoshis)\n //\n console.log(\"minDep\",this.minDep(), this.p_c_pr)\n console.log(\"minTuSz\",this.minTuSz(), this.p_c_tu)\n console.log(\"reqMinDep\",this.reqMinDep())\n console.log(\"dbtSz\",this.dbtSz(), this.satoshis)\n //\n console.log(\"isParOwn\",this.isParOwn())\n console.log(\"isA\",this.isA(), this._a_at)\n console.log(\"isD\",this.isD(), this._d_at)\n console.log(\"isCnc\",this.isCnc(), this._cnc_at)\n console.log(\"isX\",this.isX(cdt), this._x_at)\n console.log(\"isPCX\",this.isPCX(cdt), this._p_c_x_at)\n console.log(\"isGteMin\",this.isGteMin(), this._c_cnt, this.p_c_min)\n console.log(\"isLtMax\",this.isLtMax(), this._c_cnt, this.p_c_max)\n console.log(\"isLteMax\",this.isLteMax())\n console.log(\"hasPayBal\",this.hasPayBal(), this.satoshis)\n console.log(\"lifeTm\",this.lifeTm())\n console.log(\"lifeTmLft\",this.lifeTmLft(cdt))\n console.log(\"lifeLft\",this.lifeLft(cdt))\n console.log(\"hasLifeTmNext\",this.hasLifeTmNext(cdt))\n console.log(\"canP\",this.canP())\n console.log(\"canS\",this.canS())\n console.log(\"canA\",this.canA())\n console.log(\"canDep\",this.canDep())\n console.log(\"canW\",this.canW())\n console.log(\"canDstr\",this.canDstr())\n console.log(\"canDsp\",this.canDsp())\n console.log(\"canCnc\",this.canCnc())\n console.log(\"isVld\",this.isVld(cdt))\n //\n }\n \n}",{"deps":{"MLBasicJig":{"$dup":["3","deps","MLBasicJig"]},"MLJigger1":{"$jig":3},"MLPayJigger":{"$jig":5},"expect":{"$dup":["3","deps","expect"]}},"title":"MLJigger2","version":"0.0.1"},"class MLPayJigger extends Jig {\n init(owner, satoshis, title, descr) {\n expect(caller).toBeInstanceOf(MLJigger2, \"Only Jigger2 can pay\")\n this.className = \"MLPayJigger\";\n this.owner = owner\n this.satoshis = satoshis\n this.name = \"Payment Received!\"\n this.title = title || caller.title;\n this.description = descr || caller.description;\n this.from = {\n origin: caller.origin,\n location: caller.location,\n owner: caller.owner\n }\n }\n redeem(cdt){\n this.satoshis = 0;\n this._redeem_at = cdt;\n this.destroy();\n }\n}",{"deps":{"Jig":{"$dup":["1","deps","Jig"]},"MLJigger2":{"$dup":["3","deps","MLJigger2"]},"expect":{"$dup":["3","deps","expect"]}},"title":"MLPayJigger","version":"0.0.1"}]}]}
    https://whatsonchain.com/tx/40f66e5d2d44367591f8a1111e5909dbb72fbdf85be717827bc83c16c1c9cba8
Total Output:
0.00035783 BSV