Scanner API Guidelines

Development guide prepared for the implementation of additional functions after NFT holder verification.

Introduction

This document is a development guideline prepared for implementing additional functions after NFT holder verification.

Understanding of SDKs such as web3.js and ethers may be required to implement blockchain-related functions.

If you develop an API endpoint server by referring to this document, you can add the features of the example below.

Check how many NFTs the user who authenticated the wallet has Send NFTs or tokens to users recognized by the scanner Offline Stamp tour using FAVORLET and FAVORLET Scanner Access check and record management at offline holder party Various functions suitable for other situations

Please refer to the Basic usage guideline page for basic usage guide for FAVORLET scanner.

How to set End point URL

You can receive a request to the registered API server after scanning the user's authentication QR code by putting it in the service endpoint URL on the scanner setting screen.

On the scanner settings screen, you can set in the following three ways.

  1. If only the collection contract address is entered: Only the scanner's NFT holder will be verified.

  2. If you only put the service endpoint URL: Skip scanner's NFT holder verification and send request to API server.

  3. If you put both the collection contract address and service endpoint URL: Send a request to the API server after verifying the scanner's NFT holder.

Either the collection contract address or the service endpoint URL must be entered

Flow

The flow of communication between FAVORLET, Scanner, and Server is as below.

  1. FAVORLET users generate a verification QR.

  2. The scanner checks the QR code whether it is valid or not and passes the wallet address and other information to the endpoint URL (API server) you set.

  3. The requested API server responds with a scanner for success or failure.

Specifications

Request

This is the data that FAVORLET scanner request to the API server set as the service endpoint URL.

Method: POST

Header: Content-Type:application/json

Body

{
    "walletAddress": "0xd464B499639A267Da03721b2DBa7469896732947",
    "contractAddress": "0x8F5Aa6b6DCD2D952A22920E8fE3f798471D05901", // 홀더 인증을 설정한 경우
    "signature": "0xbe1b5bc3fe1378a4bd5198dd37a6c620e8a49f84347f3e4cb4eb8e8b4b0fb16545ad365d2cf19b05dfb84f88adfb922214c0d4f9ff29227f780c2f4fea0b2a9a1c" // signature 설명 아래 참고
    "expireTime": "2022-10-05T08:22:45.000Z"
}

Parameter Description

walletAddress

string

This is the wallet address delivered through QR verification.

contractAddress

string

This is the address registered in the collection contract address on the scanner settings screen. If left blank, no data will appear.

signature

string

This is the data for verifying whether walletAddress and expireTime have changed. The usage of the value is optional, see below for detailed explanation.

expireTime

string

The expiration date for the QR code generated by the user. The format is YYYY-MM-DDTHH:mm:ss.sssZ.

what issignature?

블록체인에서 문자열에 대해 지갑의 private key로 서명하여 나오는 데이터로, 이 signature 를 다시 복구했을 때 지갑 주소가 나온다면 해당 지갑으로 서명한 데이터임을 검증할 수 있습니다. This is the data that comes from signing the string with the private key of the wallet on the blockchain.

If the wallet address is found when this signature is recovered, it can be verified that the data was signed by the wallet.

Favorlet에서 QR 인증 시 "i-love-fingerlabs_" + walletAddress + "_" + expireTime 텍스트로 서명하게 되며, walletAddressexpireTime값을 검증할 수 있습니다.

Favorlet에서 QR 인증에 대한 메세지 서명은 이더리움 prefix를 사용하게 되며, 자바스크립트에서는 ethersweb3.js 라이브러리를 사용하여 서명한 주소를 복구할 수 있습니다.

자바스크립트 라이브러리 중 caver-js는 클레이튼 prefix를 사용하므로 복구할 수 없습니다.

  • 이더리움 prefix:"\x19Ethereum Signed Message:\n" + message.length + message

  • 클레이튼 prefix: "\x19Klaytn Signed Message:\n" + message.length + message

