Supersett
개발자의 하루
Supersett
Blockchain Dev
전체 방문자
오늘
어제
  • 분류 전체보기
    • 프론트
    • 회사생활
    • 블록체인
    • 프로젝트
      • 창업 프로젝트 (DRF + AWS)
      • Spring 프로젝트
    • [중앙대]멋쟁이 사자처럼
    • 기술서적
    • Problem Solving
      • 알고리즘
    • 일기장
      • 하루 정리
      • 삽질 일기
      • 조급할 때 눌러보기

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 멋쟁이사자처럼 중앙대
  • 블록체인 서버설계
  • DEPROMEET
  • 면접준비
  • 컴퓨터학원
  • 자바
  • 멋쟁이 사자처럼
  • 비트코인
  • 초보개발자
  • Near Explorer
  • 신입개발자
  • 구글소셜로그인
  • Near Scan
  • 멋쟁이 사자처럼 면접
  • 글리치해커톤
  • Luniverse
  • 국비지원
  • 멋쟁이 사자처럼 서류
  • 국비
  • 프로젝트
  • 블록체인정보가공
  • java
  • 국비교육
  • 자바스크립트
  • 해커톤
  • 디프만16기
  • 취업준비
  • 멋사 중앙대
  • Multichain API
  • 니어프로토콜

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
Supersett

개발자의 하루

Tnxs 정보를 가공해서 "분기별 트렌드 리포트"를 제공해보자📒 (feat. dApp killing feature)
블록체인

Tnxs 정보를 가공해서 "분기별 트렌드 리포트"를 제공해보자📒 (feat. dApp killing feature)

2023. 5. 27. 20:04

🎯 내가 만들고 싶은 기능

  1. 특정 유저가 이용한 dApp들의 통계를 보여주고 싶다.
  2. 근데 그 유저가 이용한 시기(분기)를 설정해서 분기마다의 이용 통계값을 반환하길 원한다.
  3. 유저가 이용하는 dApp들은 1️⃣Defi 2️⃣NFT 3️⃣Others 로 분류한다.
  4. 분기별 사용자의 이용 dApp 통계를 DTO로 반환합니다.

 

🏹 기능을 구현하는데 필요한 요소는?

특정 유저가 이용한 dApp들의 통계를 보여주고 싶다.
  1. https://doc.pikespeak.ai/
  2. /account/transactions/{contract_address} API 호출하면 아래의 json을 반환 받는다.(최근 50개의 tnxs정보)
  3. Key 값 중 "first_action_type" : "functionCall" 인 부분을 추출할 것이고
  4. "signer" 과 "receiver" 중 contract_address와 일치하지 않는 부분이 바로 사용자가 사용한 dApp의 이름이다.
[
  {
    "block_height": "92607293",
    "chunk_hash": "5bEscxzE1Nb6Q3cJs5d7uBnLQcxTRUR99FMSuydCJiDj",
    "block_hash": "4gkV7ULRZhK6MRrPbUivHqW7HAYXRPVTtstPPugGk9X5",
    "signer": "sehir.near",
    "receiver": "wrap.near",
    "method_name": "near_withdraw",
    "transaction_timestamp": "1684939010149657052",
    "id": "HHg4cDuhXetT9n2Ee92tEYypdqPJrher8Kf8RVWPP4U7",
    "first_action_type": "functionCall",
    "all_action_type": "functionCall",
    "has_error": false
  },
  {
    "block_height": "92607244",
    "chunk_hash": "F6FFxWei3fHs5x58HmjboUUBsEBidmRbNZTD9bHBd8QT",
    "block_hash": "FZ6wY6Xijc5MQVkYE1CvWFvdrCqergSZN6BmFoxQCDk3",
    "signer": "sehir.near",
    "receiver": "token.bocachica_mars.near",
    "method_name": "ft_transfer_call",
    "transaction_timestamp": "1684938954141871765",
    "id": "3Z5jEQTvNfJBxmMLyYRfhvb2GZUS32AE3NCBzRU6nx2X",
    "first_action_type": "functionCall",
    "all_action_type": "functionCall",
    "has_error": false
  }
  ]

 

