> ## Documentation Index
> Fetch the complete documentation index at: https://docs.getpara.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Private Credit Yield via ZIG Markets Vaults

> Connect Para wallets to ZIG Markets vaults on Ethereum and let users earn stablecoin yield from real-economy private credit.

Connect Para wallets to ZIG Markets vaults on Ethereum and let users earn stablecoin yield from real-economy private credit: invoice factoring, SME finance and cross-border PayFi in the GCC and beyond. ZIG Markets is the institutional yield arm of the ZIGChain ecosystem, operated under Merritt Administrators (Pty) Ltd, an FSCA-licensed financial services provider (Category I and II). The vaults are built and operated by two ecosystem protocols, **Nawa Finance** (one public USDT vault) and **Valdora Finance** (dedicated USDC or USDT vaults per distribution partner). Both are Ethereum mainnet contracts, verified on Etherscan, and both follow the same pattern: synchronous deposits, NAV-based share tokens, asynchronous redemptions.

## What You'll Learn

* How ZIG Markets vaults work on Ethereum and how they differ from ERC-4626
* How to connect a Para wallet, approve USDC or USDT and deposit into the Nawa USDT vault or a Valdora vault
* How to read a user's position, share price and vault TVL directly from the contracts
* How the asynchronous redemption flow works, which events to reconcile against, and the guardrails to code for

## Why Combine Para and ZIG Markets

| Para Wallets                                                                 | ZIG Markets Vaults                                                                    |
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
| Instant onboarding with email and social login, MPC-secured embedded wallets | Stablecoin yield from short-duration private credit, not crypto-native leverage       |
| Embedded and external wallet support across EVM chains                       | Ethereum mainnet, USDC and USDT, verified upgradeable contracts, Oak Security audited |
| White-label UX, users never handle seed phrases                              | Yield accrues to the share price, so a position is readable on-chain at any time      |
| Batch transactions: approve plus deposit in one user confirmation            | Public vault for any wallet (Nawa) or a dedicated vault per distributor (Valdora)     |

Para is already live in production on nawa.finance as the embedded wallet for the Nawa USDT vault deposit flow. The Nawa snippet in this module is distilled from that code.

## Example Use Cases

1. **Fintech savings balance**: a neobank or payments app offers a "USD earn" balance backed by a ZIG Markets vault, with Para creating the wallet behind an email login.
2. **Exchange earn tab**: a centralised exchange routes idle user stablecoins into its own dedicated Valdora vault and displays yield in-app, with omnibus accounting on one address.
3. **Remittance float**: a remittance or payout platform parks float in the Nawa USDT vault between corridors and redeems on demand.
4. **Wallet-native yield**: a consumer wallet lists ZIG Markets vaults as an earn option alongside standard DeFi lending, using the same Para session for both.

## What You Need

