본문으로 건너뛰기

TON Connect for Vue

Vue 앱을 위한 권장 SDK는 UI Vue SDK입니다. TON Connect와 상호작용하기 위한 고수준 Vue 컴포넌트를 제공합니다.

구현

설치

TON Connect를 DApp에 통합하기 위해 @townsquarelabs/ui-vue 패키지를 설치해야 합니다:

npm i @townsquarelabs/ui-vue

TON Connect 초기화

앱의 루트에 TonConnectUIProvider를 추가하세요. props를 통해 UI 옵션을 지정할 수 있습니다.

모든 TonConnect UI 훅 호출과 <TonConnectButton /> 컴포넌트는 <TonConnectUIProvider> 내부에 위치해야 합니다.

<template>
<TonConnectUIProvider :options="options">
<!-- Your app -->
</TonConnectUIProvider>
</template>

<script>
import { TonConnectUIProvider } from '@townsquarelabs/ui-vue';

export default {
components: {
TonConnectUIProvider
},
setup(){
const options = {
manifestUrl:"https://<YOUR_APP_URL>/tonconnect-manifest.json",
};
return {
options
}
}
}
</script>

지갑 연결

TonConnect Button은 연결을 초기화하기 위한 범용 UI 컴포넌트입니다. 지갑이 연결되면 지갑 메뉴로 변환됩니다. 앱의 우측 상단에 배치하는 것을 권장합니다.

<template>
<header>
<span>My App with Vue UI</span>
<TonConnectButton/>
</header>
</template>

<script>
import { TonConnectButton } from '@townsquarelabs/ui-vue';

export default {
components: {
TonConnectButton
}
}
</script>

class:style props를 버튼에 추가할 수 있습니다. TonConnectButton에는 자식 요소를 전달할 수 없습니다. <TonConnectButton class="my-button-class" :style="{ float: 'right' }"/>

리다이렉트

지갑 연결 후 특정 페이지로 사용자를 리다이렉트하려면 useTonConnectUI 훅을 사용하고 리턴 전략을 커스터마이즈할 수 있습니다.

텔레그램 미니 앱

지갑 연결 후 텔레그램 미니 앱으로 사용자를 리다이렉트하려면 TonConnectUIProvider 요소를 커스터마이즈할 수 있습니다:

<template>
<TonConnectUIProvider :options="options">
<!-- Your app -->
</TonConnectUIProvider>
</template>

<script>
import { TonConnectUIProvider } from '@townsquarelabs/ui-vue';

export default {
components: {
TonConnectUIProvider,
},
setup() {
const options = {
actionsConfiguration: { twaReturnUrl: 'https://t.me/<YOUR_APP_NAME>' },
};
return {
options,
};
},
};
</script>

SDK 문서에서 자세히 알아보기

UI 커스터마이즈

모달의 UI를 커스터마이즈하려면 useTonConnectUI 훅과 setOptions 함수를 사용할 수 있습니다. useTonConnectUI 훅에 대해 자세히 알아보려면 Hooks 섹션을 참조하세요.

useTonAddress

현재 사용자의 ton 지갑 주소를 가져오는 데 사용합니다. isUserFriendly 불리언 매개변수를 전달하여 주소 형식을 선택할 수 있습니다. 지갑이 연결되지 않은 경우 빈 문자열을 반환합니다.

<template>
<div v-if="address">
<span>User-friendly address: {{ userFriendlyAddress }}</span>
<span>Raw address: {{ rawAddress }}</span>
</div>
</template>

<script>
import { useTonAddress } from '@townsquarelabs/ui-vue';

export default {
setup() {
const userFriendlyAddress = useTonAddress();
const rawAddress = useTonAddress(false);

return {
userFriendlyAddress,
rawAddress
}
}
}
</script>

useTonWallet

현재 사용자의 ton 지갑을 가져오는 데 사용합니다. 지갑이 연결되지 않은 경우 null을 반환합니다.

지갑의 모든 속성을 확인하세요.

<template>
<div v-if="wallet">
<span>Connected wallet: {{ wallet.name }}</span>
<span>Device: {{ wallet.device.appName }}</span>
</div>
</template>

