Embed widget.
One script tag and a button. The flow opens in a modal on your page, the user signs in their own wallet, and the tokens never touch your site or ours.
Install#
Include the script once, then mark any button with data-hoodlock. Everything except
that attribute is optional — a lock-only integration is a button with nothing else on it.
<script src="https://hoodlock.tech/embed.js" data-key="pk_YOUR_KEY"></script>
<!-- lock is the default mode, so this is the whole integration -->
<button data-hoodlock>Lock tokens</button>
<!-- pre-fill the token so the user cannot pick a different one -->
<button data-hoodlock data-token="0xYourTokenAddress">Lock tokens</button>
<button data-hoodlock data-mode="burn" data-token="0xYourTokenAddress">Burn tokens</button>
<button data-hoodlock data-mode="vesting"
data-token="0xYourTokenAddress"
data-beneficiary="0xTeamWallet">Create vesting</button>0xYourTokenAddress is a placeholder. Insert the real address from your own data
when you render the page. It is different on every token page, so it is not a literal string to paste.
Your button keeps your styling#
The widget never touches how your button looks. It attaches a click handler and marks the element as wired; it sets no classes, no inline styles and no attributes that affect appearance. Style the button however you like — Tailwind, CSS modules, a design system component, anything.
This is worth stating plainly because it is the usual objection to embedded widgets: most teams want the functionality and their own design. Here you get both, because the only thing we render is the modal.
Attributes#
On the script tag#
| Attribute | Required | What it does |
|---|---|---|
data-key | yes | Your public API key. Without it the widget logs an error and does nothing. |
data-attribution | no | Set to off to leave out the “Secured by HoodLock” line. |
On a button#
| Attribute | Required | What it does |
|---|---|---|
data-hoodlock | yes | Marks the button. Nothing else is needed for a lock. |
data-mode | no | lock (default), burn or vesting. An unrecognised value falls back to lock. |
data-token | no | Pre-fills the token and makes the field read-only. Leave it out and the user picks from their own wallet. |
data-beneficiary | no | Vesting only. Pre-fills the recipient; the user can still edit it. |
data-unlock | no | Lock only. Pre-fills the unlock date as Unix seconds. |
JavaScript API#
window.HoodLock is available once the script has loaded.
// open programmatically
HoodLock.open({ token: "0x…", unlockTime: 1790000000 });
HoodLock.open({ mode: "burn", token: "0x…" });
HoodLock.open({ mode: "vesting", token: "0x…", beneficiary: "0x…" });
// one handler for every product
HoodLock.on("done", ({ type, txHash, id, token, amount }) => {
console.log(type, id, txHash); // type: "locked" | "burned" | "vested"
});
// or listen per product
HoodLock.on("locked", ({ txHash, id }) => refreshMyUi(id));
HoodLock.close(); // close the modal
HoodLock.wire(); // re-scan the DOM after rendering new buttonsCall HoodLock.wire() after any client-side render that adds buttons. It only picks
up elements it has not already wired, so calling it more than once is safe.
Events#
| Event | Payload | When |
|---|---|---|
ready | — | The modal has loaded. |
connected | { account } | The user connected a wallet. |
locked / burned / vested | { txHash, id, token, amount } | The action succeeded. |
done | the same payload plus type | Fires alongside each of the three above. |
error | { message } | Something failed. The message is already human-readable. |
close | — | The modal was dismissed. |
A payload can carry unconfirmed: true. That means the transaction was broadcast but
the receipt could not be fetched. It has most likely landed. Treat it as provisional and confirm against
the chain rather than telling the user it failed.
id is the on-chain record id and may be null if it could not be read back.
lockId is an alias kept for older integrations.
The attribution line#
The widget adds one small line after the last HoodLock button on the page:
<div class="hoodlock-attribution">
<a href="https://hoodlock.tech" rel="noopener">Secured by HoodLock</a>
</div>It inherits your text colour, appears once per page regardless of how many buttons you have, and is
a plain followable link. Turn it off with data-attribution="off" on the script tag if it does
not suit the design.
Framing and CSP#
The modal is an iframe from hoodlock.tech/embed. If your site sends a
Content-Security-Policy, allow it:
frame-src https://hoodlock.tech;
script-src https://hoodlock.tech;When the user has no wallet#
In-app browsers sometimes block wallet access inside an iframe. The widget detects that and offers a link that opens the same flow in a new tab, with your key carried through so the action still counts as yours. You do not need to handle it.
Earnings#
You earn 50% of the fee on every lock, burn and vesting schedule created by a wallet you introduced. Only genuinely new wallets count, first touch is permanent, and only actions after attribution qualify. Claim to your wallet from the developer dashboard once the balance passes $10.
Prefer to build the interface yourself? The REST API exposes the same three products as prepared transactions.