跳转至

dApps 的签名供应商

原文:https://docs.elrond.com/sdk-and-tools/erdjs/erdjs-signing-providers

该页面将引导您完成将 erdjs 签名供应商集成到不基于dapp-core的 dApp 中的过程。

重要

注意,在大多数情况下,我们建议使用 dapp-core 而不是自己集成签名供应商。

重要

本页描述的代码示例也可以在 erdjs 范例库 中找到。

以下签名提供程序可用:

  • 网络钱包提供商
  • 扩展提供商(Maiar DeFi Wallet)
  • 钱包连接提供商
  • 硬件钱包(账本)提供商

网络钱包提供商

确保你提前看了一下网钩

@elrondnetwork/erdjs-web-wallet-provider 允许 dApp 的用户使用网络钱包登录并签署交易。

为了创建提供程序的实例,请执行以下操作:

import { WalletProvider, WALLET_PROVIDER_DEVNET } from "@elrondnetwork/erdjs-web-wallet-provider";

const provider = new WalletProvider(WALLET_PROVIDER_DEVNET); 

以下供应商 URL由包定义:WALLET_PROVIDER_TESTNETWALLET_PROVIDER_DEVNETWALLET_PROVIDER_MAINNET

登录和注销

然后,要求用户登录:

const callbackUrl = encodeURIComponent("http://my-dapp");
await provider.login({ callbackUrl }); 

一旦用户打开她的钱包,网络钱包就发出一个重定向回callbackUrl,以及用户的地址。您可以获得如下地址:

import qs from "qs";

const queryString = window.location.search.slice(1);
const params = qs.parse(queryString);
console.log(params.address); 

要注销,请执行以下操作:

const callbackUrl = window.location.href.split("?")[0];
await provider.logout({ callbackUrl: callbackUrl }); 

有时,dApp(和它的后端)可能想要可靠地分配一个离线用户身份到一个Elrond地址。在这种情况下,网络钱包供应商支持login()方法的一个额外参数:一个对网络钱包完全不透明的定制认证代币,在登录时用用户的钱包签名:

// An identity token, provided by an identity provider (server-side)
// (e.g. Google ID, a custom identity token)
const authToken = "aaaabbbbaaaabbbb";

// A server-side handler used to acknowledge, validate and honour
// the relationship between "authToken" and the Elrond address of the user
const callbackUrl = encodeURIComponent("https://my-dapp/on-wallet-login");
await provider.login({ callbackUrl, token: authToken }); 

签约交易

交易可以按如下方式签名:

import { Transaction } from "@elrondnetwork/erdjs";

const firstTransaction = new Transaction({ ... });
const secondTransaction = new Transaction({ ... });

await provider.signTransactions(
    [firstTransaction, secondTransaction], 
    { callbackUrl: callbackUrl }
); 

在使用网络钱包签署交易时,用户被重定向回callbackUrl,而查询字符串包含关于交易的信息,包括它们的签名。该信息可用于使用getTransactionsFromWalletUrl()重建Transaction物体:

const plainSignedTransactions = provider.getTransactionsFromWalletUrl(); 
重要

以下解决方法可能会发生变化。

截至 2022 年 7 月,网络钱包提供商以普通字符串的形式返回数据字段。然而,erdjs' Transaction.fromPlainObject()希望它是 base64 编码的。因此,我们需要对getTransactionsFromWalletUrl()的结果应用一个变通方法(一个额外的转换)。

for (const plainTransaction of plainSignedTransactions) {
    const plainTransactionClone = structuredClone(plainTransaction);
    plainTransactionClone.data = Buffer.from(plainTransactionClone.data).toString("base64");
    const transaction = Transaction.fromPlainObject(plainTransactionClone);

    // "transaction" can now be broadcasted.
} 

签约消息

重要

本节中的文档是初步的,可能会更改。

截至 2022 年 7 月,网络钱包提供商不允许对任意消息进行签名(仅支持交易签名)。

扩展提供商(Maiar DeFi 钱包)

确保你提前看了一下这一页

@elrondnetwork/erdjs-extension-provider 允许 dApp 的用户使用 Maiar DeFi 钱包登录并签署交易。

为了获取提供程序的实例(单例),请执行以下操作:

import { ExtensionProvider } from "@elrondnetwork/erdjs-extension-provider";

const provider = ExtensionProvider.getInstance(); 

在执行任何操作之前,请确保初始化提供程序:

await provider.init(); 

登录和注销

然后,要求用户登录:

const address = await provider.login();

console.log(address);
console.log(provider.account); 

要注销,请执行以下操作:

await provider.logout(); 

login()方法支持token参数(类似于 web 钱包供应商):

// A custom identity token (opaque to the signing provider)
const authToken = "aaaabbbbaaaabbbb";

await provider.login({ token: authToken });

console.log("Address:", provider.account.address);
console.log("Token signature:", provider.account.signature); 

签约交易

交易可以按如下方式签名:

import { Transaction } from "@elrondnetwork/erdjs";

const firstTransaction = new Transaction({ ... });
const secondTransaction = new Transaction({ ... });

await provider.signTransactions([firstTransaction, secondTransaction]);

// "firstTransaction" and "secondTransaction" can now be broadcasted. 

签约消息

可以对任意消息进行如下签名:

import { SignableMessage } from "@elrondnetwork/erdjs";

const message = new SignableMessage({
    message: Buffer.from("hello")
});

await provider.signMessage(message);

console.log(message.toJSON()); 

钱包连接提供商

