diff --git a/api/contract/abi.ts b/api/contract/abi.ts
index 20a613a..c0aeb28 100644
--- a/api/contract/abi.ts
+++ b/api/contract/abi.ts
@@ -1,6 +1,770 @@
import { AbiItem } from 'caver-js'
-const abi: AbiItem[] = [
+export const ftAbi: AbiItem[] = [
+ {
+ inputs: [],
+ stateMutability: 'nonpayable',
+ type: 'constructor',
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ {
+ indexed: false,
+ internalType: 'uint256',
+ name: 'value',
+ type: 'uint256',
+ },
+ ],
+ name: 'Approval',
+ type: 'event',
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ indexed: false,
+ internalType: 'uint256',
+ name: 'value',
+ type: 'uint256',
+ },
+ ],
+ name: 'Transfer',
+ type: 'event',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ ],
+ name: 'allowance',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'approve',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'account',
+ type: 'address',
+ },
+ ],
+ name: 'balanceOf',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'decimals',
+ outputs: [
+ {
+ internalType: 'uint8',
+ name: '',
+ type: 'uint8',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'subtractedValue',
+ type: 'uint256',
+ },
+ ],
+ name: 'decreaseAllowance',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'player',
+ type: 'address',
+ },
+ ],
+ name: 'ensureAttackAmount',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'spender',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'addedValue',
+ type: 'uint256',
+ },
+ ],
+ name: 'increaseAllowance',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'name',
+ outputs: [
+ {
+ internalType: 'string',
+ name: '',
+ type: 'string',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'recipient',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'safeTransfer',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'recipient',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ {
+ internalType: 'bytes',
+ name: '_data',
+ type: 'bytes',
+ },
+ ],
+ name: 'safeTransfer',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'sender',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'recipient',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'safeTransferFrom',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'sender',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'recipient',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ {
+ internalType: 'bytes',
+ name: '_data',
+ type: 'bytes',
+ },
+ ],
+ name: 'safeTransferFrom',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'bytes4',
+ name: 'interfaceId',
+ type: 'bytes4',
+ },
+ ],
+ name: 'supportsInterface',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'symbol',
+ outputs: [
+ {
+ internalType: 'string',
+ name: '',
+ type: 'string',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'totalSupply',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'transfer',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'amount',
+ type: 'uint256',
+ },
+ ],
+ name: 'transferFrom',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+]
+
+export const nftAbi: AbiItem[] = [
+ {
+ inputs: [],
+ stateMutability: 'nonpayable',
+ type: 'constructor',
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'approved',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'Approval',
+ type: 'event',
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'operator',
+ type: 'address',
+ },
+ {
+ indexed: false,
+ internalType: 'bool',
+ name: 'approved',
+ type: 'bool',
+ },
+ ],
+ name: 'ApprovalForAll',
+ type: 'event',
+ },
+ {
+ anonymous: false,
+ inputs: [
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ indexed: true,
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'Transfer',
+ type: 'event',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'approve',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ ],
+ name: 'balanceOf',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'player',
+ type: 'address',
+ },
+ {
+ internalType: 'string',
+ name: 'tokenURI',
+ type: 'string',
+ },
+ ],
+ name: 'ensureAttackAmount',
+ outputs: [
+ {
+ internalType: 'uint256',
+ name: '',
+ type: 'uint256',
+ },
+ ],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'getApproved',
+ outputs: [
+ {
+ internalType: 'address',
+ name: '',
+ type: 'address',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'owner',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'operator',
+ type: 'address',
+ },
+ ],
+ name: 'isApprovedForAll',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'name',
+ outputs: [
+ {
+ internalType: 'string',
+ name: '',
+ type: 'string',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'ownerOf',
+ outputs: [
+ {
+ internalType: 'address',
+ name: '',
+ type: 'address',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'safeTransferFrom',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ {
+ internalType: 'bytes',
+ name: '_data',
+ type: 'bytes',
+ },
+ ],
+ name: 'safeTransferFrom',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'operator',
+ type: 'address',
+ },
+ {
+ internalType: 'bool',
+ name: 'approved',
+ type: 'bool',
+ },
+ ],
+ name: 'setApprovalForAll',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'bytes4',
+ name: 'interfaceId',
+ type: 'bytes4',
+ },
+ ],
+ name: 'supportsInterface',
+ outputs: [
+ {
+ internalType: 'bool',
+ name: '',
+ type: 'bool',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [],
+ name: 'symbol',
+ outputs: [
+ {
+ internalType: 'string',
+ name: '',
+ type: 'string',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'tokenURI',
+ outputs: [
+ {
+ internalType: 'string',
+ name: '',
+ type: 'string',
+ },
+ ],
+ stateMutability: 'view',
+ type: 'function',
+ },
+ {
+ inputs: [
+ {
+ internalType: 'address',
+ name: 'from',
+ type: 'address',
+ },
+ {
+ internalType: 'address',
+ name: 'to',
+ type: 'address',
+ },
+ {
+ internalType: 'uint256',
+ name: 'tokenId',
+ type: 'uint256',
+ },
+ ],
+ name: 'transferFrom',
+ outputs: [],
+ stateMutability: 'nonpayable',
+ type: 'function',
+ },
+]
+
+export const sbtAbi: AbiItem[] = [
{
inputs: [],
stateMutability: 'nonpayable',
@@ -127,7 +891,7 @@ const abi: AbiItem[] = [
},
{
internalType: 'string',
- name: 'tokenURI',
+ name: '_tokenURI',
type: 'string',
},
],
@@ -360,6 +1124,4 @@ const abi: AbiItem[] = [
stateMutability: 'nonpayable',
type: 'function',
},
-]
-
-export default abi
+]
\ No newline at end of file
diff --git a/api/contract/controllers.ts b/api/contract/controllers.ts
index bd008a7..2a6d7d3 100644
--- a/api/contract/controllers.ts
+++ b/api/contract/controllers.ts
@@ -1,7 +1,8 @@
+import axios from 'axios'
import Caver from 'caver-js'
import type { NextApiRequest, NextApiResponse } from 'next'
import { Blob } from 'nft.storage'
-import abi from './abi'
+import { ftAbi, nftAbi, sbtAbi } from './abi'
import * as contractService from './services'
export type PostPayload = {
@@ -45,22 +46,68 @@ export async function ensureAttackAmount(
)
caver.wallet.add(key)
- const contract = new caver.contract(abi, process.env.CONTRACT_ADDRESS)
+ // estimate gasPrice
+ const { data: gasPrice } = await axios.get<{
+ result: string
+ }>('https://api.baobab.klaytn.net:8651', {
+ headers: {
+ 'Content-Type': 'application/json',
+ },
+ data: {
+ jsonrpc: '2.0',
+ method: 'klay_gasPrice',
+ params: [],
+ id: 1,
+ },
+ })
- const tx = await contract.methods
- .ensureAttackAmount(
- address,
- // key.address,
- uri,
- )
+ const effectiveGasPrice = caver.utils.hexToNumber(gasPrice.result)
+
+ const ftContract = new caver.contract(
+ ftAbi,
+ process.env.KUPFT_CONTRACT_ADDRESS,
+ )
+
+ const ftTx = await ftContract.methods.ensureAttackAmount(address).send({
+ from: key.address,
+ // gasPrice: '75000000000',
+ gasPrice: effectiveGasPrice.toString(),
+ gas: 1000000000,
+ })
+
+ const nftContract = new caver.contract(
+ nftAbi,
+ process.env.KUPNFT_CONTRACT_ADDRESS,
+ )
+
+ const nftTx = await nftContract.methods
+ .ensureAttackAmount(address, uri)
+ .send({
+ from: key.address,
+ // gasPrice: '75000000000',
+ gasPrice: effectiveGasPrice.toString(),
+ gas: 1000000,
+ })
+
+ const sbtContract = new caver.contract(
+ sbtAbi,
+ process.env.KUPSBT_CONTRACT_ADDRESS,
+ )
+
+ const sbtTx = await sbtContract.methods
+ .ensureAttackAmount(address, uri)
.send({
- // from: address,
from: key.address,
- gasPrice: '75000000000',
+ // gasPrice: '75000000000',
+ gasPrice: effectiveGasPrice.toString(),
gas: 1000000,
})
- res.status(200).json(tx)
+ res.status(200).json({
+ ft: ftTx.transactionHash,
+ nft: nftTx.transactionHash,
+ sbt: sbtTx.transactionHash,
+ })
} catch (error: any) {
console.log(error)
res.status(500).json({ error: error.message })
diff --git a/features/Contract/components/ContractIntract.tsx b/features/Contract/components/ContractIntract.tsx
index db0f933..00e4cf3 100644
--- a/features/Contract/components/ContractIntract.tsx
+++ b/features/Contract/components/ContractIntract.tsx
@@ -37,12 +37,7 @@ const ContractInteract: React.FC<{
status === 200 &&
openModal({
title: 'Contract',
- component: (
-
- ),
+ component: ,
})
setLoading(false)
})
@@ -80,4 +75,4 @@ const ContractInteract: React.FC<{
)
}
-export default ContractInteract
+export default ContractInteract
\ No newline at end of file
diff --git a/features/Contract/components/ContractSuccess.tsx b/features/Contract/components/ContractSuccess.tsx
index 15683c2..55977e3 100644
--- a/features/Contract/components/ContractSuccess.tsx
+++ b/features/Contract/components/ContractSuccess.tsx
@@ -3,9 +3,13 @@ import axios from 'axios'
import { useEffect, useState } from 'react'
const ContractSuccess: React.FC<{
- txHash: string
+ txs: {
+ ft: string
+ nft: string
+ sbt: string
+ }
ipnft: string
-}> = ({ txHash, ipnft }) => {
+}> = ({ txs, ipnft }) => {
const [nftImageUrl, setNftImageUrl] = useState(null)
useEffect(() => {
axios
@@ -36,16 +40,35 @@ const ContractSuccess: React.FC<{
{nftImageUrl && }
-
- Transaction Info
-
+
)
}
-export default ContractSuccess
+export default ContractSuccess
\ No newline at end of file
diff --git a/types/env.d.ts b/types/env.d.ts
index b33486a..8c32547 100644
--- a/types/env.d.ts
+++ b/types/env.d.ts
@@ -2,9 +2,12 @@ declare namespace NodeJS {
interface ProcessEnv {
NEXT_PUBLIC_PLAYFAB_TITLEID: string
NFT_STORAGE_API_KEY: string
- CONTRACT_ADDRESS: string
RPC_URL: string
API_KEY: string
KEY_RING: string
+
+ KUPFT_CONTRACT_ADDRESS: string
+ KUPNFT_CONTRACT_ADDRESS: string
+ KUPSBT_CONTRACT_ADDRESS: string
}
}
\ No newline at end of file
diff --git a/utils/requester.ts b/utils/requester.ts
index 2ca394e..76addfc 100644
--- a/utils/requester.ts
+++ b/utils/requester.ts
@@ -3,6 +3,7 @@ import type { AxiosError, AxiosRequestConfig } from 'axios'
import { toast } from 'react-toastify'
const titleId: string = process.env.NEXT_PUBLIC_PLAYFAB_TITLEID
+
const Requester = axios.create({
baseURL: `https://${titleId}.playfabapi.com`,
})
@@ -27,11 +28,18 @@ Requester.interceptors.response.use(
return response
},
(error) => {
- // console.log('📲❌', error)
-
if (axios.isAxiosError(error)) {
const axiosError = error as AxiosError
- return Promise.reject(axiosError.response?.data), toast(axiosError.response?.data.errorMessage);
+
+ // when the sessionTicket's time is expired, remove it from localStorage
+ if (axiosError.response?.data.error === 'InvalidTicket') {
+ localStorage.removeItem('SessionTicket')
+ }
+
+ return (
+ Promise.reject(axiosError.response?.data),
+ toast(axiosError.response?.data.errorMessage)
+ )
}
return Promise.reject(error)