Integrating with your Dapp

We're currently upgrading the Light SDK. Below you find the legacy widget-based integration. Pure SDK integration without Widget coming soon.
👇

Off-ramp

The Light Widget Off-ramp can be used to initiate a token transfer from a user's shielded balance to a regular Solana wallet address. It supports various use cases, such as:
  • Private checkout
  • Funding new burner wallets
  • Funding a trading or margin account
  • Funding an NFT bidding wallet
  • & more
Users need to have an existing Light shielded balance to use the off-ramp. Refer to this page for details.
The most basic integration requires only one URL call.
// Define recipient solana address
const recipient = 'BTknD32D76aoNGfMce2RsZTSBFE1SqLkpdZgdZ3RfmCW';
// Define amount in lamports
const amount = '1000000'
// Trigger popup widget
const popupWindow = window.open(
`https://widget.lightprotocol.com?token=${'SOL'}&recipient=${recipient}&amount=${amount}`,
'_blank', // https://dev.widget.lightprotocol.com for devnet
`left=0,top=0,width=500,height=700`,
);
You can test the integration by opening your developer console and executing the above code snippet inside your browser console

Option URL parameters

  • You can pass an arbitrary handle i.e. 'Arbitrary+string' which will then be rendered in the widget:

Advanced usage

The Light Widget sends events (popup close, success, ...) as messages back to your website using window.postMessage()
Read more about postmessage here:
You can choose to handle these messages like so:
// optional: listen to success message and handle arbitrarily
let result = await new Promise((resolve, reject) => {
window.onmessage = (event) => {
if (event.origin === 'https://widget.lightprotocol.com') {
// https://dev.widget.lightprotocol.com for devnet
if (event.data.amount && event.data.recipient) {
if (
event.data.recipient === recipient &&
Number(event.data.amount) === Number(amount)
) {
if (event.data.unshieldSuccess) {
resolve(true);
} else {
reject('Unshielding failed.');
}
} else {
reject('Wrong recipient or amount.');
}
} else if (event.data.unshieldSuccess === false && event.data.message) {
// This will enter if anything goes wrong inside the widget, i.e. no shielded funds,...
// you can choose to handle these events
// i.e. close popoup: popupWindow.close()
// and print event.data.message next to the button.
console.log(event.data.message);
} else {
console.log('Ignoring external event.');
}
}
};
// Handle popup close
var timer = window.setInterval(function () {
if (popupWindow.closed) {
window.clearInterval(timer);
reject('Popup closed.');
}
}, 1000);
});

On-ramp

// Define amount in lamports
const amount = '1000000'
// Trigger popup widget
const popupWindow = window.open(
`https://widget.lightprotocol.com?a=shield&token=${'SOL'}&amount=${amount}`,
'_blank', // https://dev.widget.lightprotocol.com for devnet
`left=0,top=0,width=500,height=700`,
);

Fetching Shielded balance

1. Trigger widget popup

const popupWindow = window.open(
`http://widget.lightprotocol.com?a=balance`, // https://dev.widget.lightprotocol.com? for devnet
'_blank',
`left=0,top=0,width=500,height=700`,
);

2. Wait for balance to be passed down from the widget

var privateBalance;
let result = await new Promise((resolve, reject) => {
window.onmessage = (event) => {
if (event.origin === 'https://widget.lightprotocol.com') {
// https://dev.widget.lightprotocol.com for devnet
if (event.data.amount) {
console.log('Balance: ', event.data.amount); // lamports as String
privateBalance = Number(event.data.amount); //
} else {
console.log('Ignoring external event.');
}
}
};
// Handle premature popup close
var timer = window.setInterval(function () {
if (popupWindow.closed) {
window.clearInterval(timer);
reject('Popup closed.');
}
}, 1000);
});