Palma Network Overview
TRADING PLATFORMTRADING BOTWEBSITE
  • Welcome, mates!
    • Introduction
    • Quick Start Guide
    • Vision & Principles
  • MORE ABOUT PALMA
    • DeFi Market Challenges
    • Our Solution: Palma Network
    • Supported Chains & Integrations
    • Technical Architecture
    • Target Audience
    • Competitive Landscape
    • Roadmap
  • GET IN TOUCH
    • Team and Founders
    • Contact & Community
Powered by GitBook
On this page
  • πŸ”§ Backend Architecture
  • 🧱 Tech Stack
  • πŸ“ Modular Routes Example
  • πŸ” Token Info Example (Simplified)
  • πŸ” JWT Auth Middleware
  • 🧠 Solidity Example: Generic Swap
  • πŸ“Œ In Addition
  • πŸ§‘β€πŸ’» Frontend Architecture
  • 🧱 Tech Stack
  • πŸ“¦ Key Libraries Used
  • πŸ’± Swap Page Code (Excerpt)
  • πŸ” Wallet Auth (Simplified Flow)
  • πŸŒ‰ Solana Integration
  • βœ… Features
  • πŸ§ͺ Public Example: SPL Token Balance
  • πŸ” Wrapped SOL Helper
  • πŸ“Œ Disclaimer
  1. MORE ABOUT PALMA

Technical Architecture

This documentation describes part of Palma Network's tech stack, architecture, and public code examples. It is intentionally scoped to exclude sensitive logic or internal endpoints.

πŸ”§ Backend Architecture

🧱 Tech Stack

  • Runtime: Node.js

  • Framework: Express.js

  • Database: MongoDB with Mongoose

  • Smart Contracts: Solidity (EVM chains)

  • Key Libraries:

    • ethers, web3 (EVM interaction)

    • jsonwebtoken (auth)

    • cors, express, axios, dotenv

    • mongo-sanitize (security)

    • crypto (signature utils)

πŸ“ Modular Routes Example

app.use(cors());
app.use(express.json());

app.use('/api/v1/auth', authRouter);
app.use('/api/v1/user', userRouter);
app.use('/api/v1/limitOrder', limitOrderRouter);
app.use('/api/v1/swap', swapRouter);
app.use('/api/v1/twap', twapRouter);

limitOrderRouter.post('/all', limitOrderController.all);
limitOrderRouter.post('/info', limitOrderController.info);
limitOrderRouter.post('/tokens', limitOrderController.tokens);
limitOrderRouter.post('/chart', limitOrderController.chart);
limitOrderRouter.post('/create', limitOrderController.create);
limitOrderRouter.post('/edit', limitOrderController.edit);
limitOrderRouter.post('/cancel', limitOrderController.cancel);

πŸ” Token Info Example (Simplified)

async function info(req, res) {
  try {
    const data = validation.validateData({
      tknAddress: { type: 'wallet', required: true },
      tknAddressTo: { type: 'wallet', required: false, default: '0x0...' },
      amountIn: { type: 'float', required: false, default: 1 },
      chain: { type: 'string', required: true },
      gas: { type: 'int', required: false, default: 0 },
      txRepeating: { type: 'int', required: false, default: 1 },
    }, req.body);

    const tknInfo = await web3.getInfoByTokenAddr(
      data.chain, data.tknAddress, false,
      data.tknAddressTo, data.amountIn
    );

    const gasData = await web3.getDepositAmountWei(
      data.chain, data.tknAddress,
      Number(data.amountIn), Number(data.gas),
      data.txRepeating
    );

    network.sendOk(res, {
      ...tknInfo,
      gas: gasData.gas.toString(),
      amountWeiDeposit: gasData.amount.toString(),
      amountWeiFee: gasData.fee_amount.toString(),
      usdValue: gasData.usdValue.toString(),
    });
  } catch (e) {
    network.sendErr(res, e.message);
  }
}

πŸ” JWT Auth Middleware

import jwt from 'jsonwebtoken';
import User from "../core/databaseSchema/User.js";

const verifyAuthToken = async (headers) => {
  if (!headers.authorization) throw Error("Invalid token");

  const token = headers.authorization.replace("Bearer ", "");
  const verified = jwt.verify(token, process.env.JWT_SECRET_KEY);

  const timestamp = Math.floor(Date.now() / 1000);
  if ((timestamp - verified.iat) >= process.env.JWT_LIFE_TIME) {
    throw Error("Token expired");
  }

  const usr = await User.findById(verified.id, "-__v");
  if (!usr) throw Error("Invalid token");

  return usr;
};

export default { verifyAuthToken };

🧠 Solidity Example: Generic Swap

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

/// @notice Minimal ERC20 interface
interface IERC20 {
    function approve(address spender, uint256 value) external returns (bool);
    function balanceOf(address account) external view returns (uint256);
}

/// @notice Generic DEX router interface (e.g., for any AMM)
interface IDexRouter {
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] calldata path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);
}

/// @notice Basic token swap execution via external router
contract DexSwapExecutor {
    function performSwap(
        address router,
        address[] calldata path,
        address recipient,
        uint256 amountIn,
        uint256 minAmountOut,
        uint256 deadlineBuffer
    ) external returns (uint256[] memory) {
        IERC20 inputToken = IERC20(path[0]);

        require(inputToken.balanceOf(address(this)) >= amountIn, "Insufficient balance");
        require(inputToken.approve(router, amountIn), "Token approval failed");

        uint256 deadline = block.timestamp + deadlineBuffer;

        return IDexRouter(router).swapExactTokensForTokens(
            amountIn,
            minAmountOut,
            path,
            recipient,
            deadline
        );
    }
}

