Skip to main content
Get your API key at hackathon-apikey.vercel.app.
Unlink supports two different DeFi patterns:
  • execute() for adapter-based contract calls from a user’s private balance
  • BurnerWallet for temporary EOAs that interact with external protocols directly

Which path should you use?

PatternBest forWhat stays privateWhat becomes public
execute()Structured smart contract integrations routed through the Unlink adapterSender identityCalldata target, token type, and amounts
BurnerWalletTemporary EOA-based app flows where a protocol expects a normal walletMain Unlink account identityBurner address activity while it is active

Option 1: execute()

Use execute() when you want to call contracts directly from a private Unlink balance and bring outputs back into the unlink contract in the same flow.
import { buildCall, toExecuteCall } from "@unlink-xyz/sdk";

// The npk field identifies which Unlink account receives the output.
// Pass your Unlink address; the backend derives the note key automatically.
const myAddress = await unlink.getAddress();

const swap = buildCall({
  to: "0xDeFiRouter",
  abi: "function swap(address tokenIn, address tokenOut, uint256 amount) returns (uint256)",
  functionName: "swap",
  args: [tokenIn, tokenOut, amount],
});

const result = await unlink.execute({
  withdrawals: [{ token: tokenIn, amount: "1000000000000000000" }],
  calls: [toExecuteCall(swap)],
  outputs: [
    {
      npk: myAddress,
      token: tokenOut,
      min_amount: "900000000000000000",
    },
  ],
  deadline: Math.floor(Date.now() / 1000) + 3600,
});

const confirmed = await unlink.pollTransactionStatus(result.txId);
Choose this path when:
  • you already know the contract call sequence
  • you want the private-balance flow to stay inside Unlink’s adapter model
  • you want outputs deposited back into the user’s private balance automatically
See Execute for the full parameter reference and calldata helpers.

Option 2: BurnerWallet

Use a burner when the external app expects a normal EOA and you want to isolate that activity from the user’s main account.

1. Create and fund a burner

import { BurnerWallet, createUnlinkClient, unlinkAccount } from "@unlink-xyz/sdk";

const client = createUnlinkClient(engineUrl, apiKey);
const burner = await BurnerWallet.create();

// Derive account keys from the same mnemonic used with createUnlink()
const account = unlinkAccount.fromMnemonic({ mnemonic });
const accountKeys = await account.getAccountKeys();

const result = await burner.fundFromPool(client, {
  senderKeys: accountKeys,
  token: tokenIn,
  amount: "1000000000000000000",
  environment: "base-sepolia",
});

2. Use the burner as a normal wallet

import { createWalletClient, http } from "viem";
import { baseSepolia } from "viem/chains";

const burnerWalletClient = createWalletClient({
  account: burner.toViemAccount(),
  chain: baseSepolia,
  transport: http(process.env.RPC_URL),
});
At that point the burner can approve, swap, lend, or otherwise interact like any ordinary EOA.

3. Deposit back and dispose

const info = await BurnerWallet.getInfo(client);

const depositBack = await burner.depositToPool(client, {
  unlinkAddress: accountKeys.address,
  token: tokenOut,
  amount: "900000000000000000",
  environment: "base-sepolia",
  chainId: info.chain_id,
  permit2Address: info.permit2_address,
  poolAddress: info.pool_address,
  deadline: Math.floor(Date.now() / 1000) + 3600,
});

await burner.dispose(client, depositBack.txId);
await burner.deleteKey();
Choose this path when:
  • the protocol expects a normal wallet UX
  • you need direct wallet compatibility rather than adapter-driven execution
  • you want a disposable address per session, strategy, or workflow
See Burner Wallet for the full lifecycle and required Permit2 approval step before depositToPool().

Practical guidance

  • Start with execute() if the interaction can be expressed as a small, known call graph
  • Use BurnerWallet when the protocol or frontend assumes a standard EOA session
  • Use burner flows for higher-friction wallet integrations, and adapter flows for tighter private-balance integrations
For most apps, both models are useful:
  • execute() for tightly integrated swaps and automated strategies
  • BurnerWallet for broader DeFi compatibility and disposable session wallets