Tutorial - Mercury web-app library
This tutorial demonstrates the usage of the mercury web library in a simple react app using vitejs.dev.
Requirements
This tutorial assumes access to a command line terminal with npm installed, and a WASM
compatible web browser.
Web app
Initialise a react demo-app using vite:
npm create vite@latest demo-app -- --template react
Then run:
cd demo-app
This creates the following files in the demo-app
directory:
README.md
eslint.config.js
index.html
node_modules
package-lock.json
package.json
public
src/
App.css
App.jsx
assets
index.css
main.jsx
vite.config.js
First, add the mercuryweblib
to the package.json
file:
"dependencies": {
"mercuryweblib": "0.0.3",
}
Save the file and run: npm install
to install the library and dependencies.
Then create a a config file ClientConfig.js
in the src/
directory, with:
const clientConfig = {
esploraServer: "https://mutinynet.com",
statechainEntity: "https://test.mercurylayer.com",
network: "signet",
feeRateTolerance: 5,
confirmationTarget: 2,
maxFee: 1
};
export default clientConfig;
Then edit the file src/App.jsx
:
At the very top of the file, add the following two line:
import mercuryweblib from 'mercuryweblib';
import clientConfig from './ClientConfig';
Immediately after, the line function App() {
add the following lines:
const [inputWallet, setInputWallet] = useState('');
const [inputAmount, setInputAmount] = useState('1000');
const [inputStatechainId, setInputStatechainId] = useState('');
const [inputToAddress, setInputToAddress] = useState('');
const [batchId, setBatchId] = useState('');
const [isBatchTransfer, setBatchTransfer] = useState(false);
Then add wallet functions immediately after this section:
const createWallet = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
await mercuryweblib.createWallet(clientConfig, inputWallet);
console.log(`wallet ${inputWallet} created`);
setInputWallet('');
};
const newToken = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
await mercuryweblib.newToken(clientConfig, inputWallet);
console.log(`token created in the wallet ${inputWallet}` );
setInputWallet('');
};
const getDepositBitcoinAddress = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
if (inputAmount === '') {
console.log('Please enter an amount');
return;
}
const parsedAmount = parseInt(inputAmount, 10);
if (isNaN(parsedAmount)) {
console.error(`Error: Unable to convert "${inputAmount}" to an integer.`);
}
let btcAddr = await mercuryweblib.getDepositBitcoinAddress(clientConfig, inputWallet, parsedAmount);
console.log(`Address from wallet ${inputWallet}`);
console.log(btcAddr);
setInputWallet('');
};
const listStatecoins = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
const coins = await mercuryweblib.listStatecoins(clientConfig, inputWallet);
console.log(`Coins from wallet ${inputWallet}`);
console.log(coins);
setInputWallet('');
};
const withdrawCoin = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
if (inputStatechainId === '') {
console.log('Please enter a statechain id');
return;
}
if (inputToAddress === '') {
console.log('Please enter a recipient address');
return;
}
const txid = await mercuryweblib.withdrawCoin(clientConfig, inputWallet, inputStatechainId, inputToAddress, null);
console.log(`Withdraw txid: ${txid}`);
setInputWallet('');
setInputStatechainId('');
setInputToAddress('');
};
const broadcastBackupTransaction = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
if (inputStatechainId === '') {
console.log('Please enter a statechain id');
return;
}
if (inputToAddress === '') {
console.log('Please enter a recipient address');
return;
}
const txids = await mercuryweblib.broadcastBackupTransaction(clientConfig, inputWallet, inputStatechainId, inputToAddress, null);
console.log("Txids:");
console.log(txids);
setInputWallet('');
setInputStatechainId('');
setInputToAddress('');
};
const newTransferAddress = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
const transferAddress = await mercuryweblib.newTransferAddress(inputWallet, isBatchTransfer);
console.log(`Transfer address from wallet ${inputWallet}`);
console.log(transferAddress);
setInputWallet('');
};
const transferSend = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
if (inputStatechainId === '') {
console.log('Please enter a statechain id');
return;
}
if (inputToAddress === '') {
console.log('Please enter a recipient address');
return;
}
let batchIdToSend = null;
if (!!batchId) {
batchIdToSend = batchId;
}
console.log(`batchIdToSend: ${batchIdToSend}`);
const coin = await mercuryweblib.transferSend(clientConfig, inputWallet, inputStatechainId, inputToAddress, batchIdToSend);
console.log("Coin:");
console.log(coin);
setInputWallet('');
setInputStatechainId('');
setInputToAddress('');
};
const transferReceive = async () => {
if (inputWallet === '') {
console.log('Please enter a wallet name');
return;
}
const received_statechain_ids = await mercuryweblib.transferReceive(clientConfig, inputWallet);
console.log("received_statechain_ids:");
console.log(received_statechain_ids);
setInputWallet('');
};
const handleIsBatchTransferChange = (event) => {
setBatchTransfer(event.target.checked);
};
Then finally add these HTML components (replace everything in the return( ... )
section):
<>
<div>
<a href="https://vitejs.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<input
type="text"
value={inputWallet}
onChange={(e) => setInputWallet(e.target.value)}
placeholder="Enter wallet name"
style={{ marginRight: '10px' }}
/>
<input
type="text"
value={inputAmount}
onChange={(e) => setInputAmount(e.target.value)}
placeholder="Enter amount"
style={{ marginRight: '10px' }}
/>
<input
type="text"
value={inputStatechainId}
onChange={(e) => setInputStatechainId(e.target.value)}
placeholder="Enter statechain id"
style={{ marginRight: '10px' }}
/>
<input
type="text"
value={inputToAddress}
onChange={(e) => setInputToAddress(e.target.value)}
placeholder="Enter recipient address"
style={{ marginRight: '10px' }}
/>
<input
type="text"
value={batchId}
onChange={(e) => setBatchId(e.target.value)}
placeholder="Enter batchId"
style={{ marginRight: '10px' }}
/>
<label>
<input
type="checkbox"
checked={isBatchTransfer}
onChange={handleIsBatchTransferChange}
/>
Is Batch Transfer ?
</label>
</div>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<button onClick={() => createWallet()}>
Create Wallet
</button>
<button onClick={() => newToken()}>
New Token
</button>
<button onClick={() => getDepositBitcoinAddress()}>
New Deposit Address
</button>
<button onClick={() => listStatecoins()}>
List Statecoins
</button>
<button onClick={() => withdrawCoin()}>
Withdraw
</button>
<button onClick={() => broadcastBackupTransaction()}>
Broadcast Backup Transaction
</button>
<br />
<button onClick={() => newTransferAddress()} style={{ marginTop: '10px' }}>
New Transfer Address
</button>
<button onClick={() => transferSend()} style={{ marginTop: '10px' }}>
Transfer Send
</button>
<button onClick={() => transferReceive()} style={{ marginTop: '10px' }}>
Transfer Receive
</button>
<p>
Edit <code>src/App.jsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
To run the demo-app in a browser:
npm run dev