สร้าง dapp บน Tezos (ฉบับปี 2023)
ส่วนที่ 2 จาก 4-> กระเป๋าเงินและโทเค็นของผู้ใช้
ตอนนี้เรามาพูดถึงกระเป๋าสตางค์
กระเป๋าเงินเป็นองค์ประกอบสำคัญของ dapp ของคุณ หากไม่มี ผู้ใช้จะไม่สามารถโต้ตอบกับ Tezos blockchain ได้ ซึ่งผิดวัตถุประสงค์ของคุณ มีข้อควรพิจารณาหลายประการเมื่อคุณตั้งค่ากระเป๋าเงิน ซึ่งเราจะอธิบายด้านล่างนี้
ขั้นแรก เราต้องการแยกกระเป๋าเงินและการโต้ตอบและค่าต่างๆ ออกจากกันในองค์ประกอบเดียวกัน ซึ่งเรียกว่าWallet.svelteในตัวอย่างของเรา เมื่อใช้ Beacon SDK สิ่งสำคัญคือต้องให้อินสแตนซ์เดียวของ Beacon ทำงานเพื่อป้องกันข้อบกพร่อง
เมื่อติดตั้งส่วนประกอบ Wallet มีหลายสิ่งหลายอย่างที่เราต้องการทำ:
onMount(async () => {
const wallet = new BeaconWallet({
name: "Tezos dev portal dapp tutorial",
preferredNetwork: network
});
store.updateWallet(wallet);
const activeAccount = await wallet.client.getActiveAccount();
if (activeAccount) {
const userAddress = (await wallet.getPKH()) as TezosAccountAddress;
store.updateUserAddress(userAddress);
$store.Tezos.setWalletProvider(wallet);
await getWalletInfo(wallet);
// fetches user's XTZ, tzBTC and SIRS balances
const res = await fetchBalances($store.Tezos, userAddress);
if (res) {
store.updateUserBalance("XTZ", res.xtzBalance);
store.updateUserBalance("tzBTC", res.tzbtcBalance);
store.updateUserBalance("SIRS", res.sirsBalance);
} else {
store.updateUserBalance("XTZ", null);
store.updateUserBalance("tzBTC", null);
store.updateUserBalance("SIRS", null);
}
}
});
ตอนนี้ คุณต้องการตรวจสอบว่าผู้ใช้เคยเชื่อมต่อกระเป๋าเงินมาก่อนหรือไม่ Beacon จะติดตามการเชื่อมต่อสดในที่จัดเก็บในเครื่อง นี่คือวิธีที่ผู้ใช้ของคุณสามารถนำทางไปยัง dapp ของคุณและเชื่อมต่อกระเป๋าเงินของพวกเขาโดยอัตโนมัติ!
อินBeaconWalletสแตนซ์จัดเตรียมclientพร็อพเพอร์ตี้ด้วยเมธอดต่างๆ ซึ่งสิ่งที่คุณต้องการในที่นี้คือgetActiveAccount()ซึ่งจะดึงการเชื่อมต่อสดใดๆ ที่จัดเก็บไว้ในที่จัดเก็บในเครื่อง หากมีการเชื่อมต่อสด คุณสามารถดึงข้อมูลที่อยู่ของผู้ใช้และบันทึกไว้ในร้านค้า อัปเดตร้านค้าด้วยที่อยู่ของผู้ใช้ก่อนที่จะตั้งค่ากระเป๋าเงินเป็นผู้ลงนามด้วย รับข้อมูลที่คุณต้องการเกี่ยวกับกระเป๋าเงิน (โดยหลักคือ$store.Tezos.setWalletProvider(wallet)ชื่อ ของกระเป๋าเงิน) ด้วยgetWalletInfo()ฟังก์ชัน จากนั้นดึงยอดคงเหลือสำหรับที่อยู่ที่เชื่อมต่อกับfetchBalances()ฟังก์ชันที่อธิบายไว้ก่อนหน้านี้ เมื่อดึงยอดคงเหลือแล้ว ยอดคงเหลือจะถูกบันทึกไว้ในร้านค้าเพื่อแสดงในอินเทอร์เฟซ
หมายเหตุ: TezosAccountAddressเป็นประเภทกำหนดเองที่ฉันต้องการใช้เพื่อตรวจสอบความถูกต้องของที่อยู่ Tezos สำหรับบัญชีโดยนัย: type TezosAccountAddress = tz${"1" | "2" | "3"}${string}TypeScript จะส่งคำเตือนหากคุณพยายามใช้สตริงที่ไม่ตรงกับรูปแบบนี้
การเชื่อมต่อกระเป๋าเงิน
Taquito และ Beacon ทำงานพร้อมกันทำให้เชื่อมต่อกระเป๋าเงินได้ง่ายมาก โค้ดสองสามบรรทัดที่ใช้ API ของไลบรารีที่จำเป็นทั้งสองนี้บน Tezos กำลังจะสร้างปาฏิหาริย์
นี่คือวิธีการ:
const connectWallet = async () => {
if (!$store.wallet) {
const wallet = new BeaconWallet({
name: "Tezos dev portal dapp tutorial",
preferredNetwork: network
});
store.updateWallet(wallet);
}
await $store.wallet.requestPermissions({
network: { type: network, rpcUrl }
});
const userAddress = (await $store.wallet.getPKH()) as TezosAccountAddress;
store.updateUserAddress(userAddress);
$store.Tezos.setWalletProvider($store.wallet);
// finds account info
await getWalletInfo($store.wallet);
// fetches user's XTZ, tzBTC and SIRS balances
const res = await fetchBalances($store.Tezos, userAddress);
if (res) {
store.updateUserBalance("XTZ", res.xtzBalance);
store.updateUserBalance("tzBTC", res.tzbtcBalance);
store.updateUserBalance("SIRS", res.sirsBalance);
} else {
store.updateUserBalance("XTZ", null);
store.updateUserBalance("tzBTC", null);
store.updateUserBalance("SIRS", null);
}
};
ต่อไป คุณขอให้ผู้ใช้เลือกกระเป๋าเงินด้วย วิธีการที่มีอยู่ในอินสแตน ซ์requestPermissions()ของ BeaconWalletพารามิเตอร์คือวัตถุที่คุณระบุเครือข่ายที่คุณต้องการเชื่อมต่อ เช่นเดียวกับ URL ของโหนด Tezos RPC ที่คุณจะโต้ตอบด้วย
หลังจากที่ผู้ใช้เลือกกระเป๋าเงินที่จะใช้กับ dapp ของเรา คุณจะได้รับที่อยู่ของพวกเขาด้วยวิธีการgetPKH()บนBeaconWalletอินสแตนซ์ คุณอัปเดตผู้ลงนามในอินTezosToolkitสแตนซ์โดยส่งอินสแตนซ์กระเป๋าเงินไปที่setWalletProvider()คุณจะได้รับข้อมูลที่คุณต้องการจากกระเป๋าเงินและดึงข้อมูล ยอดคงเหลือของผู้ใช้
ตอนนี้กระเป๋าเงินเชื่อมต่อแล้ว และผู้ใช้จะแสดงยอดคงเหลือที่แตกต่างกัน รวมถึงสถานะการเชื่อมต่อในแถบด้านข้าง!
สำคัญ: อย่างไรก็ตาม คุณต้องการออกแบบ dapp ของคุณ สิ่งสำคัญคือต้องเก็บอินสแตนซ์เดียวของ the BeaconWalletและขอแนะนำอย่างยิ่งให้ทำเช่นเดียวกันกับอินสแตนซ์ของTezosToolkit. การสร้างหลายอินสแตนซ์ทำให้สถานะของแอปของคุณยุ่งเหยิงและกับ Taquito โดยทั่วไป
ตัดการเชื่อมต่อกระเป๋าเงิน
การตัดการเชื่อมต่อกระเป๋าเงินมีความสำคัญเท่ากับการเชื่อมต่อ ไม่มีอะไรน่าผิดหวังไปกว่าการค้นหาวิธีตัดการเชื่อมต่อกระเป๋าเงินของคุณเป็นเวลาหลายชั่วโมงทั้งที่ไม่ได้ระบุไว้อย่างชัดเจน โปรดจำไว้ว่า ผู้ใช้จำนวนมากมีกระเป๋าเงินหลายใบ (เช่น Temple หรือ Kukai) และแม้แต่ที่อยู่หลายที่อยู่ภายในกระเป๋าเงินเดียวกันที่พวกเขาต้องการใช้เพื่อโต้ตอบกับ dapp ของคุณ ทำให้การตัดการเชื่อมต่อกระเป๋าเงินเป็นเรื่องง่ายสำหรับพวกเขา
const disconnectWallet = async () => {
$store.wallet.client.clearActiveAccount();
store.updateWallet(undefined);
store.updateUserAddress(undefined);
connectedNetwork = "";
walletIcon = "";
};
$store.wallet.client.clearActiveAccount()-> ฆ่าการเชื่อมต่อกับ Beacon ปัจจุบันstore.updateWallet(undefined)-> ลบกระเป๋าเงินออกจากสถานะเพื่อทริกเกอร์การโหลดอินเทอร์เฟซใหม่store.updateUserAddress(undefined)-> ลบที่อยู่ของผู้ใช้ปัจจุบันออกจากสถานะเพื่ออัปเดต UIconnectedNetwork = ""; walletIcon = ""-> จำเป็นต้องรีเซ็ตสถานะของ dapp และนำเสนออินเทอร์เฟซที่ไม่มีการเชื่อมต่อกระเป๋าเงิน
ข้อควรพิจารณาในการออกแบบ
การเขียนโค้ดเพื่อโต้ตอบกับกระเป๋าเงินในแอปพลิเคชันแบบกระจายศูนย์เป็นกระบวนทัศน์ใหม่ และแม้ว่าคุณจะสามารถนำแนวคิดและแนวปฏิบัติที่ดีมากมายจากประสบการณ์ของคุณในฐานะนักพัฒนากลับมาใช้ใหม่ได้ แต่ก็มีสิ่งใหม่ๆ สองสามข้อที่ควรคำนึงถึง:
- อย่าแจ้งให้ผู้ใช้เชื่อมต่อกระเป๋าเงินของพวกเขาหลังจากติดตั้ง dapp แล้ว: การได้รับป๊อปอัปกระเป๋าเงินบนหน้าจอหลังจากโหลดแอปนั้นน่ารำคาญ คุณต้องจำไว้ว่าผู้ใช้จำนวนมากของคุณไม่มีความรู้ด้านเทคนิคและไม่เข้าใจว่า การเชื่อมต่อกระเป๋าเงินนั้นไม่เป็นอันตราย ดังนั้นพวกเขาอาจระวังเกี่ยวกับ dapp ของคุณหากคุณขอให้พวกเขาเชื่อมต่อกระเป๋าเงินตั้งแต่เริ่มใช้งาน ให้แสดงข้อมูลบางอย่างเกี่ยวกับ dapp ของคุณและปุ่มเพื่อเชื่อมต่อกระเป๋าเงินด้วยตนเอง หากนี่เป็นครั้งแรก
- ปุ่มสำหรับเชื่อมต่อกระเป๋าเงินต้องโดดเด่นในอินเทอร์เฟซของคุณ ไม่ว่าคุณจะทำให้มันใหญ่ขึ้น มีสีอื่น หรือแบบอักษรอื่น ผู้ใช้จะต้องไม่ใช้เวลามากกว่าสองสามวินาทีในการค้นหา
- ปุ่มต้องอยู่ในตำแหน่งที่คาดเดาได้: Dapps ส่วนใหญ่บน Tezos วางปุ่มเพื่อเชื่อมต่อกระเป๋าเงินที่ด้านบนซ้ายหรือขวาบนของ UI คุณไม่ได้"สร้างสรรค์"ด้วยการวางปุ่มในตำแหน่งอื่น คุณจะทำให้ผู้ใช้สับสน
- ข้อความในปุ่มควรอ่านว่า Connect หรือคำอื่นที่คล้ายกัน หลีกเลี่ยงการ Sync หรือคำอื่นๆ แต่คำว่า "connect" เนื่องจากอาจหมายถึงสิ่งที่แตกต่างออกไปในบริบทของแอปพลิเคชันแบบกระจายอำนาจ
- สถานะของกระเป๋าเงินจะต้องแสดงใน Dapp ไม่ว่าจะเชื่อมต่อหรือตัดการเชื่อมต่อ ผู้ใช้ควรจะสามารถบอกได้ นอกจากนี้ คุณสามารถเพิ่มข้อมูลบางอย่างเกี่ยวกับกระเป๋าเงินที่พวกเขาใช้ (เหมือนที่เราทำในบทช่วยสอนนี้) เครือข่ายที่พวกเขาเชื่อมต่อ หรือยอดคงเหลือ
- คุณต้องเปิด/ปิดการโต้ตอบของ dapp ของคุณที่ขึ้นอยู่กับกระเป๋าเงิน ผู้ใช้ไม่ควรโต้ตอบกับคุณลักษณะของแอปพลิเคชันของคุณที่ต้องเชื่อมต่อกระเป๋าเงินของพวกเขา หากไม่เป็นเช่นนั้น
หนึ่งในคุณสมบัติที่สำคัญที่สุดของ dapp ซึ่งเป็นหนึ่งในคุณสมบัติที่ง่ายที่สุดที่จะมองข้ามคือการดึงข้อมูลยอดคงเหลือของผู้ใช้ ผู้ใช้สามารถบอกได้ว่ามีสิ่งผิดปกติหากยอดคงเหลือของพวกเขาแสดงไม่ถูกต้องหรือไม่อัปเดตตามนั้นหลังจากการโต้ตอบกับสัญญา นั่นเป็นเหตุผลว่าทำไมการดูแลการแสดงและอัปเดตยอดคงเหลือจึงเป็นเรื่องสำคัญ
เนื่องจากคุณกำลังดึงข้อมูลยอดคงเหลือในส่วนประกอบต่างๆ ของแอปพลิเคชันของเรา คุณจะสร้างฟังก์ชันในไฟล์utils.tsและนำเข้าเมื่อจำเป็น
ในการเรียกยอดคงเหลือ คุณจะใช้ Taquito สำหรับยอดคงเหลือ XTZ ของผู้ใช้ และ API ยอดนิยมบน Tezos สำหรับยอดคงเหลือ tzBTC และ SIRS, TzKT API หากคุณต้องการสร้างแอปพลิเคชันที่ซับซ้อนมากขึ้นบน Tezos ความรู้ที่ดีเกี่ยวกับ TzKT API เป็นสิ่งสำคัญ เนื่องจากมีคุณสมบัติมากมายที่จะทำให้แอปของคุณมีเนื้อหาที่สมบูรณ์ยิ่งขึ้นและรวดเร็วยิ่งขึ้น
มาดูประเภทของฟังก์ชันกัน:
export const fetchBalances = async (
Tezos: TezosToolkit,
userAddress: TezosAccountAddress
): Promise<{
xtzBalance: number;
tzbtcBalance: number;
sirsBalance: number;
} | null> => {
try {
// the code will be here
} catch (error) {
console.error(error);
return null;
}
}
ขั้นแรก เรียกยอดคงเหลือ XTZ:
const xtzBalance = await Tezos.tz.getBalance(userAddress);
if (!xtzBalance) throw "Unable to fetch XTZ balance";
ต่อไป คุณตรวจสอบการมีอยู่ของยอดคงเหลือ และคุณปฏิเสธสัญญาหากไม่มีอยู่จริง หากเป็นเช่น นั้นยอดคงเหลือจะพร้อมใช้งานในรูปแบบBigNumber
หมายเหตุ: โดยส่วนใหญ่แล้ว Taquito จะส่งคืนค่าตัวเลขจากบล็อกเชนเป็น BigNumber เนื่องจากค่าบางค่าอาจเป็นตัวเลขที่สูงมาก และ JavaScript ขึ้นชื่อในเรื่องการจัดการตัวเลขจำนวนมากได้ไม่ดี
เมื่อดึงยอดคงเหลือ XTZ แล้ว คุณสามารถดำเนินการต่อและดึงยอดคงเหลือของ tzBTC และ SIRS:
import { tzbtcAddress, sirsAddress } from "./config";
// previous code for the function
const res = await fetch(
`https://api.tzkt.io/v1/tokens/balances?account=${userAddress}&token.contract.in=${tzbtcAddress},${sirsAddress}`
);
if (res.status === 200) {
const data = await res.json();
if (Array.isArray(data) && data.length === 2) {
const tzbtcBalance = +data[0].balance;
const sirsBalance = +data[1].balance;
if (!isNaN(tzbtcBalance) && !isNaN(sirsBalance)) {
return {
xtzBalance: xtzBalance.toNumber(),
tzbtcBalance,
sirsBalance
};
} else {
return null;
}
}
} else {
throw "Unable to fetch tzBTC and SIRS balances";
}
เมื่อสัญญาได้รับการแก้ไขด้วย200รหัส หมายความว่าได้รับข้อมูลแล้ว คุณแยกวิเคราะห์เป็น JSON ด้วย.json()วิธีการตอบกลับ และเราตรวจสอบว่าข้อมูลมีรูปร่างตามที่คาดไว้ นั่นคืออาร์เรย์ที่มี 2 องค์ประกอบในนั้น
องค์ประกอบแรกคือยอดคงเหลือ tzBTC และส่วนที่สองคือยอดคงเหลือ SIRS คุณเก็บไว้ในตัวแปรของตัวเองที่คุณแปลงเป็นตัวเลขก่อนที่จะตรวจสอบว่าพวกเขาถูกโยนอย่างถูกต้องisNaNด้วย หากทุกอย่างเป็นไปด้วยดี ความสมดุลทั้ง 3 จะถูกส่งกลับ และหากมีอะไรผิดพลาดระหว่างทาง ฟังก์ชันจะส่งnullกลับ
หลังจากเรียกยอดคงเหลือในส่วนประกอบใดๆ ของแอปพลิเคชันของเรา คุณจะเก็บข้อมูลนี้ในร้านค้าเพื่ออัปเดตสถานะ:
const res = await fetchBalances($store.Tezos, userAddress);
if (res) {
store.updateUserBalance("XTZ", res.xtzBalance);
store.updateUserBalance("tzBTC", res.tzbtcBalance);
store.updateUserBalance("SIRS", res.sirsBalance);
} else {
store.updateUserBalance("XTZ", null);
store.updateUserBalance("tzBTC", null);
store.updateUserBalance("SIRS", null);
}
ในส่วนที่สามการแลกเปลี่ยนโทเค็น =>





































![รายการที่เชื่อมโยงคืออะไร? [ส่วนที่ 1]](https://post.nghiatu.com/assets/images/m/max/724/1*Xokk6XOjWyIGCBujkJsCzQ.jpeg)