Skip to content

@futureverse/transact

Higher-level API for building, sponsoring, and submitting transactions on TRN — handles fee proxying, futurepass proxy wrapping, and gasless flows.

Futureverse winddown

Futureverse (the publisher of @futureverse/*) is in winddown. The hosted services this package talked to (auth.futureverse.app, pass-api.futureverse.app, signer.futureverse.app) have been re-hosted by gen3labs at futurepass.gen3labs.tech (issuer) and fpsigner.gen3labs.tech (signer). For new projects, switch to the matching @gen3labs/* package — drop-in surface, default URLs already point at the gen3labs infra. The Asset Register API has no community replacement yet; see the Migration playbook for the per-package map.

Version
0.8.0
Published
2025-08-14
License
n/a
Status
fv-winddown
npm
https://www.npmjs.com/package/@futureverse/transact
Types
./index.d.ts
Maintainers
admin-futureverse, garethdainesnpm, jcsanpedro
Depends on
viem · @polkadot/api · @polkadot/util · @polkadot/types · @futureverse/signer · ripple-binary-codec · @polkadot/util-crypto · @therootnetwork/api-types
Recent versions
0.6.0 · 0.6.1 · 0.7.0 · 0.7.1 · 0.7.0-beta.0 · 0.7.0-beta.1 · 0.7.2 · 0.8.0
## Technical notes

Why use it

You want one method to "send this call" without manually choosing between EVM eth_sendTransaction, Substrate signAndSend, FuturePass proxyExtrinsic, or FeeProxy callWithFeePreferences. Especially valuable when the user is signed in via FuturePass (custodial) — transact routes the call through the right precompile/pallet.

When to skip it

You only ever call vanilla EVM contracts with a wallet-held key. Then plain viem writeContract is simpler.

Pairs with

Alternatives

Example

ts
import { TransactClient } from '@futureverse/transact';

const client = new TransactClient({ chain: 'root', signer });
const result = await client.send(
  client.tx.assets.transfer({ assetId: 2, to: recipient, amount: 1_000_000n }),
  { feePreference: { assetId: 1 } } // pay in ROOT
);

Gotchas

  • When the signer is a FuturePass session, the call is wrapped in futurepass.proxyExtrinsic automatically — make sure the FuturePass owns the funds you’re moving.
  • Fee preference defaults to native XRP unless overridden.

Upstream README

Futureverse Transact Library

An API to help facilitate transactions on The Root Network

Installation

NPM:

bash
npm install @futureverse/transact --save

Yarn:

bash
yarn add @futureverse/transact

Dependancies

json
{
  "@futureverse/signer": "0.6.6",
  "@polkadot/api": "^10.13.1",
  "@polkadot/util": "^12.6.2",
  "@polkadot/util-crypto": "^12.6.2",
  "@polkadot/types": "^10.13.1",
  "@therootnetwork/api-types": "^1.0.3",
  "viem": "^2.18.1"
}

Usage

This example shows how to mint an NFT on a Root Network Collection

typescript
import { useAuth, useFutureverseSigner } from '@futureverse/auth-react';
import { TransactionBuilder } from '@futureverse/transact';
import { useTrnApi } from '@futureverse/transact-react';

const { userSession } = useAuth();
const [builder, setBuilder] = useState();
const signer = useFutureverseSigner();
const { trnApi } = useTrnApi();

const triggerInit = useCallback(async () => {
  if (!trnApi || !signer || !userSession) {
    return null;
  }

  const nftBuilder = await TransactionBuilder.nft(trnApi, signer, userSession.eoa, 709732).mint({ quantity: 1, walletAddress: userSession?.futurepass });

  setBuilder(nftBuilder);
}, [trnApi, signer, userSession]);

const signExtrinsic = useCallback(async () => {
  if (builder) {
    const result = await builder?.signAndSend({ onSign, onSend });
    setResult(result as ExtrinsicResult);
  }
}, [builder, onSend, onSign, toSign]);

return (
  <>
    <button
      onClick={() => {
        triggerInit();
      }}
    >
      Mint 1 Nft
    </button>

    <button
      onClick={() => {
        signExtrinsic();
      }}
    >
      Sign &amp; Send
    </button>
  </>
);

This example shows how to transfer a token to an wallet address on a Root Network Collection, but minting using the Fee Proxy to pay for gas with a chosen token.

typescript
import { useAuth, useFutureverseSigner } from '@futureverse/auth-react';
import { TransactionBuilder } from '@futureverse/transact';
import { useTrnApi } from '@futureverse/transact-react';

const { userSession } = useAuth();
const [builder, setBuilder] = useState();
const signer = useFutureverseSigner();
const { trnApi } = useTrnApi();

const triggerInit = useCallback(async () => {
  if (!trnApi || !signer || !userSession) {
    return null;
  }

  const nftBuilder = await TransactionBuilder.transfer({ destinationAddress: userSession?.futurepass, amount: 1 }).addFeeProxy({ assetId: ROOT_TOKEN_ID, slippage: 5 });

  setBuilder(nftBuilder);
}, [trnApi, signer, userSession]);

const signExtrinsic = useCallback(async () => {
  if (builder) {
    const result = await builder?.signAndSend({ onSign, onSend });
    setResult(result as ExtrinsicResult);
  }
}, [builder, onSend, onSign, toSign]);

return (
  <>
    <button
      onClick={() => {
        triggerInit();
      }}
    >
      Mint 1 Nft
    </button>

    <button
      onClick={() => {
        signExtrinsic();
      }}
    >
      Sign &amp; Send
    </button>
  </>
);

This example shows how to mint an NFT on a Root Network Collection, but minting using the FuturePass to pay the gas.

typescript
import { useAuth, useFutureverseSigner } from '@futureverse/auth-react';
import { TransactionBuilder } from '@futureverse/transact';
import { useTrnApi } from '@futureverse/transact-react';

const { userSession } = useAuth();
const [builder, setBuilder] = useState();
const signer = useFutureverseSigner();
const { trnApi } = useTrnApi();

const triggerInit = useCallback(async () => {
  if (!trnApi || !signer || !userSession) {
    return null;
  }

  const nftBuilder = await TransactionBuilder.nft(trnApi, signer, userSession.eoa, 709732).mint({ quantity: 1, walletAddress: userSession?.futurepass }).addFuturePass(userSession.futurepass);

  setBuilder(nftBuilder);
}, [trnApi, signer, userSession]);

const signExtrinsic = useCallback(async () => {
  if (builder) {
    const result = await builder?.signAndSend({ onSign, onSend });
    setResult(result as ExtrinsicResult);
  }
}, [builder, onSend, onSign, toSign]);

return (
  <>
    <button
      onClick={() => {
        triggerInit();
      }}
    >
      Mint 1 Nft
    </button>

    <button
      onClick={() => {
        signExtrinsic();
      }}
    >
      Sign &amp; Send
    </button>
  </>
);

This example shows how to batch multiple transactions on The Root Network Collection together and send them using the FuturePass to pay the gas combined with the fee proxy to pay with a chosen token.

typescript
import { useAuth, useFutureverseSigner } from '@futureverse/auth-react';
import { TransactionBuilder } from '@futureverse/transact';
import { useTrnApi } from 'providers/TRNProvider';

const { userSession } = useAuth();
const [builder, setBuilder] = useState();
const signer = useFutureverseSigner();
const { trnApi } = useTrnApi();

const triggerInit = useCallback(async () => {
  if (!trnApi || !signer || !userSession) {
    return null;
  }

  const tx1 = trnApi?.tx?.nft.mint(709732, 1, eoa);
  const tx2 = trnApi?.tx?.nft.mint(709732, 5, fp);
  const tx3 = trnApi?.tx?.assetsExt.transfer(1, fp, 1, true);
  const tx4 = trnApi?.tx?.assetsExt.transfer(2, fp, 10, true);
  const tx5 = trnApi?.tx?.nft.mint(709732, 3, eoa);

  const batchBuilder = await TransactionBuilder.batch(trnApi, signer, userSession.eoa).addExtrinsic(tx1).addExtrinsic(tx2).addExtrinsic(tx3).addExtrinsic(tx4).addExtrinsic(tx5).batchAll().addFuturePassAndFeeProxy({
    futurePass: userSession.futurepass,
    assetId: assetId,
    slippage: 5,
  });

  setBuilder(nftBuilder);
}, [trnApi, signer, userSession]);

const signExtrinsic = useCallback(async () => {
  if (builder) {
    const result = await builder?.signAndSend({ onSign, onSend });
    setResult(result as ExtrinsicResult);
  }
}, [builder, onSend, onSign, toSign]);

return (
  <>
    <button
      onClick={() => {
        triggerInit();
      }}
    >
      Mint 1 Nft
    </button>

    <button
      onClick={() => {
        signExtrinsic();
      }}
    >
      Sign &amp; Send
    </button>
  </>
);

Curated independently by Codeology. Source-attributed reference for The Root Network. Not affiliated with Futureverse / TRN Labs.