근데 그 유저가 이용한 시기(분기)를 설정해서 분기마다의 이용 통계값을 반환하길 원한다.
  1. 분기별로 제시를 한다 = txns의 데이터를 생성날짜를 기준으로 분류를 한다.
  2. "transaction_timestamp": "1684834722800094638" 부분을 연월일로 치환후 저장합니다.
  3. NEAR TimeStamp 환경설정 : number of non-leap-nanoseconds since January 1, 1970 0:00:00 UTC
  4. 1684834722800094638 = 2023년 6월 20일 8시 9분 5.472800094638초
public static List<String> convertTimestamp(String timestampStr) {
    long timestamp = Long.parseLong(timestampStr);
    Instant instant = Instant.ofEpochSecond(0, timestamp);
    LocalDateTime dateTime = LocalDateTime.ofInstant(instant, ZoneId.of("UTC"));

    int year = dateTime.getYear();
    int month = dateTime.getMonthValue();
    List<String> yearMonth = new ArrayList<>();

    yearMonth.add(String.valueOf(year));
    yearMonth.add(String.valueOf(month));
    return yearMonth;
}

 

 

유저가 이용하는 dApp들은 1️⃣Defi 2️⃣NFT 3️⃣Others 로 분류한다. 
  • 유저가 이용한 dApp의 name으로 어떤 종류의 dApp을 이용했는지 알기위해서 mapping할 자료들이 필요하다.
    • NEAR 네트워크에 존재하는 NFT 서비스들을 크롤링을 통해 NFT_data.json 을 추출했음
  • 자료구조 중, 집합(set)을 활용해서 NFT_set, Defi_set을 준비한다.
  • 사용자가 사용한 dApp의 이름 이 NFT집합 or Defi집합에 contain 하는지 확인 후, 각각 appCategory컬럼에 맞는값으로 분류해서 저장한다.