<script>
import { useTonWallet } from '@townsquarelabs/ui-vue';

export default {
setup() {
const wallet = useTonWallet();

return {
wallet
}
}

}
</script>

useTonConnectModal

모달 창을 열고 닫는 기능에 접근하는 데 이 훅을 사용합니다. 이 훅은 현재 모달 상태와 모달을 열고 닫는 메서드가 포함된 객체를 반환합니다.

<template>
<div>
<div>Modal state: {{ state?.status }}</div>
<button @click="open">Open modal</button>
<button @click="close">Close modal</button>
</div>
</template>

<script>
import { useTonConnectModal } from '@townsquarelabs/ui-vue';

export default {
setup() {
const { state, open, close } = useTonConnectModal();
return { state, open, close };
}
};
</script>

useTonConnectUI

TonConnectUI 인스턴스와 UI 옵션 업데이트 함수에 접근하는 데 사용합니다.

TonConnectUI 인스턴스 메서드에 대해 자세히 알아보기

setOptions 함수에 대해 자세히 알아보기

<template>
<div>
<button @click="sendTransaction">Send transaction</button>
<div>
<label>language</label>
<select @change="onLanguageChange($event.target.value)">
<option value="en">en</option>
<option value="ru">ru</option>
<option value="zh">zh</option>
</select>
</div>
</div>
</template>

<script>
import { Locales, useTonConnectUI } from '@townsquarelabs/ui-vue';

export default {
name: 'Settings',
setup() {
const [tonConnectUI, setOptions] = useTonConnectUI();

const onLanguageChange = (lang) => {
setOptions({ language: lang as Locales });
};

const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 60, // 60 sec
messages: [
{
address: "EQBBJBB3HagsujBqVfqeDUPJ0kXjgTPLWPFFffuNXNiJL0aA",
amount: "20000000",
// stateInit: "base64bocblahblahblah==" // just for instance. Replace with your transaction initState or remove
},
{
address: "EQDmnxDMhId6v1Ofg_h5KR5coWlFG6e86Ro3pc7Tq4CA0-Jn",
amount: "60000000",
// payload: "base64bocblahblahblah==" // just for instance. Replace with your transaction payload or remove
}
]
}

const sendTransaction = () => {
tonConnectUI.sendTransaction(myTransaction);
};

return { onLanguageChange, sendTransaction };
}
};
</script>

useIsConnectionRestored

연결 복원 프로세스의 현재 상태를 나타냅니다. 연결 복원 프로세스가 완료되었는지 감지하는 데 사용할 수 있습니다.

<template>
<div>
<div v-if="!connectionRestored">Please wait...</div>
<MainPage v-else />
</div>
</template>

<script>
import { useIsConnectionRestored } from '@townsquarelabs/ui-vue';

export default {
name: 'EntrypointPage',
setup() {
const connectionRestored = useIsConnectionRestored();
return { connectionRestored };
}
};
</script>

사용법

Vue UI SDK를 실제로 어떻게 사용하는지 살펴보겠습니다.

트랜잭션 전송

특정 주소로 TON 코인(나노톤 단위)을 전송:

<template>
<div>
<button @click="sendTransaction">Send transaction</button>
</div>
</template>

<script>
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

export default {
name: 'Settings',
setup() {
const [tonConnectUI, setOptions] = useTonConnectUI();


const myTransaction = {
validUntil: Math.floor(Date.now() / 1000) + 60, // 60 sec
messages: [
{
address: "EQBBJBB3HagsujBqVfqeDUPJ0kXjgTPLWPFFffuNXNiJL0aA",
amount: "20000000",
// stateInit: "base64bocblahblahblah==" // just for instance. Replace with your transaction initState or remove
},
{
address: "EQDmnxDMhId6v1Ofg_h5KR5coWlFG6e86Ro3pc7Tq4CA0-Jn",
amount: "60000000",
// payload: "base64bocblahblahblah==" // just for instance. Replace with your transaction payload or remove
}
]
}

const sendTransaction = () => {
tonConnectUI.sendTransaction(myTransaction);
};

return { sendTransaction };
}
};
</script>