* A Para API key and an authenticated Para session ([Para setup guides](https://docs.getpara.com))
* `@getpara/react-sdk-lite` and `@getpara/wagmi-v2-integration`, plus `@wagmi/core`, `viem` and `@tanstack/react-query`
* An Ethereum mainnet RPC endpoint
* USDT or USDC in the user's Para wallet, plus ETH for gas
* A vault address:
  * **Nawa USDT vault** is public: `0x6FE78B942C566fE2b8D0881cf3577C1B1511F204`
  * **Valdora vaults** are deployed per distribution partner. Contact ZIG Markets for a vault dedicated to your integration; the live deployments listed below can be used for read calls and interface validation.

**Availability:** \[jurisdiction and eligibility wording to be inserted by ZIG Markets before publication]

## How the Vaults Work

Both vault families share the same shape. Code against these rules and the same integration serves either.

* **Not ERC-4626.** Shares are plain ERC-20 tokens with a custom vault interface. Do not expect `totalAssets`, `convertToAssets`, `previewMint`, `withdraw` or `redeem`.
* **Deposits are synchronous.** `approve` the vault on the stablecoin, then call `deposit(amount)`. Shares mint to `msg.sender` in the same transaction at the current share price.
* **Redemptions are asynchronous.** The user calls `requestRedeem(shares)`. An operator approves and settles under the vault's terms, and the payout lands in the user's wallet. There is no `withdraw()`.
* **Yield accrues to the share price.** The user's share balance stays constant while its stablecoin value rises. Share price and TVL are pushed on-chain by an AUM updater under contract-enforced guards: 24-hour minimum between updates and a 2% maximum move per update.
* **6 decimals everywhere.** Shares match the underlying stablecoin, so there is no scaling between asset and share units.
* **Always call the proxy address.** Both families are ERC-1967 upgradeable proxies. Take the ABI from the verified implementation and call the proxy.
* **USDT quirk.** USDT's `approve` returns no bool, and a non-zero allowance must be reset to 0 before it can be changed. The snippets below handle this.

## Step-by-Step Integration

There is no off-chain SDK for ZIG Markets vaults; both paths call the contracts directly with a Para wallet as the signer.

### Step 1: Install

```bash theme={null}
npm install @getpara/react-sdk-lite @getpara/wagmi-v2-integration @wagmi/core viem @tanstack/react-query
```

### Step 2: Connect a Para wallet

This wagmi configuration is shared by both vault paths. It is the production pattern running on nawa.finance.

```typescript theme={null}
import ParaWeb, { Environment } from "@getpara/react-sdk-lite";
import "@getpara/react-sdk-lite/styles.css";
import { paraConnector } from "@getpara/wagmi-v2-integration";
import { createConfig, http, connect, getAccount } from "@wagmi/core";
import { mainnet } from "@wagmi/core/chains";
import { QueryClient } from "@tanstack/react-query";

const para = new ParaWeb(Environment.PROD, PARA_API_KEY);

export const config = createConfig({
  chains: [mainnet],
  transports: { [mainnet.id]: http(RPC_URL) },
  connectors: [paraConnector({ para, appName: "Para × ZIG Markets", options: {},
                               queryClient: new QueryClient() }) as any],
});

// Opens Para's auth modal if the user is not logged in
await connect(config, { connector: config.connectors[0] });
const { address } = getAccount(config);
```

<Tip>
  Para's [batch transactions example](https://github.com/getpara/examples-hub/blob/3.0.0/web/with-react-nextjs/signer-viem-v2/src/components/demos/BatchTransactionsDemo.tsx) lets you combine the approve and deposit calls into a single user confirmation.
</Tip>

***

## Path A: Nawa USDT Vault

### A. Deployed addresses and chains

Ethereum mainnet only.

|                                              | Address                                      |
| -------------------------------------------- | -------------------------------------------- |
| Vault (proxy, always integrate against this) | `0x6FE78B942C566fE2b8D0881cf3577C1B1511F204` |
| Implementation                               | `0xabba41142D2bF47a847987603347F94120D45043` |
| Upgrade timelock (72-hour delay)             | `0xE260d667d411Aaaa00D17260BcfF2fF87dF1C168` |
| Underlying USDT                              | `0xdAC17F958D2ee523a2206206994597C13D831ec7` |

The vault is a UUPS upgradeable proxy; upgrades can only execute 72 hours after being queued publicly on the timelock.

### B. Standard, token, decimals

Not ERC-4626. It is a custom ERC-20 share vault (OpenZeppelin upgradeable) with asynchronous redemptions, closer in spirit to ERC-7540, but no standard interface is claimed.

* Share token name: **Nawa USDT Vault**
* Symbol: **nzUSDT**
* Decimals: **6** (same as USDT)
* Underlying asset: Ethereum mainnet USDT

Yield accrues to the share **price**, not the balance: an integrator's nzUSDT balance stays constant while its USDT value grows. Audited by Oak Security.

### C. ABI

Proxy and implementation are verified on Etherscan, so the ABI is publicly fetchable from the proxy address. Contract name `NawaUSDTVault`, Solidity 0.8.19. The implementation ABI (148 entries) is also supplied with this module as [`nawa_vault_abi.json`](/files/zig-markets/nawa_vault_abi.json).

### D. Function signatures for the full flow

```solidity theme={null}
// on USDT (non-standard ERC-20: approve returns no bool, and a non-zero
// allowance must be reset to 0 before being changed)
function approve(address spender, uint256 value)

// on the vault
function deposit(uint256 amount) returns (uint256 shares)
function depositWithMinShares(uint256 amount, uint256 minSharesOut, uint256 deadline) returns (uint256 shares)
function requestRedeem(uint256 shares) returns (uint256 id)
function requestRedeemWithMinAssets(uint256 shares, uint256 minAssetsOut, uint256 deadline) returns (uint256 id)
function cancelRequest(uint256 id)               // user, only after cancelAfter
function claim() returns (uint256)               // edge case only: payouts are normally pushed
function balanceOf(address) returns (uint256)    // ERC-20, 6 decimals
function pricePerShare() view returns (uint256)  // NAV per share, 1e18 fixed-point
function previewDeposit(uint256 amount) view returns (uint256 shares)
function previewRedeem(uint256 shares) view returns (uint256 assets)
function latestAum() view returns (uint256)      // TVL in USDT units (6 dec)
function getRequest(uint256 id) view returns (RedemptionRequest)
// RedemptionRequest: user, shares, assetAmount, outstanding, originalPps, overridePps,
// requestedAt, cancelAfter, status (1 Pending, 2 Approved, 3 Funded, 4 Rejected, 5 Cancelled, 6 Settled)
```

There is deliberately no `withdraw()`: settlement is pushed to the requester's address (see F).

### E. Deposit flow

**Synchronous**: one transaction mints nzUSDT to `msg.sender` at the current share price and auto-forwards the net inflow to the strategy.

* Minimum deposit: **10 USDT** (`minDeposit()`, live-read)
* Cap: global `mintingCap` = **100,000,000 nzUSDT**
* Guard worth coding for: deposits revert with `StaleNav` if the on-chain NAV report is older than 7 days (`maxAumAge`)
* Omnibus deposits (one exchange address holding shares for many users) are explicitly fine

### F. Redemption flow

**Asynchronous, request-based.** `requestRedeem(shares)` burns the shares immediately and locks the payout at the current share price, with no repricing later.

* Settlement is **pushed** to the requester's wallet (operator settlement, FIFO netting against new deposits, or backstop funding); no claim step in the normal path
* No notice period, no redemption window, no daily limits
* SLA: the on-chain settlement deadline is 120 days (`maxSettlementWindow`); the product commitment communicated to users is up to 75 days; in practice requests settle in days
* Past each request's `cancelAfter`, the user can self-cancel and get shares re-minted
* Minimum redemption: **1 nzUSDT** (`minRedeemShares`)

### G. APY and TVL derivation

* **TVL: fully on-chain.** `latestAum()` in USDT units, already **net of the 15% performance fee** (the fee is taken off-chain before reporting; the contract charges nothing on-chain)
* **Share price: fully on-chain.** `pricePerShare()`, oracle-updated via `updateAum` with hard guards: minimum 24 h between updates, maximum 200 bps price move per update, 7-day staleness limit
* **Realised APY is derivable on-chain** from the `AumUpdated` event series (each event carries `newPricePerShare`)
* The "\~10%" shown on nawa.finance is an indicative off-chain figure for the private credit strategy, net of fee

### H. Events for reconciliation

```solidity theme={null}
Deposited(address indexed user, uint256 assets, uint256 shares, uint256 forwardedToStrategy)
RedemptionRequested(uint256 indexed id, address indexed user, uint256 shares, uint256 assetAmount)
RedemptionApproved(uint256 indexed id, address indexed user, uint256 assetAmount, uint256 originalPps, uint256 overridePps)
RedemptionRejected(uint256 indexed id, address indexed user, uint256 shares)
RedemptionCancelled(uint256 indexed id, address indexed user, uint256 shares)
RedemptionFunded(uint256 indexed id, address indexed user, uint256 amount, bool fullyFunded)
RedemptionSettled(uint256 indexed id, address indexed user, uint256 amount)
Claimed(address indexed user, uint256 amount)
AumUpdated(uint256 oldAum, uint256 newAum, uint256 newPricePerShare)
```

Plus the standard ERC-20 `Transfer` on the share token, and role and parameter-change events for governance monitoring.

### I. Permissioning

None on-chain for users. `deposit` and `requestRedeem` are permissionless; no whitelist or blacklist exists in the vault (verified: zero role-mapping constructs in the deployed bytecode). Circuit breakers only: admin pause, and a guardian 48-hour outflow freeze.

Two caveats: USDT's own token-level blacklist applies to transfers, and Nawa's official frontend performs off-chain AML screening (Chainalysis) plus on-chain deposit monitoring, but nothing blocks a direct contract call.

### J. Testnet for Para engineers

A Sepolia deployment exists (vault `0x1eCf37A291F4FD3A1025Fa0b45a2bA1b7366e8EE`, mock USDT `0x345D9b9f8Cf83b7a9F59Ca2aaF9013204D8A5FD8` with an open `mint(address,uint256)` faucet, 120-second timelock), **but it predates the security audit and its interface differs**. A fresh Sepolia deployment of the audited mainnet source is being prepared; the new addresses will be supplied as soon as it is live. Until then, treat **mainnet as the interface source of truth** and hold off coding against the old Sepolia addresses.

### K. TypeScript: connect, approve, deposit, read, redeem

Distilled from the production code running on nawa.finance. Uses the shared `config` from Step 2.

```typescript theme={null}
import { readContract, writeContract, waitForTransactionReceipt, getAccount } from "@wagmi/core";
import { parseAbi, parseUnits, formatUnits } from "viem";
import { config } from "./para";   // Step 2

const VAULT = "0x6FE78B942C566fE2b8D0881cf3577C1B1511F204";
const USDT  = "0xdAC17F958D2ee523a2206206994597C13D831ec7";

const VAULT_ABI = parseAbi([
  "function deposit(uint256 amount) returns (uint256)",
  "function requestRedeem(uint256 shares) returns (uint256)",
  "function balanceOf(address) view returns (uint256)",
  "function pricePerShare() view returns (uint256)",
  "function latestAum() view returns (uint256)",
]);
// USDT quirk: approve returns no bool; non-zero allowance must reset to 0 first
const USDT_ABI = parseAbi([
  "function approve(address spender, uint256 value)",
  "function allowance(address owner, address spender) view returns (uint256)",
]);

const { address } = getAccount(config);

// 1) approve, with USDT's reset-to-zero rule
const amount = parseUnits("10", 6); // 10 USDT minimum deposit
const allowance = await readContract(config, { address: USDT, abi: USDT_ABI,
  functionName: "allowance", args: [address!, VAULT] });
if (allowance < amount) {
  if (allowance > 0n) {
    const h = await writeContract(config, { address: USDT, abi: USDT_ABI,
      functionName: "approve", args: [VAULT, 0n] });
    await waitForTransactionReceipt(config, { hash: h });
  }
  const h = await writeContract(config, { address: USDT, abi: USDT_ABI,
    functionName: "approve", args: [VAULT, amount] });
  await waitForTransactionReceipt(config, { hash: h });
}

// 2) deposit: mints nzUSDT to the Para wallet in the same tx
const h = await writeContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "deposit", args: [amount] });
await waitForTransactionReceipt(config, { hash: h });

// 3) read the position
const [shares, pps] = await Promise.all([
  readContract(config, { address: VAULT, abi: VAULT_ABI, functionName: "balanceOf", args: [address!] }),
  readContract(config, { address: VAULT, abi: VAULT_ABI, functionName: "pricePerShare" }),
]);
console.log(`${formatUnits(shares, 6)} nzUSDT ≈ ${formatUnits(shares * pps / 10n ** 18n, 6)} USDT`);

// 4) exit: burns shares now; payout is pushed to the wallet under the vault's settlement terms
const r = await writeContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "requestRedeem", args: [shares] });
await waitForTransactionReceipt(config, { hash: r });
// Track status with getRequest(id) or the RedemptionApproved / RedemptionSettled events.
```

***

## Path B: Valdora Vaults (USDC or USDT)

Valdora deploys one vault per distribution partner so that accounting and legal terms stay segregated. Every Valdora vault runs the same verified implementation, so one integration serves any of them.

### A. Deployed addresses and chains

Ethereum mainnet only. All are ERC-1967 upgradeable proxies; call the proxy, take the ABI from the implementation.

| Vault      | Proxy (call this)                            | Implementation                               | Asset |
| ---------- | -------------------------------------------- | -------------------------------------------- | ----- |
| BloFin     | `0xbcCbf4D476e75Ed055f446D5fBBDb29f119f0312` | `0x83887a0467562c41228DDf2104Ae6F4652C21328` | USDC  |
| Coinstore  | `0x4735ee8A64F27dF957e2808D86Ed0e5e9dcF0FaE` | `0x97ce3e88c6451e9a93c19eb098e18897e031b39b` | USDT  |
| Turtle     | `0x36a9d499640340cEE22474e6340e113A5b2C2e22` | `0x9327c35240d704f46a2092582d09547fd116b468` | USDC  |
| WealthPlug | `0x1754fCD1F0EBb306286dd16F00abCf46731a92FC` | `0x7268ff31e1d4aea5474445b49bc46f0396f7eab9` | USDT  |
| GroveX     | `0x4fAE90a83f40dCf864E958346E384fFa67802387` | `0x2ab786ba07ef1f0c2ccc85de196d73eb81251672` | USDT  |

Asset addresses: USDC `0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48`, USDT `0xdAC17F958D2ee523a2206206994597C13D831ec7`.

These vaults are dedicated to the named partners. Use them for read calls and to validate the interface; write transactions should go to the vault deployed for your integration. Administrative control (upgrade, pause, parameters) sits with a 2-of-3 Gnosis Safe.

### B. Standard, token, decimals

Not ERC-4626. A custom ERC-20 share vault (UUPS upgradeable, Solidity 0.8.24) with asynchronous, operator-approved redemptions.

| Vault      | Share token name   | Symbol   | Decimals |
| ---------- | ------------------ | -------- | -------- |
| BloFin     | Valdora Blofin     | vVALDBLF | 6        |
| Coinstore  | Valdora Coinstore  | vVALDCST | 6        |
| Turtle     | Valdora Turtle     | vVALDTRT | 6        |
| WealthPlug | Valdora WealthPlug | vVALDWPL | 6        |
| GroveX     | Valdora GroveX     | vVALDGRX | 6        |

Share decimals match the underlying at 6, so no scaling between asset and share units. Yield accrues to the share price.

### C. ABI

One implementation ABI (167 entries) serves every Valdora vault; it is byte-for-byte identical across deployments. All implementations are verified on Etherscan and Blockscout, so the ABI is fetchable from any of them. It is also supplied with this module as [`valdora_vault_abi.json`](/files/zig-markets/valdora_vault_abi.json). Do not use the proxy's own 7-entry ABI.

### D. Function signatures for the full flow

```solidity theme={null}
// on the asset (USDC / USDT)
function approve(address spender, uint256 amount)

// subscribe: synchronous, shares mint to msg.sender
function deposit(uint256 amount) returns (uint256 shares)

// exit: asynchronous, two-step
function requestRedeem(uint256 shares) returns (uint64 requestId, uint256 assetAmount)
function cancelRedeem(uint64 requestId)                        // user may cancel before approval

// position and pricing
function balanceOf(address) view returns (uint256)
function assetForShares(uint256 shares) view returns (uint256)
function sharesForAsset(uint256 assets) view returns (uint256)
function redemptionQuote(uint256 shares) view returns (uint256)
function pricePerFullShare() view returns (uint256 price, uint256 supply, uint256 aum)   // price scaled by 1e18
function aum() view returns (uint256)
function effectiveAum() view returns (uint256)
function lastAumUpdateAt() view returns (uint64)
function userRequests(address user, uint256 offset, uint256 limit) view returns (RedemptionRequest[])
function request(uint64 id) view returns (RedemptionRequest)
// RedemptionRequest: id, user, shares, assetAmount, originalNav, timestamp, status,
// approvedAt, approvedBy, overrideNav, hasOverride

// metadata
function asset() · name() · symbol() · decimals() · totalSupply() · maxSupply() · paused()
```

Not present, and integrators will look for them: `totalAssets`, `convertToAssets`, `convertToShares`, `previewDeposit`, `previewRedeem`, `maxDeposit`, `mint`, `withdraw`, `redeem`.

### E. Deposit flow

**Synchronous**: `approve` then `deposit(uint256)`. Shares mint to `msg.sender` at the prevailing NAV in the same transaction. Deposits are continuous, subject to some cash drag before capital is deployed.

* Minimum: no on-chain minimum beyond a dust threshold of 1,000 base units (0.001 USDC/USDT) retained at first deposit
* Cap: `maxSupply()` is the only cap, currently unset on all vaults, adjustable by the admin
* Fee-on-transfer tokens are rejected (`FeeOnTransferNotSupported`)

### F. Redemption flow

**Asynchronous and operator-approved.** The holder calls `requestRedeem(shares)`; shares move into a pending state and the request is queued on-chain. An operator holding `REDEEM_MANAGER_ROLE` calls `approveRequest` or `rejectRequest`; approved requests settle to the user's wallet. Where liquidity allows, the vault settles immediately and emits `RedemptionSettledInstantly`.

* The holder may `cancelRedeem` before approval and get shares back
* No daily limits, no fixed lockup, no on-chain settlement deadline
* Settlement terms are set per vault and stated in that vault's agreement; the underlying facilities are short-duration credit, so expect settlement in days to weeks, with an operational minimum of about 48 hours for off-ramping
* Queue state is readable via `pendingRequests`, `pendingRedemptionShares`, `pendingRedemptionAum` and `pendingRequestCount`

### G. APY and TVL derivation

NAV-based, not a fixed rate. Performance originates in the underlying ZIG Markets facilities and flows through to the vault.

* **TVL: on-chain.** `aum()` and `effectiveAum()` in asset units. AUM is pushed by an operator holding `AUM_UPDATER_ROLE` via `updateAum()`, guarded by a 24-hour cooldown (`aumUpdateCooldownSecs`), a 2% maximum change per update (`aumChangeLimitBps`) and a maximum override deviation. Valdora is also listed on DeFiLlama.
* **Share price: on-chain.** `pricePerFullShare()` returns price (1e18 scale), supply and AUM in one call. `NAV_SCALE` is 1e18.
* **Realised APY is derivable on-chain** from the `AumUpdated` event series. There is no APY function.
* **Reward vesting:** `addReward` streams operator-added rewards into NAV over `rewardVestingSecs` (7 days) via `lockedProfit`, so the share price rises smoothly rather than in steps.

<Warning>
  a freshly deployed Valdora vault returns 0 from `pricePerFullShare()`, `aum()` and `lastAumUpdateAt()` until the first deposit and AUM update land. Check `lastAumUpdateAt() > 0` before displaying a price.
</Warning>

### H. Events for reconciliation

```solidity theme={null}
Deposit(address indexed user, uint256 assetAmount, uint256 sharesMinted, uint256 totalSupply, uint256 nav, uint256 aum)
RedemptionRequested(uint64 indexed requestId, address indexed user, uint256 shares, uint256 assetAmount, uint256 nav, uint256 aum)
RedemptionApproved(uint64 indexed requestId, address indexed user, address indexed settledBy, uint256 shares, uint256 assetAmount, uint256 settleNav, uint256 originalNav, bool hasOverride)
RedemptionRejected(uint64 indexed requestId, address indexed user, address indexed rejectedBy, uint256 sharesRefunded)
RedemptionCancelled(uint64 indexed requestId, address indexed user, uint256 sharesRefunded)
RedemptionSettledInstantly(address indexed user, uint256 shares, uint256 assetAmount, uint256 nav, uint256 aum)
AumUpdated(uint256 previousAum, uint256 aum, uint256 changeBps, uint256 nav, uint256 totalSupply)
RewardAdded(address indexed addedBy, uint256 rewardAmount, uint256 previousAum, uint256 aum)
```

Plus the standard ERC-20 `Transfer`, and `Paused`, `Unpaused`, `Upgraded`, `MaxSupplyUpdated`, `FundsManagerUpdated`, `RoleGranted`, `RoleRevoked` for governance monitoring.

### I. Permissioning

None on-chain for users. `deposit` and `requestRedeem` are permissionless at contract level; `maxSupply()` is the only cap. Access control is role-based and applies to administrative functions only (`DEFAULT_ADMIN`, `AUM_UPDATER_ROLE`, `REDEEM_MANAGER_ROLE`, `ADD_REWARD_ROLE`). Circuit breakers: admin pause.

Valdora performs off-chain AML and sanctions screening; wallets that fail screening are not permitted to use the product. USDT's own token-level blacklist applies to USDT vaults.

### J. Testnet for Para engineers

No testnet deployment is currently available. All read functions can be exercised against the verified mainnet proxies in section A. Write transactions should target the vault deployed for your integration. A testnet instance is being requested from Valdora and will be added here when live.

### K. TypeScript: connect, approve, deposit, read, redeem

Same Para connection as Path A (Step 2). Only the contract calls differ. Shown here for a USDC vault; for a USDT vault apply the reset-to-zero allowance rule from Path A.

```typescript theme={null}
import { readContract, writeContract, waitForTransactionReceipt, getAccount } from "@wagmi/core";
import { parseAbi, parseUnits, formatUnits } from "viem";
import { config } from "./para";   // Step 2

const VAULT = "0x...";   // the Valdora vault deployed for your integration
const USDC  = "0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48";

const VAULT_ABI = parseAbi([
  "function deposit(uint256 amount) returns (uint256)",
  "function requestRedeem(uint256 shares) returns (uint64, uint256)",
  "function balanceOf(address) view returns (uint256)",
  "function assetForShares(uint256 shares) view returns (uint256)",
  "function pricePerFullShare() view returns (uint256, uint256, uint256)",
  "function lastAumUpdateAt() view returns (uint64)",
]);
const ERC20_ABI = parseAbi([
  "function approve(address spender, uint256 amount) returns (bool)",
]);

const { address } = getAccount(config);

// 0) guard: a vault with no NAV yet returns 0 on every price read
const updatedAt = await readContract(config, { address: VAULT, abi: VAULT_ABI, functionName: "lastAumUpdateAt" });
if (updatedAt === 0n) throw new Error("Vault has no NAV yet");

// 1) approve (USDC returns a bool; for USDT use the allowance reset pattern from Path A)
const amount = parseUnits("100", 6);
const a = await writeContract(config, { address: USDC, abi: ERC20_ABI,
  functionName: "approve", args: [VAULT, amount] });
await waitForTransactionReceipt(config, { hash: a });

// 2) deposit: shares mint to the Para wallet in the same tx
const d = await writeContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "deposit", args: [amount] });
await waitForTransactionReceipt(config, { hash: d });

// 3) read the position
const shares = await readContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "balanceOf", args: [address!] });
const value  = await readContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "assetForShares", args: [shares] });
console.log(`${formatUnits(shares, 6)} shares ≈ ${formatUnits(value, 6)} USDC`);

// 4) exit: files the request only; an operator approves it and settlement follows the vault's terms
const r = await writeContract(config, { address: VAULT, abi: VAULT_ABI,
  functionName: "requestRedeem", args: [shares] });
await waitForTransactionReceipt(config, { hash: r });
// Track status with userRequests(address, 0, 10) or the RedemptionApproved event.
```

***

## Related Resources

* Para viem and wagmi integration guides: [https://docs.getpara.com/web/guides/evm/viem](https://docs.getpara.com/web/guides/evm/viem)
* Para batch transactions example: [https://github.com/getpara/examples-hub/blob/3.0.0/web/with-react-nextjs/signer-viem-v2/src/components/demos/BatchTransactionsDemo.tsx](https://github.com/getpara/examples-hub/blob/3.0.0/web/with-react-nextjs/signer-viem-v2/src/components/demos/BatchTransactionsDemo.tsx)
* Nawa Finance: [https://nawa.finance](https://nawa.finance) (Para live in the USDT vault deposit flow)
* Valdora Finance: [https://valdora.finance](https://valdora.finance)
* ZIG Markets and ZIGChain: [https://zigchain.com](https://zigchain.com)
* ABI files supplied with this module: [`nawa_vault_abi.json`](/files/zig-markets/nawa_vault_abi.json), [`valdora_vault_abi.json`](/files/zig-markets/valdora_vault_abi.json)
* Support and vault requests: ZIG Markets partnerships, Arsalan Khan, [arsalan@zigchain.com](mailto:arsalan@zigchain.com)