πŸ“Œ In Addition

This code is provided for demonstration purposes only and illustrates a basic token swap via an external router. It deliberately omits critical aspects such as access control, comprehensive validation, and internal routing logic to keep the example simple and clear.

In a production environment, all swap operations are securely orchestrated off-chain, incorporating features such as:

  • Gas optimization to reduce transaction costs

  • Governance-controlled permissions to ensure robust security

  • Additional safeguards and logic

These measures guarantee safe, reliable, and efficient execution of swap operations in live systems, enabling our users to perform swaps faster, cheaper, and more securely than anyone else.


πŸ§‘β€πŸ’» Frontend Architecture

🧱 Tech Stack

  • Framework: React

  • Languages: TypeScript, JavaScript

  • Build Tool: Vite

  • Styling: Tailwind CSS

  • State Management: Zustand

  • Routing: @tanstack/react-router

  • API Tools: Axios, React Query

  • Wallet/Chain: Wagmi, Viem, ConnectKit

πŸ“¦ Key Libraries Used

Abridged list, refer to package.json for full list.

  • @radix-ui/* β€” UI primitives

  • @tanstack/react-query β€” caching & data fetching

  • wagmi, viem β€” Ethereum wallet & chain interaction

  • zustand β€” state store

  • recharts β€” charting

  • axios β€” REST API calls

  • universal-cookie β€” cookie handling

πŸ’± Swap Page Code (Excerpt)

export default function SwapPage() {
  const {
    outputToken, inputToken, inputAmount,
    setIsQuoteLoading, setOutputAmount,
  } = useTokenStore();
  const { setSwapOrderPath } = useOrderStore();
  const { setTransactionStatus } = useTransactionStatusStore();
  const chainId = useChainId();

  const { data, isLoading } = useQuery({
    queryKey: [
      "swapQuote",
      outputToken.tokenContract,
      inputToken.tokenContract,
      inputAmount,
    ],
    queryFn: () =>
      getSwapAndLimitTradeInfo({
        tknAddress: inputToken.tokenContract,
        tknAddressTo: outputToken.tokenContract,
        amountIn: inputAmount ?? 0,
        chain: chainId,
      }),
  });

  useEffect(() => setIsQuoteLoading(isLoading), [isLoading]);
  useEffect(() => setTransactionStatus(TransactionStatuses.START_SWAP), []);
  useEffect(() => {
    if (!data?.result) return setOutputAmount(0);
    const pair = findMaxPriceItem(data.body.pairs);
    setOutputAmount(parseFloat(pair.price));
    setSwapOrderPath(pair);
  }, [data]);
  
  return (
    <div className="flex flex-col gap-8">
      {/* Inputs and Action Button */}
    </div>
  );
}

πŸ” Wallet Auth (Simplified Flow)

const useAuthStore = create<AuthStore>((set, get) => ({
  handleAuth: async (address, signMessageAsync) => {
    const { cookiesExist } = get();
    if (cookiesExist || get().isAuthInProgress) return;

    try {
      set({ isAuthInProgress: true, error: null });

      const { message, timestamp } = await getWalletSignMessage(address);
      const signature = await signMessageAsync({ message });

      const loginRes = await loginWithWallet(
        address, timestamp, signature, ""
      );
      if (!loginRes.result) throw new Error("Auth failed");

      addPalmaCookies(loginRes.body.accessToken, 86400);
      set({ cookiesExist: true, walletAddress: address });
    } catch (error) {
      set({ error: error.message || "Unknown error" });
    } finally {
      set({ isAuthInProgress: false });
    }
  },
}));

πŸŒ‰ Solana Integration

Palma Network supports Solana alongside EVM chains as part of our multichain aggregation.

βœ… Features

  • Read-only SPL token balance checking

  • WSOL compatibility

  • Unified quoting interface

  • Secure connection with official libraries

πŸ§ͺ Public Example: SPL Token Balance

import { Connection, PublicKey } from '@solana/web3.js';
import { getAssociatedTokenAddressSync } from '@solana/spl-token';

const connection = new Connection('https://api.mainnet-beta.solana.com');

async function getTokenBalance(walletAddress: string, tokenMint: string) {
  const owner = new PublicKey(walletAddress);
  const mint = new PublicKey(tokenMint);

  const ata = getAssociatedTokenAddressSync(mint, owner);
  const accountInfo = await connection.getTokenAccountBalance(ata);

  return {
    amount: accountInfo.value.uiAmount,
    decimals: accountInfo.value.decimals,
  };
}

πŸ” Wrapped SOL Helper

const WSOL_MINT = "So11111111111111111111111111111111111111112";

function isWrappedSOL(tokenMint: string) {
  return tokenMint === WSOL_MINT;
}

These are public utility snippets. No private logic or internal API flow is exposed.


πŸ“Œ Disclaimer

The code and examples in this documentation represent only part of Palma Network’s infrastructure. Critical business logic, private APIs, and internal mechanics have been intentionally excluded for security and confidentiality.

PreviousSupported Chains & IntegrationsNextTarget Audience

Last updated 15 days ago

Page cover image