Atomic Swap is a general algorithm to achieve the exchange between two parties without having to trust a third party.
Atomic Swap Contract is the VSYS implementation of Atomic Swap which supports atomic-swapping tokens on VSYS chain with other tokens(either on VSYS chain or on other atomic-swap-supporting chain like Ethereum).
We have written a helper which exclusively serve when both users' accounts and tokens are on VSYS chain.
Register an Atomic Swap Contract instance.
import * as jv from '@virtualeconomy/js-vsys';
// acnt: jv.Account
// tokId: string
const ac = await jv.AtomicSwapCtrt.register(acnt, tokId);
console.log(ac.ctrtId);
Example output
CtrtID(CFAAxTu44NsfwMUfpmVd6y4vuN9xQNVFtGa)
Get an object for an existing contract instance.
import * as jv from '@virtualeconomy/js-vsys';
// ch: Chain
const ctrtId = 'CFAAxTu44NsfwMUfpmVd6y4vuN9xQNVFtGa';
const atomicCtrt = new jv.AtomicSwapCtrt(atomicCtrtId, ch);
The address that made this contract instance.
// ac: AtomicSwapCtrt
console.log(await ac.getMaker());
Example output
Addr { data: 'AU8h6YH5iJuwFzcUdGugUwKo2E8tbEHdtqu' }
The token ID of the token deposited into this contract.
// ac: AtomicSwapCtrt
console.log(await ac.getTokId());
Example output
TokenID { data: 'TWt6EyaxKRPeG92Hq3HpHzc4vnYY7JxmfCGMhgYh2' }
The unit of the token deposited into this contract.
// ac: AtomicSwapCtrt
console.log(await ac.getUnit());
Example output
1
The balance of the token deposited into this contract for the given user.
// ac: AtomicSwapCtrt
// acnt: Account
console.log(await ac.getCtrtBal(acnt.addr.data));
Example output
Token { data: BigNumber { s: 1, e: 2, c: [ 100 ] }, unit: 1 }
Get the owner of the swap based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapOwner(makerLockTxId));
Example output
Addr { data: 'AU8h6YH5iJuwFzcUdGugUwKo2E8tbEHdtqu' }
Get the recipient of the swap based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: str E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapRecipient(makerLockTxId));
Example output
Addr { data: 'AU1KWrn3sFwddbZjfeKnauh4zAYiDTmo9gM' }
Get the hashed puzzle(i.e. secret) of the swap based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapPuzzle(makerLockTxId));
Example output
DYu3G8aGTMBW1WrTw76zxQJQU4DHLw9MLyy7peG4LKkY
Get the token amount locked into the swap based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapAmount(makerLockTxId));
Example output
Token { data: BigNumber { s: 1, e: 2, c: [ 100 ] }, unit: 1 }
Get the expiration time of the swap based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapExpiredTime(makerLockTxId));
Example output
VSYSTimestamp { data: BigNumber { s: 1, e: 21, c: [ 16552542 ] } }
Get the status of the swap(if the swap is active) based on the given token-locking transaction ID(e.g. the transaction ID obtained from taking the maker locking action).
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
console.log(await ac.getSwapStatus(makerLockTxId));
Example output
true
For this lock function sample code, we consider it as the maker lock of the atomic swap.
Maker is the one who first creates the swap contract, and creates the secret.
If the lock is executed by the taker, we need the hashed secret bytes from the maker lock transaction.
// ac: AtomicSwapCtrt
// acnt0: Account
// acnt1: Account
// lockAmount: number
import * as jv from '@virtualeconomy/js-vsys';
// maker lock sample code
secret = 'abc';
const puzzleBytes = jv.sha256Hash(Buffer.from(secret, 'latin1'));
const makerLockTimestamp = Date.now() + 1800 * 1000;
resp = await ac.lock(
acnt0, // by
lockAmount, // amount
acnt1.addr.data, // recipient
puzzleBytes, // hashedSecret
makerLockTimestamp // expireTime
);
console.log(resp);
Example output
{
type: 9,
id: 'CH9jjspCxK21vdbyRBj2TVzUkk9KMsVubpxaHfLxdE8r',
fee: 30000000,
feeScale: 100,
timestamp: 1654829045256000000,
proofs: [
{
proofType: 'Curve25519',
publicKey: 'AGy4ASY2CmVPSjQX4rNHrSHmcYAL4DNBawdyKT7p8vot',
address: 'AU8h6YH5iJuwFzcUdGugUwKo2E8tbEHdtqu',
signature: '5q9uAGEiNaGw4pDwK7Eu25nzCyPvUhXEro6rouDwjz2NKsm9ZGDzE3qqj6huKH2tdPAb9LFtZ34fa88nini91QQs'
}
],
contractId: 'CF4YKpuuevHY7CVPK9r9sUKKNuZVJWAkgM3',
functionIndex: 0,
functionData: '1CC6B9Tu94MGLm9e7vM4r9GXknWei3sxHSq9u8oQ5USoxMPKC3ibdKttMtsYbtshrTTsbw8fcUyjskyt1BYMEsixZ5meVf3dpvdDEPnkPKdKWdu',
attachment: ''
}
If the solve function is executed by the maker, then the maker takes the tokens locked by the taker and reveals the plain text of the hashed secret.
If the solve function is executed by the taker, then the taker will get the revealed secret and takes the tokens locked by the maker.
The following sample code shows how maker solve runs.
// ac: AtomicSwapCtrt instance of TAKER's
// maker: Account
// takerLockTxId: string E.g. "D5ZPPhw7y4eWcL6zBNWNHdWf9jGxPAi5XCP5KxuZzirP"
// secret: string E.g. "abc"
resp = await ac.solve(
maker, // by
takerLockTxId, // lockTxId
secret // secret
);
console.log(resp);
Example output
{
type: 9,
id: 'AJYjfwsxWeLaMKgRYuixqVus3njjHedM6XkbVP8XEpXv',
fee: 30000000,
feeScale: 100,
timestamp: 1654829867740000000,
proofs: [
{
proofType: 'Curve25519',
publicKey: 'AGy4ASY2CmVPSjQX4rNHrSHmcYAL4DNBawdyKT7p8vot',
address: 'AU8h6YH5iJuwFzcUdGugUwKo2E8tbEHdtqu',
signature: '2Ra9bj4wNppbJbN4aaFwQiCXNbAUwB9pS5R8kmCvxeasZCdzkpoeC2NTft4iS2yxhqB9yxj84yUiRiu2t2uAVY5D'
}
],
contractId: 'CFDec4GueRAqaGoukCN4ire6QQv4vnfogMZ',
functionIndex: 1,
functionData: '12yhZiG93rnjqP4EWEUhxYRt7BWTcHHQVQm4nBikhmQxGgbFFtKVzoUudt',
attachment: ''
}
Either the maker or taker withdraws the tokens from the contract after the expiration time.
The example below shows the withdraw after expiration by the maker. It is the same for the taker.
// ac: AtomicSwapCtrt
// makerLockTxId: string E.g. "FHZdvf3yyWuDnNTYeR6MZKTEqLJ1QxKfrDBqFrHDVBeJ"
resp = await ac.expWithdraw(
acnt0, // by
makerLockTxId // lockTxId
);
console.log(resp);
Example output
{
type: 9,
id: '5Wwi3zAZFhdRx3ngrjt4fDX1hAtsi4ZQLGt9u9U1uBR2',
fee: 30000000,
feeScale: 100,
timestamp: 1654830809754000000,
proofs: [
{
proofType: 'Curve25519',
publicKey: 'AGy4ASY2CmVPSjQX4rNHrSHmcYAL4DNBawdyKT7p8vot',
address: 'AU8h6YH5iJuwFzcUdGugUwKo2E8tbEHdtqu',
signature: '278Ydo6hju5XvRgDFhqyHgK56ndxobPzYS71eKKinS5oVEQaVsR7ZZn88pNNuAzvEvAqZTRFnixoEPZ7aqMtwgiV'
}
],
contractId: 'CF4YKpuuevHY7CVPK9r9sUKKNuZVJWAkgM3',
functionIndex: 2,
functionData: '1TeCHms39cxgn3ifBZdtv8FQUUMgPhjGtupGUVPgEC1bqdfKZ',
attachment: ''
}