<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.runcraft.io/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zhell</id>
	<title>RunWiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.runcraft.io/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Zhell"/>
	<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/view/Special:Contributions/Zhell"/>
	<updated>2026-05-19T12:30:57Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.31.16</generator>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=539</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=539"/>
		<updated>2026-02-07T16:13:01Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Beware that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other method, essentially only allowing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy.&lt;br /&gt;
&lt;br /&gt;
This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
Also, properties could be used to turn on/off specific features in the contract.&lt;br /&gt;
&lt;br /&gt;
== full code for preventing overrides ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // this will allow deploy but break on instance creation (as expected)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version -&amp;gt; we check the entire prototype chain to avoid any bypass&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=538</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=538"/>
		<updated>2026-02-07T15:54:43Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Beware that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other method, essentially only allowing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy.&lt;br /&gt;
&lt;br /&gt;
This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
== full code for preventing overrides ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // this will allow deploy but break on instance creation (as expected)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version -&amp;gt; we check the entire prototype chain to avoid any bypass&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=537</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=537"/>
		<updated>2026-02-07T05:29:16Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Beware that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other method, essentially only allowing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy.&lt;br /&gt;
&lt;br /&gt;
This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
== full code for preventing overrides ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // /!\ beware this actually isnt strong enough bc it only checks at 1 level, so 2 extends are enough to bypass it&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version -&amp;gt; we check the entire prototype chain to avoid any bypass&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=536</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=536"/>
		<updated>2026-02-01T06:13:00Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When you extend Token, redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nonetheless, since it detects the situation as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test, just comment the init() entirely in TokenA to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const log = console.log&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function displayTokensOnAddress() {&lt;br /&gt;
    await run.inventory.sync()&lt;br /&gt;
    const tokens = run.inventory.jigs&lt;br /&gt;
    log(&amp;quot;---tokens on address:&amp;quot;, tokens.length)&lt;br /&gt;
    for (const token of tokens) {&lt;br /&gt;
        log(&amp;quot;token:&amp;quot;, token.constructor.ticker, token.amount / (10 ** token.constructor.decimals), token.constructor.origin)&lt;br /&gt;
    }&lt;br /&gt;
    log(&amp;quot;---end---\n&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
_main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=535</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=535"/>
		<updated>2026-02-01T06:10:06Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;When you extend Token, redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nonetheless, since it detects the situation as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const log = console.log&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function displayTokensOnAddress() {&lt;br /&gt;
    await run.inventory.sync()&lt;br /&gt;
    const tokens = run.inventory.jigs&lt;br /&gt;
    log(&amp;quot;---tokens on address:&amp;quot;, tokens.length)&lt;br /&gt;
    for (const token of tokens) {&lt;br /&gt;
        log(&amp;quot;token:&amp;quot;, token.constructor.ticker, token.amount / (10 ** token.constructor.decimals), token.constructor.origin)&lt;br /&gt;
    }&lt;br /&gt;
    log(&amp;quot;---end---\n&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
_main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=534</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=534"/>
		<updated>2026-02-01T05:59:59Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nonetheless, since it detects the situation as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const log = console.log&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function displayTokensOnAddress() {&lt;br /&gt;
    await run.inventory.sync()&lt;br /&gt;
    const tokens = run.inventory.jigs&lt;br /&gt;
    log(&amp;quot;---tokens on address:&amp;quot;, tokens.length)&lt;br /&gt;
    for (const token of tokens) {&lt;br /&gt;
        log(&amp;quot;token:&amp;quot;, token.constructor.ticker, token.amount / (10 ** token.constructor.decimals), token.constructor.origin)&lt;br /&gt;
    }&lt;br /&gt;
    log(&amp;quot;---end---\n&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress()&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
_main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=533</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=533"/>
		<updated>2026-02-01T05:59:25Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nonetheless, since it detects the situation as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const log = console.log&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function displayTokensOnAddress() {&lt;br /&gt;
    await run.inventory.sync()&lt;br /&gt;
    const tokens = run.inventory.jigs&lt;br /&gt;
    log(&amp;quot;---tokens on address:&amp;quot;, tokens.length)&lt;br /&gt;
    for (const token of tokens) {&lt;br /&gt;
        log(&amp;quot;token:&amp;quot;, token.constructor.ticker, token.amount / (10 ** token.constructor.decimals), token.constructor.origin)&lt;br /&gt;
    }&lt;br /&gt;
    log(&amp;quot;---end---\n&amp;quot;)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
_main()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=532</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=532"/>
		<updated>2026-02-01T05:51:16Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nonetheless, since it detects the situation as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=531</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=531"/>
		<updated>2026-02-01T05:50:45Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=530</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=530"/>
		<updated>2026-02-01T05:50:26Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
- &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
- 'caller' variable which should be the class TokenA, but becomes instead:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=529</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=529"/>
		<updated>2026-02-01T05:49:57Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
      - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
      - 'caller' variable which should be the class TokenA,&lt;br /&gt;
         but becomes instead: &amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting', which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=528</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=528"/>
		<updated>2026-02-01T05:49:38Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
      - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
      - 'caller' variable which should be the class TokenA,&lt;br /&gt;
         but becomes instead: &amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
                location: 'error://Undeployed',&lt;br /&gt;
                origin: 'error://Undeployed',&lt;br /&gt;
                nonce: 0,&lt;br /&gt;
                owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
                satoshis: undefined&lt;br /&gt;
            }&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
      Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
      which manages to still pass the check and mint the token.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=527</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=527"/>
		<updated>2026-02-01T05:49:08Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;Redefining init() with a call to super.init() inside causes issues:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; - 'caller' variable which should be the class TokenA,&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;but becomes instead: Object &amp;amp;lt;Object &amp;amp;lt;Object &amp;amp;lt;Object &amp;amp;lt;Complex prototype&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; {&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; location: 'error://Undeployed',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; origin: 'error://Undeployed',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; nonce: 0,&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; satoshis: undefined&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; }&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; which manages to still pass the check and mint the token.&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('../../libs/run.0.6.44.node.min.js');&lt;br /&gt;
const { runMain, log, displayTokensOnAddress } = require('../helpers.js');&lt;br /&gt;
&lt;br /&gt;
let run = new Run({ network: 'mock', trust: 'state' })&lt;br /&gt;
&lt;br /&gt;
// pure copy of the Token20 with only some added logging&lt;br /&gt;
class Token20Copy extends Jig {&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        // The base Token class cannot be created on its own&lt;br /&gt;
        const extended = this.constructor !== Token20Copy&lt;br /&gt;
        if (!extended) throw new Error('Token must be extended')&lt;br /&gt;
&lt;br /&gt;
        // Make sure we are calling from ourself&lt;br /&gt;
        const minting = caller === this.constructor&lt;br /&gt;
        const sending = caller &amp;amp;&amp;amp; caller.constructor === this.constructor&lt;br /&gt;
        console.log(&amp;quot;minting =&amp;quot;, minting, &amp;quot;, sending =&amp;quot;, sending, &amp;quot;, \n caller =&amp;quot;, caller)&lt;br /&gt;
        if (!minting &amp;amp;&amp;amp; !sending) throw new Error('Must create token using mint()')&lt;br /&gt;
&lt;br /&gt;
        this.sender = sending ? caller.owner : null&lt;br /&gt;
        this.amount = amount&lt;br /&gt;
        if (owner) this.owner = owner&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    static mint(amount, owner) {&lt;br /&gt;
        this.supply += amount&lt;br /&gt;
        return new this(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    send(to, amount = this.amount) {&lt;br /&gt;
        this._checkAmount(amount)&lt;br /&gt;
&lt;br /&gt;
        if (this.amount === amount) {&lt;br /&gt;
            this.destroy()&lt;br /&gt;
        } else if (this.amount &amp;gt; amount) {&lt;br /&gt;
            this.amount -= amount&lt;br /&gt;
        } else {&lt;br /&gt;
            throw new Error('Not enough funds')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        return new this.constructor(amount, to)&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    combine(...tokens) {&lt;br /&gt;
        // If no tokens to combine, nothing to do&lt;br /&gt;
        if (!tokens.length) return this&lt;br /&gt;
&lt;br /&gt;
        // Each token to combine must all be of this type&lt;br /&gt;
        const all = tokens.concat(this)&lt;br /&gt;
        if (all.some(token =&amp;gt; token.constructor !== this.constructor)) {&lt;br /&gt;
            throw new Error('Cannot combine different token classes')&lt;br /&gt;
        }&lt;br /&gt;
&lt;br /&gt;
        // Check for duplicate tokens in the array&lt;br /&gt;
        const countOf = token =&amp;gt; all.reduce((count, next) =&amp;gt; next === token ? count + 1 : count, 0)&lt;br /&gt;
        if (all.some(token =&amp;gt; countOf(token) &amp;gt; 1)) throw new Error('Cannot combine duplicate tokens')&lt;br /&gt;
&lt;br /&gt;
        // Destroy each token, absorbing it into this one&lt;br /&gt;
        tokens.forEach(token =&amp;gt; {&lt;br /&gt;
            this.amount += token.amount&lt;br /&gt;
            token.destroy()&lt;br /&gt;
        })&lt;br /&gt;
&lt;br /&gt;
        // There is no sender for combined tokens&lt;br /&gt;
        this.sender = null&lt;br /&gt;
&lt;br /&gt;
        // Make sure our new amount is within safe range&lt;br /&gt;
        this._checkAmount(this.amount)&lt;br /&gt;
&lt;br /&gt;
        return this&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    destroy() {&lt;br /&gt;
        super.destroy()&lt;br /&gt;
&lt;br /&gt;
        this.amount = 0&lt;br /&gt;
        this.sender = null&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    _checkAmount(amount) {&lt;br /&gt;
        if (typeof amount !== 'number') throw new Error('amount is not a number')&lt;br /&gt;
        if (!Number.isInteger(amount)) throw new Error('amount must be an integer')&lt;br /&gt;
        if (amount &amp;lt;= 0) throw new Error('amount must be positive')&lt;br /&gt;
        if (amount &amp;gt; Number.MAX_SAFE_INTEGER) throw new Error('amount too large')&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class TokenA extends Token20Copy {&lt;br /&gt;
    /** Redefining init() with a call to super.init() inside causes issues:&lt;br /&gt;
     * - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&lt;br /&gt;
     * - 'caller' variable which should be the class TokenA,&lt;br /&gt;
     *    but becomes instead: Object &amp;lt;Object &amp;lt;Object &amp;lt;Object &amp;lt;Complex prototype&amp;gt;&amp;gt;&amp;gt;&amp;gt; {&lt;br /&gt;
     *           location: 'error://Undeployed',&lt;br /&gt;
     *           origin: 'error://Undeployed',&lt;br /&gt;
     *           nonce: 0,&lt;br /&gt;
     *           owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&lt;br /&gt;
     *           satoshis: undefined&lt;br /&gt;
     *       }&lt;br /&gt;
     * &lt;br /&gt;
     * Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&lt;br /&gt;
     * which manages to still pass the check and mint the token.&lt;br /&gt;
     **/&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        super.init(amount, owner)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
TokenA.decimals = 2&lt;br /&gt;
TokenA.ticker = 'TokenA'&lt;br /&gt;
TokenA.currency = 'TokenA'&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
async function _main() {&lt;br /&gt;
    const owner = run.owner.address&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
&lt;br /&gt;
    TokenA = run.deploy(TokenA)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
    TokenA = await run.load(TokenA.origin)&lt;br /&gt;
    log(&amp;quot;TokenA.owner =&amp;quot;, TokenA.owner)&lt;br /&gt;
&lt;br /&gt;
    log(&amp;quot;minting TokenA&amp;quot;)&lt;br /&gt;
    let tokenACoins = TokenA.mint(10 * 10 ** TokenA.decimals, owner)&lt;br /&gt;
    await run.sync()&lt;br /&gt;
&lt;br /&gt;
    await displayTokensOnAddress(owner, run)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
runMain(_main, run, null)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Issues]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=526</id>
		<title>Super.init() caller</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Super.init()_caller&amp;diff=526"/>
		<updated>2026-02-01T05:47:46Z</updated>

		<summary type="html">&lt;p&gt;Zhell: Created page with &amp;quot;&amp;lt;div&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;Redefining init() with a call to super.init() inside causes issues:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; - &amp;quot;minting = false, sending = true&amp;quot; (should be...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;div&amp;gt;&amp;lt;br&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;div&amp;gt;Redefining init() with a call to super.init() inside causes issues:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; - &amp;quot;minting = false, sending = true&amp;quot; (should be the opposite)&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; - 'caller' variable which should be the class TokenA,&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp;but becomes instead: Object &amp;amp;lt;Object &amp;amp;lt;Object &amp;amp;lt;Object &amp;amp;lt;Complex prototype&amp;amp;gt;&amp;amp;gt;&amp;amp;gt;&amp;amp;gt; {&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; location: 'error://Undeployed',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; origin: 'error://Undeployed',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; nonce: 0,&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; owner: 'mo61dRQheTcBMf1d7UEv91ybaDqXUyKUwd',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; satoshis: undefined&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; }&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; Note that despite these issues, it works nontheless, since it detects as 'sending' instead of 'minting',&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;amp;nbsp; &amp;amp;nbsp; &amp;amp;nbsp; which manages to still pass the check and mint the token.&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;Full Code you can test (just comment the init() entirely in TokenA) to see the difference in logs while running it:&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&amp;lt;div&amp;gt;[[Category:Issues]]&amp;lt;/div&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Category:Issues&amp;diff=525</id>
		<title>Category:Issues</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Category:Issues&amp;diff=525"/>
		<updated>2026-02-01T05:44:58Z</updated>

		<summary type="html">&lt;p&gt;Zhell: Created page with &amp;quot;List of known issues&amp;amp;nbsp;&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;List of known issues&amp;amp;nbsp;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=524</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=524"/>
		<updated>2026-01-30T04:51:26Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Beware that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other method, essentially only allowing:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy.&lt;br /&gt;
&lt;br /&gt;
This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
== full code for preventing overrides ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=523</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=523"/>
		<updated>2026-01-30T04:50:13Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Note that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other function, essentially only allowing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy. This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
== full code for preventing overrides ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=522</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=522"/>
		<updated>2026-01-30T04:49:57Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Note that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other function, essentially only allowing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy. This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
full code for preventing overrides&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=521</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=521"/>
		<updated>2026-01-30T04:49:41Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Note that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other function, essentially only allowing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy. This could be a new type of Runcraft contracts, that we may call &amp;quot;clone contracts&amp;quot; since all children are a guaranteed clone of the parent (except for properties).&lt;br /&gt;
&lt;br /&gt;
# full code for for preventing overrides&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=520</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=520"/>
		<updated>2026-01-30T04:42:34Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Note that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other function, essentially only allowing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
and changing class properties before deploy&lt;br /&gt;
&lt;br /&gt;
Here is the full code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=519</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=519"/>
		<updated>2026-01-30T04:41:13Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Here is a solution that we found to prevent child classes (using extends) to override some specific methods from your parent class.&lt;br /&gt;
&lt;br /&gt;
Note that this has limitations though: it does NOT prevent someone to create a new function and implement any behavior they want. So while they may not be able to change how send() works, they can still create send2() and do anything they want in it.&lt;br /&gt;
&lt;br /&gt;
We might be able to use this to prevent also adding any other function, essentially only allowing&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class MyToken extends MyParentTokenClass {}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=518</id>
		<title>Prevent child classes from redefining methods</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Prevent_child_classes_from_redefining_methods&amp;diff=518"/>
		<updated>2026-01-30T04:38:36Z</updated>

		<summary type="html">&lt;p&gt;Zhell: Created page with &amp;quot;&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;  class MyParentTokenClass extends Token {      init(amount, owner) {         const extended = this.constructor != MyParentTokenClass...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
class MyParentTokenClass extends Token {&lt;br /&gt;
&lt;br /&gt;
    init(amount, owner) {&lt;br /&gt;
        const extended = this.constructor != MyParentTokenClass&lt;br /&gt;
        if (!extended) throw new Error('This contract must be extended');&lt;br /&gt;
&lt;br /&gt;
        super.init(amount, owner);&lt;br /&gt;
&lt;br /&gt;
        // --- prevent redefining send() in child classes&lt;br /&gt;
&lt;br /&gt;
        // basic version (prevent overriding only one method like &amp;quot;send&amp;quot;)&lt;br /&gt;
        // const proto = Object.getPrototypeOf(this);&lt;br /&gt;
        // if (proto.send !== MyParentTokenClass.prototype.send) {&lt;br /&gt;
        //     throw new Error(`Method 'send' cannot be overridden by class ${this.constructor.name}`);&lt;br /&gt;
        // }&lt;br /&gt;
&lt;br /&gt;
        // advanced version, for ex to prevent overriding all methods&lt;br /&gt;
        function getDeepPropertyNames(obj) {&lt;br /&gt;
            const props = new Set(); // set to keep unique names&lt;br /&gt;
            let current = obj;&lt;br /&gt;
            while (current &amp;amp;&amp;amp; current !== Object.prototype) {&lt;br /&gt;
                // Get all string properties (including non-enumerable ones)&lt;br /&gt;
                const ownProps = Object.getOwnPropertyNames(current);&lt;br /&gt;
                ownProps.forEach(prop =&amp;gt; props.add(prop));&lt;br /&gt;
                // Move one level up the chain&lt;br /&gt;
                current = Object.getPrototypeOf(current);&lt;br /&gt;
            }&lt;br /&gt;
            return Array.from(props);&lt;br /&gt;
        }&lt;br /&gt;
        const childProto = Object.getPrototypeOf(this);&lt;br /&gt;
        const parentProto = Object.getPrototypeOf(childProto);&lt;br /&gt;
        const childMethods = Object.getOwnPropertyNames(parentProto);&lt;br /&gt;
        // console.log(&amp;quot;childMethods:&amp;quot;, childMethods);&lt;br /&gt;
        const parentMethods = getDeepPropertyNames(MyParentTokenClass.prototype);&lt;br /&gt;
        // console.log(&amp;quot;parentMethods:&amp;quot;, parentMethods)&lt;br /&gt;
        let overriddenMethods = childMethods.filter(method =&amp;gt;&lt;br /&gt;
            parentMethods.includes(method) &amp;amp;&amp;amp; method !== 'constructor'&lt;br /&gt;
            // &amp;amp;&amp;amp; method !== 'init' // unsure if we want to allow overriding init() or not, might depend on case&lt;br /&gt;
        );&lt;br /&gt;
        console.log(&amp;quot;overriddenMethods:&amp;quot;, overriddenMethods);&lt;br /&gt;
        if (overriddenMethods.includes('send')) {&lt;br /&gt;
            throw new Error(&lt;br /&gt;
                `Error: Subclass &amp;quot;${this.constructor.name}&amp;quot; is not allowed to override the critical methods: [${overriddenMethods}]. ` +&lt;br /&gt;
                `These methods must remain as implemented in the base class.`&lt;br /&gt;
            );&lt;br /&gt;
        }&lt;br /&gt;
        // console.log(`-- No forbidden overrides detected in &amp;quot;${this.constructor.name}&amp;quot;. --\n`);&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=517</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=517"/>
		<updated>2026-01-20T18:57:50Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== '''Signing Flow''' ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Right now the flow is:&lt;br /&gt;
#client builds tx with no funding, doesn't sign anything, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, and signs them, sends back to client&lt;br /&gt;
#client finally signs their input, and broadcasts&lt;br /&gt;
If we want payserver to handle the broadcast itself right after signing for funding, we would need to adapt the flow (but maybe this would introduce concurrency issues since no signing on first ping would not activate _pendingUtxos array in payserver purse, so we would need to add a new management for reserved utxos + timeout, and this would add one more round-trip so 200-800 ms of latency)&lt;br /&gt;
&lt;br /&gt;
note: the only reason i'm considering this 2nd flow is bc i thought it might reduce race conditions, but since every run instance already manages its own internal queue for utxos &amp;amp; signing, it seems useless. Just make sure to have a different purse on each server (for ex if you have multiple payservers).&lt;br /&gt;
&lt;br /&gt;
New flow would be:&lt;br /&gt;
#client builds, no funding, no sign, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, no signing, sends back to client&lt;br /&gt;
#client signs their input, sends to payserver again&lt;br /&gt;
#payserver signs their funding input + broadcast (ex with /finalize endpoint)&lt;br /&gt;
&amp;lt;h2 class=&amp;quot;mwt-heading&amp;quot; &amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/h2&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;h3 class=&amp;quot;mwt-heading&amp;quot; &amp;gt;Pourquoi ne pas utiliser '''SIGHASH_ANYONECANPAY ?'''&amp;lt;/h3&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=516</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=516"/>
		<updated>2026-01-20T18:54:24Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Signing Flow'''&lt;br /&gt;
&lt;br /&gt;
Right now the flow is:&lt;br /&gt;
#client builds tx with no funding, doesn't sign anything, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, and signs them, sends back to client&lt;br /&gt;
#client finally signs their input, and broadcasts&lt;br /&gt;
If we want payserver to handle the broadcast itself right after signing for funding, we would need to adapt the flow to this (but maybe this would introduce concurrency issues since no signing on first ping would not activate _pendingUtxos array in payserver purse, so we would need to add a new management for reserved utxos + timeout, and this would add one more round-trip so 200-800 ms of latency):&lt;br /&gt;
#client builds, no funding, no sign, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, no signing, sends back to client&lt;br /&gt;
#client signs their input, sends to payserver again&lt;br /&gt;
#payserver signs their funding input + broadcast (ex with /finalize endpoint)&lt;br /&gt;
note: the only reason i'm considering the 2nd flow is bc i thought it might reduce race conditions, but since every run instance already manages its own internal queue for utxos &amp;amp; signing, it seems useless. Just make sure to have a different purse on each server (for ex if you have multiple payservers).&lt;br /&gt;
&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=515</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=515"/>
		<updated>2026-01-20T18:50:15Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Signing Flow'''&lt;br /&gt;
&lt;br /&gt;
Right now the flow is:&lt;br /&gt;
#client builds tx with no funding, doesn't sign anything, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, and signs them, sends back to client&lt;br /&gt;
#client finally signs their input, and broadcasts&lt;br /&gt;
If we want payserver to handle the broadcast itself right after signing for funding, we would need to adapt the flow to this (but maybe this would introduce concurrency issues since no signing on first ping would not activate _pendingUtxos array in payserver purse):&lt;br /&gt;
#client builds, no funding, no sign, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, no signing, sends back to client&lt;br /&gt;
#client signs their input, sends to payserver again&lt;br /&gt;
#payserver signs their funding input + broadcasts''''''&lt;br /&gt;
&amp;lt;p&amp;gt;''''''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=514</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=514"/>
		<updated>2026-01-20T18:49:21Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Signing Flow'''&lt;br /&gt;
&lt;br /&gt;
Right now the flow is:&lt;br /&gt;
#client builds tx with no funding, doesn't sign anything, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, and signs them, sends back to client&lt;br /&gt;
#client finally signs their input, and broadcasts&lt;br /&gt;
If we want payserver to handle the broadcast itself right after signing for funding, we would need to adapt the flow to:&lt;br /&gt;
#client builds, no funding, no sign, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, no signing, sends back to client&lt;br /&gt;
#client signs their input, sends to payserver again&lt;br /&gt;
#payserver signs their funding input + broadcasts''''''&lt;br /&gt;
&amp;lt;p&amp;gt;''''''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=513</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=513"/>
		<updated>2026-01-20T18:49:11Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Signing Flow'''Right now the flow is:&lt;br /&gt;
#client builds tx with no funding, doesn't sign anything, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, and signs them, sends back to client&lt;br /&gt;
#client finally signs their input, and broadcasts&lt;br /&gt;
If we want payserver to handle the broadcast itself right after signing for funding, we would need to adapt the flow to:&lt;br /&gt;
#client builds, no funding, no sign, sends to payserver&lt;br /&gt;
#payserver adds input funding + change output, no signing, sends back to client&lt;br /&gt;
#client signs their input, sends to payserver again&lt;br /&gt;
#payserver signs their funding input + broadcasts''''''&lt;br /&gt;
&amp;lt;p&amp;gt;''''''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=512</id>
		<title>Pay server</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Pay_server&amp;diff=512"/>
		<updated>2026-01-20T18:33:43Z</updated>

		<summary type="html">&lt;p&gt;Zhell: Created page with &amp;quot;&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt; &amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structur...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p&amp;gt;'''Pourquoi pay() doit avoir lieu avant les autres signatures'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Engagement de signature'''&amp;amp;nbsp;: Les signatures Bitcoin hachent l’intégralité de la structure de la transaction (inputs, outputs, montants, scripts). Modifier quoi que ce soit après la signature invalide les signatures (le hash change).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Dans les transactions multi-parties :&amp;lt;br&amp;gt;La fonction&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;modifie la transaction (elle ajoute des inputs/outputs pour les frais) → elle&amp;amp;nbsp;'''doit'''&amp;amp;nbsp;donc intervenir&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;les signatures finales sur ces nouvelles parties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si une partie signe en premier, puis que&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;&amp;amp;nbsp;ajoute des inputs → les signatures sont cassées (elles s’étaient engagées sur l’ancien hash).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;permettrait théoriquement au client de signer&amp;amp;nbsp;'''avant'''&amp;amp;nbsp;le&amp;amp;nbsp;&amp;lt;code&amp;gt;pay()&amp;lt;/code&amp;gt;, mais voici pourquoi&amp;amp;nbsp;'''Run n’utilise pas SIGHASH_ANYONECANPAY'''&amp;amp;nbsp;dans son code par défaut :&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Le protocole&amp;amp;nbsp;'''Run'''&amp;amp;nbsp;(avant RunCraft) utilise exclusivement&amp;amp;nbsp;'''SIGHASH_ALL'''&amp;amp;nbsp;pour garantir l’intégrité des jigs.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Sécurité et engagement'''&amp;amp;nbsp;:&amp;lt;br&amp;gt;SIGHASH_ANYONECANPAY permet à n’importe qui d’ajouter des inputs plus tard sans casser les signatures existantes. C’est très utile pour des transactions collaboratives comme les atomic swaps ou les coinjoins, mais c’est&amp;amp;nbsp;'''risqué'''&amp;amp;nbsp;pour le système de jigs de Run.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Les jigs/tokens sont&amp;amp;nbsp;'''stateful'''&amp;amp;nbsp;(propriété, méthodes, références dans OP_RETURN, etc.), donc Run veut un&amp;amp;nbsp;'''engagement total'''&amp;amp;nbsp;sur la transaction pour empêcher toute manipulation.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Si un client signait avec ANYONECANPAY, un PayServer malveillant (ou un intermédiaire) pourrait ajouter des inputs/outputs malveillants (ex. : voler des fonds).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''SIGHASH_ALL'''&amp;amp;nbsp;garantit que le signataire accepte&amp;amp;nbsp;'''exactement'''&amp;amp;nbsp;la forme de la transaction telle qu’elle est au moment de la signature.# Markdown syntax guide&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=511</id>
		<title>OrderLock</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=511"/>
		<updated>2025-11-22T17:44:14Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;OrderLock contract code&lt;br /&gt;
&lt;br /&gt;
might be a bit outdated, for newer versions check [https://docs.scrypt.io/bsv-docs/tokens/tutorials/ordinal-lock/ https://docs.scrypt.io/bsv-docs/tokens/tutorials/ordinal-lock/]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
contract OrderLock {&lt;br /&gt;
  // double hash of designated output, i.e. hash256(satoshis + varint + output script)&lt;br /&gt;
  Sha256 hashOutput;&lt;br /&gt;
&lt;br /&gt;
  // trailingPrevouts = concat all inputs (txid1 + vout1 + txid2 + vout2 + ...),&lt;br /&gt;
  // excluding first 2 inputs, i.e. cancel baton input and self input&lt;br /&gt;
  public function unlock(SigHashPreimage preimage, bytes trailingPrevouts, bool isCancel) {&lt;br /&gt;
      // c3 = SIGHASH_SINGLE | ANYONECANPAY, checks self input, self output&lt;br /&gt;
      SigHashType sigHashType = SigHashType(b'c3');&lt;br /&gt;
      if (isCancel) {&lt;br /&gt;
          // 42 = SIGHASH_NONE, checks all inputs, no outputs&lt;br /&gt;
          sigHashType = SigHashType(b'42');&lt;br /&gt;
          // token lock input txid + vout, 32 + 4 bytes&lt;br /&gt;
          bytes selfOutpoint = preimage[68 : 104];&lt;br /&gt;
          // cancel baton input, same locking tx as token lock input, vout must be 0&lt;br /&gt;
          bytes cancelOutpoint = selfOutpoint[: 32] + b'00000000';&lt;br /&gt;
          // reconstruct full prevouts, double hash, check against preimage hashPrevouts&lt;br /&gt;
          require(hash256(selfOutpoint + cancelOutpoint + trailingPrevouts) == preimage[4 : 36]);&lt;br /&gt;
      } else {&lt;br /&gt;
          // check against preimage hashOutputs, with SIGHASH_SINGLE, only self output is hashed&lt;br /&gt;
          require(preimage[len(preimage) - 40 : len(preimage) - 8] == this.hashOutput);&lt;br /&gt;
      }&lt;br /&gt;
      // check preimage&lt;br /&gt;
      require(Tx.checkPreimageAdvanced(&lt;br /&gt;
          preimage,&lt;br /&gt;
          PrivKey(0xeb1c653e7471a63154d06b27f95bb028a5e826b4e73665ed3effe549cc85b2cd),&lt;br /&gt;
          PubKey(b'02dca1e194dd541a47f4c85fea6a4d45bb50f16ed2fddc391bf80b525454f8b409'),&lt;br /&gt;
          0x377d4cbae29bc1e717958cb6b030f71e2e634e1e700991a0ea02181c6ba241f9,&lt;br /&gt;
          0x2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f,&lt;br /&gt;
          b'2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f',&lt;br /&gt;
          sigHashType&lt;br /&gt;
      ));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=510</id>
		<title>OrderLock</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=510"/>
		<updated>2025-11-22T16:00:43Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;OrderLock contract code&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
contract OrderLock {&lt;br /&gt;
  // double hash of designated output, i.e. hash256(satoshis + varint + output script)&lt;br /&gt;
  Sha256 hashOutput;&lt;br /&gt;
&lt;br /&gt;
  // trailingPrevouts = concat all inputs (txid1 + vout1 + txid2 + vout2 + ...),&lt;br /&gt;
  // excluding first 2 inputs, i.e. cancel baton input and self input&lt;br /&gt;
  public function unlock(SigHashPreimage preimage, bytes trailingPrevouts, bool isCancel) {&lt;br /&gt;
      // c3 = SIGHASH_SINGLE | ANYONECANPAY, checks self input, self output&lt;br /&gt;
      SigHashType sigHashType = SigHashType(b'c3');&lt;br /&gt;
      if (isCancel) {&lt;br /&gt;
          // 42 = SIGHASH_NONE, checks all inputs, no outputs&lt;br /&gt;
          sigHashType = SigHashType(b'42');&lt;br /&gt;
          // token lock input txid + vout, 32 + 4 bytes&lt;br /&gt;
          bytes selfOutpoint = preimage[68 : 104];&lt;br /&gt;
          // cancel baton input, same locking tx as token lock input, vout must be 0&lt;br /&gt;
          bytes cancelOutpoint = selfOutpoint[: 32] + b'00000000';&lt;br /&gt;
          // reconstruct full prevouts, double hash, check against preimage hashPrevouts&lt;br /&gt;
          require(hash256(selfOutpoint + cancelOutpoint + trailingPrevouts) == preimage[4 : 36]);&lt;br /&gt;
      } else {&lt;br /&gt;
          // check against preimage hashOutputs, with SIGHASH_SINGLE, only self output is hashed&lt;br /&gt;
          require(preimage[len(preimage) - 40 : len(preimage) - 8] == this.hashOutput);&lt;br /&gt;
      }&lt;br /&gt;
      // check preimage&lt;br /&gt;
      require(Tx.checkPreimageAdvanced(&lt;br /&gt;
          preimage,&lt;br /&gt;
          PrivKey(0xeb1c653e7471a63154d06b27f95bb028a5e826b4e73665ed3effe549cc85b2cd),&lt;br /&gt;
          PubKey(b'02dca1e194dd541a47f4c85fea6a4d45bb50f16ed2fddc391bf80b525454f8b409'),&lt;br /&gt;
          0x377d4cbae29bc1e717958cb6b030f71e2e634e1e700991a0ea02181c6ba241f9,&lt;br /&gt;
          0x2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f,&lt;br /&gt;
          b'2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f',&lt;br /&gt;
          sigHashType&lt;br /&gt;
      ));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=509</id>
		<title>OrderLock</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=509"/>
		<updated>2025-11-22T15:56:35Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
contract OrderLock {&lt;br /&gt;
  // double hash of designated output, i.e. hash256(satoshis + varint + output script)&lt;br /&gt;
  Sha256 hashOutput;&lt;br /&gt;
&lt;br /&gt;
  // trailingPrevouts = concat all inputs (txid1 + vout1 + txid2 + vout2 + ...),&lt;br /&gt;
  // excluding first 2 inputs, i.e. cancel baton input and self input&lt;br /&gt;
  public function unlock(SigHashPreimage preimage, bytes trailingPrevouts, bool isCancel) {&lt;br /&gt;
      // c3 = SIGHASH_SINGLE | ANYONECANPAY, checks self input, self output&lt;br /&gt;
      SigHashType sigHashType = SigHashType(b'c3');&lt;br /&gt;
      if (isCancel) {&lt;br /&gt;
          // 42 = SIGHASH_NONE, checks all inputs, no outputs&lt;br /&gt;
          sigHashType = SigHashType(b'42');&lt;br /&gt;
          // token lock input txid + vout, 32 + 4 bytes&lt;br /&gt;
          bytes selfOutpoint = preimage[68 : 104];&lt;br /&gt;
          // cancel baton input, same locking tx as token lock input, vout must be 0&lt;br /&gt;
          bytes cancelOutpoint = selfOutpoint[: 32] + b'00000000';&lt;br /&gt;
          // reconstruct full prevouts, double hash, check against preimage hashPrevouts&lt;br /&gt;
          require(hash256(selfOutpoint + cancelOutpoint + trailingPrevouts) == preimage[4 : 36]);&lt;br /&gt;
      } else {&lt;br /&gt;
          // check against preimage hashOutputs, with SIGHASH_SINGLE, only self output is hashed&lt;br /&gt;
          require(preimage[len(preimage) - 40 : len(preimage) - 8] == this.hashOutput);&lt;br /&gt;
      }&lt;br /&gt;
      // check preimage&lt;br /&gt;
      require(Tx.checkPreimageAdvanced(&lt;br /&gt;
          preimage,&lt;br /&gt;
          PrivKey(0xeb1c653e7471a63154d06b27f95bb028a5e826b4e73665ed3effe549cc85b2cd),&lt;br /&gt;
          PubKey(b'02dca1e194dd541a47f4c85fea6a4d45bb50f16ed2fddc391bf80b525454f8b409'),&lt;br /&gt;
          0x377d4cbae29bc1e717958cb6b030f71e2e634e1e700991a0ea02181c6ba241f9,&lt;br /&gt;
          0x2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f,&lt;br /&gt;
          b'2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f',&lt;br /&gt;
          sigHashType&lt;br /&gt;
      ));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=508</id>
		<title>OrderLock</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=OrderLock&amp;diff=508"/>
		<updated>2025-11-22T15:55:27Z</updated>

		<summary type="html">&lt;p&gt;Zhell: Created page with &amp;quot;&amp;lt;code class=&amp;quot;mwt-code&amp;quot;&amp;gt; contract OrderLock {   // double hash of designated output, i.e. hash256(satoshis + varint + output script)   Sha256 hashOutput;    // trailingPrevouts...&amp;quot;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;code class=&amp;quot;mwt-code&amp;quot;&amp;gt;&lt;br /&gt;
contract OrderLock {&lt;br /&gt;
  // double hash of designated output, i.e. hash256(satoshis + varint + output script)&lt;br /&gt;
  Sha256 hashOutput;&lt;br /&gt;
&lt;br /&gt;
  // trailingPrevouts = concat all inputs (txid1 + vout1 + txid2 + vout2 + ...),&lt;br /&gt;
  // excluding first 2 inputs, i.e. cancel baton input and self input&lt;br /&gt;
  public function unlock(SigHashPreimage preimage, bytes trailingPrevouts, bool isCancel) {&lt;br /&gt;
      // c3 = SIGHASH_SINGLE | ANYONECANPAY, checks self input, self output&lt;br /&gt;
      SigHashType sigHashType = SigHashType(b'c3');&lt;br /&gt;
      if (isCancel) {&lt;br /&gt;
          // 42 = SIGHASH_NONE, checks all inputs, no outputs&lt;br /&gt;
          sigHashType = SigHashType(b'42');&lt;br /&gt;
          // token lock input txid + vout, 32 + 4 bytes&lt;br /&gt;
          bytes selfOutpoint = preimage[68 : 104];&lt;br /&gt;
          // cancel baton input, same locking tx as token lock input, vout must be 0&lt;br /&gt;
          bytes cancelOutpoint = selfOutpoint[: 32] + b'00000000';&lt;br /&gt;
          // reconstruct full prevouts, double hash, check against preimage hashPrevouts&lt;br /&gt;
          require(hash256(selfOutpoint + cancelOutpoint + trailingPrevouts) == preimage[4 : 36]);&lt;br /&gt;
      } else {&lt;br /&gt;
          // check against preimage hashOutputs, with SIGHASH_SINGLE, only self output is hashed&lt;br /&gt;
          require(preimage[len(preimage) - 40 : len(preimage) - 8] == this.hashOutput);&lt;br /&gt;
      }&lt;br /&gt;
      // check preimage&lt;br /&gt;
      require(Tx.checkPreimageAdvanced(&lt;br /&gt;
          preimage,&lt;br /&gt;
          PrivKey(0xeb1c653e7471a63154d06b27f95bb028a5e826b4e73665ed3effe549cc85b2cd),&lt;br /&gt;
          PubKey(b'02dca1e194dd541a47f4c85fea6a4d45bb50f16ed2fddc391bf80b525454f8b409'),&lt;br /&gt;
          0x377d4cbae29bc1e717958cb6b030f71e2e634e1e700991a0ea02181c6ba241f9,&lt;br /&gt;
          0x2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f,&lt;br /&gt;
          b'2cde0b36a3821ef6dbd1cc8d754dcbae97526904b063c2722da89735162d282f',&lt;br /&gt;
          sigHashType&lt;br /&gt;
      ));&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Basic_examples&amp;diff=507</id>
		<title>Basic examples</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Basic_examples&amp;diff=507"/>
		<updated>2025-04-06T09:27:50Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These are some basic examples to get your imagination flowing.&lt;br /&gt;
&lt;br /&gt;
= Dragon =&lt;br /&gt;
&lt;br /&gt;
When one company makes a digital pet dragon, another can make a house to live in. Jigs interact with each other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dragon extends Jig {&lt;br /&gt;
    init(name) {&lt;br /&gt;
        this.name = name&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class DragonHouse extends Jig {&lt;br /&gt;
    init(dragon) {&lt;br /&gt;
        this.dragon = dragon&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    clean() {&lt;br /&gt;
        this.dirty = false&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Axe =&lt;br /&gt;
&lt;br /&gt;
The base class is the parent of all weapons in the game. Each weapon subclass independently sets the damage it delivers. Then you check whether a particular weapon is the correct type to allow in the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon // true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Loyalty Card =&lt;br /&gt;
&lt;br /&gt;
Any card you’d have in your iOS or Android wallet: boarding passes, prepaid cards.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class LoyaltyCard extends Jig {&lt;br /&gt;
    init() {&lt;br /&gt;
        this.stamps = 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    stamp() {&lt;br /&gt;
        this.stamps += 1&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Product =&lt;br /&gt;
&lt;br /&gt;
Track a physical good from manufacturing through delivery to the customer. Store both the unique serial number and the shared model number. When you transfer ownership, the official record is on-chain.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Product extends Jig {&lt;br /&gt;
    init(model, serial, date) {&lt;br /&gt;
        this.model = model&lt;br /&gt;
        this.serial = serial&lt;br /&gt;
        this.creation = date&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    transfer(to) {&lt;br /&gt;
        this.owner = to&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Vote =&lt;br /&gt;
&lt;br /&gt;
For any recorded decision, you can build a graphical user interface with a dropdown selection. Then, after a milestone, tally up the votes and set in motion the transition of power.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Vote extends Jig {&lt;br /&gt;
    vote(candidate) {&lt;br /&gt;
        this.candidate = candidate&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Election extends Jig {&lt;br /&gt;
    // ...&lt;br /&gt;
&lt;br /&gt;
    tally() {&lt;br /&gt;
        const counts = { 'Alice': 0, 'Bob': 0, 'Carol': 0 }&lt;br /&gt;
        this.voters.forEach((name, vote) =&amp;gt; {&lt;br /&gt;
            counts[vote.candidate] += 1&lt;br /&gt;
        })&lt;br /&gt;
        return counts&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Dollar =&lt;br /&gt;
&lt;br /&gt;
Directly or indirectly link backing to a token. Send numerical amounts and provide the functionality of SLP and ERC20 tokens.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dollar extends Token { }&lt;br /&gt;
&lt;br /&gt;
Dollar.decimals = 2&lt;br /&gt;
Dollar.currency = 'USD'&lt;br /&gt;
Dollar.backingBank = 'HSBC'&lt;br /&gt;
Dollar.accountNumber = '#103947000'&lt;br /&gt;
&lt;br /&gt;
run.deploy(Dollar)&lt;br /&gt;
&lt;br /&gt;
const coin = Dollar.mint(100000)&lt;br /&gt;
&lt;br /&gt;
coin.send(address, 1000)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Permissions =&lt;br /&gt;
&lt;br /&gt;
Allow several people edit access to a website or raise a digital pet together with your friends. Also updates to the permissions are as easy as a cheap bitcoin transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class User extends Jig { }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class UserGroup extends Jig {&lt;br /&gt;
    init() {&lt;br /&gt;
        this.users = []&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    addUser(user) {&lt;br /&gt;
        if (!this.users.includes(user)) {&lt;br /&gt;
            this.users.push(user)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    removeUser(user) {&lt;br /&gt;
        this.users = this.users.filter(u =&amp;gt; user !== u)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=506</id>
		<title>Installing the run sdk</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=506"/>
		<updated>2025-03-02T01:23:43Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to get the latest version is to run&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[deprecated, instead retrieve the compiled sdk file from runcraft.io] npm install run-sdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;Another solution is to download the SDK as a file from [https://runcraft.io/ https://runcraft.io]. At the time of writing the latest version is 0.6.37&lt;br /&gt;
&lt;br /&gt;
= Getting Started =&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
If you're new to Run, let the [https://run.network/lessons tutorial series] guide your journey to get acquainted. You can write code without installing anything. The web browser Console will be your playground.&lt;br /&gt;
&lt;br /&gt;
The details written here in the Docs have example code in the sidebar on the right-hand side. Anything you read in paragraphs, you can preview in-action over there.&lt;br /&gt;
&lt;br /&gt;
Run works everywhere including all major browsers, on desktop and mobile, as well as Node.js 10+ on servers. The Run SDK is written in JavaScript ES6 and uses the [https://github.com/moneybutton/bsv bsv library] to build and sign transactions. To get started:&lt;br /&gt;
&lt;br /&gt;
*For a webpage: Add &amp;lt;code&amp;gt;bsv.browser.min.js&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;run.browser.min.js&amp;lt;/code&amp;gt; to the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
*For Node.js: Run &amp;lt;code&amp;gt;npm install run-sdk&amp;lt;/code&amp;gt; to install both the run and bsv libraries&lt;br /&gt;
And that's it. All your code and jigs will be saved on-chain and Run will use public APIs to interact with the Bitcoin network. You don't need to deploy any servers to use Run. All the logic works client-side.&lt;br /&gt;
&lt;br /&gt;
You can also find the SDK at [https://github.com/runonbitcoin/sdk the github repo].&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
Load both bsv and run in the browser&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/bsv@1.5.6&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/run-sdk&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load run in Node.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('run-sdk')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
A &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance manages your communication with the Bitcoin network. The default network is &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (Mainnet), but for development and testing, we recommend &amp;lt;code&amp;gt;mock&amp;lt;/code&amp;gt;. Mock is an in-memory simulation blockchain that does not require funds to use. We like to call it the mockchain. For more configuration options, see [https://run.network/docs/#api-reference-run API Reference: Run.]&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({ network: 'mock' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;After that you are ready to [[Creating and_loading_jigs|create and load jigs]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=505</id>
		<title>Installing the run sdk</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=505"/>
		<updated>2025-03-02T01:23:08Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to get the latest version is to run&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
[deprecated, instead retrieve the compiled sdk file from runcraft.io] npm install run-sdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;Another solution is to download the SDK as a zip file from [https://run.network/ https://run.network/]. At the time of writing the latest version is [https://github.com/runonbitcoin/sdk/archive/refs/tags/v0.6.37.zip version 0.6.37].&lt;br /&gt;
&lt;br /&gt;
= Getting Started =&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
If you're new to Run, let the [https://run.network/lessons tutorial series] guide your journey to get acquainted. You can write code without installing anything. The web browser Console will be your playground.&lt;br /&gt;
&lt;br /&gt;
The details written here in the Docs have example code in the sidebar on the right-hand side. Anything you read in paragraphs, you can preview in-action over there.&lt;br /&gt;
&lt;br /&gt;
Run works everywhere including all major browsers, on desktop and mobile, as well as Node.js 10+ on servers. The Run SDK is written in JavaScript ES6 and uses the [https://github.com/moneybutton/bsv bsv library] to build and sign transactions. To get started:&lt;br /&gt;
&lt;br /&gt;
*For a webpage: Add &amp;lt;code&amp;gt;bsv.browser.min.js&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;run.browser.min.js&amp;lt;/code&amp;gt; to the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
*For Node.js: Run &amp;lt;code&amp;gt;npm install run-sdk&amp;lt;/code&amp;gt; to install both the run and bsv libraries&lt;br /&gt;
And that's it. All your code and jigs will be saved on-chain and Run will use public APIs to interact with the Bitcoin network. You don't need to deploy any servers to use Run. All the logic works client-side.&lt;br /&gt;
&lt;br /&gt;
You can also find the SDK at [https://github.com/runonbitcoin/sdk the github repo].&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
Load both bsv and run in the browser&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/bsv@1.5.6&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/run-sdk&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load run in Node.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('run-sdk')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
A &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance manages your communication with the Bitcoin network. The default network is &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (Mainnet), but for development and testing, we recommend &amp;lt;code&amp;gt;mock&amp;lt;/code&amp;gt;. Mock is an in-memory simulation blockchain that does not require funds to use. We like to call it the mockchain. For more configuration options, see [https://run.network/docs/#api-reference-run API Reference: Run.]&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({ network: 'mock' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;After that you are ready to [[Creating and_loading_jigs|create and load jigs]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=504</id>
		<title>Installing the run sdk</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=504"/>
		<updated>2025-03-02T01:22:45Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[deprecated, instead retrieve the compiled sdk file from runcraft.io] The easiest way to get the latest version is to run&amp;lt;pre&amp;gt;npm install run-sdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;Another solution is to download the SDK as a zip file from [https://run.network/ https://run.network/]. At the time of writing the latest version is [https://github.com/runonbitcoin/sdk/archive/refs/tags/v0.6.37.zip version 0.6.37].&lt;br /&gt;
&lt;br /&gt;
= Getting Started =&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
If you're new to Run, let the [https://run.network/lessons tutorial series] guide your journey to get acquainted. You can write code without installing anything. The web browser Console will be your playground.&lt;br /&gt;
&lt;br /&gt;
The details written here in the Docs have example code in the sidebar on the right-hand side. Anything you read in paragraphs, you can preview in-action over there.&lt;br /&gt;
&lt;br /&gt;
Run works everywhere including all major browsers, on desktop and mobile, as well as Node.js 10+ on servers. The Run SDK is written in JavaScript ES6 and uses the [https://github.com/moneybutton/bsv bsv library] to build and sign transactions. To get started:&lt;br /&gt;
&lt;br /&gt;
*For a webpage: Add &amp;lt;code&amp;gt;bsv.browser.min.js&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;run.browser.min.js&amp;lt;/code&amp;gt; to the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
*For Node.js: Run &amp;lt;code&amp;gt;npm install run-sdk&amp;lt;/code&amp;gt; to install both the run and bsv libraries&lt;br /&gt;
And that's it. All your code and jigs will be saved on-chain and Run will use public APIs to interact with the Bitcoin network. You don't need to deploy any servers to use Run. All the logic works client-side.&lt;br /&gt;
&lt;br /&gt;
You can also find the SDK at [https://github.com/runonbitcoin/sdk the github repo].&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
Load both bsv and run in the browser&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/bsv@1.5.6&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/run-sdk&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load run in Node.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('run-sdk')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
A &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance manages your communication with the Bitcoin network. The default network is &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (Mainnet), but for development and testing, we recommend &amp;lt;code&amp;gt;mock&amp;lt;/code&amp;gt;. Mock is an in-memory simulation blockchain that does not require funds to use. We like to call it the mockchain. For more configuration options, see [https://run.network/docs/#api-reference-run API Reference: Run.]&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({ network: 'mock' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;After that you are ready to [[Creating and_loading_jigs|create and load jigs]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Basic_examples&amp;diff=503</id>
		<title>Basic examples</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Basic_examples&amp;diff=503"/>
		<updated>2025-03-02T01:21:50Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;These examples were originally found on run's homepage&lt;br /&gt;
&lt;br /&gt;
= Dragon =&lt;br /&gt;
&lt;br /&gt;
When one company makes a digital pet dragon, another can make a house to live in. Jigs interact with each other.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dragon extends Jig {&lt;br /&gt;
    init(name) {&lt;br /&gt;
        this.name = name&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class DragonHouse extends Jig {&lt;br /&gt;
    init(dragon) {&lt;br /&gt;
        this.dragon = dragon&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    clean() {&lt;br /&gt;
        this.dirty = false&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Axe =&lt;br /&gt;
&lt;br /&gt;
The base class is the parent of all weapons in the game. Each weapon subclass independently sets the damage it delivers. Then you check whether a particular weapon is the correct type to allow in the game.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon // true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Loyalty Card =&lt;br /&gt;
&lt;br /&gt;
Any card you’d have in your iOS or Android wallet: boarding passes, prepaid cards.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class LoyaltyCard extends Jig {&lt;br /&gt;
    init() {&lt;br /&gt;
        this.stamps = 0&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    stamp() {&lt;br /&gt;
        this.stamps += 1&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Product =&lt;br /&gt;
&lt;br /&gt;
Track a physical good from manufacturing through delivery to the customer. Store both the unique serial number and the shared model number. When you transfer ownership, the official record is on-chain.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Product extends Jig {&lt;br /&gt;
    init(model, serial, date) {&lt;br /&gt;
        this.model = model&lt;br /&gt;
        this.serial = serial&lt;br /&gt;
        this.creation = date&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    transfer(to) {&lt;br /&gt;
        this.owner = to&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Vote =&lt;br /&gt;
&lt;br /&gt;
For any recorded decision, you can build a graphical user interface with a dropdown selection. Then, after a milestone, tally up the votes and set in motion the transition of power.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Vote extends Jig {&lt;br /&gt;
    vote(candidate) {&lt;br /&gt;
        this.candidate = candidate&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class Election extends Jig {&lt;br /&gt;
    // ...&lt;br /&gt;
&lt;br /&gt;
    tally() {&lt;br /&gt;
        const counts = { 'Alice': 0, 'Bob': 0, 'Carol': 0 }&lt;br /&gt;
        this.voters.forEach((name, vote) =&amp;gt; {&lt;br /&gt;
            counts[vote.candidate] += 1&lt;br /&gt;
        })&lt;br /&gt;
        return counts&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Dollar =&lt;br /&gt;
&lt;br /&gt;
Directly or indirectly link backing to a token. Send numerical amounts and provide the functionality of SLP and ERC20 tokens.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dollar extends Token { }&lt;br /&gt;
&lt;br /&gt;
Dollar.decimals = 2&lt;br /&gt;
Dollar.currency = 'USD'&lt;br /&gt;
Dollar.backingBank = 'HSBC'&lt;br /&gt;
Dollar.accountNumber = '#103947000'&lt;br /&gt;
&lt;br /&gt;
run.deploy(Dollar)&lt;br /&gt;
&lt;br /&gt;
const coin = Dollar.mint(100000)&lt;br /&gt;
&lt;br /&gt;
coin.send(address, 1000)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Permissions =&lt;br /&gt;
&lt;br /&gt;
Allow several people edit access to a website or raise a digital pet together with your friends. Also updates to the permissions are as easy as a cheap bitcoin transaction.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class User extends Jig { }&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class UserGroup extends Jig {&lt;br /&gt;
    init() {&lt;br /&gt;
        this.users = []&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    addUser(user) {&lt;br /&gt;
        if (!this.users.includes(user)) {&lt;br /&gt;
            this.users.push(user)&lt;br /&gt;
        }&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    removeUser(user) {&lt;br /&gt;
        this.users = this.users.filter(u =&amp;gt; user !== u)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=502</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=502"/>
		<updated>2025-02-27T04:10:06Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and onchain-data ecosystem, but the protocol could be adapted to work on any Bitcoin-like blockchain, including BTC.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''Our goal is to port and improve the doc by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=501</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=501"/>
		<updated>2025-02-27T04:09:29Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and onchain-data ecosystem, but the protocol could be adapted to work on any Bitcoin-like blockchain, including BTC.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''Our goal is to port and improve the doc by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=500</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=500"/>
		<updated>2025-02-27T04:09:12Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and onchain-data ecosystem, but the protocol could be adapted to work on any Bitcoin-like blockchain, even BTC.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''Our goal is to port and improve the doc by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=499</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=499"/>
		<updated>2025-02-27T04:08:39Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and rich ecosystem, but the protocol could be adapted to work on any Bitcoin-like blockchain, even on BTC.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''Our goal is to port and improve the doc by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=498</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=498"/>
		<updated>2025-02-27T04:07:29Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture not affiliated with the owners of RUN. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and rich ecosystem.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''Our goal is to port and improve the doc by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=497</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=497"/>
		<updated>2025-02-27T04:06:27Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run's original logo|right|top|thumb|run.network's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture not affiliated with the owners of RUN. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and rich ecosystem.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''We believe our first step is to port the '''[https://run.network/docs/#introduction official documentation]''' by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=496</id>
		<title>Welcome</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Welcome&amp;diff=496"/>
		<updated>2025-02-27T04:05:41Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&amp;lt;p style=&amp;quot;text-align: center;&amp;quot;&amp;gt;&amp;lt;span style=&amp;quot;font-size: 24pt;&amp;quot;&amp;gt;'''Learn to build on Bitcoin with a token protocol for whatever you can dream up.'''&amp;lt;/span&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Welcome to runWiki =&lt;br /&gt;
&lt;br /&gt;
[[File:Run logo.png|300px|alt=run.network's original logo|right|top|thumb|run.network's original logo]]&lt;br /&gt;
&lt;br /&gt;
This wiki is a community-driven platform where users can '''share and collaborate''' on information related to the '''RUN token protocol''' (also known as RUN-on-Bitcoin) which has been running on the Bitcoin protocol since 2019.&lt;br /&gt;
&lt;br /&gt;
The goal of this Wiki is to provide a '''central repository of knowledge and resources''' for the RUN-on-Bitcoin community. We encourage all users to contribute their expertise and experiences to help grow and improve the wiki. It is hosted by RunCraft, which is an independant venture not affiliated with the owners of RUN. The implementation of the Bitcoin protocol that we use in the examples provided is Bitcoin SV (BSV) for its low fees and rich ecosystem.&lt;br /&gt;
&lt;br /&gt;
This Wiki is '''created and maintained by a team of dedicated volunteers'''. If you have any questions or need assistance, please don't hesitate to contact us at [https://runcraft.io/ runcraft.io]&lt;br /&gt;
&lt;br /&gt;
== Getting started ==&lt;br /&gt;
&lt;br /&gt;
=== install Run and use it ===&lt;br /&gt;
&lt;br /&gt;
*[[Installing the_run_sdk|install the run SDK]] and then&amp;amp;nbsp;[[Creating_and_loading_jigs|learn about creating jigs]]&lt;br /&gt;
*check the '''[[Tutorials|tutorials]]''' or the '''[[Documentation|documentation]]'''&lt;br /&gt;
*check [[Special:AllPages|all the wiki pages.]]&lt;br /&gt;
&lt;br /&gt;
=== contribute to this Wiki ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*refer to the [[Contributing|contributing]] page&lt;br /&gt;
&lt;br /&gt;
== Why was this Wiki created? ==&lt;br /&gt;
This wiki is a community effort to have a community maintained documentation of the RUN protocol and library.&lt;br /&gt;
&lt;br /&gt;
Since the original creators decided to leave the project, we have reuploaded and improved the documentation for the RUN library on this wiki.&lt;br /&gt;
&lt;br /&gt;
'''We believe our first step is to port the '''[https://run.network/docs/#introduction official documentation]''' by cleverly leveraging wiki's ability to link pages to make it easier to search. If you want to help, check out the [[Contributing|contributing]] page.'''&lt;br /&gt;
&lt;br /&gt;
What's more, some members of the RUN community are already willing to build tools and to explore expanding the protocol, so this wiki is a place for them to share their efforts and collaborate in public.&lt;br /&gt;
= What is RUN? =&lt;br /&gt;
Run's website originally described it this way:&amp;lt;pre&amp;gt;Imagine. Then, Build. A token protocol for whatever you can dream up.&lt;br /&gt;
jigs // interactive objects&lt;br /&gt;
&amp;lt;/pre&amp;gt;[[File:Relayx amm.png|300px|alt=RelayX's AMM is built based on RUN tokens|right|top|thumb|RelayX's AMM is built based on RUN tokens]]&amp;lt;p&amp;gt;'''Run is a protocol and SDK to build apps and tokens on Bitcoin'''. Developers create applications using interactive objects, called jigs. Jigs allow you to build almost anything you can dream up: tokens, contracts, artwork, elections, games, digital pets, and more — all run on Bitcoin.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;'''Run supports full object-oriented programming''' and arbitrary code today. It is secure and performant for real applications. These docs will help you get started!&amp;lt;/p&amp;gt;&lt;br /&gt;
In a more technical language, RUN is a '''Bitcoin based UTXO-enforced layer2 protocol similar to javascript''' that allows you to create interactive objects. It can allow you to create NFTs or blockchain tokens that can be used to build pretty much anything.&lt;br /&gt;
&lt;br /&gt;
 Copyrights notice: the RUN protocol was created by Brenton Gunning at [https://github.com/runonbitcoin/run-sdk this github repo] under the MIT license.&lt;br /&gt;
&lt;br /&gt;
== Examples of projects that have been built ==&lt;br /&gt;
Here are a few of the projects that have already been built using Run:&lt;br /&gt;
*game objects that users own and can resell&amp;lt;br&amp;gt;&lt;br /&gt;
*[[NFT|NFTs]] for art, music and 3D&amp;lt;br&amp;gt;&lt;br /&gt;
*[[DEX|DEXs]] and [[AMM|AMMs]]&amp;lt;br&amp;gt;&lt;br /&gt;
*social media platforms&amp;lt;br&amp;gt;&lt;br /&gt;
*[[Wrapped]] dollars ([[Stablecoins]])&lt;br /&gt;
*voting tokens&lt;br /&gt;
*tracing products on the blockchain&amp;lt;br&amp;gt;&lt;br /&gt;
*handling permissions&lt;br /&gt;
*loyalty cards&lt;br /&gt;
&lt;br /&gt;
== How it looks ==&lt;br /&gt;
Here is how some Run code looks. In this example we create an Axe NFT that causes 9001 damage. You can find other [[basic examples|basic examples]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Weapon extends Jig {&lt;br /&gt;
    init(damage) {&lt;br /&gt;
        this.damage = damage&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
class Axe extends Weapon {&lt;br /&gt;
    init() {&lt;br /&gt;
        super.init(9001)&lt;br /&gt;
    }&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
new Axe() instanceof Weapon  // is true&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Feeling ready to get started ? then head over to the [[Installing the_run_sdk|installation and setup]].&amp;lt;/p&amp;gt;&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Tutorial_5_-_Setting_icons_for_your_jigs:_emojis_and_SVG_images&amp;diff=495</id>
		<title>Tutorial 5 - Setting icons for your jigs: emojis and SVG images</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Tutorial_5_-_Setting_icons_for_your_jigs:_emojis_and_SVG_images&amp;diff=495"/>
		<updated>2023-09-26T16:58:35Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens and jigs is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the first tutorial [[Tutorial 1_-_Intro_to_jigs_that_run_on_Bitcoin:_Mocknet_and_Web_Console|Intro to jigs on the Mockchain]], you began by opening the RUN Explorer and loading an address that had several jigs in it. You may have noticed that those jigs had icons. Did you wonder how those icons were assigned? In this tutorial, you'll find out.&lt;br /&gt;
&lt;br /&gt;
Icons let people visualize your jigs and they give your jigs a personality. You'll see your icons in the RUN Explorer today, and in the future, they will also show up in wallets, apps, and exchanges. When jigs are sent to others, their icons go with them.&lt;br /&gt;
&lt;br /&gt;
In this tutorial, we'll cover how to add two different kinds of icons to your jigs: emojis and custom images. You will find them both useful in different places. In particular, you'll learn how to:&lt;br /&gt;
*Discover an emoji to assign to your jigs&lt;br /&gt;
*Set an emoji to your jig using metadata&lt;br /&gt;
*Upload an SVG image on-chain using Bitcoin Files&lt;br /&gt;
*Load an image locally and give credit to its author&lt;br /&gt;
*Attach an image you loaded locally to your jigs&lt;br /&gt;
*Upgrade an existing class to attach new icons&lt;br /&gt;
*See your emojis and image icons on the RUN Explorer&lt;br /&gt;
Let's get started!&lt;br /&gt;
&lt;br /&gt;
= Getting started =&lt;br /&gt;
&lt;br /&gt;
We'll be creating real jigs in this tutorial. You're going to need a funded purse that works on the Bitcoin Mainnet. You will also need a RelayX or MoneyButton wallet. If you don't yet have these, pause for a second and take the [[Tutorial 2_-_Running_jigs_on_Bitcoin_Mainnet,_Part_1|Mainnet, Part 1 tutorial]] to get prepared. We'll be here when you return.&lt;br /&gt;
&lt;br /&gt;
You're going to be coding in the browser again. On this tutorial page, pop open the '''Web Console'''. In Firefox, you can press '''Control-Shift-K''' on Windows or '''Command-Option-K''' on macOS. In other browsers, your shortcuts will be different. Once you have your Web Console open, copy and paste the following code into it:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const purse = '_YOUR_PURSE_PRIVATE_KEY_HERE_'&lt;br /&gt;
&lt;br /&gt;
const network = 'main'&lt;br /&gt;
&lt;br /&gt;
const run = new Run({ purse, network })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Replace &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;_YOUR_PURSE_PRIVATE_KEY_HERE_&amp;lt;/span&amp;gt; with your actual purse private key, then press '''Enter'''. If the console shows &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;undefined&amp;lt;/span&amp;gt;, you're good to go![[File:1 getting started.png|500px|center|middle|thumb]]&lt;br /&gt;
= Emojis =&lt;br /&gt;
&lt;br /&gt;
Emojis are pictures we use to express ideas and emotions. We can also use them to represent jigs. You may be used to seeing emojis in chat messages on your phone, but emojis work almost everywhere. Even your browser can show emojis: 👋&lt;br /&gt;
&lt;br /&gt;
To our devices, emojis are just characters like A, B, and C. This means they can appear anywhere that letters can. Images usually can't do this. Imagine an app in the future like Venmo where users send jigs to each other instead of money. Using emojis, every trade could be shown to everyone else in a public feed:&lt;br /&gt;
&lt;br /&gt;
 Twenty minutes ago, Zoe traded &amp;lt;span style=&amp;quot;background-color: rgb(251, 238, 184);&amp;quot;&amp;gt;💵 21 Dollars&amp;lt;/span&amp;gt; for Yolanda's &amp;lt;span style=&amp;quot;background-color: rgb(251, 238, 184);&amp;quot;&amp;gt;🐅 2 Tigers&amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;background-color: rgb(251, 238, 184);&amp;quot;&amp;gt;🎶 7 Songs.&amp;lt;/span&amp;gt;&lt;br /&gt;
Pretty cool, right?&lt;br /&gt;
&lt;br /&gt;
= Discovering your spirit emoji =&lt;br /&gt;
&lt;br /&gt;
In the '''Web Console''', type the following code, but don't press Enter quite yet:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class DragonEgg extends Jig { }&lt;br /&gt;
&lt;br /&gt;
DragonEgg.metadata = { emoji: '_EGG_EMOJI_HERE_' }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
We're defining a jig class called &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt;. It would be great to find an emoji for it. '''Right-click''' on this link to an emoji search engine ➞ [https://emojifinder.com/ Emoji Finder]. Then click '''Open Link in New Window'''. Go ahead and search for the word &amp;quot;egg&amp;quot; and then '''click''' on the egg emoji highlighted below. This will copy the egg's emoji codes to your clipboard.[[File:2 emoji-finder.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
You can use this search engine anytime you need to find an emoji for your jigs. '''Close''' the window for Emoji Finder and come back to the '''Web Console'''.&lt;br /&gt;
&lt;br /&gt;
 '''Tip:''' If you can't find a good emoji for your jigs, don't worry! You'll learn how to attach custom images in the next section. The Unicode Consortium also adds new emojis every year. You can see what's coming [https://emojipedia.org/new here].&lt;br /&gt;
&lt;br /&gt;
= Setting your emoji =&lt;br /&gt;
Select &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;_EGG_EMOJI_HERE_&amp;lt;/span&amp;gt; by double-clicking and then paste the egg emoji you just copied by pressing '''Control-V''' on Windows or '''Command-V''' on macOS. Now, press '''Enter'''.[[File:3 set-emoji.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Congratulations! This is how you set an emoji for your jigs: you set your emoji on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;emoji&amp;lt;/span&amp;gt; property of the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt; object on your class.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt; object where you set the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;emoji&amp;lt;/span&amp;gt; on is special in RUN — it's where you put meta-information for wallets and other apps. You set the metadata on the jig class because the information applies to every instance. Jig instances will use the icon from their class. You'll see this in a second.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;emoji&amp;lt;/span&amp;gt; property should always be a single emoji symbol. That's what wallets and apps are expecting, and if you set it to something other than a single emoji, then your emoji might not show properly. There is other metadata you can set too. You can learn all about the most common metadata [https://run.network/docs/#advanced-usage-standard-metadata here].&lt;br /&gt;
&lt;br /&gt;
 '''Beginner programmers:''' If you need a refresher on the difference between classes and instances, see the expandable section in the first tutorial, [[Tutorial 1_-_Intro_to_jigs_that_run_on_Bitcoin:_Mocknet_and_Web_Console|Intro to jigs on the Mockchain.]]&lt;br /&gt;
&lt;br /&gt;
= Seeing your emoji =&lt;br /&gt;
Let's create a new egg instance and print its location. Paste the following code and then press '''Enter'''.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const egg = new DragonEgg()&lt;br /&gt;
&lt;br /&gt;
await egg.sync()&lt;br /&gt;
&lt;br /&gt;
console.log(egg.location)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now '''right-click''' on this link to the [https://run.network/explorer RUN Explorer] and select '''Open Link in New Window'''. Then, search for the location for your egg instance you just printed:[[File:4 explorer-egg.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Although you set the emoji on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt; class, notice your instance shows the emoji too. Now click on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt; text. The Explorer will open the page for the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt; class, and notice that it also shows the same emoji. Emojis are applied to both classes and instances.&lt;br /&gt;
&lt;br /&gt;
 '''Advanced programmers: '''Jig instances are also allowed to have their own metadata separate from their classes, which may be useful when the class is ''abstract'', or used for many different kinds of objects. To set instance-specific metadata, you set the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt; property on the jig in a method.&lt;br /&gt;
&lt;br /&gt;
= Custom Images =&lt;br /&gt;
So, you've just learned how to set an emoji. Now it's time to level up and set a real image you choose yourself. You're going to continue using the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt; class you wrote earlier and you will add an SVG image to it.&lt;br /&gt;
&lt;br /&gt;
RUN lets you set both SVG and PNG images as icons. SVG and PNG are both popular image formats that every web browser supports. Here's a quick rundown comparing the different icon formats:&lt;br /&gt;
&lt;br /&gt;
[[File:5 custom images.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
'''Emojis:''' Emojis are the smallest in size and they usually load instantly. They are great for using in bodies of text. However, you may not always be able to find a good emoji for your jig. They also don't always scale up well and they will look different depending on your device.&lt;br /&gt;
&lt;br /&gt;
'''PNG''': PNG images are the best at representing high-resolution detail and three-dimensional photos. They are made up of many small colored pixels. However, they are the slowest to load and use up the most space on disk. They might also look pixelated, or blocky, when scaled up for large screens. We recommend using them only when there is no other suitable format.&lt;br /&gt;
&lt;br /&gt;
'''SVG''': SVG images are in some sense a balance between emojis and PNGs. They are small in size like emoji but they can also be customized like PNG. They also scale up great for large displays. The only downside is that they can only represent two-dimensional illustrations. SVGs are vector graphics, meaning they are made up of colored geometry layered on to top of each other.&lt;br /&gt;
&lt;br /&gt;
Our advice — Whenever possible, we recommend using an SVG image as your primary icon, and setting an emoji as backup to be used in bodies of text. That's what you'll be doing in this tutorial. 👌&lt;br /&gt;
&lt;br /&gt;
= Finding an image =&lt;br /&gt;
&lt;br /&gt;
Let's find an SVG image for your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt;. You can certainly create an image yourself if you have the artistic talent, and we recommend it. For the rest of us, you can find an appropriate icon for your jig on the web.&lt;br /&gt;
&lt;br /&gt;
A great website to discover SVG images is [https://flaticon.com/ Flaticon]. They have millions of images, and most of them are free to use, even commercially — so long as you give credit to the author, which we will.&lt;br /&gt;
&lt;br /&gt;
'''Right-click''' on this link to [https://flaticon.com/ Flaticon.com] and select '''Open Link in New Window'''. Then, type &amp;quot;baby dragon&amp;quot; in the search box and press '''Enter'''. Somewhere on the page, you should see the icon highlighted below. Do you see it? Click on it when you do.[[File:6 dragon-search.png|500px|center|thumb]]&lt;br /&gt;
 '''Tip''': If you see an icon with a golden crown below it, like the one in the top-left of the picture above, that means it is a premium image on Flaticon. You'll have to pay for those.&lt;br /&gt;
Now, on the right side of the page, you should see a green '''SVG''' button. Go ahead and click that which will open up a new dialog box.&lt;br /&gt;
&lt;br /&gt;
[[File:7 download-dragon-svg.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Finally, click the green '''Free download''' button highlighted below to begin the download. Make sure to save the file in a safe place on your computer. You're going to use it shortly.&lt;br /&gt;
&lt;br /&gt;
[[File:8 download-dragon-free.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Once the Dragon SVG image finishes downloading, continue on.&lt;br /&gt;
&lt;br /&gt;
= Using BitcoinFiles to upload your image =&lt;br /&gt;
&lt;br /&gt;
Images you attach to your jigs need to be stored on Bitcoin just like the jigs themselves. This lets applications access a single shared database, Bitcoin, to completely load your jigs. We can use &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;op_return&amp;lt;/span&amp;gt; data, essentially a memo field, in a Bitcoin transaction to store our images. Pretty futuristic, huh?&lt;br /&gt;
&lt;br /&gt;
You're going to use a tool called BitcoinFiles to upload the image on-chain. BitcoinFiles is like Dropbox or Google Drive for Bitcoin, except everything you upload is available for all to see. You can use this tool to upload images, HTML pages, movies, and more. For this part, you'll need either a RelayX or MoneyButton wallet.&lt;br /&gt;
&lt;br /&gt;
'''Right-click''' on this link to [https://www.bitcoinfiles.org/ BitcoinFiles.org] and select '''Open Link in New Window'''. You should see a page like the one below.&lt;br /&gt;
&lt;br /&gt;
[[File:9 bitcoin-files.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Click '''Import Files'''. Then, find and select your Dragon SVG image file. Because SVG images are small, it will only cost you 1c to upload. Swipe using your wallet to start the upload.&lt;br /&gt;
&lt;br /&gt;
[[File:10 upload-pay.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Once your image finishes uploading, you will see a screen like a PC folder with all of your files. Click on your '''Dragon SVG''', and then click on the '''Copy Link''' button. We will use this link in a second to get the transaction ID.[[File:11 copy-link.png|500px|center|thumb]]&lt;br /&gt;
= Loading your image using RUN =&lt;br /&gt;
&lt;br /&gt;
In the web console, paste the link you just copied. Then remove the URL so that you just have the transaction ID, the 64 numbers and characters at the end of your link. Save it to a variable called &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;txid&amp;lt;/span&amp;gt; like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const txid = 'e605923f307c0fd02957fed0b4a15af550219207a8b6fd393ee202afed98e504'&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, load the image using the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const image = await Run.extra.B.load(txid)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You've just used RUN to load your uploaded SVG image into a JavaScript object that you can use in jigs.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;B&amp;lt;/span&amp;gt; class, accessible as &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;Run.extra.B&amp;lt;/span&amp;gt;, is a helper class that RUN provides for you. &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;B&amp;lt;/span&amp;gt; loads data from Bitcoin stored in the B:// protocol. What's the B:// protocol? The [https://github.com/runcraft-bitcoin/B-protocol B:// protocol] is a way of storing arbitrary media on the blockchain using &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;op_return&amp;lt;/span&amp;gt;. Many apps are already using it today. When you uploaded your image using BitcoinFiles, it was stored using the B:// protocol.&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;image&amp;lt;/span&amp;gt; object returned has several fields on it. Don't worry, you don't need to know the details! But for the curious, &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;base64data&amp;lt;/span&amp;gt; is your actual image data, and &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;mediaType&amp;lt;/span&amp;gt; specifies the type of image it is, whether SVG or PNG. You can read more about the B class and its properties [https://run.network/docs/#api-reference-extras-b here].&lt;br /&gt;
&lt;br /&gt;
 '''Advanced programmers:''' The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;B&amp;lt;/span&amp;gt; class is what's known as a ''berry class''. Berries are an advanced feature of RUN. They let you load data from third-party protocols into JavaScript objects that may be used in jigs. For more about berries, read up about them in the docs ➞ [https://run.network/docs/#advanced-usage-berries here].&lt;br /&gt;
&lt;br /&gt;
= Giving credit to your artist =&lt;br /&gt;
Images you find online have what's called a ''license''. The license is a document chosen by the author that describes in legal terms how the image may be used. It's important to always follow its rules when you use media from someone else.&lt;br /&gt;
&lt;br /&gt;
There are many different licenses out there. For jig icons, the key requirement that all licenses must allow is ''commercial'' use. This allows any app in Bitcoin to show your image.&lt;br /&gt;
&lt;br /&gt;
Most images you download from Flaticon use the Flaticon License, which allows for commercial use as long as you give credit to the author. Here is its summary:&lt;br /&gt;
&lt;br /&gt;
[[File:12 license-summary.png|500px|center|thumb]]&lt;br /&gt;
 '''Note:''' Even if the license doesn't require it, you should still give attribution to the artist. This is how they make a living!&lt;br /&gt;
How do you give credit using RUN? You can simply call a different method on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;B&amp;lt;/span&amp;gt; class:&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt; loadWithMetadata(txid, metadata)&amp;lt;/span&amp;gt;. The second parameter of this method, &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt;, is an object that stores the attribution information you want to attach to the image. The four properties you almost always want to set on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt; are:&lt;br /&gt;
*&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;title&amp;lt;/span&amp;gt; - Name of the image&lt;br /&gt;
*&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;license&amp;lt;/span&amp;gt; - Name of the license and an optional link&lt;br /&gt;
*&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;author&amp;lt;/span&amp;gt; - Individual or business that created the asset&lt;br /&gt;
*&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;source&amp;lt;/span&amp;gt; - URL to the website or other location where you found the asset&lt;br /&gt;
For Flaticon, you can find all of this information on the icon's webpage:&lt;br /&gt;
&lt;br /&gt;
[[File:13 attribution-info.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Let's now load the image with the artist metadata. Paste this code into your browser's Web Console, then press '''Enter''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const attribution = {&lt;br /&gt;
    title: 'Dragon free icon',&lt;br /&gt;
    license: 'Flaticon License',&lt;br /&gt;
    author: 'Freepik',&lt;br /&gt;
    source: 'https://www.flaticon.com/free-icon/dragon_477192'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
const imageWithMetadata = await Run.extra.B.loadWithMetadata(txid, attribution)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Always take time to make sure you have permissions and add attribution. The files you upload onto the blockchain are there for everyone to see, forever. 😳&lt;br /&gt;
&lt;br /&gt;
= Upgrading a class to use the image =&lt;br /&gt;
&lt;br /&gt;
Finally, you are ready to attach the image, now with attribution metadata, to your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;DragonEgg&amp;lt;/span&amp;gt; class. To add the image as an icon, all you have to do is set the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;image&amp;lt;/span&amp;gt; property on the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;metadata&amp;lt;/span&amp;gt; object of your class. It's very similar to setting an emoji.&lt;br /&gt;
&lt;br /&gt;
In this case, you've already deployed your class on-chain, so can you change metadata that was already set? Yes! You can upgrade your class. This is a feature of RUN that allows you to replace the behavior and properties of a class with completely new behavior and properties. Jig instances that use your class will get the upgraded code when they sync.&lt;br /&gt;
&lt;br /&gt;
To do an upgrade, the first step is to declare the new class. Paste this code into your Web Console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const DragonEggWithImage = class DragonEgg extends Jig { }&lt;br /&gt;
&lt;br /&gt;
DragonEggWithImage.metadata = {&lt;br /&gt;
    emoji: '🥚',&lt;br /&gt;
    image: imageWithMetadata&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
When you upgrade your own classes, you need to recreate the entire class. Also, see how you can set both an emoji and an image on metadata. The image will be the preferred icon if it exists, and the emoji will be used in places where the image cannot, like bodies of text.&lt;br /&gt;
&lt;br /&gt;
And now for the upgrade. Paste the following code and then press '''Enter''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const OldClass = await run.load(DragonEgg.location)&lt;br /&gt;
&lt;br /&gt;
OldClass.upgrade(DragonEggWithImage)&lt;br /&gt;
&lt;br /&gt;
await run.sync()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You just upgraded your class. It's time to see the new image on the RUN Explorer.&lt;br /&gt;
&lt;br /&gt;
= Seeing your image =&lt;br /&gt;
&lt;br /&gt;
Grab the location of the egg one more time:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
console.log(egg.location)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now, copy that location. '''Right-click''' and open the [https://run.network/explorer RUN Explorer] in a new window. Then, paste the location into the search bar and press '''Enter'''.&lt;br /&gt;
&lt;br /&gt;
Drumroll, please…&lt;br /&gt;
&lt;br /&gt;
[[File:14 explorer-old.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Uh oh. That's still showing the emoji. Here's what happened. Your jig is still referencing the old class before the upgrade. Every instance has a link to its class at a particular state. To receive the upgrade, you need to sync it to use the new class. In code, you would sync it using &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;await egg.sync()&amp;lt;/span&amp;gt;, but in the RUN Explorer, you can click the '''Sync''' button.[[File:15 sync-button.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
The sync button updates the jig and all of its references. Think of it like updating an app on your phone. New jigs you create from the class won't need to sync, and old jigs will be upgraded when they are synced or when they interact with already-upgraded jigs. '''Click''' the sync button now.[[File:16 explorer-new.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
Much better. Congratulations! 🎉&lt;br /&gt;
&lt;br /&gt;
= Where to go from here =&lt;br /&gt;
&lt;br /&gt;
You learned a lot in this tutorial. You learned how to set both emojis and images as metadata on jig classes. You learned how to upgrade existing code to add icons. You learned how to use Flaticon, EmojiFinder, and BitcoinFiles to discover and then upload icons to the blockchain.&lt;br /&gt;
&lt;br /&gt;
You're hopefully now seeing that RUN is part of a bigger ecosystem of interactive data. Data on the blockchain, like the images you uploaded, can be used in many different apps for many different purposes. Your jigs may be shown in wallets, exchanges, and even other applications that build on top of yours. Transactions on Bitcoin are the packages that store all this data, and JavaScript is the language that connects it all together. It's a powerful and exciting frontier.&lt;br /&gt;
&lt;br /&gt;
Here are some advanced challenges you can try:&lt;br /&gt;
*Add SVG images and emojis to your own jigs&lt;br /&gt;
*Create tradable sticker packs like [https://emojibles.store/what-are-emojibles/ Emojibles]&lt;br /&gt;
*Create your own berry class for loading B protocol data&lt;br /&gt;
*Upload other kinds of content besides images using BitcoinFiles and B&lt;br /&gt;
*Learn about [https://run.network/docs/#advanced-usage-standard-metadata other metadata] you can set on jig classes&lt;br /&gt;
*Study up on image licensing and attribution&lt;br /&gt;
When you’re ready to move on, dive into the next lesson, [[Tutorial 6 - Taking security seriously with sandboxing for jigs on Bitcoin]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Tutorial_4_-_Running_a_Pay_Server_on_Bitcoin_Testnet&amp;diff=494</id>
		<title>Tutorial 4 - Running a Pay Server on Bitcoin Testnet</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Tutorial_4_-_Running_a_Pay_Server_on_Bitcoin_Testnet&amp;diff=494"/>
		<updated>2023-09-26T16:58:13Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens and jigs is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
In the previous tutorials, you learned how to fund your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt; in [[Tutorial_2_-_Running_jigs_on_Bitcoin_Mainnet,_Part_1|Part 1 with WhatsOnChain]] and how to import your private key in [[Tutorial_3_-_Running_jigs_on_Bitcoin_Mainnet,_Part_2|Part 2 with Electrum SV]].&lt;br /&gt;
&lt;br /&gt;
You’re about to learn not only how to use RUN on the Bitcoin Testnet, but also how to use a Pay Server to fund the transactions instead of having to use your own &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The Bitcoin Testnet acts just like the Mainnet: there are miners with servers around the world that mine bitcoin by packaging up transactions into blocks. The only difference is that the Testnet bitcoins aren’t worth anything on the exchanges, so the mining difficulty is much lower. Developers use the Testnet to make sure that their applications will work correctly before putting any real bitcoin at stake.&lt;br /&gt;
&lt;br /&gt;
Companies will use Pay Servers to comp their customer’s transactions. Think of it like when you go to a store and they don’t charge you anything to use your credit card. The store owner is paying something like 2.5% as a fee to the credit card processor. The store owner eats the cost for your convenience so that you will hopefully shop there more. You could imagine a similar business model working for Bitcoin transactions, especially since the fees are much, much lower—only a fraction of a USD cent.&lt;br /&gt;
&lt;br /&gt;
Imagine a video game company that develops a game that records moves onto the blockchain. The game company would pay for the transactions for all their players because they could make money in other ways like selling game items: potions, armor, weapons.&lt;br /&gt;
&lt;br /&gt;
When you put these two concepts together, the Testnet and the Pay Server, then you get a powerful environment for developing real-world applications that utilize data on the blockchain.&lt;br /&gt;
&lt;br /&gt;
= Getting Started =&lt;br /&gt;
&lt;br /&gt;
This tutorial builds on the knowledge that you’ve learned from the other three tutorials. Think of this one as intermediate level. We’re going to go quite fast and to try and save space, provide fewer beginner-friendly explanations about the tooling in this one. If you find yourself struggling, try going back to make sure you grok everything in the[[Tutorial 1_-_Intro_to_jigs_that_run_on_Bitcoin:_Mocknet_and_Web_Console| Intro to Jigs tutorial]]. But also, don’t be shy about sending us feedback. We love to hear from you and we’re always improving.&lt;br /&gt;
&lt;br /&gt;
To set up your development environment, open the [https://run.network/ RUN Homepage] in the '''Firefox''' browser. You'll be coding right on this homepage.&lt;br /&gt;
&lt;br /&gt;
By itself, RUN will upload, read, and call code, then sign and send transactions. But RUN also includes many optional plug-ins you might find useful. The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;PayServer&amp;lt;/span&amp;gt; is one such plug-in, and we’re going to use it in this tutorial. You can already use the BitIndex and WhatsOnChain APIs as alternatives to RUN Connect and you can imagine that as the Bitcoin developer ecosystem expands in the future, other companies will build plug-ins that you can hook into RUN too. You’ll be able to select the most competitive offering that fits your needs. You’ll also be able to write your own Pay Server if you have the know-how to run a server in-house.&lt;br /&gt;
&lt;br /&gt;
Since RUN is being developed as an open-source project, all Bitcoin companies are free to contribute to its development and make use of its ability to interact with jigs.&lt;br /&gt;
&lt;br /&gt;
= Connecting to Testnet and the Pay Server =&lt;br /&gt;
&lt;br /&gt;
== Understanding server APIs ==&lt;br /&gt;
&lt;br /&gt;
A Pay Server is a remote application programming interface, colloquially known as an API. You send the server requests and it responds with answers. Server APIs will usually require that you use an API Key. The API Key is like your user account with the server so that it knows who you are. If you misbehave by, for example, sending too many requests per second, then your access will get revoked.&lt;br /&gt;
&lt;br /&gt;
Normally you would get your API Key from your User Profile after you had logged in on a website. Since this tutorial is only using the Testnet, the bitcoins are free, so we’ve included a handy widget in the tutorial to generate an API Key.&lt;br /&gt;
&lt;br /&gt;
Click Generate to create an API Key for you to use to connect to the server:&lt;br /&gt;
&lt;br /&gt;
[https://run.network/lessons/testnet-pay-server-explorer/#:~:text=Convenient%20widget%20%F0%9F%98%8E-,Request%20an%20API%20Key,-Generate Click here to open the widget]&lt;br /&gt;
&lt;br /&gt;
== Request an API Key ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Pro tip: To select a whole string, double-click it. That makes it easy to copy and paste elsewhere.&lt;br /&gt;
&lt;br /&gt;
Now that you’ve got your API Key, you’re ready to connect the server.&lt;br /&gt;
&lt;br /&gt;
From the getting_started.html tab, open the Developer Tools Console by pressing Control-Shift-K on Windows or Command-Option-K on macOS.&lt;br /&gt;
&lt;br /&gt;
Type this code into the Console, replacing the fill-in-the-blank underscore characters with your actual API Key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const apiKey = '_YOUR_API_KEY_HERE_'&lt;br /&gt;
&lt;br /&gt;
const run = new Run({ network: 'test', &lt;br /&gt;
                      purse: new Run.plugins.PayServer(apiKey) })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
There are a couple of new concepts in that code. You’re connecting to Testnet by passing &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;'test'&amp;lt;/span&amp;gt; as the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;network &amp;lt;/span&amp;gt;parameter. Also, instead of specifying a private key for the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt;, you pass a &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;PayServer&amp;lt;/span&amp;gt; instance. The Pay Server is replacing the functionality of the standard &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt;. The Pay Server will return signed transactions and provide funds for the mining fees.&lt;br /&gt;
&lt;br /&gt;
= Coding up your digital pets =&lt;br /&gt;
&lt;br /&gt;
In the previous tutorials, you stayed close to the basics in your JavaScript code, but this time, your code will become more advanced.&lt;br /&gt;
&lt;br /&gt;
Type this code into the Console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dragon extends Jig {&lt;br /&gt;
  // 1&lt;br /&gt;
  init(name) {&lt;br /&gt;
    this.name = name&lt;br /&gt;
    this.flights = []&lt;br /&gt;
  }&lt;br /&gt;
  // 2&lt;br /&gt;
  fly() {&lt;br /&gt;
    this.flights.push(this.flights.length + 1)&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Dragon.icon = { emoji: '🐉' }&lt;br /&gt;
// 3&lt;br /&gt;
const stevie = new Dragon('Stevie')&lt;br /&gt;
const wonder = new Dragon('Wonder')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Here’s what you’re doing with that code:&lt;br /&gt;
&lt;br /&gt;
You use &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;init()&amp;lt;/span&amp;gt; to declare all your properties and give them default values. In this case, you provide a convenience initializer that accepts &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;name&amp;lt;/span&amp;gt; as a parameter.&lt;br /&gt;
The&amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt; fly()&amp;lt;/span&amp;gt; method updates the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;flights&amp;lt;/span&amp;gt; property to keep track of how many times you take your dragon out for a ride. After all, every once in a while, it is important to give your dragon some exercise and let him or her breathe some fresh outdoor air.&lt;br /&gt;
You bring two dragons to life. With two dragons in your service, you’ll be able to assert your authority like Dany over the Seven Kingdoms in Game of Thrones! 🤩&lt;br /&gt;
&lt;br /&gt;
= Using the Testnet Explorer =&lt;br /&gt;
&lt;br /&gt;
The first thing you’ll want to do is check and make sure the dragons are live on the Testnet. Type this code into the Console to get your dragons’ status:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
console.log('Stevie: ', stevie.location)&lt;br /&gt;
console.log('Wonder: ', wonder.location)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You’ll see the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;locations&amp;lt;/span&amp;gt; for both of your dragons:[[File:1 stevie-location.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can explore locations with the RUN Explorer.&lt;br /&gt;
&lt;br /&gt;
Select '''Stevie’s''' &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt; as shown in the screenshot above, and copy it.&lt;br /&gt;
&lt;br /&gt;
From the '''getting_started.htm'''l page, click the '''Explorer''' link in the top right corner:[[File:2 explorer.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click the '''network toggle''' to select '''Testnet''':[[File:3 search-testnet.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Mainnet and Testnet are separate networks each with their own blocks and transaction IDs. Since your dragon transactions are on Testnet, you’ll need to make sure you’re looking in the right place for them.&lt;br /&gt;
&lt;br /&gt;
Paste '''Stevie’s''' &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt; into the '''Search''' box. If everything went according to the plan, then you’ll be able to see the properties for your instance of &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;Dragon&amp;lt;/span&amp;gt;. Your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt; and &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; will be different than the ones in the screenshot because you’ve generated your own transactions.&lt;br /&gt;
&lt;br /&gt;
Try searching for '''Wonder’s''' &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt; as well.&lt;br /&gt;
&lt;br /&gt;
Now that you’ve confirmed your dragons are alive on Testnet, you can interact with them.&lt;br /&gt;
&lt;br /&gt;
Type this code into the Console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
wonder.fly()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
You don’t want to show favoritism to just one dragon, so you need to make sure you take Stevie outside as well. Type this code into the Console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
stevie.fly()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Now that you’ve got both dragons out on the town, you can travel around, put the villagers on high alert, and scare some of your enemies. 🙀&lt;br /&gt;
&lt;br /&gt;
= Managing the owner private key =&lt;br /&gt;
&lt;br /&gt;
To ensure Wonder and Stevie continue to listen to you, you’ll need to safeguard your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; private key. As long as you possess the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; private key, you can call methods on jigs to give them instructions. But without the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; private key, you would merely become an observer, unable to issue new instructions.&lt;br /&gt;
&lt;br /&gt;
Type this code in the Console to get the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; private key:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.owner.privkey.toString()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Save the '''private key''' string returned by the Console [[Tutorial 7_(extra)_-_Private_key_management|safely encrypted]] in a '''password manager''' app on your computer. Give it a good name: '''run Pay Server on Testnet: owner.''' If anyone else gets your private key, they’ll be able to give instructions to your dragons. You certainly don't want that to happen, so take care with how you manage your keys.&lt;br /&gt;
&lt;br /&gt;
Next, copy your '''API Key''' from the Generator above and save it using the same method as you did for the private key. Give it a good name as well: '''run Tutorials: Testnet API Key.'''&lt;br /&gt;
&lt;br /&gt;
By having both keys, you’ll be able to take a break, close your browser, even restart your computer, and still continue working on your code another day.&lt;br /&gt;
&lt;br /&gt;
= Resuming your Testnet session =&lt;br /&gt;
&lt;br /&gt;
When you have both keys written elsewhere, hover over the Firefox browser tab and click × to close the tab.&lt;br /&gt;
&lt;br /&gt;
Then open '''getting_started.html''' in a new tab.&lt;br /&gt;
&lt;br /&gt;
Open the '''Console''' by pressing '''Control-Shift-K''' on Windows or '''Command-Option-K''' on macOS.&lt;br /&gt;
&lt;br /&gt;
Type the following code into the '''Console''', replacing the fill-in-the-blank underscore characters with your actual '''API Key''' and also separately, your actual &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; '''private key''':&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
// 1&lt;br /&gt;
const apiKey = '_your_API_Key_here_'&lt;br /&gt;
// 2&lt;br /&gt;
const run = new Run({ network: 'test', &lt;br /&gt;
                      purse: new Run.plugins.PayServer(apiKey), &lt;br /&gt;
                      owner: '_your_owner_private_key_here_' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 '''Pro tip:''' A string with underscore spacers between the words acts like a single word, so you can double-click it to select the whole string. That makes it easy to replace placeholders when copying and pasting.&lt;br /&gt;
Here’s what’s happening in that code:&lt;br /&gt;
#As you might have surmised, &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;apiKey&amp;lt;/span&amp;gt; is not something that comes from RUN. Instead, it represents your user account for the RUN Pay Server. When you have a valid API Key, the RUN Pay Server will cover the cost of the transaction fees for your actions in RUN. That way, you don’t need to fund your own &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt;. The API Key is like your user account from the company. As you become a more experienced developer, API Keys will be a familiar tool you’ll use to get things done. Many companies offer different APIs for your convenience. A good example is the company, Twilio, which has APIs to send phone text SMS messages and start a video call. When you find ways to integrate APIs into your apps, you’ll save yourself development time because the code is written for you so you don’t have to fuss with device compatibility and edge cases.&lt;br /&gt;
#When you created the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;Run&amp;lt;/span&amp;gt; instance at the beginning of the tutorial, you instructed RUN to assign you a random owner since you did not pass anything for the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; property. But now that you’re restoring your session, this time you passed in your saved &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; private key. RUN will use that account instead of a random one.&lt;br /&gt;
To check if you still own your dragons, type this code into the Console:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
await run.inventory.sync()&lt;br /&gt;
&lt;br /&gt;
run.inventory.jigs&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;jigs&amp;lt;/span&amp;gt; array get downloaded when you initialize RUN with an &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt; and call &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;run.inventory.sync()&amp;lt;/span&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Jigs will be added and removed from the array as you interact in your RUN session. If you know that updates have happened on the network over time, off of your local client, then you can call &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;await run.inventory.sync()&amp;lt;/span&amp;gt; to grab all the latest updates from the network.&lt;br /&gt;
&lt;br /&gt;
Wherever you see &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;await&amp;lt;/span&amp;gt;, that is a JavaScript Promise. It will asynchronously, meaning, in the background, fetch all the jigs from the network that are owned by the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;owner&amp;lt;/span&amp;gt;. You use the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;await&amp;lt;/span&amp;gt; keyword to allow the fetch to finish before checking out the result.&lt;br /&gt;
&lt;br /&gt;
If everything went according to plan, you will get back an array with your two dragons.&lt;br /&gt;
&lt;br /&gt;
Click the disclosure triangle for '''Array [ Proxy, Proxy ]''' to reveal the contents of the array and then click two more disclosure triangles to reveal the contents of '''0: Proxy''' and then ''': Object:'''[[File:4 expand-jig.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
From here you can see the properties that Wonder the dragon has. Notice that the value of &amp;lt;span style=&amp;quot;color: #e03e2d;&amp;quot;&amp;gt;origin&amp;lt;/span&amp;gt; is different than the value of &amp;lt;span style=&amp;quot;color: #e03e2d;&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt; because you updated the instance by instructing Wonder to fly().&lt;br /&gt;
&lt;br /&gt;
Select the '''Transaction ID''' portion of the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;location&amp;lt;/span&amp;gt;, the bit before the underscore, as shown in the screenshot above.&lt;br /&gt;
&lt;br /&gt;
Copy the '''Transaction ID'''.&lt;br /&gt;
&lt;br /&gt;
Open a new browser tab and navigate to [http://whatsonchain.com/ WhatsOnChain.com]:[[File:5 whatsonchain-testnet.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once the page loads:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
#From the header, navigate to '''Network ▸ Testnet.'''&lt;br /&gt;
#In the Search box, paste the '''Transaction ID''' and press '''Return''' on your keyboard.&lt;br /&gt;
You’ll see the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;op_return&amp;lt;/span&amp;gt; text in the output index, &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;_o0&amp;lt;/span&amp;gt;:[[File:6 whatsonchain-transaction.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;span style=&amp;quot;color: #e03e2d;&amp;quot;&amp;gt;op_return&amp;lt;/span&amp;gt; text is encrypted during the Alpha phase, but it basically just contains the method call, &amp;lt;span style=&amp;quot;color: #e03e2d;&amp;quot;&amp;gt;fly()&amp;lt;/span&amp;gt;. On the left side of the page, the inputs reference the parent transactions.&lt;br /&gt;
&lt;br /&gt;
Coming from the previous Mainnet tutorial, you already knew how to step through forwards and backwards using transaction inputs and outputs. But now, in this tutorial, you’ve seen how to use WhatsOnChain with Testnet transactions too.&lt;br /&gt;
&lt;br /&gt;
Since you’ve successfully restored your RUN Testnet session, you’re the rightful owner of the dragons and you’re ready to use the Pay Server to cover the cost of the next actions you want to take with the dragons.&lt;br /&gt;
&lt;br /&gt;
= Where to go from here =&lt;br /&gt;
&lt;br /&gt;
You learned how to configure RUN to use Testnet as an alternative to both Mainnet and the local machine Mockchain. While transactions on Testnet do require paying mining fees, you can get Testnet bitcoins for free since they don’t have real-world value on exchanges. Visit a [https://faucet.bitcoincloud.net/ faucet like bitcoincloud.net to acquire Testnet bitcoins]. You’ll be able to send those Testnet bitcoins to your &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt; and operate RUN on Testnet without a Pay Server. As a challenge, see if you can complete this tutorial without using a Pay Server but still using Testnet. To get you started, make sure you know how to use the &amp;lt;span style=&amp;quot;color: rgb(224, 62, 45);&amp;quot;&amp;gt;purse&amp;lt;/span&amp;gt; with bitcoin loaded into it, check out: [[Tutorial 2 - Running jigs on Bitcoin Mainnet, Part 1]]. You’ll just need to use Testnet bitcoin instead of Mainnet bitcoin.&lt;br /&gt;
&lt;br /&gt;
In this tutorial, you got to see how companies could pay or their customers transactions with a Pay Server. On Testnet, using a Pay Server is not that big of a deal since the Testnet bitcoins don't have an exchange price. But you can imagine a project like this would be a practice session before deploying to Mainnet. On Mainnet, using a Pay Server could save your customers the mining fee, a fraction of a cent, for every action they take. You could build a game that writes data to the Bitcoin blockchain without bundling a bitcoin wallet into the app. The customer wouldn’t even have to necessarily know they are using Bitcoin. 🤩&lt;br /&gt;
&lt;br /&gt;
You’re beginning to see that jigs can be used by many different kinds of businesses, like video game companies and even shipping logistics companies. By using Bitcoin as a neutral datastore, separate companies can collaborate with a single source of truth. With a Pay Server, companies could insert RUN into their existing infrastructure and not require every operator to have a bitcoin wallet. A Pay Server transforms RUN into merely another API like how a shipping company updates your package tracking number each time it reaches a new stage in the shipping process.&lt;br /&gt;
&lt;br /&gt;
When you’re ready to move on, jump into the next lesson, [[Tutorial 5 - Setting icons for your jigs: emojis and SVG images]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Tutorial_3_-_Running_jigs_on_Bitcoin_Mainnet,_Part_2&amp;diff=493</id>
		<title>Tutorial 3 - Running jigs on Bitcoin Mainnet, Part 2</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Tutorial_3_-_Running_jigs_on_Bitcoin_Mainnet,_Part_2&amp;diff=493"/>
		<updated>2023-09-26T16:55:05Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens and jigs is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
In [[Tutorial 2 - Running jigs on Bitcoin Mainnet, Part 1|Part 1]], you learned how to upload code to the Bitcoin network and inspect the transactions on a block explorer. In Part 2, you’ll learn how to backup your funds and reload your saved jigs.&lt;br /&gt;
&lt;br /&gt;
= Getting started =&lt;br /&gt;
&lt;br /&gt;
This tutorial continues where Part 1 finished, so you’ll need to have your Firefox browser tab with the same Console session.&lt;br /&gt;
&lt;br /&gt;
In RUN, the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; are separate bitcoin accounts:[[File:1 purse-owner.jpg|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You store money with the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; and you store jigs with the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt;. If you gave them personified roles, the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; would be a banker persona and the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; would be a dog walker persona. The &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; as a dog walker can give instructions to the jigs, but he doesn't have any money. The &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; as a banker character provides the funds.&lt;br /&gt;
&lt;br /&gt;
Keeping the two separate helps performance as well as security.&lt;br /&gt;
&lt;br /&gt;
Each one has a separate public address you can see on the block explorer and its own separate private key that allows you to make new transactions.&lt;br /&gt;
&lt;br /&gt;
= Searching for the jig owner address =&lt;br /&gt;
&lt;br /&gt;
At the end of Part 1 tutorial, you searched for a &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; on the RUN Explorer:[[File:2 search-dragon.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The address in the '''owned by''' section is the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Your transaction IDs and addresses will look different than mine because they are unique to you. Don’t worry, you will still complete the tutorial--just use the screenshots as your guide.&lt;br /&gt;
&lt;br /&gt;
Click on the '''address''' in the ''owned'' by section (highlighted in green above):[[File:3 search-owner.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The RUN Explorer shows that this address owns one jig, a &amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;, that was recently updated.&lt;br /&gt;
&lt;br /&gt;
You can verify if the address you see is really your &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; address in the Console.&lt;br /&gt;
&lt;br /&gt;
Type the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.owner.address&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The Console will return the address:[[File:4 print-owner-address.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Yes! Both addresses match as expected. 😅&lt;br /&gt;
&lt;br /&gt;
Now copy the '''address''' and search for it in the other tab with the '''WhatsOnChain''' block explorer:[[File:5 whatsonchain2.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The address was involved in two transactions. The first transaction is the one that uploaded the class definition and the second transaction is the one that updated the instance by calling the &amp;lt;code&amp;gt;setName(name)&amp;lt;/code&amp;gt; method.&lt;br /&gt;
&lt;br /&gt;
You have already seen both addresses in action:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*'''1HM…56R''' is the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; address that controls the jigs. Each output only has dust, 546 satoshis, so that it can perform the next update on the jigs it owns.&lt;br /&gt;
*'''1PK…qst''' is the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; address that controls the money. It holds 700,000 satoshis to help you finance all the future updates you will perform in RUN.&lt;br /&gt;
&lt;br /&gt;
= Getting the owner private key =&lt;br /&gt;
&lt;br /&gt;
You already retrieved the private key for the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; address like 14e…UZc in the beginning of the Part 1 tutorial. That private key allows you to restore the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; after you end this session.&lt;br /&gt;
&lt;br /&gt;
You will also want to restore your saved jigs. You wouldn’t want to lose access to them when you close the browser.&lt;br /&gt;
&lt;br /&gt;
To get the private key for the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; you use the same pattern as the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt;. Navigate back to the tab with the Console and type the following code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.owner.privkey&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Console will print out your private key:[[File:6 print-owner-privkey.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Treat the private key with care. Don’t share it with anyone and [https://run.network/lessons/private-key-1-password-manager-enpass store it securely encrypted] in a '''password manager'''. If anyone gets access to the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; private key then they control your jigs and can mess with them.&lt;br /&gt;
&lt;br /&gt;
Now that you’ve got the private keys for both the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; and the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt;, you can fully restore your Console session next week when you’re taking another tutorial. 😉&lt;br /&gt;
&lt;br /&gt;
= Restoring the purse and owner with private keys =&lt;br /&gt;
&lt;br /&gt;
Make a new browser tab and open the [https://run.network/ RUN Homepage]. A new tab will have a different Console session than all your previous work. It is a bit like if you closed the browser and wanted to resume working again later.&lt;br /&gt;
&lt;br /&gt;
Open the '''Console''' in the new tab by pressing '''Control-Shift-K''' on Windows or '''Command-Option-K''' on macOS.&lt;br /&gt;
&lt;br /&gt;
Open your '''password manager''', and locate your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; private key and your &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; private key. Then type the following code into the '''Console''', replacing the fill-in-the-blank underscore characters with the actual private keys:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({purse: &amp;quot;_privkey_&amp;quot;, owner: &amp;quot;_privkey_&amp;quot;}) &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That code creates a new instance of &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt;, but instead of giving you a random &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; it restores your previous ones.&lt;br /&gt;
&lt;br /&gt;
Check if they restored correctly. First type this code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.owner.address&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Then type this code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.purse.address&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The Console will print out both addresses:[[File:7 print-owner-and-purse-addresses.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
It worked! You will have different addresses than me, but if you remember back to the beginning of this tutorial, those addresses were the ones you saw in the block explorer screenshot.&lt;br /&gt;
&lt;br /&gt;
= Importing purse private key in Electrum SV =&lt;br /&gt;
&lt;br /&gt;
Your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; is just like any other bitcoin wallet, so you can import it into other wallet apps.&lt;br /&gt;
&lt;br /&gt;
 '''Exercise caution''': Don’t import your &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; address into money wallet apps. Most wallet apps don’t know how to read jigs… yet. 😉 If you import your &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt; into a wallet app meant for money, the wallet app will try to spend the bitcoin output associated with your jig. Spending the output would destroy your jig. So long story short, only import your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; into wallet apps, not the &amp;lt;code&amp;gt;owner&amp;lt;/code&amp;gt;. One day soon, wallet apps will know how to differentiate between a jig wallet and a bitcoin money wallet.&lt;br /&gt;
First, download Electrum SV. Select the correct version for your operating system:[[File:8 electrum-sv-download.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Install it as you would any other app.&lt;br /&gt;
&lt;br /&gt;
 '''Note for Mac users''': On the Mac, after the install, you’ll need to open the '''Applications''' folder in Finder app. Then '''Control-Click''' the '''Electrum SV''' app and click '''Open''' in the context menu. A Confirm dialog will appear. Click '''Open'''. This workflow stems from Apple trying to keep you safe by making it a little harder to open untrusted apps.&lt;br /&gt;
Once you get Electrum SV open, it will display any previous wallets that you’ve had before:[[File:9 electrum-sv-wallet-setup.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
If you see this dialog, you’ll need to unlock the wallet by typing the '''password''' you set up. Then click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
Now you can access the Menu items:[[File:10 electrum-sv-menu.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
From the Menu, select '''File ▸ New/Restore'''. Give your wallet a descriptive name, '''run_tutorials''':[[File:11 electrum-sv-restore.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
The wizard will ask what you kind of wallet you would like to create. Select '''Import Bitcoin addresses or private keys''', then click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
Navigate to your browser tab with the Console open.&lt;br /&gt;
&lt;br /&gt;
Copy your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; private key from the &amp;lt;code&amp;gt;new Run()&amp;lt;/code&amp;gt; initialization:[[File:12 create-with-privkeys.png|900px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Once you’ve copied the private key, paste it into Electrum SV:[[File:13 electrum-sv-import.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
The wizard will offer you the opportunity to encrypt the wallet with a password. Choose a strong one:[[File:14 electrum-sv-password.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Click '''Next'''.&lt;br /&gt;
&lt;br /&gt;
Electrum SV will show the history:[[File:15 electrum-sv-history.png|650px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
From here you can verify how much money each RUN transaction uses. The first transaction to write the class definition used 1697 satoshis, while the second transaction to update the jig with &amp;lt;code&amp;gt;setName(name)&amp;lt;/code&amp;gt; only used 531 satoshis.&lt;br /&gt;
&lt;br /&gt;
Over time, Bitcoin mining fees will drop as more people use the network. It will be a bit like how IKEA can afford to sell furniture so cheaply. They make money with volume, by selling lots of items at a low margin. RUN will always use the best price it can for each transaction. As mining fees drop over time, the transactions RUN creates will become even cheaper, unlocking more use cases.&lt;br /&gt;
&lt;br /&gt;
When you decide that you’re done using RUN, you can use Electrum SV to send the money away from your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; to another wallet address or to another wallet app like HandCash.&lt;br /&gt;
&lt;br /&gt;
= Where to go from here =&lt;br /&gt;
&lt;br /&gt;
You’ve learned all about how to restore both your jigs and your money.&lt;br /&gt;
&lt;br /&gt;
Now you can work on building complex jigs over many weeks. The only limit is your creativity. Discover all the things you can accomplish by diving into the '''Docs'''.&lt;br /&gt;
&lt;br /&gt;
When you’re ready to move on to more advanced usage of RUN, continue to the next tutorial in the Digital Pet series: [[Tutorial 4 - Running a Pay Server on Bitcoin Testnet]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Tutorial_2_-_Running_jigs_on_Bitcoin_Mainnet,_Part_1&amp;diff=492</id>
		<title>Tutorial 2 - Running jigs on Bitcoin Mainnet, Part 1</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Tutorial_2_-_Running_jigs_on_Bitcoin_Mainnet,_Part_1&amp;diff=492"/>
		<updated>2023-09-26T16:48:39Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens and jigs is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Category:Tutorials]]&lt;br /&gt;
By completing the [[Tutorial 1 - Intro to jigs that run on Bitcoin: Mocknet and Web Console|Tutorial 1 - Intro to jigs that run on Bitcoin: Mocknet and Web Console]], you simulated transactions locally on your computer. In this tutorial, you’ll learn how to send transactions to the real Bitcoin Mainnet.&lt;br /&gt;
&lt;br /&gt;
= Getting started =&lt;br /&gt;
&lt;br /&gt;
First, open the[[https://run.network/|RUN Homepage]]&lt;br /&gt;
&lt;br /&gt;
in the Firefox browser. You'll be coding up your jigs there.&lt;br /&gt;
&lt;br /&gt;
 '''Pro tip:''' We’ve also included run.js on our Docs page, so you can play in the Console while viewing the documentation.&lt;br /&gt;
Now, open the '''Web Console''' in Firefox by pressing '''Control-Shift-K''' on Windows or '''Command-Option-K''' on macOS.&lt;br /&gt;
&lt;br /&gt;
Create a new empty instance of run by typing this code into the command prompt:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Press '''Return''' to submit the command:&lt;br /&gt;
&lt;br /&gt;
If everything went correctly, you’ll see &amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt; as the result. That means there was no error and you’re ready to continue. 🙌&lt;br /&gt;
&lt;br /&gt;
= Understanding custody =&lt;br /&gt;
When you create a new empty instance of &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt;, you are automatically assigned a random private key using the&lt;br /&gt;
&lt;br /&gt;
The private key is constructed locally and is not shared with any server.&lt;br /&gt;
The private key resides locally in your browser and explicitly not on the server. The wallet is non-custodial; no one can spend the money except for you.&lt;br /&gt;
== Noting down your private key ==&lt;br /&gt;
The first thing you’ll want to do is write down your private key since there is no backup.&lt;br /&gt;
&lt;br /&gt;
 '''Exercise caution:''' No one will be able to help you recover your purse if you skip this step and close your browser.&lt;br /&gt;
To get your private key, type the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.purse.privkey&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Press '''Return''' to submit it:&lt;br /&gt;
&lt;br /&gt;
[[File:3 privkey.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Copy the private key into your password manager. If you’re unsure about that, check out a[https://run.network/lessons/private-key-1-password-manager-enpass tutorial about how to manage your keys]&lt;br /&gt;
&lt;br /&gt;
with an app called, Enpass.&lt;br /&gt;
&lt;br /&gt;
 '''Note:''' Don’t store private keys unencrypted on your computer as notes or text files. Also, don’t share your private key with anyone. If someone gets your private key, they can spend your bitcoin.&lt;br /&gt;
 == Finding your purse address ==&lt;br /&gt;
Your purse address is what you give people who want to send you bitcoin. You’re going to use your purse address to fund your &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance so that you will be able to upload code and call methods on jigs.&lt;br /&gt;
&lt;br /&gt;
To figure out what address you need to use, type the following code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
run.purse.address&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Press '''Return''' to submit it. Console will display your bitcoin address.&lt;br /&gt;
&lt;br /&gt;
== Funding your RUN purse ==&lt;br /&gt;
You can fund this address using any BSV you have on any wallet, or simply ask a friend to send you a dollar of BSV. If you are looking for a wallet with an easy way to top-up using your credit card, we recommend you try HandCash.&lt;br /&gt;
&lt;br /&gt;
To fund your purse, copy the purse address (which you can get with &amp;lt;code&amp;gt;run.purse.address&amp;lt;/code&amp;gt;) and send some BSV using the wallet of your choice. We recommend just sending $1 so that you can pay for the mining fees when sending your transactions. Once you’ve sent a bit of money to the &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt;, you’re ready to upload the code for a jig. You can have at least 100 interactions with jigs for $1 USD (actually much more).&lt;br /&gt;
&lt;br /&gt;
In the future, RUN will be integrated into wallets so that users can easily send jigs to each other. Also, companies could use a Pay Server to fund transaction fees, so users won’t need to use their own money at all! 🤩&lt;br /&gt;
&lt;br /&gt;
== Reusing your private key ==&lt;br /&gt;
&lt;br /&gt;
Now the next time you want to start using run, you can reuse your funded private key easily like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({purse: &amp;quot;&amp;lt;my-private-key&amp;gt;&amp;quot;})&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
this will automatically reuse the previous purse, and you can check your purse's balance easily as well (in satoshis):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const satoshis = await run.purse.balance()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
= Understanding the commodity ledger =&lt;br /&gt;
The code for a jig is stored in a Bitcoin transaction. It is optimized and stored as text in the memo field, known as the &amp;lt;code&amp;gt;op_return&amp;lt;/code&amp;gt;. Miners charge transaction fees based on the number of bytes. Right now, the standard is one satoshi for two bytes. ''1sat'' is the smallest unit of bitcoin, or 0.00000001 BSV.&lt;br /&gt;
&lt;br /&gt;
The longer your code is, the more you’ll have to pay. But, don’t worry, even substantially long jig code might cost only one US cent (1¢):&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[File:4 ledger.jpg|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Bitcoin is a commodity ledger. That means anyone can pay for space to record a transaction. A transaction could send bitcoin as money, but it could also represent other things including posting data or changing the ownership of a non-bitcoin asset like a digital pet or a land title.&lt;br /&gt;
&lt;br /&gt;
It is important for the space in the commodity ledger to be valuable to prevent spam. However, everything that is worth recording for a fraction of a cent can be recorded and backed by the full strength of the network. The ledger is a neutral territory where all people, companies, and governments can collaborate together.&lt;br /&gt;
&lt;br /&gt;
Ownership of jigs like creating, updating, or sending are all the kind of transactions that are important enough to pay the mining fee.&lt;br /&gt;
&lt;br /&gt;
= Using a block explorer =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Open a '''new browser tab''' to[https://whatsonchain.com/ WhatsOnChain]&lt;br /&gt;
&lt;br /&gt;
. To check the amount of bitcoin in your purse address, search for your '''address''':&lt;br /&gt;
&lt;br /&gt;
[[File:5 whatsonchain.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Here’s what’s happening in that screenshot:&lt;br /&gt;
#Your address will be different than the one in the screenshot because each person has a unique purse.&lt;br /&gt;
#Look at the transactions to verify that you’ve got some money in your purse. If you have a transaction for something like 0.005 BSV, then you’re ready to post transactions.&lt;br /&gt;
#While the transaction has the status of Unconfirmed, the balance in the address will still show “0”. But don’t worry, you can spend unconfirmed money using RUN.&lt;br /&gt;
&lt;br /&gt;
= Writing code to the blockchain =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Navigate to the first tab with the RUN page that has the open Console. Create a new jig by typing the following code:&lt;br /&gt;
&lt;br /&gt;
 '''Pro tip:''' You can create a new line in command prompt without executing code by pressing '''Shift-Return'''. Or for speed, you can '''copy and paste '''the following code in its entirety.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dragon extends Jig {&lt;br /&gt;
  setName(name) {&lt;br /&gt;
    this.name = name&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
Dragon.metadata = { emoji: '🐉' }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Press '''Return''' to execute the code.&lt;br /&gt;
&lt;br /&gt;
You defined a &amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt; jig with a method to set the animal’s name and an icon. The code is called the class definition or the type of your jig.&lt;br /&gt;
&lt;br /&gt;
 '''Advanced programmers:''' We keep a best practice to support JavaScript 2015 (ES6) for maximum compatibility with Node.js. In the code above, you set the &amp;lt;code&amp;gt;emoji&amp;lt;/code&amp;gt; metadata outside of the class because that's how static properties work in ES6.&lt;br /&gt;
The definition of the class is like the schematic or blueprint for the jig. Now that you’ve got the blueprint, you can give birth to a real instance.&lt;br /&gt;
&lt;br /&gt;
Create an instance of the class by typing this code:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const dragon = new Dragon()&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now your dragon is living and breathing:&lt;br /&gt;
&lt;br /&gt;
[[File:6 dragon.gif|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
By convention, the instance uses a lowercase first letter like &amp;lt;code&amp;gt;dragon&amp;lt;/code&amp;gt;, and the type uses an uppercase first letter like &amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Check the origin of the type:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
Dragon.origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Then check the origin of the instance:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.origin&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt; is composed of two pieces, the transaction ID (before the underscore) and the output index (after the underscore).&lt;br /&gt;
&lt;br /&gt;
Both the type and the instance have the same transaction ID, but a different output index. You can see the difference on a block explorer. Copy the transaction ID—the part before the underscore:&lt;br /&gt;
&lt;br /&gt;
[[File:7 dragon-origin.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Navigate to the '''WhatsOnChain tab''' and search for the transaction ID:&lt;br /&gt;
&lt;br /&gt;
[[File:8 whatsonchain2.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
The output indexes start at zero, so they are:&amp;lt;code&amp;gt; o0, o1, o2, o3&amp;lt;/code&amp;gt;, etc. In the code you’ve uploaded here, the definition of the &amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt; type resides at &amp;lt;code&amp;gt;o1&amp;lt;/code&amp;gt; and the instance of &amp;lt;code&amp;gt;dragon&amp;lt;/code&amp;gt; resides at &amp;lt;code&amp;gt;o2&amp;lt;/code&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
The text displayed in the &amp;lt;code&amp;gt;op_return&amp;lt;/code&amp;gt; at &amp;lt;code&amp;gt;o0&amp;lt;/code&amp;gt; contains all the information necessary to interact with the jig.&lt;br /&gt;
&lt;br /&gt;
= Updating a jig =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt; is the very first &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; of a jig. So, the &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt; is the place in the blockchain where you can find the original definition of a jig. Each time you update a jig, its &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; will change.&lt;br /&gt;
&lt;br /&gt;
Navigate to the '''first tab''' with the RUN page that has the open Console. Type this code:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.location&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Verify that the current &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; of the instance is the same as its &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
[[File:9 locations.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Update the jig by setting the name of the dragon with this code in the Console:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.setName('Empress')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Now that your dragon has a name, you can also check how the update affected its location:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.location&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Copy the new transaction ID (the part before the underscore). Search for it with the block explorer:&lt;br /&gt;
&lt;br /&gt;
[[File:10 whatsonchain3.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Notice how the &amp;lt;code&amp;gt;op_return&amp;lt;/code&amp;gt; text at &amp;lt;code&amp;gt;o0&amp;lt;/code&amp;gt; is much shorter this time. That’s because the only information that is stored is the method call, set(name).&lt;br /&gt;
&lt;br /&gt;
You’re looking at the state of a jig. The state consists of the jig definition and all the updates that have been applied to it. If you have the origin, you can step forward in transactions until you can’t go any farther. Using a block explorer, you can step transactions forwards and backwards. In this case, you’re at the current &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; and so you could step backwards in transactions until you get to the origin transaction.&lt;br /&gt;
&lt;br /&gt;
In the screenshot above, locate the '''first input''', &amp;lt;code&amp;gt;i0&amp;lt;/code&amp;gt;, click transaction ID step backwards to the previous transaction.&lt;br /&gt;
&lt;br /&gt;
Now you’re back at the &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt; transaction:&lt;br /&gt;
&lt;br /&gt;
[[File:11 whatsonchain4.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You can tell that you’re back at the &amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt; transaction because the &amp;lt;code&amp;gt;op_return&amp;lt;/code&amp;gt; data is much longer since it contains the full class definition.&lt;br /&gt;
&lt;br /&gt;
= Seeing your jig in the RUN Explorer =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Navigate back to the '''first tab''' with the Console open.&lt;br /&gt;
&lt;br /&gt;
'''Copy''' the entire &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; from your &amp;lt;code&amp;gt;dragon&amp;lt;/code&amp;gt;, including its output index:&lt;br /&gt;
&lt;br /&gt;
[[File:12 dragon-location.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Open the RUN Explorer. You can get there by clicking in the top-right hand part of the [[https://run.network/|RUN homepage].&lt;br /&gt;
&lt;br /&gt;
[[File:13 explorer.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
Paste your &amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt; into the search field:&lt;br /&gt;
&lt;br /&gt;
[[File:14 search-dragon.png|500px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
You see your jig, complete with its latest method call, and emoji metadata. Pretty cool, eh!&lt;br /&gt;
&lt;br /&gt;
= Where to go from here? =&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
You learned how to upload code onto the live Bitcoin network and check out transactions with a block explorer.&lt;br /&gt;
&lt;br /&gt;
Developing with RUN is accessible to everyone, even beginners. If you can write a few lines of JavaScript, you can unleash interactive objects that run on Bitcoin. Jigs can be something always-changing like a digital pet, or they can represent something as unchanging as a still photograph.&lt;br /&gt;
&lt;br /&gt;
As a challenge, try importing the private key from the beginning of tutorial into Electrum SV. That way, you’ll be able to recover your funds and use the money left over from your transactions. Browse the Docs to figure out how you can specify a private key as a parameter when you create a new &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance. If you succeed, you’ll be able to fund your &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; once and then use the same &amp;lt;code&amp;gt;purse&amp;lt;/code&amp;gt; over and over again.&lt;br /&gt;
&lt;br /&gt;
Once you’ve given the challenge some thought, discover the solution in the next tutorial: [[Tutorial 3 - Running jigs on Bitcoin Mainnet, Part 2]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Tutorial_1_-_Intro_to_jigs_that_run_on_Bitcoin:_Mocknet_and_Web_Console&amp;diff=491</id>
		<title>Tutorial 1 - Intro to jigs that run on Bitcoin: Mocknet and Web Console</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Tutorial_1_-_Intro_to_jigs_that_run_on_Bitcoin:_Mocknet_and_Web_Console&amp;diff=491"/>
		<updated>2023-09-26T16:48:24Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens and jigs is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;div&amp;gt;A ''jig'' is an interactive object, run on Bitcoin.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;People interact with jigs by giving them instructions. And, jigs also interact with each other. With jigs, you can build almost anything you can dream up as digital property you can own.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;You might create tokens, contracts, and interfaces. Jigs can power document signing, logistics, even voting in elections. The most fun, of course, will be video game items and lifelike digital pets!&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;RUN is an open-source software development kit (SDK) that uploads code to the Bitcoin blockchain. You’ll use it to create and update jigs.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/div&amp;gt;&lt;br /&gt;
&amp;lt;div&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Getting Started ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;By using object-oriented programming, you can write computer code to describe interactions between objects.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The cool thing about jigs is that many people all around the world already have enough knowledge to build jigs since they’re familiar with common tools like JavaScript. RUN abstracts away a lot of the Bitcoin-specific details, so that you can focus on the code for the smart objects themselves.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Imagine the classic example of a car. It’s got wheels and an engine. It can perform&amp;amp;nbsp;''actions''&amp;amp;nbsp;like driving, and it has&amp;amp;nbsp;''attributes''&amp;amp;nbsp;like red paint color:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Car.png|400px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The car is owned by someone. You can tell it to do things like turn on the windshield wipers, and you can sell it when you want to get a new one.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Jigs have many of the same traits as cars with a key difference: they’re described by code as digital property.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Setting up your browser ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Right-click on this link for RunCraft's homepage ➞ '''[https://runcraft.io/ runcraft.io]'''&amp;lt;strong style=&amp;quot;font-style: italic;&amp;quot;&amp;gt;. &amp;lt;/strong&amp;gt;Then left-click&amp;amp;nbsp;'''Open link in new window''''''.'''&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;strong style=&amp;quot;font-style: italic;&amp;quot;&amp;gt;&amp;lt;/strong&amp;gt;&amp;lt;p&amp;gt;'Click and drag the '''window''' to arrange two browser windows side-by-side so that you can see both '''RunCraft's homepage''' and '''this tutorial''' at the same time:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Side-by-side.jpg|300px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Exploring jigs ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;To discover your first jigs, look near the top right of the page in the navbar and click&amp;amp;nbsp;'''Explorer''':&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Explorer.png|400px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;You’re going to search for a bitcoin address:&amp;amp;nbsp;'''14aJe8iM3HopTwa44Ed5ZQq2UxdDvrEMXo'''. Double-click the&amp;amp;nbsp;'''address&amp;amp;nbsp;'''to select it. Then copy and paste it into the Explorer&amp;amp;nbsp;'''search box'''.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;This bitcoin address holds three jigs, and you can also see when they were last updated:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Search-owner.png|400px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Locate the&amp;amp;nbsp;&amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;&amp;amp;nbsp;jig in the list, and click on the&amp;amp;nbsp;'''last updated time'''. Notice that the search field has been changed to a&amp;amp;nbsp;''transaction ID'': f97…bbb. That is a bitcoin transaction:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Search-dragon.png|400px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The transaction has a method call,&amp;amp;nbsp;&amp;lt;code&amp;gt;init(name, age)&amp;lt;/code&amp;gt;. That means the latest transaction on the jig was to create a new dragon and assign a couple of properties.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Bitcoin transactions have a&amp;amp;nbsp;''memo field''&amp;amp;nbsp;where people can put extra details about a transaction just like the memo line on a physical written check:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Check.gif|400px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The protocol data for RUN is stored there in the memo field, or&amp;amp;nbsp;&amp;lt;code&amp;gt;op_return&amp;lt;/code&amp;gt;, of the transaction.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Each time you want to update a jig, you’ll send a new transaction with the method call.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Jigs are property that individuals own. Only the owner of the jig can update it because only the owner of a Bitcoin output can spend it. Your jigs are just as secure as your bitcoins.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Coding in the Web Console ==&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The quickest way to play around with the RUN library is to use your browser’s Web Console. In this tutorial, you’ll use Firefox as a playground. But you could use a different browser if you need to: Chrome, Opera, Safari, and even Edge. RUN works everywhere. 😎&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;To pop open the&amp;amp;nbsp;'''Web Console''',&amp;amp;nbsp;press&amp;amp;nbsp;'''Control-Shift-K'''&amp;amp;nbsp;on Windows or&amp;amp;nbsp;'''Command-Option-K'''&amp;amp;nbsp;on macOS.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;Note: If you use a different web browser than Firefox, the keyboard shortcut could be different.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You’ll see a command prompt chevron where you can type commands:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Prompt.png|500px|center|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The Console is a lot like the desktop app Terminal, if you’ve ever used that. You type commands into the command prompt and press Return to submit them. The Console is also where any errors in your code will show up.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Create a new instance of&amp;amp;nbsp;&amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt;&amp;amp;nbsp;by typing this code next to the blue chevron:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({ network: 'mock' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The Mock network keeps all the Bitcoin transactions local to your machine. So while everything that happens on the Mock network is a simulation, you’re still using real, signed Bitcoin transactions.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Press&amp;amp;nbsp;'''Return'''&amp;amp;nbsp;to execute the line of code:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Setup-run.png|300px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The Console displays a new line with the result, or&amp;amp;nbsp;''return value,''&amp;amp;nbsp;of whatever code you executed. When there is no return value, the Console shows,&amp;amp;nbsp;&amp;lt;code&amp;gt;undefined&amp;lt;/code&amp;gt;. But don’t worry! Your code is stored safely in the Console session. It is telling you that nothing was returned and that the last command didn’t cause an error. You’re ready to continue. ✔️&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Pro Tip''':&amp;amp;nbsp;Whenever you want to make a new line or jump to the next line, without executing the code, press&amp;amp;nbsp;'''Shift-Return'''. Use that when you want to write more code on another line without executing the first. Go ahead and try it. The cursor will move one line down. The Console isn’t picky about empty lines, so you can add as many spacing lines as you like between lines of code.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Uploading a jig ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Earlier you learned that method calls on a jig are stored in a Bitcoin transaction. Well, the class definition of a jig is stored in the same way. So the class definition transaction is like the seed of a tree and the method calls are the branches that grow out from the original transaction:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Growth.jpg|300px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Copy and paste this code into the Console to create your first jig:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
class Dragon extends Jig {&lt;br /&gt;
 setName(name) {&lt;br /&gt;
 this.name = name&lt;br /&gt;
 }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Press&amp;amp;nbsp;'''Return'''&amp;amp;nbsp;to submit it.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Now is the moment you’ve been waiting for, you’re about to put code into Bitcoin. Type the following code:&amp;lt;/p&amp;gt;&lt;br /&gt;
const dragon = new Dragon()&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Press&amp;amp;nbsp;Return&amp;amp;nbsp;to submit it. And that’s it!&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Behind the scenes, several things are happening. You created a new instance of the&amp;amp;nbsp;&amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;&amp;amp;nbsp;class--that much is clear. But RUN has done the heavy lifting for you.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Advanced programmers''': The definition of&amp;amp;nbsp;&amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;&amp;amp;nbsp;has been stored as JSON in the output of a Bitcoin transaction. Both the class definition and the new instance are stored in the same Bitcoin transaction on different outputs. RUN is smart enough to save money by packaging multiple jig instructions into a single transaction, and allowing the classes and instances to operate independently in the future.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Beginner programmers:''' click here to read [[Programming Basics|Programming Basics]] before you continue&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;You can point to any jig or class definition by its&amp;amp;nbsp;&amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;. The&amp;amp;nbsp;&amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;&amp;amp;nbsp;is the pair of a transaction ID and an output index together, separated by an underscore:&amp;amp;nbsp;&amp;lt;code&amp;gt;transactionID_outputIndex&amp;lt;/code&amp;gt;&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Type the following code:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
console.log('class: ', Dragon.location)&lt;br /&gt;
console.log('instance: ', dragon.location)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;blockquote&amp;gt;'''Pro Tip:''' You can execute these lines separately by pressing Return after each one, or you can practice adding multiple lines of code before executing by pressing Shift-Return before typing the second line.&amp;lt;/blockquote&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Console will print out the&amp;amp;nbsp;&amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;s of the two:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Locations.png|550px|center|thumb]]&amp;lt;p&amp;gt;You can see that the class definition and the instance have the same transaction ID (the long first part—something like,&amp;amp;nbsp;&amp;lt;code&amp;gt;&amp;quot;155…2bf&amp;quot;&amp;lt;/code&amp;gt;) but have separate output indexes (the short second part,&amp;amp;nbsp;&amp;lt;code&amp;gt;&amp;quot;o1&amp;quot;&amp;lt;/code&amp;gt;&amp;amp;nbsp;&amp;amp;&amp;amp;nbsp;&amp;lt;code&amp;gt;&amp;quot;o2&amp;quot;&amp;lt;/code&amp;gt;).&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;If you’re not a programmer all this probably sounds über nerdy. The important takeaway is that both the description of the dragon (the class definition) and your actual live dragon (the instance) are stored on the Bitcoin blockchain. Or, as we like to say, the data is&amp;amp;nbsp;''on-chain''.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Updating a jig ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Now that you’ve uploaded the class definition and created the first instance, the next step is to perform some actions with your jig. To perform an action, you call a method. You defined the&amp;amp;nbsp;&amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;&amp;amp;nbsp;class with a single method,&amp;amp;nbsp;&amp;lt;code&amp;gt;setName(name)&amp;lt;/code&amp;gt;.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;To call the method is as easy as can be. Just type the following code:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.setName(&amp;quot;Empress&amp;quot;)&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;You’re calling a method on the instance of the&amp;amp;nbsp;&amp;lt;code&amp;gt;Dragon&amp;lt;/code&amp;gt;&amp;amp;nbsp;class — the individual dragon — called&amp;amp;nbsp;&amp;lt;code&amp;gt;dragon&amp;lt;/code&amp;gt;, to give it a friendly name. The method call is just another Bitcoin transaction.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;The value of a jig is defined by all the modifications or updates that have happened to it over time. To calculate and verify the current state of a jig, your wallet will replay the history of transactions from the beginning, when the jig was initialized.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;RUN has built-in protection to keep you from publishing a transaction that wouldn’t be accepted.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;But, you may want to double-check whether you’ve made your update correctly. You can access a property of a jig by typing the following code into the Console:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.name&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The console will show you the result:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Dragon-name.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;And what about if you wanted to check that the jig had indeed been updated in a new transaction? Type the following code:&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
dragon.location&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;The console shows you the result:&amp;lt;/p&amp;gt;&lt;br /&gt;
[[File:Dragon-location.png|550px|center|middle|thumb]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;So the transaction ID is now different for&amp;amp;nbsp;&amp;lt;code&amp;gt;location&amp;lt;/code&amp;gt;&amp;amp;nbsp;than it was before. If you want to access the original location where the jig was first defined, use the&amp;amp;nbsp;&amp;lt;code&amp;gt;origin&amp;lt;/code&amp;gt;. The jig is fully expressed by all the updates from its origin, leading up to the current location.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Where to go from here? ==&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;Congratulations on writing your first jig.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;Use the documentation in this wiki as a reference along your journey. Over time, you’ll get to know all the features in the RUN SDK.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;In this tutorial, you used the Mockchain to speed up development. As a challenge, try moving over to Mainnet. If you are successful, not only will you be able to see your jig on the RUN Explorer (deprecated for now, but will come back at some point later), you’ll also be able to see your bitcoin address and transactions on a block explorer like WhatsOnChain.&amp;lt;/p&amp;gt;&lt;br /&gt;
&amp;lt;p&amp;gt;We’re at the beginning of something very big here. You’re on the ground level of a new platform. Now anyone can build interactive objects that run on Bitcoin. Jigs might just become your new familiar friends.&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;For a guided journey, head on over to the next tutorial: [[Tutorial 2 - Running jigs on Bitcoin Mainnet, Part 1|Tutorial 2 - Running jigs on Bitcoin Mainnet, Part 1]]&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== Ideas ===&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
*Interacting tokens as jigs run on Bitcoin&lt;br /&gt;
*Code stable coins as jigs run on Bitcoin&lt;br /&gt;
*Code a video game with jigs run on Bitcoin&lt;br /&gt;
*Unleash a digital pet as a jig run on Bitcoin&lt;br /&gt;
*Create jigs that can be mined like Bitcoin&lt;br /&gt;
*Launch tradable artwork like stickers&lt;br /&gt;
*Send micro-transactions with the Pay Server&lt;br /&gt;
*Integrate with Phaser or PlayCanvas&lt;br /&gt;
*Create a serverless app using Bitcoin&lt;br /&gt;
*Learn what RUN does under the hood for you like magic&lt;br /&gt;
[[Category:Tutorials]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
	<entry>
		<id>https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=490</id>
		<title>Installing the run sdk</title>
		<link rel="alternate" type="text/html" href="https://wiki.runcraft.io/index.php?title=Installing_the_run_sdk&amp;diff=490"/>
		<updated>2023-09-26T16:29:24Z</updated>

		<summary type="html">&lt;p&gt;Zhell: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| style=&amp;quot;border-collapse:collapse; background-color:red;&amp;quot;&lt;br /&gt;
| style=&amp;quot;padding:10px; text-align:center; font-weight:bold; color:white;&amp;quot; |&lt;br /&gt;
ALERT: This Page is Outdated and Waiting for Update&lt;br /&gt;
The current way of testing the RUN library to create tokens is to open the devtools console at [https://runcraft.io Runcraft.io], then head over to [[Creating_and_loading_jigs|creating and loading jigs]].&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
The easiest way to get the latest version is to run&amp;lt;pre&amp;gt;npm install run-sdk&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;Another solution is to download the SDK as a zip file from [https://run.network/ https://run.network/]. At the time of writing the latest version is [https://github.com/runonbitcoin/sdk/archive/refs/tags/v0.6.37.zip version 0.6.37].&lt;br /&gt;
&lt;br /&gt;
= Getting Started =&lt;br /&gt;
&lt;br /&gt;
== Installation ==&lt;br /&gt;
&lt;br /&gt;
If you're new to Run, let the [https://run.network/lessons tutorial series] guide your journey to get acquainted. You can write code without installing anything. The web browser Console will be your playground.&lt;br /&gt;
&lt;br /&gt;
The details written here in the Docs have example code in the sidebar on the right-hand side. Anything you read in paragraphs, you can preview in-action over there.&lt;br /&gt;
&lt;br /&gt;
Run works everywhere including all major browsers, on desktop and mobile, as well as Node.js 10+ on servers. The Run SDK is written in JavaScript ES6 and uses the [https://github.com/moneybutton/bsv bsv library] to build and sign transactions. To get started:&lt;br /&gt;
&lt;br /&gt;
*For a webpage: Add &amp;lt;code&amp;gt;bsv.browser.min.js&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;run.browser.min.js&amp;lt;/code&amp;gt; to the &amp;lt;code&amp;gt;&amp;lt;head&amp;gt;&amp;lt;/code&amp;gt; tag.&lt;br /&gt;
*For Node.js: Run &amp;lt;code&amp;gt;npm install run-sdk&amp;lt;/code&amp;gt; to install both the run and bsv libraries&lt;br /&gt;
And that's it. All your code and jigs will be saved on-chain and Run will use public APIs to interact with the Bitcoin network. You don't need to deploy any servers to use Run. All the logic works client-side.&lt;br /&gt;
&lt;br /&gt;
You can also find the SDK at [https://github.com/runonbitcoin/sdk the github repo].&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
Load both bsv and run in the browser&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;html&amp;quot;&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/bsv@1.5.6&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;script src=&amp;quot;https://unpkg.com/run-sdk&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Load run in Node.js&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const Run = require('run-sdk')&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Setup ==&lt;br /&gt;
A &amp;lt;code&amp;gt;Run&amp;lt;/code&amp;gt; instance manages your communication with the Bitcoin network. The default network is &amp;lt;code&amp;gt;main&amp;lt;/code&amp;gt; (Mainnet), but for development and testing, we recommend &amp;lt;code&amp;gt;mock&amp;lt;/code&amp;gt;. Mock is an in-memory simulation blockchain that does not require funds to use. We like to call it the mockchain. For more configuration options, see [https://run.network/docs/#api-reference-run API Reference: Run.]&lt;br /&gt;
&lt;br /&gt;
=== Code ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;javascript&amp;quot;&amp;gt;&lt;br /&gt;
const run = new Run({ network: 'mock' })&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;p&amp;gt;After that you are ready to [[Creating and_loading_jigs|create and load jigs]].&amp;lt;/p&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Documentation]]&lt;/div&gt;</summary>
		<author><name>Zhell</name></author>
		
	</entry>
</feed>