What is JellySwap?
JellySwap is a cross-chain atomic swap protocol that supports many different blockchains. The Ethereum package is used to interact with the Ethereum Hash Time Locked Contracts and to handle blockchain events. The main components of the module are Providers, Contract, Event, Adapter and Config.
Install package
Using yarn
Copy $ yarn add @jelly-swap/ethereum
Using npm
Copy $ npm install @jelly-swap/ethereum
Importing
JavaScript (ES3)
Copy const jellyEth = require ( '@jelly-swap/ethereum' );
JavaScript (ES6) / TypeScript
Copy import * as jellyEth from '@jelly-swap/ethereum' ;
Config Module
This module contains the main configuration for the whole package
Copy const config = jellyEth .Config ();
//Expected output
{
network : 'ETH' ,
explorer : 'https://ropsten.etherscan.io/tx/' ,
providerUrl : 'https://ropsten.infura.io/v3/8fe4fc9626494d238879981936dbf144' ,
contractAddress : '0xc961b206901a821affddd77fac831e9ff1be89c0' ,
receiverAddress : '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7' ,
blockTime : 15 ,
expiration : 10800 ,
decimals : 18 ,
unix : true
}
Provider Module
A Provider abstracts a connection to the Ethereum blockchain, for issuing queries and sending signed state changing transactions.
JsonRpcProvider - allows you to connect to Ethereum nodes you control or have access to, including mainnet, testnets, proof-of-authority (PoA) nodes or Ganache by providing a URL to the node.
Copy const jsonProvider = new jellyEth . Providers .JsonRpcProvider (providerUrl);
Web3Provider - used with Web3 application, or Web3-compatible Provider (e.g. MetaMask’s web3.currentProvider).
Copy const jsonRpcProvider = new jellyEth . Providers .Web3Provider (web3);
WalletProvider - manages a private/public key pair which is used to cryptographically sign transactions and prove ownership on the Ethereum network. Use when there is no Web3Provider available.
Copy const walletProvider = new jellyEth . Providers .WalletProvider (privateKey , providerUrl ? )
Contract Module
Contract module is used to interact with the Solidity Contract and get blockchain specific data (balance, blockNumber, subscribe to events, get past events)
Create contract instance:
Copy const ethContract = new jellyEth .Contract (provider);
subscribe
Copy await ethContract .subscribe (onEvent , filter ? );
getPastEvents
Returns past blockchain events.
Copy const pastEvents = await ethContract .getPastEvents (eventType , filter ? , currentBlock ? );
getCurrentBlock
Returns the latest block.
Copy const currentBlock = await ethContract .getCurrentBlock ();
getBalance
Returns the balance of the given address.
Copy const balance = await ethContract .getBalance (address);
getStatus
Returns the swaps statuses by given ids.
Copy const statuses = await ethContract .getStatus (ids);
newContract
Creates and broadcasts a new swap transaction.
Copy const transactionHashSwap = await ethContract .newContract (swap);
withdraw
Creates and broadcasts a withdraw transaction.
Copy const transactionHashWithdraw = await ethContract .withdraw (withdraw);
refund
Creates and broadcasts a refund transaction.
Copy const transactionHashRefund = await ethContract .refund (contractRefund);
Event module
Event module is used to read past blockchain events and subscribe for new ones
Initialize event module:
Copy const ethEvents = new jellyEth .Event (ethContract);
getPast
Returns past blockchain events.
Copy const pastEvents = await ethEvents .getPast (eventType , filter ? , currentBlock ? );
subscribe
Copy await ethEvents .subscribe (onEvent , filter ? );
Adapter module
The Adapter module is used to format the client data and prepare the input for the swaps.
Initialize adapter module:
Copy const ethAdapter = new jellyEth .Adapter ();
generateId
Generate swap id based on the input parameters. The same id will be generated by the Solidity Contract.
Copy const id = ethAdapter .generateId (input);
addressValid
Checks if the passed address is valid or not.
Copy const isAddressValid = ethAdapter .addressValid (address);
parseAddress
Returns the address in lower case.
Copy const addressParsed = ethAdapter .parseAddress (address);
parseToNative
Parse ether amount to wei amount i.e. 0.1 to 100000000000000000
Copy const result = ethAdapter .parseToNative (amount);
parseFromNative
Parse wei amount to ether amount i.e. 100000000000000000 to 0.1
Copy const result = ethAdapter .parseFromNative (amount);
formatInput
Returns object of type UserInputSwap.
Copy const swapInput = ethAdapter .formatInput (data , receiver);
Example
Copy const jellyEth = require ( '@jelly-swap/ethereum' );
const provider = new jellyEth . Providers .WalletProvider ( 'ETH_PRIVATE_KEY' );
const ethContract = new jellyEth .Contract (provider);
const adapter = new jellyEth .Adapter ();
async function start () {
// Subscribe for contract events and pass handle function
await ethContract .subscribe (e => {
console .log (e);
});
// Get past blockchain events
const swaps = await ethContract .getPastEvents ( 'new' , s => s);
console .log (swaps);
// [
// {
// eventName: 'NEW_CONTRACT',
// expiration: '1578325310',
// hashLock: '0xa36a1b50af73816c902beb41e7dce13df8e3bf49ee89ef0e7f26048768d57a10',
// id: '0x94f1b5d123b35a02f370f27a5d27caab6ada5d5004b3b3d1b4f0f0eb84548a17',
// inputAmount: '10000000000000000',
// isSender: true,
// network: 'ETH',
// outputAddress: '0x40efc259a58d70d21939e45d8f67dc1517f8e495',
// outputAmount: '99213154',
// outputNetwork: 'TRX',
// receiver: '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7',
// sender: '0xd9DabDeac2c54004beD2A3d0FEE27B1c5D063Cf2',
// status: 2,
// transactionHash: '0x686c5ac5768bfbee3eb5dc3a83c42cbcbf132adeba1a71f1211224af761210d3',
// },
// ];
const withdraws = await ethContract .getPastEvents ( 'withdraw' , w => w);
console .log (withdraws);
// [
// {
// eventName: 'WITHDRAW',
// hashLock: '0x07d7feb413329c6a92fc30481b0144d874e4eccb189d8f351a932055f3f77edd',
// id: '0xadb8121fe8e376f3aeb7b128c2e6dd3270cf2b6014d5620af42b3cebbb615b85',
// network: 'ETH',
// receiver: '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7',
// secret: '0x2f6bd9d321e8a1e0ddd295238503b9eed5e86a63667be9b51a7ad232aa38fc90',
// sender: '0xB7B4043aD3E6986D39f344c551AA78266Fb140D4',
// transactionHash: '0xaa6bdc80007864aff30b5b96e46157d9efbf12345326bfa4d856f48c170fb792',
// },
// ];
const refunds = await ethContract .getPastEvents ( 'refund' , r => r);
console .log (refunds);
// [
// {
// eventName: 'REFUND',
// hashLock: '0xa36a1b50af73816c902beb41e7dce13df8e3bf49ee89ef0e7f26048768d57a10',
// id: '0x94f1b5d123b35a02f370f27a5d27caab6ada5d5004b3b3d1b4f0f0eb84548a17',
// network: 'ETH',
// receiver: '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7',
// sender: '0xd9DabDeac2c54004beD2A3d0FEE27B1c5D063Cf2',
// transactionHash: '0x20d29c71fdfdfe18bc3084575bcd944d2f73e426c8aca58c823bc409972edd8e',
// },
// ];
const currentBlock = await ethContract .getCurrentBlock ();
console .log (currentBlock);
// 7085825
const balance = await ethContract .getBalance ( '0xB7B4043aD3E6986D39f344c551AA78266Fb140D4' );
console .log (balance);
// 1000000000000000000
const statuses = await ethContract .getStatus ([
'0x9ee52df91acbdd56079c885cf24f7d0fa74b8ca7ecdbe4385b28f566feb51896' ,
'0xb8504b8a996634a96294d6e631de9d8b2599d16ca5b85db4f776339690e2fa8a' ,
]);
console .log (statuses);
// [1, 4]
// ACTIVE: 1,
// REFUNDED: 2,
// WITHDRAWN: 3,
// EXPIRED: 4
// ================ SWAP ================
const userInputSwap = {
inputAmount : '0.01' ,
network : 'ETH' ,
outputAddress : '0x7bc272693510354a84e1632cca005253dbb08d18' ,
outputAmount : '98917611' ,
outputNetwork : 'TRX' ,
secret : 'pond cram isolate chair float moon tongue firm spirit hand peace together' ,
sender : '0xd9dabdeac2c54004bed2a3d0fee27b1c5d063cf2' ,
};
const swap = adapter .formatInput (userInputSwap);
console .log (swap);
// {
// expiration: 1578487450;
// hashLock: '0x4af116ee28ecde1d2b71e49fb964fe76a20c694c94f6895c1baa8ed1d1b06dda';
// inputAmount: '10000000000000000';
// network: 'ETH';
// options: {
// value: v;
// }
// outputAddress: '0x7bc272693510354a84e1632cca005253dbb08d18';
// outputAmount: '98917611';
// outputNetwork: 'TRX';
// receiver: '0xF684C21Ec023E93da0B402ac0a274317eb51C2c7';
// sender: '0xd9dabdeac2c54004bed2a3d0fee27b1c5d063cf2';
// }
//broadcast swap transaction
const swapHash = await ethContract .newContract (swap);
console .log (swapHash);
// 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905
// ================ REFUND ================
const refund = {
id : '0xfa033fb78799f986cffba5e965db049d8da4f9764e6b791cb8aeb6df842c0e52' ,
};
const refundHash = await ethContract .refund (refund);
console .log (refundHash);
// 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905
// ================ WITHDRAW ================
const withdraw = {
id : '0xfa033fb78799f986cffba5e965db049d8da4f9764e6b791cb8aeb6df842c0e54' ,
secret : '0x307afe7a1a9bc9f94b7bf5b091441bac10222f4c797ee4441cb213aae7ac18a2' ,
};
const withdrawHash = await ethContract .withdraw (withdraw);
console .log (withdrawHash);
// 0x9aaee4781efd92f214cfc625e385492241e4f252f9400cdf6b1706668137f905
}