Headless Client Quickstart
This SDK only supports the cross-chain swaps service. For access to the on/offramp or exchange services, see the Commerce Widget documentation.
The Halliday Payments Headless Client allows developers to build commerce into DApps without rendering any Halliday UI elements.
It provides a maximally flexible integration, enabling developers to build custom swap interfaces or integrate swap functionality into existing systems without a predefined UI.
To get the simplest means of integrating swaps, see the Commerce Widget documentation.
Installation
First, install the Halliday Payments SDK in the root folder of a web project.
npm install @halliday-sdk/commerce
Next, import the Halliday Payments SDK into an existing application.
import { HallidaySwapClient } from '@halliday-sdk/commerce';
Initialize the Client
First, create a swap client using an account's apiKey
.
const client = await HallidaySwapClient.create({ apiKey });
To use testnets, construct a sandbox client.
const client = await HallidaySwapClient.create({ apiKey, useSandbox: true });
HallidaySwapClient Object
Name | Type | Description |
---|---|---|
isInitialized | function | Check if the HallidaySwapClient is initialized. Returns a boolean. |
isAuthenticated | function | Check if the HallidaySwapClient is authenticated. Authentication is required to access the Halliday Swap functionality. Returns a boolean. |
login | function | Authenticate the HallidaySwapClient. Accepts an Ethers 6 Signer object and an optional chain ID as a number. Returns a boolean. |
createSwap | function | Creates a new swap. Accepts the source and destination address as strings, both optional. Returns a Swap object wrapped in a promise. |
getStatus | function | Get the status of a swap. Accepts an object with a swapId . Returns a SwapStatus object wrapped in a promise. |
getActiveSwaps | function | Get all active swaps for the authenticated user. Returns an array of Swap objects wrapped in a promise. |
recover | function | Recovers a swap if the session is interrupted. Accepts an object with a swapId . Returns a Swap object wrapped in a promise. |
getSupportedInputs | function | Get supported input tokens for a swap. If outputToken (optional string) is provided, an array of supported input tokens for the output token is returned. If outputToken is not provided, an array of all supported input tokens is returned. |
getSupportedOutputs | function | Get supported output tokens for swap. If inputToken (optional string) is provided, returns the list of supported output tokens for the input token. If inputToken is not provided, returns the list of all supported output tokens. |
logout | function | Performs a logout of the HallidaySwapClient. Returns a promise that resolves when complete. |
Authenticate the User
Authenticate to the client by prompting the user to sign a message.
const provider = new ethers.BrowserProvider(window.ethereum);
const signer = await provider.getSigner();
const client = await HallidaySwapClient.create({ apiKey });
if (!client.isAuthenticated()) {
const chainId = 42161; // Arbitrum, our swap's source token chain ID
await client.login(signer, chainId);
}
Get a Quote
Next, create a swap by providing a source of funds sourceAddress
and recipient destinationAddress
.
// Get the user's wallet address from the Ethers signer object
const sourceAddress = signer.address, destinationAddress = signer.address;
const swap = await client.createSwap({ sourceAddress, destinationAddress })
Fetch a quote for a given inputToken
, outputToken
, and inputAmount
.
const quote = await swap.getQuoteExactInput({
inputToken: {
chainId: 42161,
address: '0xaddress'
},
outputToken: {
chainId: 42161,
address: '0xaddress'
},
inputAmount: 1.234
});
Funding the Swap and Accepting a Quote
Next, ensure the user approves or transfers in any necessary funds to perform the swap.
const approvalReqs = quote.approvalNeeded();
const transferReqs = quote.transferInNeeded();
The approvalReqs
will describe the amount and token needing approval, if necessary. The transferReqs
will describe the amount and token needing to be transferred into the smart account, if necessary.
const transferInNeeded = quote.transferInNeeded();
const { amount, chainId, toAddress, tokenAddress } = transferInNeeded;
// Transfer the precise amout of swap input token to the smart account
const token = new ethers.Contract(tokenAddress, erc20Abi, signer);
const decimals = await token.decimals();
const transferAmount = amount * Math.pow(10, Number(decimals));
const tx = await token.transfer(toAddress, transferAmount);
await tx.wait();
If the user chooses to accept the quote, call the accept method on the quote object.
await quote.accept();
Alternatively, the user can request another quote using the same method as above.
Finally, wait for the swap to complete. In the event that the quote can no longer be obtained without slippage, new adjusted quotes will be provided that can be accepted or rejected.
for await (const newQuote of quote.acceptAndWait()) {
if (await user.ask(newQuote)) {
newQuote.accept();
} else {
newQuote.reject();
}
Recovering from Session Interruptions
If a session is interrupted by closing the browser window, it can be resumed by getting the active swaps and recovering.
const swaps = await client.getActiveSwaps();
// ...
const swap = await client.recover({ swapId });
await swap.execute();
await swap.wait();
Example Custom Interface with the Headless Client
Below is an HTML and vanilla JS example for implementing the Halliday Payments Headless SDK to do a cross chain swap with a custom interface.

The source code for this app can be found in this GitHub Gist (opens in a new tab).