Skip to content

Secret complex example

Chun Lam edited this page Feb 21, 2024 · 3 revisions
import { NetworkType, Account, SecretLockTransaction, Deadline, HashType, Mosaic, 
    UInt64, MosaicId, Convert as convert, SecretProofTransaction 
} from "tsjs-xpx-chain-sdk";
import { randomBytes } from "crypto";
import { Network } from "../utils";
import { sha3_256 } from 'js-sha3';
import { bytesToHex } from '@noble/hashes/utils';

const PRIVATE_NETWORK_TYPE = NetworkType.MIJIN_TEST;
const PUBLIC_NETWORK_TYPE = NetworkType.MIJIN_TEST;

const pub_network = new Network('http://localhost:3000');
const priv_network = new Network('http://localhost:3000');

const pub_alice = Account.createFromPrivateKey('0123456789012345678901234567890123456789012345678901234567890124', PUBLIC_NETWORK_TYPE, 1);
const priv_alice = Account.createFromPrivateKey('FFFFFFFFFF012345678901234567890123456789012345678901234567890124', PRIVATE_NETWORK_TYPE, 1);
const pub_bob = Account.createFromPrivateKey('ABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD', PUBLIC_NETWORK_TYPE, 1);
const priv_bob = Account.createFromPrivateKey('FFFFFFFFFFEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCDEFABCD', PRIVATE_NETWORK_TYPE, 1);

// you can use hexadecimal string id for MosaicId
const pub_mosaicFromAliceToBob = new Mosaic(new MosaicId([
    481110499,
    231112638
]), UInt64.fromUint(1 * 1000000));

const priv_mosaicFromBobToAlice = new Mosaic(new MosaicId([
    481110499,
    231112638
]), UInt64.fromUint(1 * 1000000));


const secretSeed = randomBytes(20);
const secret = sha3_256.create().update(secretSeed).hex();
const proof = bytesToHex(secretSeed);

// Alice starts the whole process by offering some funds (mosaic) to Bob in first network (public network in "our" example)
// She uses a SECRET - hash of random PROOF - as part of the announcement
const pub_secretLockTransaction = SecretLockTransaction.create(
    Deadline.create(),
    pub_mosaicFromAliceToBob,
    // number of blocks this transaction can be finalized with the PROOF
    // Bob will use this value to compute "enough time" for himself to close the deal on the other side
    // Bob's value will be SMALLER, see priv_secretLockTransaction
    UInt64.fromUint(1000),
    HashType.Op_Sha3_256,
    secret,
    pub_bob.address,
    PUBLIC_NETWORK_TYPE);

pub_network.networkProperties.then(public_network_properties => {
    const signedPub_secretLockTransaction = pub_alice.preV2Sign(pub_secretLockTransaction, public_network_properties.generationHash);
    pub_network.announceAndWaitForConfirmation(signedPub_secretLockTransaction).then(tx => {
        console.log('Secret lock in public network confirmed. Alice offers her part of the deal.');
        // now Bob can see that Alice is offering him funds in public network
        // Bob has to use the same SECRET for his secret lock transaction in private network (other part of the deal)

        const priv_secretLockTransaction = SecretLockTransaction.create(
            Deadline.create(),
            priv_mosaicFromBobToAlice,
            // it generally has to be less than in Alice's pub_secretLockTransaction, so if Alice manages to claim the
            // mosaic with the PROOF, Bob still has enough(!) time to use the same PROOF to seal the deal on his side
            UInt64.fromUint(500),
            HashType.Op_Sha3_256,
            secret,
            priv_alice.address,
            PRIVATE_NETWORK_TYPE
        );

        priv_network.networkProperties.then(private_network_properties => {
            const signedPriv_secretLockTransaction = priv_bob.preV2Sign(priv_secretLockTransaction, private_network_properties.generationHash);
            priv_network.announceAndWaitForConfirmation(signedPriv_secretLockTransaction).then(tx => {
                console.log('Secret lock in private network confirmed. Bob offers his part of the deal.');
                // now Alice can see that Bob did his part and announced some mosaic in exchange
                // Alice can use the PROOF to claim the mosaic in private network

                const priv_secretProofTransaction = SecretProofTransaction.create(
                    Deadline.create(),
                    HashType.Op_Sha3_256,
                    secret,
                    priv_alice.address,
                    proof,
                    PRIVATE_NETWORK_TYPE
                );
                const signedPriv_secretProofTransaction = priv_alice.preV2Sign(priv_secretProofTransaction, private_network_properties.generationHash);
                priv_network.announceAndWaitForConfirmation(signedPriv_secretProofTransaction).then(tx => {
                    console.log("Secret proof in private network announced. Alice claims her mosaic.");
                    // now Bob can see the publicly announced "proof" and can use the same proof to close the other part of the deal.

                    const pub_secretProofTransaction = SecretProofTransaction.create(
                        Deadline.create(),
                        HashType.Op_Sha3_256,
                        secret,
                        pub_bob.address,
                        proof,
                        PUBLIC_NETWORK_TYPE
                    );
                    const signedPub_secretProofTransaction = pub_bob.preV2Sign(pub_secretProofTransaction, public_network_properties.generationHash);
                    pub_network.announceAndWaitForConfirmation(signedPub_secretProofTransaction).then(tx => {
                        console.log('Secret proof in public network announced. Bob claims his mosaic.');
                    });
                });
            });
        });
    });
});
Clone this wiki locally