Show-me-wallet 運作原理
Proof of wallet (自證wallet QR code)
證明wallet的部份,app裡做了幾件事:
(1) connect Phantom wallet, 得知用戶的wallet address (後稱為<wallet address>)。
(2) 在app裡生成一對本地儲存的keypair作為grant key。
(keypair及public key後稱為<grant keypair>及<grant public key>)。
(3) 草擬一段援權聲明 (後稱為<grant payload message>):
v0: Approve 'Show-me-wallet' grant key '<grant public key>' for scope 'nftOwnerProof' between time '<grant nbf>' and '<grant exp>'.
這裡<grant nbf>與<grant exp>都是一個ISO8601格式時間, 意思就是一般auth token應用的not-before及expire。簡單來說就是只能在這兩個時間之間的時間段內生效。
目前這裡我是設定了1小時授權時間。
實際的message大概會是這樣:
我們會提交到Phantom Wallet要求做off-chain簽名。(Ed25519簽名及base58 encode)
(4) 至此app裡所持有的數據:
用戶wallet address (<wallet address>)
app內本地grant key keypair (<grant keypair>)
授權聲明 (<grant payload message>)
授權聲明簽名 (<grant payload message signature>)
雖然現在已經擁有授權作proof of wallet, 但我們不會只用這些授權來直接使用。因為一小時授權很長, 如果被人偷去這份聲明, 就能在一小時內扮演其他人。
所以流程上, 我們要求有二次授權去證明其繼續持有有效證明。
(5) 我們會要求用<grant keypair>, 每10秒為周期生成短期的二次授權。
二次授權message (後稱為<grant proof message>)如下:
iss=<grant proof issue time>;nbfs=5;exps=10
這裡的幾個attribute意思:
iss, 就是"二次授權"生成時間。
nbfs與exps, 也就是"二次授權"允許的not-before秒數及epxire秒數。
整體意思就是說, 這是在iss的timestamp時生成, 而使用時不能早於iss前5秒, 而且也會在iss後10秒失效。
我們app裡會用<grant keypair>去sign這二次授權message, 得到<grant proof message signature>。
這裡也是用Ed25519簽名及base58 encode的格式。
由於這是用本地keypair sign也就不用再經phantom wallet了。
(6) 如何把這些東西呈現呢? 我們把它們塞進json用QR code顯示出來。
json payload格式如下(實際上是compacted):
{
"owner": <wallet address>,
"ownerGrantMsg": <grant payload message (packed)>,
"ownerGrantMsgSign": <grant payload message signature>,
"grantProofMsg": <grant proof message>,
"grantProofMsgSign": <grant proof message signature>,
}
留意下, ownerGrantMsg我們不是用原本那臭長的sign message string, 而是用compacted string格式以節省payload長度。
compacted string格式如下:
v=0;app=Show-me-wallet;gk=<grant public key>;scp=nftOwnerProof;nbf=<grant nbf>;exp=<grant exp>
整體還是臭長的, 不過算了XD
我們就用這去生成QR code了。
驗證wallet QR code
驗證的流程如下:
(1) 當然是Scan QR code, 提取前面生成QR code的那些內容。
(2) 從Payload裡, 先提取用戶wallet address。
然後將"ownerGrantMsg部份重新構成grant payload message, 及驗證其signature。
再由grant payload message中提取獲授權的grant key。再與"grantProofMsg"及signature做驗證。
以上除了signature驗證, 也會加上NBF及expire時間的各驗證。
{
"owner": <wallet address>,
"ownerGrantMsg": <grant payload message (packed)>,
"ownerGrantMsgSign": <grant payload message signature>,
"grantProofMsg": <grant proof message>,
"grantProofMsgSign": <grant proof message signature>,
}
以上做了那麼多, 其實就只是為了驗證用戶的wallet address身份。
(3) 得知身份後, 就用Helius的API查看用戶wallet address有什麼NFT。
然後就是在畫面上把NFT的資料及圖片顯示出來。