메세지 서명과 관련된 자세한 내용을 알고 싶다면 Ethereum Signed Message Verification Tool를 참조 바라며, 검증에 대한 방법은 본 문서 아래의 서버 예제를 참고 바랍니다.

Response

This is the data that the API server you set as the service endpoint URL should respond with FAVORLET scanner.

Header: Content-Type:application/json

  • Case1: success

    {
        "success": true,
        "title": "Success! 😀",
        "reason": "Authentication succeeded."
    }
  • Case2: fail

    {
        "success": false,
        "title": "Fail! 😥",
        "reason": "Authentication failed."
    }

Screenshot

Parameter Description

success

boolean

요청에 대한 성공 여부이며 true또는 false를 반환해야 합니다.

title

string

스캐너에서 요청 결과 팝업 제목에 표시되는 텍스트입니다.

reason

string

스캐너에서 요청 결과 팝업 설명에 표시되는 텍스트입니다.

응답 결과는 JSON 형태로 응답해야 하며 Response status code는 스캐너에서 참조하지 않습니다.

API 서버 예제 (Node.js)

1. Node.js 설치

2. 프로젝트 폴더 생성 및 이동

mkdir api_endpoint_example
cd api_endpoint_example

3. 패키지 설치

npm install express ethers

4. index.js 파일 작성

const express = require('express');
const ethers = require('ethers');

const app = express();
app.use(express.json());

// signature 인증
const qrVerify = (walletAddress, signature, expireTime) => {
  // recover할 메세지 생성
  const msgHash = ethers.utils.hashMessage(`i-love-fingerlabs_${walletAddress}_${expireTime}`);
  // 메세지에 대해 Byte Array 타입으로 변경
  const msgHashBytes = ethers.utils.arrayify(msgHash);

  // signature로 서명한 주소 recover
  const recoverAddress = ethers.utils.recoverAddress(msgHashBytes, signature);

  // recover한 주소와 walletAddress 비교, QR 만료 시간 확인
  if (recoverAddress !== walletAddress || new Date(expireTime) < new Date()) {
    throw new Error('Validation Failed.');
  }
};

// 요청받을 API 엔드포인트
app.post('/', (req, res) => {
  const { walletAddress, signature, expireTime } = req.body;

  //walletAddress, signature, expireTime에 대해 검증
  qrVerify(walletAddress, signature, expireTime);


  /**
   * 작업할 코드
   * ex) NFT mint, Token airdrop, Holder pass...
   */

  // 성공
  res.send({
    success: true,
    title: "Success! 😀",
    reason: "Authentication succeeded."
  });
});

// 에러 핸들러
app.use((err, req, res, next) => {
  // 실패
  res.send({
    success: false,
    title: "Fail! 😥",
    reason: "Authentication failed."
  });
});

// 3000번 포트로 listen
app.listen(3000, () => {
  console.log('running => http://localhost:3000');
});

5. 터미널에서 실행

node index.js

6. 새 터미널에서 테스트

curl --location --request POST 'http://localhost:3000' \
--header 'Content-Type: application/json' \
--data-raw '{
    "walletAddress": "0xe13F97c9b97BC41BF2540fc2e8CA6998439100AB",
    "signature": "0xf5c6c3c9817146d22818c5367a6e77e4de295bb3432c79d117b8b9bf72ae954c5a2dd93b9fa9417112fb71160bac1e06c22cf22e5a9da8c97ff08f9759bd02a91b",
    "expireTime": "2023-04-10T03:16:25.168Z"
}'

7. 결과 확인

{
  "success":true,
  "title":"Success! 😀",
  "reason":"Authentication succeeded."
}

만약 스캐너앱의 기본 기능 외에 다른 액션을 추가하고 싶으신데 개발에 어려움을 겪고 있다면 favorlet@fingerlabs.io 로 이메일 주시길 바랍니다.

Last updated