Skip to content
This repository has been archived by the owner on Feb 11, 2024. It is now read-only.

Commit

Permalink
156 febeウォレット連携前に投稿したトークンをマイページで確認ウォレット連携で振込 (#157)
Browse files Browse the repository at this point in the history
  • Loading branch information
sey323 authored Nov 19, 2023
1 parent 15fc747 commit c575233
Show file tree
Hide file tree
Showing 20 changed files with 274 additions and 26 deletions.
34 changes: 29 additions & 5 deletions components/MyProfile.vue
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,14 @@
<h3>{{ props.displayName }}</h3>
<div class="stats px-5">
<div class="stat text-center">
<i>現金と交換可能なトークン</i>
<i class="grid">{{ exchangeableToken }}<span>pts</span></i>
<i>獲得したビンゴトークン</i>
<i class="grid"
>{{ exchangeableToken
}}<span
>pts
{{ !props.walletAccount?.address ? "(付与前)" : "" }}
</span></i
>
</div>
</div>
<div class="stats px-5">
Expand All @@ -33,6 +39,13 @@
><p class="text-white" style="word-break: break-all">
{{ walletAddress }}
</p>
<p
v-if="hasPreGrantBingoToken"
class="text-white"
style="word-break: break-all"
>
{{ hasPreGrantBingoTokenMessage }}
</p>
</v-icon>
</div>
</div>
Expand Down Expand Up @@ -73,17 +86,28 @@ const avatarImageURL = computed(() => {

const exchangeableToken = computed(() => {
if (!props.walletAccount?.address) {
return "???";
return props.userInfo?.preGrantBingoToken ?? "0";
}
// トークン取得は未実装
return props.bingoToken?.quantityOwned ?? "???";
return props.bingoToken?.quantityOwned ?? "0";
});
const walletAddress = computed(() => {
return (
props.walletAccount?.address ??
"接続されていません。ウォレットと接続してください"
);
});
const hasPreGrantBingoToken = computed(() => {
return (
props.userInfo?.preGrantBingoToken && props.userInfo?.preGrantBingoToken > 0
);
});
const hasPreGrantBingoTokenMessage = computed(() => {
return (
`ウォレットと接続すると` +
props.userInfo?.preGrantBingoToken +
`pt付与されます!`
);
});
</script>

<style lang="scss" scoped>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
from contract_proxy.core.bingoCard.request import BingoUserTokenMintRequest
from contract_proxy.core.bingoCard.response import BingoUserTokenMintResponse
from contract_proxy.core.bingo_token.request import BingoUserTokenMintRequest
from contract_proxy.core.bingo_token.response import BingoUserTokenMintResponse
from contract_proxy.facades.thirdweb.erc1155_bingo_token_contract import (
transfer_nft,
)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from typing import List
from pydantic import BaseModel, Field


class MemoryNftsMintRequest(BaseModel):
memoryTokenIds: List[str] = Field([], description="NFTのIDリスト")
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from typing import List
from pydantic import BaseModel, Field


class MemoryNftsMintResponse(BaseModel):
memoryTokenIds: List[str] = Field([], description="NFTのIDリスト")
22 changes: 22 additions & 0 deletions functions/contract_proxy/contract_proxy/core/memory_nft/route.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
from contract_proxy.core.memory_nft.request import MemoryNftsMintRequest
from contract_proxy.core.memory_nft.response import MemoryNftsMintResponse
from contract_proxy.facades.thirdweb.erc1155_memory_nft_contract import (
add_owner_nfts,
)
from fastapi import APIRouter


memory_nft_router = APIRouter(
prefix="/mint-memory-nfts", tags=["mint_memory_nfts"]
)


@memory_nft_router.put(
"/{wallet_address}",
)
async def mint_memory_nfts(
wallet_address: str,
request: MemoryNftsMintRequest,
):
add_owner_nfts(wallet_address, request.memoryTokenIds)
return MemoryNftsMintResponse(memoryTokenIds=request.memoryTokenIds)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
from typing import List
import contract_proxy.config as config
from contract_proxy.facades.thirdweb import sdk


contract = sdk.get_contract(config.ERC1155_CONTRACT_ADDRESS)


def add_owner_nfts(address: str, memoryTokenIds: List[str]):
for memoryTokenId in memoryTokenIds:
try:
tx = contract.erc1155.mint_additional_supply(memoryTokenId, 1)
token_id = tx.id
_ = tx.data()
print(f"mint_additional_supply Success. token_id: {token_id}")
except Exception as e:
print("mint_additional_supply Error", e)

try:
_ = contract.erc1155.transfer(address, memoryTokenId, 1)
print(f"transfer Success. address: {address}, ")
except Exception as e:
print("transfer Error", e)
4 changes: 3 additions & 1 deletion functions/contract_proxy/contract_proxy/main.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from contract_proxy.core.bingoCard.route import bingo_token_router
from contract_proxy.core.bingo_token.route import bingo_token_router
from contract_proxy.core.memory_nft.route import memory_nft_router
import uvicorn


Expand All @@ -16,6 +17,7 @@ def get_application() -> FastAPI:
allow_headers=["*"],
)
app.include_router(bingo_token_router)
app.include_router(memory_nft_router)
return app


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@
from create_complete_movie.models.bingo_card import BingoCardCell
from google.cloud.firestore_v1.base_query import FieldFilter

from create_complete_movie.models.user import (
User,
)

COLLECTION_PREFIX = "bingoCard"


Expand Down Expand Up @@ -35,7 +39,7 @@ def fetch_bingo_card_name(bingo_card_id: str) -> Union[str, None]:

def fetch_bingo_card_answer_users(
bingo_card_id: str,
) -> Union[list[str], None]:
) -> list[User]:
"""ビンゴカードに紐づく回答者の一覧を取得する
Args:
Expand All @@ -59,9 +63,7 @@ def fetch_bingo_card_answer_users(
)

return [
answered_user.to_dict().get("walletAddress")
for answered_user in answered_user_list
if answered_user.to_dict().get("walletAddress") is not None
User(**answered_user.to_dict()) for answered_user in answered_user_list
]


Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
from typing import Union
from create_complete_movie.facades.firestore import db
from create_complete_movie.models.bingo_card import BingoCardCell


COLLECTION_PREFIX = "users"


def update_pre_grant_memory_nft_token_ids(
token_id: str, uids: list[str]
) -> Union[list[BingoCardCell], None]:
"""ユーザーが取得漏れたNFTの一覧を更新する
Args:
token_id (str): _description_
uids (list[str]): _description_
Returns:
Union[list[BingoCardCell], None]: _description_
"""
for uid in uids:
user = db.fetch(collection=COLLECTION_PREFIX, id=uid)
# preGrantMemoryNftTokenIdsが存在しない場合は、初期化する
if "preGrantMemoryNftTokenIds" not in user:
user["preGrantMemoryNftTokenIds"] = []

user["preGrantMemoryNftTokenIds"].append(str(token_id))
db().collection(COLLECTION_PREFIX).document(uid).set(user)
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def mint_movie_nft(name: str, animation_url: str, supply: int = 1):


def transfer_nft(token_id: str, to_address_list: list[str]):
print(to_address_list)
for to_address in to_address_list:
try:
tx = contract.erc1155.transfer(to_address, token_id, 1)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
from typing import Optional
from pydantic import BaseModel, Field


class User(BaseModel):
uid: str = Field(..., description="ユーザーID")
walletAddress: Optional[str] = Field(None, description="ウォレットアドレス")
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@
mint_movie_nft,
transfer_nft,
)
from create_complete_movie.facades.firestore.user import (
update_pre_grant_memory_nft_token_ids,
)


def mint_and_transfer_nft(bingo_card_id, bingo_card_name, public_url):
Expand All @@ -16,16 +19,29 @@ def mint_and_transfer_nft(bingo_card_id, bingo_card_name, public_url):
"""
bingo_card_answer_users = fetch_bingo_card_answer_users(bingo_card_id)

if len(bingo_card_answer_users) == 0:
print("匿名ユーザの回答者のみのため、NFTをmintしません")
return
# walletAddressのみを取得する、Noneの場合は除外する
bingo_card_answer_user_wallet_address = [
user.walletAddress
for user in bingo_card_answer_users
if user.walletAddress is not None and user.walletAddress != ""
]

# NFTをmintする. ビンゴカードに回答した人数分mintする
mint_count = len(bingo_card_answer_users)
# ビンゴカードに回答したメンバーにウォレットを保有する人がいない場合でも、のちに配布する可能性があるため、Supplyを0としてmintする
mint_count = len(bingo_card_answer_user_wallet_address)
token_id, nft = mint_movie_nft(
bingo_card_name, public_url, supply=mint_count
)

print(bingo_card_answer_users)
# walletAddressを保有しないユーザには、のちに配布できるように、DBにNFTの情報を保存する
update_pre_grant_memory_nft_token_ids(
token_id, [user.uid for user in bingo_card_answer_users]
)

if len(bingo_card_answer_users) == 0:
print("匿名ユーザの回答者のみのため、NFTを配布しません")
return

# 回答者全員にNFTを送る
transfer_nft(token_id, bingo_card_answer_users)
transfer_nft(token_id, bingo_card_answer_user_wallet_address)
print(f"token_id: {token_id}")
10 changes: 5 additions & 5 deletions server/api/bingoCardCell/[bingoCardId].put.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,12 +87,12 @@ export default defineEventHandler(async (event) => {

// トークンを発行
const assignToken = Math.floor(requestBody.imageAiCheckScore * 10);
const user = await getUserInfo(uid);
const user = (await getUserInfo(uid)) as UserInfo;
if (user === undefined || user.walletAddress === undefined) {
// 存在しない場合はトークンを付与しない
// TODO: トークンを付与しないことを通知する、ユーザ情報にキャッシュする
console.log("user or walletAddress is undefined", uid);
await updateUserPreGrantBingoToken(uid, assignToken);
// ウォレットアドレスが存在しない場合はトークンを付与しない。
// DBに、本来付与されるトークンを保存しておく
const updateValue = user.preGrantBingoToken ?? 0 + assignToken; // 更新後の値
await updateUserPreGrantBingoToken(uid, updateValue);
} else {
// 存在する場合はトークン付与
const request = {
Expand Down
61 changes: 59 additions & 2 deletions server/api/user/wallet/index.put.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,61 @@
import { idAuthentication } from "@/server/facades/auth/idAuthentication";
import { updateUserWallet } from "@/server/facades/repositories/users";
import {
updateUserPreGrantBingoToken,
updateUserPreGrantMemoryNftTokenIds,
updateUserWallet,
} from "@/server/facades/repositories/users";
import {
mintBingoToken,
mintMemoryNts,
} from "@/server/facades/contracts/contractProxy";
import { MintBingoTokenPutRequest } from "@/server/models/facades/contracts/contractProxy";

export default defineEventHandler(async (event) => {
try {
const token = await getHeaders(event)["authorization"];
const uid = await idAuthentication(token);

const body = (await readBody(event).then((b) => JSON.parse(b))) as any;
const body = (await readBody(event).then((b) =>
JSON.parse(b)
)) as UserWalletPutDto;

// DBに追加
const userWallet = await updateUserWallet(uid, body);

// アサイン前のトークンがあれば、アサインする
if (hasNonAssignToken(userWallet)) {
console.log("アサイン前のトークンがあるので、アサインします。");
const request = {
supply: userWallet?.preGrantBingoToken, // index.vueに表示される値と同じ
} as MintBingoTokenPutRequest;
mintBingoToken(body.walletAddress, request).then(() => {
console.log("トークンをアサインしました。", uid, request.supply);
// アサインしたので、DBの値をリセット
updateUserPreGrantBingoToken(uid, 0);
console.log("DBの値をリセットしました。", uid);
});
}

// アサイン前のトークンがあれば、アサインする
if (
userWallet?.preGrantMemoryNftTokenIds &&
userWallet?.preGrantMemoryNftTokenIds.length > 0
) {
console.log("アサイン前のNFTがあるので、アサインします。");
mintMemoryNts(body.walletAddress, {
memoryTokenIds: userWallet?.preGrantMemoryNftTokenIds,
}).then(() => {
console.log(
"NFTをアサインしました。",
uid,
userWallet?.preGrantMemoryNftTokenIds
);
// アサインしたので、DBの値をリセット
updateUserPreGrantMemoryNftTokenIds(uid, []);
console.log("DBの値をリセットしました。", uid);
});
}

return {
message: "OK",
userWallet: userWallet,
Expand All @@ -22,3 +68,14 @@ export default defineEventHandler(async (event) => {
};
}
});

/**
* 付与前のトークンとウォレットアドレスが登録されているかどうか
*/
function hasNonAssignToken(userWallet: UserInfo | undefined) {
return (
userWallet?.preGrantBingoToken &&
userWallet?.preGrantBingoToken > 0 &&
userWallet?.walletAddress
);
}
Loading

0 comments on commit c575233

Please sign in to comment.