해시로 트랜잭션 상태 이해하기

Payment Processing(tonweb 사용)에 있는 원칙입니다. 자세히 알아보기

연결 요청 매개변수 추가(ton_proof)

메시지 서명 및 확인 방법 이해하기: 서명 및 확인

tonConnectUI.setConnectRequestParameters 함수를 사용하여 연결 요청 매개변수를 전달합니다.

이 함수는 하나의 매개변수를 받습니다:

백엔드에서 응답을 기다리는 동안 상태를 'loading'으로 설정합니다. 이 때 사용자가 지갑 연결 모달을 열면 로더가 표시됩니다.

import { ref } from 'vue';
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const tonConnectUI = useTonConnectUI();

tonConnectUI.setConnectRequestParameters({
state: 'loading'
});

또는

상태를 'ready'로 설정하고 tonProof 값을 정의합니다. 전달된 매개변수는 연결 요청(QR 및 범용 링크)에 적용됩니다.

import { ref } from 'vue';
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const tonConnectUI = useTonConnectUI();

tonConnectUI.setConnectRequestParameters({
state: 'ready',
value: {
tonProof: '<your-proof-payload>'
}
});

또는

state: 'loading'을 통해 활성화된 로더를 제거합니다(예: 백엔드에서 응답 대신 오류를 받은 경우). 연결 요청은 추가 매개변수 없이 생성됩니다.

import { ref } from 'vue';
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const tonConnectUI = useTonConnectUI();

tonConnectUI.setConnectRequestParameters(null);

tonProof 페이로드의 수명이 제한된 경우 tonConnectUI.setConnectRequestParameters를 여러 번 호출할 수 있습니다(예: 10분마다 연결 요청 매개변수를 새로 고침할 수 있습니다).

import { ref } from 'vue';
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const tonConnectUI = useTonConnectUI();

// enable ui loader
tonConnectUI.setConnectRequestParameters({ state: 'loading' });

// fetch you tonProofPayload from the backend
const tonProofPayload: string | null = await fetchTonProofPayloadFromBackend();

if (!tonProofPayload) {
// remove loader, connect request will be without any additional parameters
tonConnectUI.setConnectRequestParameters(null);
} else {
// add tonProof to the connect request
tonConnectUI.setConnectRequestParameters({
state: "ready",
value: { tonProof: tonProofPayload }
});
}

지갑이 연결되면 wallet 객체에서 ton_proof 결과를 찾을 수 있습니다:

import { ref, onMounted } from 'vue';
import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const tonConnectUI = useTonConnectUI();

onMounted(() =>
tonConnectUI.onStatusChange(wallet => {
if (wallet.connectItems?.tonProof && 'proof' in wallet.connectItems.tonProof) {
checkProofInYourBackend(wallet.connectItems.tonProof.proof, wallet.account);
}
}));

지갑 연결 해제

지갑 연결을 해제하려면:

import { useTonConnectUI } from '@townsquarelabs/ui-vue';

const [tonConnectUI] = useTonConnectUI();

await tonConnectUI.disconnect();

문제 해결

애니메이션이 작동하지 않는 경우

환경에서 애니메이션이 작동하지 않는 문제가 발생하는 경우 Web Animations API 지원이 부족하기 때문일 수 있습니다. 이 문제를 해결하려면 web-animations-js 폴리필을 사용할 수 있습니다.

npm 사용

폴리필을 설치하려면 다음 명령을 실행하세요:

npm install web-animations-js

그런 다음 프로젝트에 폴리필을 가져오세요:

import 'web-animations-js';

CDN 사용

또는 HTML에 다음 스크립트 태그를 추가하여 CDN을 통해 폴리필을 포함할 수 있습니다:

<script src="https://www.unpkg.com/web-animations-js@latest/web-animations.min.js"></script>

두 방법 모두 Web Animations API의 폴백 구현을 제공하므로 발생하는 애니메이션 문제를 해결할 수 있습니다.

예제

  • 데모 dApp - @townsquarelabs/ui-vue를 사용한 DApp 예제.