UPD — Universal Private DollarSDK Reference

Oracle

Fetch signed ETH/USD price attestations for UPD mint and burn operations.

Oracle

UPD minting and burning require a signed price attestation — an ETH/USD price signed by an authorized oracle signer. The PriceOracle contract validates the signature, staleness, and deviation against Chainlink + Uniswap V3.

Oracle Client (SDK)

The SDK includes a thin HTTP client that fetches attestations from any oracle service:

import { createOracleClient } from '@permissionless-technologies/upd-sdk/oracle'

const oracle = createOracleClient({
  oracleUrl: 'https://oracle.upd.io', // default
  timeout: 5000,                       // default
})

// Get a signed attestation (ready to pass to mint/burn)
const attestation = await oracle.getEthUsdAttestation()

// Or just the price
const { price, timestamp } = await oracle.getEthUsdPrice()

The attestation object matches the Solidity PriceAttestationQuery struct exactly:

interface PriceAttestationQuery {
  price: bigint         // 18 decimals (e.g. 2000e18 = $2000)
  decimals: number      // always 18
  dataTimestamp: bigint  // milliseconds since epoch
  assetPair: Hex        // keccak256("MORPHER:ETH_USD")
  signature: Hex        // ECDSA from authorized signer
}

Mock Attestations (Testing)

For local development with MockPriceOracle:

import { createMockAttestation } from '@permissionless-technologies/upd-sdk/oracle'

const attestation = createMockAttestation(2000n * 10n ** 18n) // $2000
// signature is 0x — only works with MockPriceOracle, not production

Running Your Own Oracle

The oracle service is published as a separate package:

npm install @permissionless-technologies/upd-oracle
import { startOracleService, BinanceFeed } from '@permissionless-technologies/upd-oracle'

await startOracleService({
  config: {
    signerPrivateKey: '0x...',  // must match SIGNER_ROLE on PriceOracle contract
    port: 3000,
  },
  feed: new BinanceFeed(),
})

This starts an Express server with:

  • GET /v1/ethusd — returns a signed price attestation
  • GET /health — signer address and feed status

Custom Price Feeds

Implement the IPriceFeed interface to use any price source:

import type { IPriceFeed, PriceFeedResult } from '@permissionless-technologies/upd-oracle'

class MyFeed implements IPriceFeed {
  name = 'MyFeed'

  async getPrice(pair: string): Promise<PriceFeedResult> {
    // Fetch from your source
    return {
      price: 2000n * 10n ** 18n,  // 18 decimals
      timestamp: BigInt(Date.now()),
    }
  }
}

Signature Format

The oracle signs prices in the format PriceOracle.sol expects:

  1. messageHash = keccak256(abi.encodePacked(price, decimals, timestamp, assetPair))
  2. signMessage({ message: { raw: messageHash } }) — applies \x19Ethereum Signed Message:\n32 prefix
  3. Contract recovers signer via ECDSA.recover and checks SIGNER_ROLE

On this page