Skip to content
SwapDK is a powerful suite of tools for building blockchain applications.

NEAR Integration

This guide covers the NEAR Protocol integration in SwapDK, including the NEAR toolbox for direct blockchain operations and the NEAR plugin for enhanced features like NEAR Names service.

The NEAR integration provides:

  • NEAR Toolbox: Core blockchain operations (transfers, balance queries, contract interactions)
  • NEAR Plugin: NEAR Names service and cross-chain swaps via NEAR
  • NEP-141 Support: Full support for NEAR’s fungible token standard
  • Implicit Accounts: Support for NEAR’s unique implicit account system
  • Contract Factory: Type-safe contract interactions
Terminal window
# Using the full SDK (recommended)
npm install @swapdk/sdk
# Or individual packages for smaller bundles
npm install @swapdk/toolboxes @swapdk/plugins
// @noErrorValidation
import { createSwapKit } from '@swapdk/sdk';
const swapDK = createSwapKit();
const nearWallet = await swapDK.getWallet(Chain.Near);

NEAR supports two types of accounts:

  • Named accounts: Human-readable names like alice.near
  • Implicit accounts: 64-character hex strings derived from public keys
// @noErrorValidation
const toolbox = await getNearToolbox({
phrase: "your mnemonic phrase",
});
const accountId = toolbox.getAddress();
console.log(accountId);
const publicKey = await toolbox.getPublicKey();
console.log(publicKey);
// @noErrorValidation
import { AssetValue } from "@swapdk/sdk";
const txHash = await toolbox.transfer({
recipient: "receiver.near",
assetValue: AssetValue.from({
chain: Chain.Near,
value: "1.5",
}),
memo: "Payment for services",
});
console.log(`Transaction hash: ${txHash}`);

NEP-141 is NEAR’s fungible token standard, similar to ERC-20 on Ethereum.

// @noErrorValidation
const usdcTransfer = await toolbox.transfer({
recipient: "receiver.near",
assetValue: AssetValue.from({
chain: Chain.Near,
symbol: "USDC",
address: "usdc.near",
value: "100",
}),
});
const usdcToken = await toolbox.nep141("usdc.near");
const metadata = await usdcToken.getMetadata();
console.log(metadata);
const storage = await usdcToken.getStorageBalance("receiver.near");
if (!storage || storage.total === "0") {
await usdcToken.storageDeposit({
accountId: "receiver.near",
registrationOnly: true,
});
}
await usdcToken.ftTransfer({
receiverId: "receiver.near",
amount: "100000000",
memo: "USDC transfer",
});

The NEAR toolbox provides multiple ways to interact with smart contracts:

// @noErrorValidation
const result = await toolbox.callFunction({
contractId: "my-contract.near",
methodName: "set_value",
args: { key: "name", value: "Alice" },
attachedDeposit: "1000000000000000000000000",
});
const value = await toolbox.viewFunction("my-contract.near", "get_value", {
key: "name",
});

For better type safety and developer experience:

// @noErrorValidation
const contractInterface = {
contractId: "my-dapp.near",
viewMethods: ["get_balance", "get_user_info"],
changeMethods: ["deposit", "withdraw", "transfer"],
};
const contract = await toolbox.createContract(contractInterface);
const balance = await contract.get_balance({ account: "alice.near" });
const txResult = await contract.deposit({}, "1000000000000000000000000");

NEAR allows creating sub-accounts under your main account:

// @noErrorValidation
const subAccountId = `sub.${accountId}.near`;
const subAccountPubKey = "ed25519:...";
const txHash = await toolbox.createSubAccount(
subAccountId,
subAccountPubKey,
"5"
);
console.log(`Created sub-account: ${subAccountId}`);

NEAR uses a fixed gas price determined by the network, so there’s no concept of fee priority:

// @noErrorValidation
const transferFee = await toolbox.estimateTransactionFee({
recipient: "receiver.near",
assetValue: AssetValue.from({ chain: Chain.Near, value: "1" }),
});
import { estimateGas } from "@swapdk/toolboxes/near";
const gasEstimate = await estimateGas(
{
sender: accountId,
receiver: "contract.near",
actions: [
{
type: "FunctionCall",
methodName: "complex_operation",
args: {
/* ... */
},
attachedDeposit: "0",
},
],
},
account
);
console.log(`Estimated gas: ${gasEstimate} TGas`);

The NEAR plugin extends SwapDK with NEAR-specific features:

