处理来自 nearlib 的账户和交易签名
Handling accounts and transaction signatures from nearlib
我有一份名为 exchange
的合同。用户 Bob
想要花费 near tokens
通过放置 Order
的方式购买 markets
中的位置。
Order
有一个名为 owner
的字段,在这种情况下 Bob
,合同必须证明某个 order
属于某个地址,这一点很重要。
目前如何处理发送至 exchange
的交易流程类似于:
const init = async () => {
this.near = await window.nearlib.connect(Object.assign({ deps: { keyStore: new window.nearlib.keyStores.BrowserLocalStorageKeyStore() } }, window.nearConfig));
this.walletAccount = new window.nearlib.WalletAccount(this.near);
this.accountId = this.walletAccount.getAccountId();
this.exchange = await this.near.loadContract(window.nearConfig.contractName, {
viewMethods: [],
changeMethods: ["place_new_order"],
sender: this.accountId,
});
}
await init();
// Bob logs into to near
this.walletAccount.requestSignIn(
window.nearConfig.contractName,
window.nearConfig.contractName,
);
// Login process
[...]
// Bob wants to place a new order
this.exchange.place_new_order(price, amount);
exchange
合约导入了一个名为 Order
的 struct
。
Order
看起来像:
use std::string::String;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize, Clone)]
pub struct Order {
pub owner: String,
pub amount: u64,
pub price: u64,
}
impl Order {
pub fn new(owner: String, amount: u64, price: u64) -> Self {
Order {
owner,
amount,
price
}
}
}
在这种情况下,Exchange
是执行 mod order
的合约。 Exchange
有 place_new_order
方法,这是我希望能够确保 Bob
是发送交易的人:
use near_bindgen::{near_bindgen, env};
[...]
mod Order;
[...]
pub fn place_new_order(&mut self, amount: u64, price: u64) {
// Stuff happens here
let order = Order::new(env::current_account_id(), amount, price);
// Stuff happens here
}
现在的问题是,以防万一,使用这个 nearlib 代码 env::current_account_id()
将始终 return exchange
作为 current_account_id
。这是有道理的,因为所有登录所做的就是创建一个 access_key
,它允许 exchange
以 Bob
的名义做一些事情,但它仍然是 Exchange
签署交易.
这里的问题是:我如何确保交易所知道 Bob
是发起交易的人?
一种有意义的工作方式:
Bob
用他的私钥签署每笔交易,我在这里的问题是:如何?
这会导致类似 Metamask 的 UX 问题,其中在每个 tx 上签名都是糟糕的 UX。
我的建议如下:
Bob
使用 deposit
方法在 exchange
上存入一定数量的 near-tokens
并且 exchange
可以花费它,只要它可以证明它是通过 Bob
签名的 "login-access-token" 来实现的,这里的问题又是:这可能吗?如果可能的话如何?
简答
您应该使用 env::predecessor_account_id()
来获取调用交换方法的用户或合约的帐户 ID。
详情
在你的情况下,即使通过指向 exchange
的访问密钥,它仍然由 bob. The
signer_idand the
predecessor_id[=14= 签名]鲍勃`.
执行过程中有3种不同类型的账户:
env::current_account_id()
returns 当前正在执行的合约的当前账户 ID。
env::signer_account_id()
returns 签署原始交易的用户的帐户 ID。大多数时候你不应该依赖签名者账户 ID,因为当前调用可以从另一个合约完成。
env::predecessor_account_id()
return调用当前合约的前任账户ID。您应该使用它来验证呼叫您的用户的身份。
我有一份名为 exchange
的合同。用户 Bob
想要花费 near tokens
通过放置 Order
的方式购买 markets
中的位置。
Order
有一个名为 owner
的字段,在这种情况下 Bob
,合同必须证明某个 order
属于某个地址,这一点很重要。
目前如何处理发送至 exchange
的交易流程类似于:
const init = async () => {
this.near = await window.nearlib.connect(Object.assign({ deps: { keyStore: new window.nearlib.keyStores.BrowserLocalStorageKeyStore() } }, window.nearConfig));
this.walletAccount = new window.nearlib.WalletAccount(this.near);
this.accountId = this.walletAccount.getAccountId();
this.exchange = await this.near.loadContract(window.nearConfig.contractName, {
viewMethods: [],
changeMethods: ["place_new_order"],
sender: this.accountId,
});
}
await init();
// Bob logs into to near
this.walletAccount.requestSignIn(
window.nearConfig.contractName,
window.nearConfig.contractName,
);
// Login process
[...]
// Bob wants to place a new order
this.exchange.place_new_order(price, amount);
exchange
合约导入了一个名为 Order
的 struct
。
Order
看起来像:
use std::string::String;
use borsh::{BorshDeserialize, BorshSerialize};
use serde::{Deserialize, Serialize};
#[derive(Debug, Serialize, Deserialize, BorshDeserialize, BorshSerialize, Clone)]
pub struct Order {
pub owner: String,
pub amount: u64,
pub price: u64,
}
impl Order {
pub fn new(owner: String, amount: u64, price: u64) -> Self {
Order {
owner,
amount,
price
}
}
}
在这种情况下,Exchange
是执行 mod order
的合约。 Exchange
有 place_new_order
方法,这是我希望能够确保 Bob
是发送交易的人:
use near_bindgen::{near_bindgen, env};
[...]
mod Order;
[...]
pub fn place_new_order(&mut self, amount: u64, price: u64) {
// Stuff happens here
let order = Order::new(env::current_account_id(), amount, price);
// Stuff happens here
}
现在的问题是,以防万一,使用这个 nearlib 代码 env::current_account_id()
将始终 return exchange
作为 current_account_id
。这是有道理的,因为所有登录所做的就是创建一个 access_key
,它允许 exchange
以 Bob
的名义做一些事情,但它仍然是 Exchange
签署交易.
这里的问题是:我如何确保交易所知道 Bob
是发起交易的人?
一种有意义的工作方式:
Bob
用他的私钥签署每笔交易,我在这里的问题是:如何?
这会导致类似 Metamask 的 UX 问题,其中在每个 tx 上签名都是糟糕的 UX。
我的建议如下:
Bob
使用deposit
方法在exchange
上存入一定数量的near-tokens
并且exchange
可以花费它,只要它可以证明它是通过Bob
签名的 "login-access-token" 来实现的,这里的问题又是:这可能吗?如果可能的话如何?
简答
您应该使用 env::predecessor_account_id()
来获取调用交换方法的用户或合约的帐户 ID。
详情
在你的情况下,即使通过指向 exchange
的访问密钥,它仍然由 bob. The
signer_idand the
predecessor_id[=14= 签名]鲍勃`.
执行过程中有3种不同类型的账户:
env::current_account_id()
returns 当前正在执行的合约的当前账户 ID。env::signer_account_id()
returns 签署原始交易的用户的帐户 ID。大多数时候你不应该依赖签名者账户 ID,因为当前调用可以从另一个合约完成。env::predecessor_account_id()
return调用当前合约的前任账户ID。您应该使用它来验证呼叫您的用户的身份。