Skip to content

TypeScript SDK

Installation

bun add @unionlabs/client

The Union Client is TypeScript-first and framework agnostic. At app.union.build we use Svelte but you can use any framework or no frameworks at all. If you’re a React developer, checkout this demo on Stackblitz.

Client Initialization

import {
function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount

@description Creates an Account from a private key.

@returnsA Private Key Account.

privateKeyToAccount
} from "viem/accounts"
import {
function createUnionClient(parameters: EvmClientParameters): ReturnType<(parameters: EvmClientParameters) => Client<FallbackTransport | HttpTransport | CustomTransport, {
blockExplorers: {
readonly default: {
readonly name: "Etherscan";
readonly url: "https://sepolia.etherscan.io";
readonly apiUrl: "https://api-sepolia.etherscan.io/api";
};
};
contracts: {
readonly multicall3: {
readonly address: "0xca11bde05977b3631167028862be2a173976ca11";
readonly blockCreated: 751532;
};
readonly ensRegistry: {
readonly address: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
};
readonly ensUniversalResolver: {
readonly address: "0xc8Af999e38273D658BE1b921b88A9Ddf005769cC";
readonly blockCreated: 5317080;
};
};
id: 11155111;
name: "Sepolia";
nativeCurrency: {
readonly name: "Sepolia Ether";
readonly symbol: "ETH";
readonly decimals: 18;
};
rpcUrls: {
readonly default: {
readonly http: readonly ["https://sepolia.drpc.org"];
};
};
sourceId?: number | undefined;
testnet: true;
custom?: Record<string, unknown> | undefined;
fees?: ChainFees<undefined> | undefined;
formatters?: undefined;
serializers?: ChainSerializers<undefined, TransactionSerializable> | undefined;
} | {
blockExplorers: {
readonly default: {
readonly name: "Scrollscan";
readonly url: "https://sepolia.scrollscan.com";
readonly apiUrl: ... (+2 overloads)

@example

import { createUnionClient } from "@union/client"
import { privateKeyToAccount } from "viem/accounts"
const client = createUnionClient({
chainId: "11155111",
transport: http("https://rpc.sepolia.org"),
account: privateKeyToAccount(`0x${PRIVATE_KEY}`) // or from wagmi configuration
})

createUnionClient
,
function http(url?: string | undefined, config?: HttpTransportConfig): HttpTransport

@description Creates a HTTP transport that connects to a JSON-RPC API.

http
} from "@unionlabs/client"
const
const client: Client<FallbackTransport | HttpTransport | CustomTransport, {
blockExplorers: {
readonly default: {
readonly name: "Etherscan";
readonly url: "https://sepolia.etherscan.io";
readonly apiUrl: "https://api-sepolia.etherscan.io/api";
};
};
... 10 more ...;
serializers?: ChainSerializers<undefined, TransactionSerializable> | undefined;
} | {
...;
} | {
...;
} | {
...;
}, Account | ... 1 more ... | undefined, WalletRpcSchema, {
...;
} & ... 1 more ... & WalletActions<...>>
client
=
function createUnionClient(parameters: EvmClientParameters): ReturnType<(parameters: EvmClientParameters) => Client<FallbackTransport | HttpTransport | CustomTransport, {
blockExplorers: {
readonly default: {
readonly name: "Etherscan";
readonly url: "https://sepolia.etherscan.io";
readonly apiUrl: "https://api-sepolia.etherscan.io/api";
};
};
contracts: {
readonly multicall3: {
readonly address: "0xca11bde05977b3631167028862be2a173976ca11";
readonly blockCreated: 751532;
};
readonly ensRegistry: {
readonly address: "0x00000000000C2E074eC69A0dFb2997BA6C7d2e1e";
};
readonly ensUniversalResolver: {
readonly address: "0xc8Af999e38273D658BE1b921b88A9Ddf005769cC";
readonly blockCreated: 5317080;
};
};
id: 11155111;
name: "Sepolia";
nativeCurrency: {
readonly name: "Sepolia Ether";
readonly symbol: "ETH";
readonly decimals: 18;
};
rpcUrls: {
readonly default: {
readonly http: readonly ["https://sepolia.drpc.org"];
};
};
sourceId?: number | undefined;
testnet: true;
custom?: Record<string, unknown> | undefined;
fees?: ChainFees<undefined> | undefined;
formatters?: undefined;
serializers?: ChainSerializers<undefined, TransactionSerializable> | undefined;
} | {
blockExplorers: {
readonly default: {
readonly name: "Scrollscan";
readonly url: "https://sepolia.scrollscan.com";
readonly apiUrl: ... (+2 overloads)

@example

import { createUnionClient } from "@union/client"
import { privateKeyToAccount } from "viem/accounts"
const client = createUnionClient({
chainId: "11155111",
transport: http("https://rpc.sepolia.org"),
account: privateKeyToAccount(`0x${PRIVATE_KEY}`) // or from wagmi configuration
})

createUnionClient
({
chainId: "80084",
EvmClientParameters.chainId: "11155111" | "534351" | "421614" | "80084"
EvmClientParameters.transport: FallbackTransport | HttpTransport | CustomTransport
transport
:
function http(url?: string | undefined, config?: HttpTransportConfig): HttpTransport

@description Creates a HTTP transport that connects to a JSON-RPC API.

http
("https://bartio.rpc.berachain.com"),
EvmClientParameters.account?: `0x${string}` | Account | undefined
account
:
function privateKeyToAccount(privateKey: Hex, options?: PrivateKeyToAccountOptions): PrivateKeyAccount

@description Creates an Account from a private key.

@returnsA Private Key Account.

privateKeyToAccount
(`0x${
var process: NodeJS.Process
process
.
NodeJS.Process.env: NodeJS.ProcessEnv

The process.env property returns an object containing the user environment. See environ(7).

An example of this object looks like:

{
TERM: 'xterm-256color',
SHELL: '/usr/local/bin/bash',
USER: 'maciej',
PATH: '~/.bin/:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin',
PWD: '/Users/maciej',
EDITOR: 'vim',
SHLVL: '1',
HOME: '/Users/maciej',
LOGNAME: 'maciej',
_: '/usr/local/bin/node'
}

It is possible to modify this object, but such modifications will not be reflected outside the Node.js process, or (unless explicitly requested) to other Worker threads. In other words, the following example would not work:

Terminal window
node -e 'process.env.foo = "bar"' &#x26;&#x26; echo $foo

While the following will:

import { env } from 'node:process';
env.foo = 'bar';
console.log(env.foo);

Assigning a property on process.env will implicitly convert the value to a string. This behavior is deprecated. Future versions of Node.js may throw an error when the value is not a string, number, or boolean.

import { env } from 'node:process';
env.test = null;
console.log(env.test);
// => 'null'
env.test = undefined;
console.log(env.test);
// => 'undefined'

Use delete to delete a property from process.env.

import { env } from 'node:process';
env.TEST = 1;
delete env.TEST;
console.log(env.TEST);
// => undefined

On Windows operating systems, environment variables are case-insensitive.

import { env } from 'node:process';
env.TEST = 1;
console.log(env.test);
// => 1

Unless explicitly specified when creating a Worker instance, each Worker thread has its own copy of process.env, based on its parent thread's process.env, or whatever was specified as the env option to the Worker constructor. Changes to process.env will not be visible across Worker threads, and only the main thread can make changes that are visible to the operating system or to native add-ons. On Windows, a copy of process.env on a Worker instance operates in a case-sensitive manner unlike the main thread.

@sincev0.1.27

env
.
string | undefined
PRIVATE_KEY
}`),
})

Transferring Assets

We will transfer 1 HONEY from Berachain bArtio to Stride Testnet.

You have the option to trigger the approval transaction manually by setting autoApprove to false then calling .approveTransaction before calling .transferAsset.

import { unionClient } from "./client.ts"
import type { TransferAssetsParameters } from "@unionlabs/client"
const transferPayload = {
amount: 1n,
autoApprove: false,
// ^ we will approve manually for this example
destinationChainId: "stride-internal-1",
receiver: "stride17ttpfu2xsmfxu6shl756mmxyqu33l5ljegnwps",
denomAddress: "0x0E4aaF1351de4c0264C5c7056Ef3777b41BD8e03",
// ^ HONEY contract address
} satisfies TransferAssetsParameters<"80084">
const approval = await unionClient.approveTransaction(transferPayload)
if (approval.isErr()) {
console.error(approval.error)
process.exit(1)
}
console.info(`Approval hash: ${approval.value}`)
const transfer = await unionClient.transferAsset(transferPayload)
if (transfer.isErr()) {
console.error(transfer.error)
process.exit(1)
}
console.info(`Transfer hash: ${transfer.value}`)

Run the above example

PRIVATE_KEY="" bun x tsx main.ts