Skip to content

Interaction with a Smart card via NFC and FIDO.

Component designed to handle interactions with Smart card via NFC by WebNFC or FIDO2. It provides a user interface for the interaction process and abstracts the complexity of communicating with these devices across different platforms (web browser, Android/iOS WebView).

Features

  • Multi-platform Support: Works in standard web browsers (Chrome, Safari).
  • Multiple Communication Protocols: Supports WebNFC and FIDO2 (WebAuthn) in browsers.
  • Chunked Data Transfer: Handles large data payloads by splitting them into chunks for NFC communication.
  • UI for User Guidance: Displays a modal window to guide the user through the process of tapping their card.
  • Error Handling and Retries: Implements a retry mechanism for failed NFC read/write operations.

How it Works

To use the component, import it and place it on your page. Then, create a reference (ref) to the component — this reference allows you to call the nfcProgressHandler method. The method manages reading and writing data to the card and displays the visual interface for the NFC operation.

Exposed Methods

nfcProgressHandler(request, expectedSize, longNfc = false)

Description

Performs a single-step NFC interaction, where a single command/request is sent to the NFC card and a single response is received.
This is typically used for simple signing or data read/write operations.

Parameters

NameTypeRequiredDescription
requestUint8Array or object✅ YesThe raw command/data to be sent to the NFC card.
expectedSizeobject✅ YesAn object that must contain a parseResponse(responseBuffer) method, which transforms the NFC raw response (ArrayBuffer) into a readable format or parsed object.
longNfcboolean❌ OptionalSet to true if the NFC request is large and needs to be sent as a "long NFC request".

nfcProgressChunksHandler(request, pinCode = null, longNfc = false)

Description

Handles multi-step (chunked) NFC interactions.
Used for larger transactions or signing processes that require sending multiple commands sequentially to the card.


Parameters

NameTypeRequiredDescription
requestobject✅ YesMust contain an array named chunks, where each chunk object defines how to build and process its NFC request/response.
pinCodestring | null❌ OptionalThe card PIN code, if required for authentication or signing.
longNfcboolean❌ OptionalEnables long NFC message mode for larger payloads.

Chunk Object Structure

Each chunk inside request.chunks must implement two methods:

MethodDescription
buildCardRequest({ pin })Async function that returns a Uint8Array representing the NFC command to send.
processCardResponse(responseBuffer)Function that processes the card’s response and prepares any necessary state for the next chunk.

Props overview

These props allow you to customize its appearance, control its state, and handle error display from a parent component.

PropTypeDefault ValueDescription
modelValueString | nullnullA standard prop for v-model usage. While declared, its direct implementation for data binding within the component's logic is not shown.
titleString | null'Touch your card.'The main title text displayed at the bottom of the handler window. This text guides the user on the primary action to take. It can be dynamically updated during retries.
subTitleString | null'Hold your card flat against the back of your device until this window is open.'The subtitle text displayed below the main title. It provides more detailed instructions or context to the user. This also gets updated during retry attempts.
errorMessageString | nullnullA prop intended to receive an error message string. Its direct usage is not present in the template, but it's available for future implementation.
errorString | nullnullSimilar to errorMessage, this prop is designed to handle an error string passed from the parent.
isActiveBooleantrueCrucial for controlling the component. Use v-model:isActive to programmatically show or hide the NFC handler window. The component's internal logic watches this prop to start and stop the NFC process and manage its lifecycle.
isLoadingBooleanundefinedA prop intended to reflect a loading state. The component emits an update:isLoading event, suggesting it's designed to be used with v-model:isLoading for two-way binding with a parent component's state.

Usage Example

Here’s how you would integrate and use the NFCHandlerWindow in a parent component to sign a transaction.

vue
<template>
  <div>
    <button @click="signTransaction">Sign with NFC</button>

    <!-- NFC handler window -->
    <NFCHandlerWindow
      v-model:isActive="isActive"
      ref="nfcHandler"
      :title="'Touch your card.'"
      :subTitle="'Hold your card flat against your device until the window closes.'"
    />
  </div>
</template>

<script setup>
import { ref } from 'vue'
import NFCHandlerWindow from '@/components/NFCHandlerWindow.vue'
import { TransactionSigner } from '@/api/card-communication.js'

const nfcHandler = ref(null)
const isActive = ref(false)

// Example transaction data
const transactionData = new Uint8Array([0x01, 0x02, 0x03, 0x04])

// Create a signer helper
const signer = new TransactionSigner(transactionData)

async function signTransaction() {
  try {
    // Build the raw NFC command
    const request = signer.buildCardRequest()

    // Start NFC operation
    const result = await nfcHandler.value.nfcProgressHandler(
      request,                          // raw data to send
      { parseResponse: signer.parseResponse }, // parser for the response
      false                             // optional longNfc flag
    )

    console.log('✅ NFC operation completed successfully:', result)
  } catch (error) {
    console.error('❌ NFC operation failed:', error)
  }
}
</script>