在上篇瞭解完整個工作流程後,我們就來學習如何用程式碼構建屬於自己的Actions & Blinks吧!其實身為開發者,需要做的只有一件事:部署自己的後端伺服器用來接收GET/POST requests!這邊提供簡單的範例程式碼可以參考!
因為Actions & Blinks是一個有特定規範的服務,所以在接下來的程式碼講解中我不會帶到太多邏輯,只會介紹格式該怎麼設置。首先我們來講解GET函式中的架構。
在GET中我們主要是希望Actions Provider回傳要顯示的精美小視窗內容,而這必須符合特定格式(ActionGetResponse)的Response如下,其中每個欄位的意義寫在註解中:
const requestUrl = new URL(req.url);
const payload: ActionGetResponse = {
title: "Your title",
icon: new URL("/path-of-the-icon-file ", requestUrl.origin).toString(), // the path of icon should be the path under /public
description: "Your description",
label: "Does not matter", // this value will be ignored since `links.actions` exists
links: {
actions: [
{
label: "", // button text
href: `${baseHref}&amount=${"1"}`, //when user click the button, send a POST req to this url
},
{
label: "Send SOL", // button text
href: `${baseHref}token_amount={amount}`, // this href will have a text input and bring the variable
parameters: [ // if we have multiple parameters, there will be multiple lines of input, but only one button
{ // the input value will be the value of variable
name: "amount", // variableconst body: ActionPostRequest = await req.json();
// Validate to confirm the user publickey received is valid before use
let account: PublicKey;
try {
account = new PublicKey(body.account);
} catch (err) {
return new Response('Invalid "account" provided', {
status: 400,
headers: ACTIONS_CORS_HEADERS, //Must include CORS HEADERS
});
} name in the `href` above
label: "Enter the amount of SOL to send", // placeholder of the text input
required: true,
},
],
},
],
},
};
最終將payload包起來傳回去即可:
return Response.json(payload, {
headers,
});
在GET的外面要記得加上下面這段!不然會遇到CORS問題導致瀏覽器阻擋(不知道CORS是什麼沒關係,記得加上就對了!後面有一些其他設定也都是為了CORS)
export const OPTIONS = async (req: Request) => {
return new Response(null, { headers });
};
至此我們就成功建好GET的形式啦~其實很多地方都照抄格式即可,是不是很容易呀~
接著來看POST,我們知道在GET中的action在使用者點擊後會發送一POST req到對應的href(用同一個url帶入參數即可),所以我們的POST就是要處理使用者點擊後我們希望他的錢包做的事情,首先會用以下程式碼獲取使用者的錢包地址(account):
const body: ActionPostRequest = await req.json();
let account: PublicKey;
try {
account = new PublicKey(body.account);
} catch (err) {
return new Response('Invalid "account" provided', {
status: 400,
headers: ACTIONS_CORS_HEADERS, //Must include CORS HEADERS
});
}
接著我們要獲取透過url傳過來的參數值(此範例中是password),用以下的程式碼即可:
const params = new URL(req.url).searchParams;
const password = params.get("password");
在獲使用者選擇的參數後,我們就可以任意的編寫我們的程式碼,如同一般我們用@solana/web3.js製造transaction一樣。在範例程式中我們根據已經部署好的鏈上合約創建了一連串的instructions(airdropInstruction),至於中間如何創建instruction就不在今天的範圍內,是需要根據不同的鏈上合約來變化的。總之包完instructions後利用下面這段程式碼包成transaction,並設定好recentBlockhash & feePayer
const transaction = new Transaction().add(airdropInstruction);
transaction.recentBlockhash = (
await connection.getLatestBlockhash()
).blockhash;
transaction.feePayer = account;
最後回傳Response如下格式即可:
const payload: ActionPostResponse = await createPostResponse({
fields: {
transaction,
message: "Successfully claimed!",
},
});
return Response.json(payload, {
headers: ACTIONS_CORS_HEADERS,
});
到此我們終於建立好我們API entry了。最後別忘了加入 /app/actions.json/route.ts這也是為了避免CORS問題,可以照範例程式碼直接複製貼上就好!
至此我們終於大功告成。如果要測試我們的程式碼是否正確,可以到此網址,記得修改API route和port number:https://dial.to?action=solana-action : http:/ localhost: 3000/api/actions/your_api_route,還有一個重點是如果你的合約是部署在devnet上的話,要改用這個domain:https://dial.to/devnet才會正常呼叫到合約喔!