@elrondnetwork/erdjs-wallet-connect-provider 允许 dApp 的用户使用 Maiar(移动应用)登录并签署交易。

首先,让我们看一个使用 qrcode (和引导程序)构建 QR 对话的(简单)方法:

import QRCode from "qrcode";

async function openModal(connectorUri) {
    const svg = await QRCode.toString(connectorUri, { type: "svg" });

    // The referenced elements must be added to your page, in advance
    $("#MyWalletConnectQRContainer").html(svg);
    $("#MyWalletConnectModal").modal("show");
}

function closeModal() {
    $("#MyWalletConnectModal").modal("hide");
} 

为了创建提供程序的实例,请执行以下操作:

import { WalletConnectProvider } from "@elrondnetwork/erdjs-wallet-connect-provider";

var provider;

const bridgeUrl = "https://bridge.walletconnect.org";

const callbacks = {
    onClientLogin: async function () {
        // closeModal() is defined above
        closeModal();
        const address = await provider.getAddress();
        console.log("Address:", address);
    },
    onClientLogout: async function () {
        console.log("onClientLogout()");
    }
};

const provider = new WalletConnectProvider(bridgeUrl, callbacks); 

在执行任何操作之前,请确保初始化提供程序:

await provider.init(); 

登录和注销

然后,要求用户在手机上使用 Maiar 登录:

const connectorUri = await provider.login();

// openModal() is defined above
openModal(connectorUri); 

一旦用户确认登录,就会执行onClientLogin()回调(如上所述)。

要注销,请执行以下操作:

await provider.logout(); 

签约交易

交易可以按如下方式签名:

import { Transaction } from "@elrondnetwork/erdjs";

const firstTransaction = new Transaction({ ... });
const secondTransaction = new Transaction({ ... });

await provider.signTransactions([firstTransaction, secondTransaction]);

// "firstTransaction" and "secondTransaction" can now be broadcasted. 

或者,可以使用方法signTransaction()签署单个交易。

签约消息

重要

本节中的文档是初步的,可能会更改。

截至 2022 年 7 月,erdjs 的钱包连接供应商不允许对任意消息进行签名(仅支持交易签名)。

硬件钱包(账本)提供商

确保你提前看了一下这一页

@elrondnetwork/erdjs-hw-provider 允许 dApp 的用户使用账本设备登录并签署交易。

为了创建提供程序的实例,请执行以下操作:

import { HWProvider } from "@elrondnetwork/erdjs-hw-provider";

const provider = new HWProvider(); 

在执行任何操作之前,请确保初始化提供程序(此外,Elrond应用程序必须在设备上打开):

await provider.init(); 

登录

在要求用户使用账本登录之前,您可能想要获取设备上所有可用的地址,显示它们,并让用户选择其中一个:

const addresses = await provider.getAccounts();
console.log(addresses); 

登录如下所示:

const chosenAddressIndex = 3;
await provider.login({ addressIndex: chosenAddressIndex });
alert(`Logged in. Address: ${await provider.getAddress()}`); 

或者,为了在登录后选择设备上的特定地址,调用setAddressIndex():

const addressIndex = 3;
await provider.setAddressIndex(addressIndex);
console.log(`Address has been set: ${await provider.getAddress()}.`); 

总帐提供程序本身不支持注销操作(在此上下文中不适用)。

登录流支持token参数(类似于其他供应商),使用方法tokenLogin():

// A custom identity token (opaque to the signing provider)
const authToken = "aaaabbbbaaaabbbb";

// Note the additional suffix (required as of July 2022):
const payloadToSign = Buffer.from(`${authToken}{}`);
const { address, signature } = await provider.tokenLogin({ addressIndex: 0, token: payloadToSign });

console.log("Address:", address);
console.log("Signature:", signature.hex()); 

签约交易

交易可以按如下方式签名:

import { Transaction } from "@elrondnetwork/erdjs";

const firstTransaction = new Transaction({ ... });
const secondTransaction = new Transaction({ ... });

await provider.signTransactions([firstTransaction, secondTransaction]);

// "firstTransaction" and "secondTransaction" can now be broadcasted. 

或者,可以使用方法signTransaction()签署单个交易。

签约消息

可以对任意消息进行如下签名:

import { SignableMessage } from "@elrondnetwork/erdjs";

const message = new SignableMessage({
    message: Buffer.from("hello")
});

await provider.signMessage(message);

console.log(message.toJSON()); 

验证登录代币签名

如前所述,dApp(及其后端)可能希望可靠地为Elrond地址分配一个离线用户身份。为此,签名供应商允许在登录流中使用一个登录代币——这个代币是使用用户的钱包签名的。之后,后端应用程序通常会验证代币的签名,如下所示:

export function verifyAuthTokenSignature(address, authToken, signature) {
    console.log("verifyAuthTokenSignature()");
    console.log("address:", address);
    console.log("authToken:", authToken);
    console.log("signature:", signature);

    // Note that the verification API will be improved in a future version of erdjs-walletcore.
    // As of @elrondnetwork/[email protected], this API is a bit tedious:
    const verifier = UserVerifier.fromAddress(new Address(address));

    const message = new SignableMessage({
        signature: { hex: () => signature },
        message: Buffer.from(`${address}${authToken}{}`)
    });

    const ok = verifier.verify(message);
    if (ok) {
        return `The bearer of the token [${authToken}] is also the owner of the address [${address}].`;
    }

    return "Verification failed.";
} 

上述代码片段中应用的解决方法有待改进。



回到顶部