复杂数据结构编码
在上一小节,我们实现了可以验证签名信息的智能合约,并且为了方便学习测试,发布到了测试网上。
这一小节,我们来研究如何使用TypeScript SDK来构建签名。
准备工作
- 使用mint.ts示例代码mint一个
ProfileSBT Object. - 使用get.ts示例代码查询到
ProfileSBT Object的handle, points, last_time等属性信息。 
构建签名
在sign.ts示例代码中,提供了对合约add_points函数的构建签名函数signMessage.
export const signMessage = async(id: string, add_points: number, last_time: number): Promise<Uint8Array> => {
    const profile_data = bcs.struct('Profile', {
        id: bcs.Address,
        add_points: bcs.u64(),
        last_time: bcs.u64(),
    });
    const profile_bytedata = profile_data.serialize({ id: id, add_points: add_points, last_time: last_time }).toBytes(); // Bytes
    const hash = keccak256(profile_bytedata); // Hex
    const hash_bytes = fromHex(hash); // Bytes
    const signature_bytes = await keypair.sign(hash_bytes); // Bytes
    return signature_bytes;
}
包含以下环节
BCS 序列化
BCS是把数据结构变为二进制编码的序列化格式标准。
先按照智能合约里的Profile格式去定义序列化数据结构
const profile_data = bcs.struct('Profile', {
    id: bcs.Address,
    add_points: bcs.u64(),
    last_time: bcs.u64(),
});
把函数输入的数据做序列化处理
const profile_bytedata = profile_data.serialize({ id: id, add_points: add_points, last_time: last_time }).toBytes();
哈希计算
把bcs序列化的结果profile_bytedata放去使用keccak256算法计算哈希值。得到的结果是十六进制,再转为二进制。
const hash = keccak256(profile_bytedata);
const hash_bytes = fromHex(hash);
产生签名
最后,对二进制数据做签名。
const signature_bytes = await keypair.sign(hash_bytes);
构建交易
add_points.ts展示了调用签名函数然后构建交易的示例代码。
const sign_bytedata = await signMessage(profile_id, add_points, profile_last_time);
const tx = new Transaction();
tx.moveCall({
    package: PACKAGE,
    module: "profile",
    function: "add_points",
    arguments: [
        tx.object(profile_id),
        tx.pure(bcs.u64().serialize(add_points).toBytes()),
        tx.pure(bcs.vector(bcs.u8()).serialize(sign_bytedata).toBytes()),
        tx.object("0x6"),
    ],
});
tx.setSender(address);
作业
为上一小节作业的edit_handle函数实现构建签名和交易信息的TypeScript代码。
