
Security News
Critical Security Vulnerability in React Server Components
React disclosed a CVSS 10.0 RCE in React Server Components and is advising users to upgrade affected packages and frameworks to patched versions now.
@anastasia-labs/smart-handles-offchain
Advanced tools
Smart Handles is a customizable Cardano contract that allows users to circumvent frontend of their favorite DEXs for submitting a swap request. It does so by acting as an intermediary and offering a "router fee" to incentivise arbitrary entities for carrying out the swaps.
A valid UTxO for the contract address should have at most 2 assets, and a datum that carries 3 values:
The Reclaim endpoint only checks for the consent of its owner.
The Swap endpoint validates a few things:
The off-chain side determines the offered asset by inspecting the input value: if there is only one asset (i.e. Ada), it'll consider the request as a simple token purchase. However, if there are 2 assets, the other asset will be considered as the offer. It'll fail if there are more assets.
All endpoints provide two variants: single and batch. These two correspond
to two different script addresses. The former works for single
request/reclaim/swaps per transaction, while the latter allows batch actions.
Both variants of endpoints return a Result that, if successful, carries the
completed transaction (i.e. ready to be signed and submitted).
npm install @anastasia-labs/smart-handles-offchain
or:
pnpm install @anastasia-labs/smart-handles-offchain
To produce a valid UTxO at the smart script address, use either singleRequest
or batchRequest function. For each request, you'll need to provide a
SwapRequest:
type SwapRequest = {
fromAsset: Asset;
quantity: bigint;
toAsset: Asset;
}
Where Asset can either be "lovelace" or Unit of a token (which is the
concatenation of its policy ID and its token name in hex), and quantity is the
amount of the offered asset.
Here's an example for producing an Ada to MIN request UTxO:
import {
singleRequest,
SingleRequestConfig,
toUnit,
MIN_SYMBOL_PREPROD,
MIN_TOKEN_NAME,
} from "@anastasia-labs/smart-handles-offchain";
const requestConfig: SingleRequestConfig = {
swapRequest: {
fromAsset: "lovelace",
quantity: 50_000_000n,
toAsset: toUnit(MIN_SYMBOL_PREPROD, MIN_TOKEN_NAME),
},
testnet: true,
};
// Assuming `lucid` is already set up for the user
const requestTxUnsigned = await singleRequest(lucid, requestConfig);
if (requestTxUnsigned.type == "error") {
throw requestTxUnsigned.error;
} else {
const requestTxSigned = await requestTxUnsigned.data.sign().complete();
const requestTxHash = await requestTxSigned.submit();
await lucid.awaitTx(requestTxHash);
}
You can either fetch all the request UTxOs (at either single or batch scripts),
or only grab the ones belonging to a specific user.
import { fetchSingleRequestUTxOs } from "@anastasia-labs/smart-handles-offchain";
const allSingleRequests = await fetchSingleRequestUTxOs(
lucid, // Selected wallet here doesn't matter
true // Indicates that it is intended for testnet (preprod)
);
Any user can retract from their swap requests at any time. Here's a batch example:
import {
batchReclaim,
BatchReclaimConfig,
fetchUsersBatchRequestUTxOs,
} from "@anastasia-labs/smart-handles-offchain";
// Assuming `lucid` is already set up for the user
const usersAddress = await lucid.wallet.address();
const usersUTxOs = await fetchUsersBatchRequestUTxOs(
lucid, // Here selected wallet in `lucid` doesn't matter
usersAddress,
true // For testnet
);
const reclaimConfig: BatchReclaimConfig = {
requestOutRefs: usersUTxOs.map(u => u.outRef),
testnet: true,
};
// This instance of `lucid` needs to belong to the user
const reclaimTxUnsigned = await batchReclaim(lucid, reclaimConfig);
// ...plus further steps for submitting the transaction.
If the reward address of the staking validator is not already registered, you'll need to submit its registration transaction (costs about 2.2 Ada).
This is only required for batch actions as they utilize the "withdraw 0 trick."
import {
getBatchVAs,
BatchVAs,
Lucid,
} from "@anastasia-labs/smart-handles-offchain"
// We first need to grab the stake validator's address:
const batchVAsRes = getBatchVAs(lucid, true);
if (batchVAsRes.type == "error") return batchVAsRes;
const batchVAs: BatchVAs = batchVAsRes.data;
const rewardAddress = batchVAs.stakeVA.address;
// The selected wallet will pay for the registration fee:
const registerationTxUnsigned = await lucid
.newTx()
.registerStake(rewardAddress)
.complete();
const registerationTxSigned = await registerationTxUnsigned
.sign()
.complete();
const registerationTxHash = await registerationTxSigned.submit();
await lucid.awaitTx(registerationTxHash);
Anyone can spend a smart handle UTxO as long as they perform the requested swap
properly. The ROUTER_FEE is for incentivising third parties for carrying out
swaps.
Note that the pool ID is optional: If it's set, there won't be any validation for its correctness. And if it's not set, it'll fetch all the Minswap pools in order to find the desired pool ID.
MIN-to-tBTC example transactions below are carried out without specifying the pool ID.
import {
batchSwap,
BatchSwapConfig,
fetchBatchRequestUTxOs,
} from "@anastasia-labs/smart-handles-offchain";
const allUTxOs = await fetchBatchRequestUTxOs(lucid, true);
const swapConfig: BatchSwapConfig = {
swapConfig: {
blockfrostKey: "routing agent's blockfrost key",
poolId: "OPTIONAL pool ID or token name of the corresponding LP token",
slippageTolerance: 20n,
},
requestOutRefs: allUTxOs.map(u => u.outRef),
testnet: true,
};
// Assuming `lucid` is set up for the routing agent
const swapTxUnsigned = await batchSwap(lucid, swapConfig);
// ...plus further steps for submitting the transaction.
Reward address registration: 8227766d19fea7523ec78262230dfbc25cc00d238759df967d381dddb655f421
Batch swap requests: 272c43a0e8427ad69d5321b287ad2ce4135ceeb23d8e6016c53353634fbd8831
Batch swap by routing agent: cdb903d2e22bed41f52f0afa2fed91da6633a68f858fe587de784fc1bf92b5de
Batch swap requests: 4343f9ac73f83b04a37fab998bddf3e1294597f3e81df5b8278860ceeb989668
Batch swap by routing agent: a2c62eb9218110f8d6cc3e55730c310a162ecfc22d38dd2a25e321641a61d873
While this SDK is currently curated for working with Minswap V1, in near future it'll also offer interfaces for providing customized variants of the base contract. Meaning for example choosing between other DEXs, or perhaps requiring more strict validations.
FAQs
https://docs.github.com/en/packages/quickstart
The npm package @anastasia-labs/smart-handles-offchain receives a total of 9 weekly downloads. As such, @anastasia-labs/smart-handles-offchain popularity was classified as not popular.
We found that @anastasia-labs/smart-handles-offchain demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
React disclosed a CVSS 10.0 RCE in React Server Components and is advising users to upgrade affected packages and frameworks to patched versions now.

Research
/Security News
We spotted a wave of auto-generated “elf-*” npm packages published every two minutes from new accounts, with simple malware variants and early takedowns underway.

Security News
TypeScript 6.0 will be the last JavaScript-based major release, as the project shifts to the TypeScript 7 native toolchain with major build speedups.