npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@emurgo/links

v0.1.4

Published

Cardano CIP-13 URI + brand deep-link parsing/building for wallet integrations (yoroi://, secondfi://, web+secondfi://, https fallback). Supports payment, browse, transfer, exchange, browser-launch, and chain-aware partner payment links.

Readme

@emurgo/links

Cardano URI parsing and brand-specific deep link handling.

Installation

@emurgo/links is published on GitHub Packages, not the public npm registry. GitHub Packages requires authentication for npm installs, even for public packages, so consumers need a GitHub personal access token (PAT) with the read:packages scope. The token can belong to the consuming developer's own GitHub account; they do not need to be a member of the Emurgo organization.

  1. Create a GitHub PAT

    In GitHub, go to Settings → Developer settings → Personal access tokens → Tokens (classic), create a token with the read:packages scope, and expose it locally as GITHUB_TOKEN.

    export GITHUB_TOKEN=ghp_your_token_here
  2. Add to your project's .npmrc (or ~/.npmrc):

    @emurgo:registry=https://npm.pkg.github.com
    //npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}
  3. Verify authentication:

    npm whoami --registry=https://npm.pkg.github.com
  4. Install:

    npm install @emurgo/links effect
    # or
    bun add @emurgo/links effect

The effect package is a runtime dependencyparse() returns an Effect<...> and InvalidUriError is built on Effect's tagged-error helpers. If your project does not yet use Effect, install it; it's a single small runtime addition (≈ 30 KB gzipped).

Features

  • Parse and build Cardano URIs (web+cardano://...) per CIP-13
  • Legacy CIP-13 bare address format (web+cardano:<address>?amount=...)
  • Brand-specific deep links (yoroi://..., secondfi://..., https://yoroi-wallet.com/w1/...)
  • 12 URI authorities for the Cardano protocol
  • Type-safe with Effect-TS
  • Round-trip parsing (parse -> build -> same URI)

Cardano URIs (web+cardano://)

Supported Authorities

| Authority | Format | Purpose | |-----------|--------|---------| | claim | web+cardano://claim/<faucet>/<code> | Token faucet claims (CIP-99) | | browse | web+cardano://browse/<type>/<id> | Block explorer links (CIP-158) | | pay | web+cardano://pay?address=...&amount=... | Payment requests (CIP-13) | | payment | Alias for pay | Legacy compatibility | | stake | web+cardano://stake/<pool_id> | Stake pool delegation | | drep | web+cardano://drep/<drep_id> | DRep delegation | | transaction | web+cardano://transaction/<hash> | View transaction (CIP-107) | | block | web+cardano://block/<hash> | View block (CIP-107) | | address | web+cardano://address/<addr> | View address (CIP-134) | | connect | web+cardano://connect?... | Wallet connect | | wallet | web+cardano://wallet?encrypted=... | Wallet import | | legacy-transfer | web+cardano://legacy-transfer?... | Byron wallet transfer |

The legacy CIP-13 bare address format web+cardano:<address>?amount=...&memo=... is also supported and parses as a pay authority.

Parsing

import { parse, isCardanoUri } from '@emurgo/links'
import { Effect } from 'effect'

// Parse a payment URI
const result = await Effect.runPromise(
  parse('web+cardano://pay?address=addr1...&amount=1000000')
)
// { authority: 'pay', address: 'addr1...', amount: 1000000n }

// Legacy CIP-13 bare address format also works
const legacy = await Effect.runPromise(
  parse('web+cardano:addr1...?amount=5000000')
)
// { authority: 'pay', address: 'addr1...', amount: 5000000n }

// Type guard
isCardanoUri('web+cardano://pay?address=addr1...') // true
isCardanoUri('web+cardano:addr1...')                // true (legacy)
isCardanoUri('https://example.com')                 // false

Building

import { build } from '@emurgo/links'

const payUri = build({
  authority: 'pay',
  address: 'addr1...',
  amount: 5000000n,
  message: 'Coffee'
})
// 'web+cardano://pay?address=addr1...&amount=5000000&message=Coffee'

const stakeUri = build({ authority: 'stake', poolId: 'pool1abc' })
// 'web+cardano://stake/pool1abc'

Direct Authority Access

import { Authorities } from '@emurgo/links'

const uri = Authorities.Pay.build('addr1...', 1000000n, 'Tip')

Brand-Specific Links

Brand links handle brand-specific deep links that use the native brand scheme (yoroi://, secondfi://), the browser-extension-safe web scheme (web+secondfi://), or HTTPS fallback (https://yoroi-wallet.com/w1/...).

Supported Use Cases

| Feature | Use Case | Purpose | |---------|----------|---------| | transfer | request/ada | Multi-target ADA payment request | | transfer | request/ada-with-link | Payment with embedded web+cardano:// link | | transfer | request/crypto | Chain-aware native/token payment request | | exchange | order/show-create-result | Exchange order result display | | browser | launch | Launch dApp URL in in-app browser |

All brand links support partner integration fields (appId, authorization, signature, redirectTo).

Parsing Brand Links

import { parseBrandLink, isBrandLink } from '@emurgo/links'

// Detect brand links
isBrandLink('yoroi://yoroi-wallet.com/w1/browser/launch?dappUrl=...', 'yoroi') // true
isBrandLink('https://yoroi-wallet.com/w1/browser/launch?dappUrl=...')           // true
isBrandLink('web+secondfi://secondfi.io/w1/browser/launch?dappUrl=...', 'secondfi') // true

// Parse
const action = parseBrandLink(
  'yoroi://yoroi-wallet.com/w1/browser/launch?dappUrl=https%3A%2F%2Fapp.com',
  'yoroi'
)
// { feature: 'browser', useCase: 'launch', params: { dappUrl: 'https://app.com' } }

Building Brand Links

import { buildBrandLink } from '@emurgo/links'

const url = buildBrandLink(
  { feature: 'browser', useCase: 'launch', params: { dappUrl: 'https://app.com' } },
  'yoroi'
)
// 'yoroi://yoroi-wallet.com/w1/browser/launch?dappUrl=https%3A%2F%2Fapp.com'

Chain-Aware Transfer Requests

Partner integrations can request a concrete wallet send with transfer/request/crypto. The amount value is base units: lovelace for ADA, wei for ETH, and token base units for ERC-20s such as USDC. Pass redirectTo as the raw HTTPS return URL; the builder applies the query encoding and preserves nested callback parameters.

This is the recommended SecondFi/Encryptus callback format for off-ramp deposit requests. It replaces the old Yoroi/Cardano-only flow that first built a web+cardano://pay?... link and then wrapped it with transfer.request.adaWithLink. Partners should call buildTransferRequestCryptoLink directly for both ADA and supported EVM transfers.

Accepted chains are exported as a const tuple so partners get IDE autocomplete:

import { KNOWN_TRANSFER_CHAINS, type KnownTransferChain } from '@emurgo/links'

KNOWN_TRANSFER_CHAINS // readonly ['cardano:mainnet', 'eip155:1']
import { buildTransferRequestCryptoLink } from '@emurgo/links'

const url = buildTransferRequestCryptoLink({
  chain: 'eip155:1',
  asset: 'ETH',
  address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
  amount: '50000000000000000',
  redirectTo: 'https://hub.encryptus.co/pw/?orderId=123',
  appId: '18d1545a-a59b-45cb-a180-157b110c77fe',
})
// 'secondfi://secondfi.io/w1/transfer/request/crypto?...'

For browser-extension callbacks, use the web+secondfi scheme option because extensions register web protocol handlers such as web+secondfi, not the native-app secondfi:// scheme:

const extensionUrl = buildTransferRequestCryptoLink(
  {
    chain: 'ETHEREUM',
    name: 'USDC',
    address: '0x742d35Cc6634C0532925a3b844Bc454e4438f44e',
    amount: '5050000',
    client: 'encryptus',
    callbackPlatform: 'web',
  },
  { scheme: 'web+secondfi' }
)
// 'web+secondfi://secondfi.io/w1/transfer/request/crypto?...'

Encryptus Integration Snippet

import { buildTransferRequestCryptoLink } from '@emurgo/links'

const createSecondfiLink = ({
  chain,
  name,
  address,
  amount,
  callbackPlatform,
  sourceWalletGroupId,
  sourceWalletAccountIndex,
}: {
  chain: 'CARDANO' | 'ETHEREUM' | 'ETH'
  name: 'ADA' | 'USDC' | 'ETH'
  address: string
  amount: string // base-unit integer string, e.g. 5050000 for 5.05 USDC
  callbackPlatform: 'web' | 'app'
  sourceWalletGroupId?: string // echo the value SecondFi passed to the Encryptus widget
  sourceWalletAccountIndex?: string // echo with sourceWalletGroupId when provided
}) =>
  buildTransferRequestCryptoLink(
    {
      client: 'encryptus',
      chain,
      name,
      address,
      amount,
      callbackPlatform,
      sourceWalletGroupId,
      sourceWalletAccountIndex,
      redirectTo: window.location.href,
      appId: '18d1545a-a59b-45cb-a180-157b110c77fe',
      authorization: 'uuid-v4',
    },
    { scheme: callbackPlatform === 'web' ? 'web+secondfi' : 'secondfi' },
  )

Important integration notes:

  • client='encryptus' enables the Encryptus label normalizer.
  • callbackPlatform='web' tells Encryptus this callback is for the browser extension and should use web+secondfi://...; use callbackPlatform='app' for native mobile app callbacks and secondfi://....
  • If SecondFi passes sourceWalletGroupId and sourceWalletAccountIndex to the Encryptus widget, echo them back unchanged in buildTransferRequestCryptoLink. The wallet uses them to restore the source wallet and account selected when the off-ramp handoff started.
  • Encryptus chain='CARDANO' with name='ADA' maps to chain='cardano:mainnet' and asset='ADA'.
  • Encryptus chain='ETHEREUM' with name='USDC' maps to chain='eip155:1', asset='USDC', and the Ethereum mainnet USDC contract token.
  • Encryptus chain='ETH'/chain='ETHEREUM' with name='ETH' maps to native Ethereum. The amount must already be wei.
  • Without a supported client, pass canonical values directly, for example chain='cardano:mainnet' or chain='eip155:1'.
  • amount must be an integer string in base units. For example, 2000000 means 2 ADA, and 5050000 means 5.05 USDC.
  • Pass redirectTo as a raw URL. Do not wrap it with encodeURIComponent; this helper handles query encoding.
  • If window.location.href contains very large transient state, prefer a shorter HTTPS order/status URL that can resume the Encryptus session.
  • The generated link uses web+secondfi://secondfi.io/w1/... for callbackPlatform='web' and secondfi://secondfi.io/w1/... for callbackPlatform='app'.

Error Handling

import { parse, InvalidUriError } from '@emurgo/links'
import { Effect, Exit } from 'effect'

const result = await Effect.runPromiseExit(parse('invalid-uri'))

if (Exit.isFailure(result)) {
  // Handle InvalidUriError
  console.error('Parse failed:', result.cause)
}

Development

The package is part of the chimera monorepo. To run its tests from a checkout:

bun vitest run packages/links

License

Apache-2.0