Skip to content

ymuichiro/atomic-port

Repository files navigation

logo

Atomic port

This package is for HTLC transactions between the any blockchains. HTLC stands for Hashed time lock contract. HTLC allows direct transactions between different chains. Usage and examples are shown below.


Attention

This script was created and released for research and experimentation and is not intended to encourage actual use. Trading of crypto assets may require licenses, applications, or approvals in some countries. Please consider using them at your own risk.


Test is now open to the public.

Transactions on each chain in this library are currently available only on the testnet. If you wish to use it in a production environment, please change the network and other parameters.


Chains or Tokens

The following chains & tokens are supported

Example

A lock transaction is created to execute HTLC and initiate the transaction. The executor keeps the generated Proof and shares the Secret with the counterparty.

async function lock() {
  // setup
  const client = new SymbolHtlc(
    SYMBOL.NETWORK.ENDPOINT,
    NetworkType.TEST_NET,
    SYMBOL.NETWORK.GENERATION_HASH_SEED,
    SYMBOL.NETWORK.EPOCH_ADJUSTMENT
  );
  const recipientAccount = Account.createFromPrivateKey(SYMBOL.PRIVATEKEY.TO, NetworkType.TEST_NET);
  const senderAccount = Account.createFromPrivateKey(SYMBOL.PRIVATEKEY.FROM, NetworkType.TEST_NET);
  const hashPair = client.createHashPair();
  // lock
  const transaction = client.lock(recipientAccount.address.plain(), SYMBOL.CURRENCY.MOSAIC_ID, hashPair.secret, 1);
  const signedTx = await client.sign(SYMBOL.PRIVATEKEY.FROM, transaction);
  console.log('----- wait until transaction is approved -----', {
    fromAddress: senderAccount.address.pretty(),
    toAddress: recipientAccount.address.pretty(),
    transactionHash: signedTx.hash,
    proof: hashPair.proof,
    secret: hashPair.secret,
  });
  // Wait for secret transaction to be approved
  await waitConfirmedTransaction(SYMBOL.NETWORK.ENDPOINT, senderAccount.address, signedTx.hash);
}

async function start() {
  await lock();
}

When a transaction is completed, you will receive tokens from the block. The Proof generated at this time is used.

async function withDraw(proof: string, secret: string) {
  const client = new SymbolHtlc(
    SYMBOL.NETWORK.ENDPOINT,
    NetworkType.TEST_NET,
    SYMBOL.NETWORK.GENERATION_HASH_SEED,
    SYMBOL.NETWORK.EPOCH_ADJUSTMENT
  );
  const recipientAccount = Account.createFromPrivateKey(SYMBOL.PRIVATEKEY.TO, NetworkType.TEST_NET);
  const drawTx = client.withDraw(recipientAccount.address.plain(), proof, secret);
  const signedTx = await client.sign(recipientAccount.privateKey, drawTx);
  console.log('waiting...', signedTx.hash);
  await waitConfirmedTransaction(SYMBOL.NETWORK.ENDPOINT, recipientAccount.address, signedTx.hash);
  console.log(signedTx);
}

async function start() {
  const proof = '************************';
  const secret = '************************';
  await withDraw(proof, secret);
}

An example of a flow is shown below. ※ If you cannot see the following as a figure, please check with your browser.

sequenceDiagram
    actor Alice
    participant Chain A
    participant Chain B
    actor Bob
    Note over Alice,Bob: Start trading
    Note over Alice: Create Secret&Proof
    Alice ->>  Chain A: Create Lock Tx(A) from Secret
    Note over Chain A: Tx Alice to Bob(is Lock)
    Alice -->> Bob:  Secret used is shared separately
    Bob -->> Chain A: Check if lock Tx(A) has block
    Bob ->> Chain B: Create Lock Tx(B) from Secret
    Note over Chain B: Tx Bob to Alice(is Lock)
    Alice -->> Chain B: Check if lock Tx(B) has block
    Alice ->> Chain B: Unlock Tx(B) using owned Proof
    Note over Chain B: Tx Bob to Alice(is unlock)
    Bob -->> Chain B: Get proof by Tx(B)
    Bob ->> Chain A: Unlock Tx(A) using acquired Proof
    Note over Chain A: Tx Alice to Bob(is unlock)
    Note over Alice,Bob: Transaction Completed