public class NftUtil {
    public static void addContractNamesFromJson(Nft nft, String filePath) {
        ObjectMapper objectMapper = new ObjectMapper();

        try {
            List<ContractDTO> contracts = objectMapper.readValue(new File(filePath), new TypeReference<List<ContractDTO>>() {});
            for (ContractDTO contract : contracts) {
                nft.addContractName(contract.getContract_name());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
[
  { "id": 0, "contract_name": "x.paras.near", "category": "nft" },
  { "id": 1, "contract_name": "marketplace.paras.near", "category": "nft" },
  { "id": 2, "contract_name": "token.paras.near", "category": "nft" },
  { "id": 3, "contract_name": "staking.paras.near", "category": "nft" },
  { "id": 4, "contract_name": "market.fewandfar.near", "category": "nft" },
  {
    "id": 5,
    "contract_name": "pack.promotional.nfl.playible.near",
    "category": "nft"
  },
  {
    "id": 6,
    "contract_name": "pack.promotional.basketball.playible.near",
    "category": "nft"
  },
  { "id": 7, "contract_name": "spin-nft-contract.near", "category": "nft" },
  { "id": 8, "contract_name": "dragonnation.near", "category": "nft" },
  {
    "id": 9,
    "contract_name": "simple.market.mintbase1.near",
    "category": "nft"
  },
  { "id": 10, "contract_name": "mintbase1.near", "category": "nft" },
  { "id": 11, "contract_name": "market.tradeport.near", "category": "nft" },
  { "id": 12, "contract_name": "serumnft.near", "category": "nft" },
  { "id": 13, "contract_name": "nearnautsnft.near", "category": "nft" },
  { "id": 14, "contract_name": "nft.alienbearcrew.near", "category": "nft" },
  { "id": 15, "contract_name": "nft.uniqart.near", "category": "nft" },
  {
    "id": 16,
    "contract_name": "game.basketball.playible.near",
    "category": "nft"
  },
  { "id": 17, "contract_name": "game.fnl.playible.near", "category": "nft" },
  {
    "id": 18,
    "contract_name": "laboratory.secretskelliessociety.near",
    "category": "nft"
  },
  { "id": 19, "contract_name": "nativo-minter.near", "category": "nft" },
  { "id": 20, "contract_name": "proxy2.minista.near", "category": "nft" }
]

 

분기별 사용자의 이용 dApp 통계를 DTO로 반환합니다.
  • 유저의 사용 dApp의 이름 상위 5위를 반환합니다. dApp은 오늘을 포함하는 분기에 해당하는 정보들이 반환됩니다.
public List<UsedAppDTO> getTopUsedAppsByUser(String userAddress) {
    Defi defi = new Defi();
    DefiUtil.addContractNamesFromJson(defi, "src/main/java/ni/co/nico/set/defi/defiData.json");
    Set<String> defiSet = defi.getContractNames();

    Nft nft = new Nft();
    NftUtil.addContractNamesFromJson(nft, "src/main/java/ni/co/nico/set/nft/nftData.json");
    Set<String> nftSet = nft.getContractNames();


    LocalDate currentDate = LocalDate.now();
    int currentYear = currentDate.getYear();
    int currentQuarter = (currentDate.getMonthValue() - 1) / 3 + 1;
    LocalDate quarterStart = LocalDate.of(currentYear, (currentQuarter - 1) * 3 + 1, 1);
    LocalDate quarterEnd = quarterStart.plusMonths(3).minusDays(1);


    List<UsedApp> usedApps = usedAppRepository.findByUserAddress(userAddress);
    List<UsedApp> usedAppsInQuarter = usedApps.stream()
            .filter(usedApp -> {
                LocalDate appDate = LocalDate.parse(usedApp.getCreatedDate()); // Assuming createdDate is the field representing the date
                return !appDate.isBefore(quarterStart) && !appDate.isAfter(quarterEnd);
            })
            .collect(Collectors.toList());

    // 현재 분기 내 개수로 매핑 앱 이름 매핑
    Map<String, Integer> appNameCountMapInQuarter = new HashMap<>();

    // 현재 분기 내에서 앱 이름당 사용 횟수 계산
    for (UsedApp usedApp : usedAppsInQuarter) {
        String appName = usedApp.getAppName();
        appNameCountMapInQuarter.put(appName, appNameCountMapInQuarter.getOrDefault(appName, 0) + 1);
    }

    // 개수별로 내림차순으로 정렬하고 상위 5개만 추출
    List<Map.Entry<String, Integer>> sortedEntries = appNameCountMapInQuarter.entrySet()
            .stream()
            .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
            .limit(5)
            .collect(Collectors.toList());

    // 결과를 담을 리스트
    List<UsedAppDTO> usedAppDTOs = new ArrayList<>();

    // 정렬된 엔트리를 순회하며 DTO로 변환하여 리스트에 추가
    for (Map.Entry<String, Integer> entry : sortedEntries) {
        String appName = entry.getKey();
        int count = entry.getValue();

        UsedAppDTO usedAppDTO = new UsedAppDTO();
        usedAppDTO.setUserAddress(userAddress);
        usedAppDTO.setAppName(appName);
        usedAppDTO.setCount(count);
        usedAppDTO.setYear(currentYear);
        usedAppDTO.setQuarter(currentQuarter);
        // appCategory 설정
        if (defiSet.contains(appName)) {
            usedAppDTO.setAppCategory("defi");
        } else if (nftSet.contains(appName)) {
            usedAppDTO.setAppCategory("nft");
        } else {
            usedAppDTO.setAppCategory("others");
        }
        usedAppDTOs.add(usedAppDTO);
    }

    return usedAppDTOs;
}

이렇게 반환됩니다

'블록체인' 카테고리의 다른 글

[Hackathon](후기: 대회 1등을 했습니다😉) KYC dApp Project ( Multichain API, Webhook, Json RPC)  (0) 2023.06.05
[Polygon Hackathon] Backend Dashboard (5.30 ~ 6.4)  (0) 2023.05.30
[Digital Signiture] 암호화의 원리🔐  (0) 2023.05.24
[Hackathon] NICO dApp Project (feat. Block Explorer, SBT, Community)  (0) 2023.05.22
[Hackathon] Backend DashBoard is underway👾  (2) 2023.05.14
    '블록체인' 카테고리의 다른 글
    • [Hackathon](후기: 대회 1등을 했습니다😉) KYC dApp Project ( Multichain API, Webhook, Json RPC)
    • [Polygon Hackathon] Backend Dashboard (5.30 ~ 6.4)
    • [Digital Signiture] 암호화의 원리🔐
    • [Hackathon] NICO dApp Project (feat. Block Explorer, SBT, Community)
    Supersett
    Supersett
    하루를 돌아보고 공부한 티를 내기 위해 블로그를 만들었습니다.

    티스토리툴바