🚨 Shai-Hulud Strikes Again:834 Packages Compromised.Technical Analysis →
Socket
Book a DemoInstallSign in
Socket

@anastasia-labs/smart-handles-offchain

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@anastasia-labs/smart-handles-offchain

https://docs.github.com/en/packages/quickstart

npmnpm
Version
0.2.0
Version published
Weekly downloads
9
350%
Maintainers
1
Weekly downloads
 
Created
Source

Table of Contents

Off-Chain SDK for Smart Handles

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.

Contract Logic

A valid UTxO for the contract address should have at most 2 assets, and a datum that carries 3 values:

  • Address of the owner
  • Policy ID of the desired asset
  • Token name of the desired asset

The Reclaim endpoint only checks for the consent of its owner.

The Swap endpoint validates a few things:

  • Index of the UTxO matches the one specified by the redeemer
  • The reproduced UTxO is going to the swap address (specified as a parameter)
  • The new UTxO at the swap address carries an identical value with the router fee deduced
  • Exactly 1 UTxO is getting spent from the smart handle script (the batch version doesn't require this)
  • The custom validation function passes (this is the customizable part of the contract, currently implemented for Minswap)

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.

How to Use

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).

Install Package

npm install @anastasia-labs/smart-handles-offchain

or:

pnpm install @anastasia-labs/smart-handles-offchain

Submit One or More Request UTxOs

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);
}

Fetch Swap Requests

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)
);

Reclaim a Swap Request

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.

Register the Staking Validator (Optional)

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);

Perform a Swap by Routing Agent

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.

Sample Transactions on Preprod

Common

Reward address registration: 8227766d19fea7523ec78262230dfbc25cc00d238759df967d381dddb655f421

ADA to MIN

Batch swap requests: 272c43a0e8427ad69d5321b287ad2ce4135ceeb23d8e6016c53353634fbd8831

Batch swap by routing agent: cdb903d2e22bed41f52f0afa2fed91da6633a68f858fe587de784fc1bf92b5de

MIN to tBTC

Batch swap requests: 4343f9ac73f83b04a37fab998bddf3e1294597f3e81df5b8278860ceeb989668

Batch swap by routing agent: a2c62eb9218110f8d6cc3e55730c310a162ecfc22d38dd2a25e321641a61d873

Future

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

Package last updated on 07 Jun 2024

Did you know?

Socket

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.

Install

Related posts