Para’s embedded wallets provide seamless access to M0’s programmable stablecoin infrastructure. Build next-generation financial applications with custom digital dollars.

Prerequisites

  • Para API key configured
  • Node.js 18+ environment
  • Understanding of stablecoin mechanics
  • M0 contract addresses for your network

Installation

1

Install packages

Install the required packages:
npm install @getpara/server-sdk@alpha @getpara/viem-v2-integration@alpha viem@^2

Setup

1

Import dependencies

Import the required Para SDK and Viem components:
import { ParaServer } from "@getpara/server-sdk@alpha";
import { createParaViemClient, createParaAccount } from "@getpara/viem-integration@alpha";
import { http } from 'viem';
import { mainnet } from 'viem/chains';
2

Initialize Para SDK

Set up Para server instance:
const para = new ParaServer(process.env.PARA_API_KEY);
3

Create wallet

Check for existing wallet or create new pregenerated wallet:
const hasWallet = await para.hasPregenWallet({
  pregenId: { email: 'user@example.com' },
});

let pregenWallet;
if (!hasWallet) {
  pregenWallet = await para.createPregenWallet({
    type: 'EVM',
    pregenId: { email: "user@example.com" },
  });
}
4

Create Para account and client

Set up the account and Viem client for M0 interactions:
const account = await createParaAccount(para);
const client = createParaViemClient(para, {
  account,
  chain: mainnet,
  transport: http(),
});

Contract Configuration

M0 Contract Addresses

const M_ADDRESS = '0x866A2BF4E572CbcF37D5071A7a58503Bfb36be1b';
const WM_ADDRESS = '0x437cc33344a0B27A429f795ff6B469C72698B291';

Contract ABIs

const ERC20_ABI = [
  { name: 'approve', type: 'function', inputs: [{ name: 'spender', type: 'address' }, { name: 'amount', type: 'uint256' }], outputs: [{ type: 'bool' }] },
  { name: 'transfer', type: 'function', inputs: [{ name: 'recipient', type: 'address' }, { name: 'amount', type: 'uint256' }], outputs: [{ type: 'bool' }] }
];

const WM_ABI = [
  { name: 'wrap', type: 'function', inputs: [{ name: 'recipient', type: 'address' }, { name: 'amount', type: 'uint256' }], outputs: [{ type: 'uint240' }] },
  { name: 'unwrap', type: 'function', inputs: [{ name: 'recipient', type: 'address' }, { name: 'amount', type: 'uint256' }], outputs: [{ type: 'uint240' }] }
];

Usage

Wrapping $M to $wM

1

Approve $M tokens

async function wrapMToWM(amount) {
  const approveHash = await client.writeContract({
    address: M_ADDRESS,
    abi: ERC20_ABI,
    functionName: 'approve',
    args: [WM_ADDRESS, amount]
  });
  console.log('Approve hash:', approveHash);
2

Wrap tokens

  const wrapHash = await client.writeContract({
    address: WM_ADDRESS,
    abi: WM_ABI,
    functionName: 'wrap',
    args: [account.address, amount]
  });
  console.log('Wrap hash:', wrapHash);
}

Unwrapping $wM to $M

async function unwrapWMToM(amount) {
  const unwrapHash = await client.writeContract({
    address: WM_ADDRESS,
    abi: WM_ABI,
    functionName: 'unwrap',
    args: [account.address, amount]
  });
  console.log('Unwrap hash:', unwrapHash);
}

Token Transfers

async function transferToken(tokenAddress, recipient, amount) {
  const transferHash = await client.writeContract({
    address: tokenAddress,
    abi: ERC20_ABI,
    functionName: 'transfer',
    args: [recipient, amount]
  });
  console.log('Transfer hash:', transferHash);
}

Examples

Basic Operations

await wrapMToWM(1000000n);
await unwrapWMToM(1000000n);
await transferToken(M_ADDRESS, '0xRecipientAddress', 1000000n);

Next Steps