NEAR Names is a decentralized naming service similar to ENS on Ethereum:

// @noErrorValidation
import { SwapKit } from "@swapdk/sdk";
const swapDK = SwapKit.create();
const isAvailable = await swapDK.nearNames.isAvailable("myname");
if (isAvailable) {
const txHash = await swapDK.nearNames.register({
name: "myname",
publicKey: "ed25519:...",
});
console.log(`Registered myname.near: ${txHash}`);
}
const owner = await swapDK.nearNames.resolve("alice");
console.log(`alice.near is owned by: ${owner}`);
const info = await swapDK.nearNames.getInfo("alice");
console.log(info);
const names = await swapDK.nearNames.lookupNames(
"8fac9c5b1f4e8b4c9a7d2e6f1a3b5c7d9e2f4a6b8c1d3e5f7a9b1c3d5e7f9a1b"
);
console.log(`Names owned: ${names}`);
const transferTx = await swapDK.nearNames.transfer("myname", "new-owner.near");

The NEAR plugin supports cross-chain swaps using NEAR as an intermediary:

// @noErrorValidation
const quote = await swapDK.getQuote({
sellAsset: "ETH.ETH",
sellAmount: "0.1",
buyAsset: "NEAR.NEAR",
senderAddress: "0x...",
recipientAddress: "receiver.near",
});
const swapTx = await swapDK.swap({
route: quote.routes[0],
recipient: "receiver.near",
});

NEAR Protocol uses a fixed gas price determined by the network validators. Unlike some other chains, NEAR doesn’t support fee priority or multipliers - all transactions pay the same gas price:

// @noErrorValidation
const fee = await toolbox.estimateTransactionFee({
recipient: "receiver.near",
assetValue: AssetValue.from({ chain: Chain.Near, value: "1" }),
});

NEAR operations can throw specific errors that should be handled:

// @noErrorValidation
import { SwapKitError } from "@swapdk/sdk";
try {
await toolbox.transfer({
/* ... */
});
} catch (error) {
if (error instanceof SwapKitError) {
switch (error.code) {
case "toolbox_near_no_signer":
console.error("No signer available");
break;
case "toolbox_near_invalid_address":
console.error("Invalid NEAR address");
break;
case "toolbox_near_invalid_amount":
console.error("Invalid transfer amount");
break;
case "toolbox_near_transfer_failed":
console.error("Transfer failed:", error.cause);
break;
case "plugin_near_invalid_name":
console.error("Invalid NEAR name format");
break;
default:
console.error("Unknown error:", error);
}
}
}

You can provide your own signer implementation:

// @noErrorValidation
import { KeyPair } from "near-api-js/lib/utils";
const customSigner = {
keyPair: KeyPair.fromString("ed25519:..."),
async getPublicKey() {
return this.keyPair.getPublicKey();
},
async signMessage(message: Uint8Array) {
const signature = this.keyPair.sign(message);
return { signature: signature.signature };
},
};
const toolbox = await getNearToolbox({
signer: customSigner,
accountId: "custom.near",
});

To use NEAR testnet:

// @noErrorValidation
import { SKConfig } from '@swapdk/sdk';
SKConfig.setEnv('isStagenet', true);
SKConfig.setRpcUrl(Chain.Near, 'https://example.com'
const toolbox = await getNearToolbox({ phrase: "..." });

The toolbox provides utility functions for gas calculations:

// @noErrorValidation
import { tgasToGas, gasToTGas } from "@swapdk/toolboxes/near";
const gasUnits = tgasToGas("30");
const tgas = gasToTGas("30000000000000");
  1. Always validate addresses before sending transactions:

    import { validateNearAddress } from "@swapdk/toolboxes/near";
    if (!validateNearAddress(recipient)) {
    throw new Error("Invalid NEAR address");
    }
  2. Check storage deposits for NEP-141 tokens:

    const token = await toolbox.nep141("token.near");
    const storage = await token.getStorageBalance(recipient);
    if (!storage || BigInt(storage.total) === 0n) {
    await token.storageDeposit({ accountId: recipient });
    }
  3. Use appropriate gas amounts for contract calls:

    const gas = tgasToGas("100");
  4. Handle implicit accounts carefully:

    const implicitAccount =
    "8fac9c5b1f4e8b4c9a7d2e6f1a3b5c7d9e2f4a6b8c1d3e5f7a9b1c3d5e7f9a1b";
    try {
    const balance = await toolbox.getBalance(implicitAccount);
    } catch {}